provider

package
v0.10.54 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 26, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package provider is the single LLM transport for Coremetry.

FAZ 1.1 (AI Assistant tasarımı, docs/plans/ai-assistant-design-2026-08-16.md §2.1 / §4-Faz1). Bugün 8 ayrı istek üreticisi var (copilot.go ×3, chat.go ×2, stream.go ×2, rag.go embed) ve her biri gövde şeklini, header'ları ve salvage zincirini KENDİ kopyasıyla taşıyor. Bunun bedeli ölçüldü: 1024 max_tokens paritesi ~1000 sürüm boyunca anthropic/github yollarında eksik kaldı (v0.9.1120). Tek transport o sınıfı kapatır.

FAZ 1.2 — kapsam ÜÇ sağlayıcının BUFFERED explain yolunun tamamı: DoOpenAI (JSON merdiveni dahil) + DoAnthropic + DoGitHub. Eski buffered üreticiler (explain*WithUsage) silindi; artık tek yazılış var. Stream (stream:true) ve tool-calling (chat.go) üreticileri bilinçli olarak DIŞARIDA — onlar sonraki dilimde taşınır; bu dilimde yalnız salvage/parse zincirini buradan çağırırlar, yani kurtarma mantığı da tek yerde.

Tasarım kuralı: provider DURUM TUTMAZ. Config bir SNAPSHOT olarak dışarıdan gelir; canlı yapılandırmanın (kilit, 30s refresh, TLS-skip, timeout, GitHub oturum jetonu, JSON-yetenek kararları) sahibi copilot.Service'tir ve öyle kalır. Merdiven de öyle: hangi basamağın DENENECEĞİ ve reddedilince ne yapılacağı Service'in kararı, gövdeye hangi response_format'ın basılacağı buranın işi.

Index

Constants

View Source
const (
	JSONPlain  = 0 // response_format yok
	JSONObject = 1 // {"type":"json_object"}
	JSONSchema = 2 // {"type":"json_schema", …}
)

JSON zorlama basamakları. DoOpenAI üçünü de basar; hangi basamağın deneneceğine ve reddedilince bir alta inileceğine copilot.Service karar verir (yetenek kararları uç-başına önbellekli, yani DURUM).

Basamak sınırın DIŞINDAysa ya da JSONSchema şemasız gelirse DoOpenAI açık hata döndürür: sessizce kısıtsız çağrıya düşmek, isteyen yüzeyin garantisini haber vermeden kaybettirirdi (fail-open-silently-unapplies sınıfı).

View Source
const SalvagedThinkingPrefix = "⚠ Bu metin modelin DÜŞÜNCE bloğundan kurtarıldı — " +
	"nihai cevabı değil, çalışma notu. Çıkarımlar ve sayılar yarım olabilir.\n\n"

SalvagedThinkingPrefix — kurtarılmış düşünce bloğunun önüne konan uyarı. Dışa açık, çünkü tüketiciler (arayüz, denetim) bu metni TANIYABİLMELİ — dizgeyi kendi kopyalarında tekrar yazmasınlar.

Variables

This section is empty.

Functions

func EmptyAnswerError

func EmptyAnswerError(finishReason string) error

EmptyAnswerError — kurtarılacak hiçbir şey kalmadığında operatöre EYLEME DÖNÜK hata. finish_reason="length" ayrı bir teşhistir: bütçe düşünme fazında tükenmiştir, çözüm max_tokens'ı yükseltmek ya da düşünmeyi kapatmaktır.

Metinler copilot.go'daki ikizleriyle BİREBİR aynı tutuluyor — canary sırasında aynı yüzey iki yoldan da aynı cümleyi döndürmeli (parity testi bunu pinler).

func IsSalvagedThinking added in v0.10.37

func IsSalvagedThinking(s string) bool

IsSalvagedThinking — bu cevap düşünce bloğundan mı kurtarıldı.

Tüketiciler (arayüz rozeti, denetim sorgusu) buna bakıyor; dizge karşılaştırmasını kendi içlerinde yazmak, işaret değişince sessizce kopmak demekti.

func MarkSalvagedThinking added in v0.10.37

func MarkSalvagedThinking(s string) string

MarkSalvagedThinking — düşünce bloğunu işaretler.

Boş girdi boş kalır: işaretin tek başına gitmesi, olmayan bir cevabı varmış gibi göstermek olurdu.

func SalvageAnswer

func SalvageAnswer(content, reasoningContent, reasoning string) string

SalvageAnswer — cevabı modelin koyduğu yerden çeker, öncelik sırasıyla:

  1. son </think> sonrasındaki content (normal hâl),
  2. ayrılmış reasoning alanı (reasoning_content → reasoning),
  3. son çare: <think> bloğunun İÇİ.

Hiçbiri yoksa boş döner — çağıran EmptyAnswerError ile teşhis eder.

func StripThinking

func StripThinking(s string) string

StripThinking, bazı yerel reasoning modellerinin content'e gömdüğü <think>…</think> bloğunu atar; SON </think> sonrasını döndürür. Blok yoksa yalnız trim eder.

func ThinkingContent

func ThinkingContent(s string) string

ThinkingContent, İLK <think>…</think> bloğunun İÇİNİ döndürür — StripThinking hiçbir şey bırakmadığında son çare. Bazı modeller yalnız düşünce bloğu üretir ve o düşünce genelde açıklamanın kendisidir; kurtarmak, isteği başarısız saymaktan iyidir.

Types

type ChatMessage added in v0.9.1125

type ChatMessage struct {
	Role        string       // "user" | "assistant"
	Text        string       `json:",omitempty"`
	ToolCalls   []ToolCall   `json:",omitempty"`
	ToolResults []ToolResult `json:",omitempty"`
}

ChatMessage, sağlayıcı-nötr tek konuşma turu. Bir kullanıcı turu Text (soru) VEYA ToolResults (fonksiyon çıktıları) taşır. Bir asistan turu Text (düz metin) ve/veya ToolCalls (çalıştırılmasını istediği fonksiyonlar) taşır.

type ChatRequest added in v0.9.1125

type ChatRequest struct {
	Model     string
	MaxTokens int
	// Temperature nil = gövdeye HİÇ koyma (bkz. Request.Temperature).
	Temperature *float64
	System      string
	Messages    []ChatMessage
	Tools       []ToolSpec
}

ChatRequest — çok turlu, tool'lu tek bir model çağrısının girdileri. Request'in (tek-atış explain) tool'lu ikizi: aynı ayar alanları, System + tek User yerine Messages + Tools.

type ChatResponse added in v0.9.1125

type ChatResponse struct {
	Text         string
	ToolCalls    []ToolCall
	InputTokens  int
	OutputTokens int
}

ChatResponse — çözümlenmiş tur. ToolCalls doluysa çağıran onları çalıştırıp döngüye devam eder; boşsa Text nihai cevaptır.

func ChatAnthropicTools added in v0.9.1125

func ChatAnthropicTools(ctx context.Context, cfg Config, req ChatRequest) (ChatResponse, error)

ChatAnthropicTools tek bir tool'lu Messages turu yürütür.

func ChatGitHubTools added in v0.9.1125

func ChatGitHubTools(ctx context.Context, cfg Config, req ChatRequest) (ChatResponse, error)

ChatGitHubTools tek bir tool'lu Copilot turu yürütür. cfg.APIKey = ÇÖZÜLMÜŞ oturum jetonu (jeton takası DURUM taşır ve copilot.Service'te kalır — DoGitHub ile aynı kural).

func ChatOpenAITools added in v0.9.1125

func ChatOpenAITools(ctx context.Context, cfg Config, req ChatRequest) (ChatResponse, error)

ChatOpenAITools tek bir tool'lu openai-compat turu yürütür.

type Config

type Config struct {
	BaseURL    string
	APIKey     string
	Model      string
	HTTPClient *http.Client
}

Config — çağrı anındaki yapılandırma SNAPSHOT'ı.

HTTPClient zorunlu: timeout (operatör-ayarlı, v0.9.1120) ve TLS-skip transport'u onun içinde yaşıyor. Nil'e sessizce http.DefaultClient koymak, 180s local-LLM timeout'unu ve kurumsal-CA muafiyetini haber vermeden düşürürdü.

type EmbedRequest added in v0.9.1126

type EmbedRequest struct {
	Model string
	// Inputs — sıra ANLAMLIDIR. Çağıran vektörleri girdi indeksiyle
	// eşleştirir (rag chunk_idx'e yazar); yanıt `index` alanına göre
	// yeniden sıralanır, geliş sırasına DEĞİL.
	Inputs []string
}

EmbedRequest — bir /embeddings çağrısının tel-üstü girdileri.

Toplu-iş (batch) sınırı BURADA DEĞİL, çağırandadır: rag kendi embedBatchMax=64 döngüsünü korur, çünkü sınırın sebebi uç-başına istek boyu ve o karar yapılandırmanın sahibinin işi. Burada dilimleme yapmak, ai_calls'ta "bir satır = bir HTTP çağrısı" sözleşmesini de sessizce bozardı.

type EmbedResponse added in v0.9.1126

type EmbedResponse struct {
	Vectors     [][]float32
	InputTokens int
}

EmbedResponse — çözümlenmiş yanıt.

InputTokens `usage.prompt_tokens`tan gelir. OpenAI ve vLLM ikisi de embeddings yanıtında usage yollar; yollamayan uçlarda 0 kalır ve kaydedici satırı yine yazar (gecikme + statü tek başına değerli — Response'un usage sözleşmesiyle aynı duruş).

func DoEmbeddings added in v0.9.1126

func DoEmbeddings(ctx context.Context, cfg Config, req EmbedRequest) (EmbedResponse, error)

DoEmbeddings tek bir /embeddings çağrısı yapar ve vektörleri GİRDİ SIRASINDA döndürür.

Hata semantiği eski ikiziyle aynı: taşıma hatası "embedding isteği: %w", 200 dışı yanıt "embedding endpoint %d: <gövde>" — artık HTTPError tipiyle, yani statü metinden ayıklanmadan okunabiliyor.

func ParseEmbeddings added in v0.9.1126

func ParseEmbeddings(r io.Reader, n int) (EmbedResponse, error)

ParseEmbeddings, /embeddings yanıtını çözer ve vektörleri GİRDİ indeksine göre yerleştirir.

Kardeşlerinden farklı olarak []byte değil io.Reader alır ve okuma TAVANI YOKTUR — bilerek: 64 metinlik bir bge-m3 batch'i 64×1024 float32'yi JSON olarak ~4-5MB'ta taşır, yani chat yolunun 1MB'lık maxRespBytes tavanı burada yanıtın ORTASINDAN keserdi. Kesik gövde "decode" hatası olarak görünür ve teşhisi çok pahalıya patlardı.

type HTTPError added in v0.9.1124

type HTTPError struct {
	// Provider — hata metnindeki önek. Sağlayıcı adının kendisi değil,
	// eski kodun BASTIĞI etiket: "openai-compat", "anthropic",
	// "github copilot".
	Provider string
	Status   int
	// Body — kırpılmış yanıt gövdesi (okuma tavanı maxRespBytes).
	Body string
}

errors.go — taşımanın hata sözleşmesi.

İki tüketicisi var ve ikisi de METNE bakıyordu:

  1. copilot.isQuotaErr — mesajda " 429" / "quota" / "rate limit" arayıp kota devre-kesicisini kuruyor (v0.9.200). Yeni bir cümle kurmak kesiciyi sessizce silahsız bırakırdı.
  2. JSON merdiveni — "response_format'ı anlamadım" ailesini (400, 422, 501) statüden ayırt ediyor.

(1) metinle çalışmaya devam ediyor: string sözleşmesi eskiden beri pinli. (2) artık metinden statü ayıklamıyor — HTTPError tipli hata statüyü TAŞIYOR, çağıran errors.As ile okuyor. Bu, "gövde metninde üç haneli sayı ara" sınıfını tamamen kapatır.

func (*HTTPError) Error added in v0.9.1124

func (e *HTTPError) Error() string

type Request

type Request struct {
	Model     string
	MaxTokens int
	// Temperature nil = gövdeye HİÇ koyma. copilot.Service bugün
	// daima bir değer gönderiyor (tuneTemperature ok=true); nil hâli,
	// bazı reasoning uçlarının temperature'ı reddettiği gelecekteki
	// "hiç gönderme" durumu için ifade edilebilir tutuluyor.
	Temperature *float64
	System      string
	User        string
	// JSONLevel — JSONPlain | JSONObject | JSONSchema. Yalnız
	// openai-compat yolunda uygulanır: anthropic ve github uçlarına
	// response_format bugüne kadar hiç gönderilmedi ve bu dilim
	// DAVRANIŞ TAŞIYOR, değiştirmiyor. O iki taşıyıcı JSONPlain
	// dışındaki basamağı açık hatayla reddeder ki "uyguladım" sanılmasın.
	JSONLevel int
	// JSONSchemaName / JSONSchema — yalnız JSONLevel==JSONSchema'da
	// okunur ve İKİSİ de zorunludur. Boş şemayla json_schema göndermek
	// 400 alır ve o uç için GEREKSİZ bir yetenek kararı yazdırırdı
	// (v0.9.527); Service şemasız isteği zaten bir alt basamağa indirir,
	// buradaki denetim o sözleşmenin ikinci kilidi.
	JSONSchemaName string
	JSONSchema     map[string]any
}

Request — bir LLM çağrısının tel-üstü girdileri.

Model burada da, Config'te de var: Config kimlik/uç bilgisidir (baseURL+key+varsayılan model), Request ise O çağrının modelidir. Boşsa Config.Model, o da boşsa sağlayıcı varsayılanı kullanılır.

type Response

type Response struct {
	Text         string
	InputTokens  int
	OutputTokens int
}

Response — çözümlenmiş yanıt. Token sayıları `usage` alanından gelir; bazı yerel uçlar (eski Ollama, vLLM) usage yollamaz ve 0 kalır — kaydedici satırı yine yazar (gecikme + statü değerli).

func DoAnthropic added in v0.9.1124

func DoAnthropic(ctx context.Context, cfg Config, req Request) (Response, error)

DoAnthropic tek bir buffered Messages çağrısı yapar.

max_tokens ve temperature Request'ten gelir. Bu, v0.9.1120'nin düzelttiği hatanın taşınmış hâli: bu yol ~1000 sürüm boyunca sabit 1024 ve HİÇ temperature göndermişti (openai-compat 4096 alırken). Değerlerin sahibi Service; buranın işi onları gövdeye basmak.

func DoGitHub added in v0.9.1124

func DoGitHub(ctx context.Context, cfg Config, req Request) (Response, error)

DoGitHub tek bir buffered Copilot chat.completion çağrısı yapar. cfg.APIKey = ÇÖZÜLMÜŞ oturum jetonu (yukarıdaki (1)).

func DoOpenAI

func DoOpenAI(ctx context.Context, cfg Config, req Request) (Response, error)

DoOpenAI tek bir buffered (stream'siz) chat.completion çağrısı yapar ve kurtarma zincirinden geçmiş metni döndürür.

Hata semantiği copilot.go'daki ikiziyle aynı tutulmuştur: taşıma hatası "openai-compat call: %w", ≥300 yanıtı "openai-compat %d: <gövde>" (HTTPError tipiyle, statü ayıklanabilir). Kota kesicisi (429 → 1h pencere) ve JSON merdiveni ÇAĞIRANDA kalır: transport döner, Service karar verir.

func ParseAnthropic added in v0.9.1124

func ParseAnthropic(respBody []byte) (Response, error)

ParseAnthropic, buffered bir Messages gövdesini çözer. Saf: ağ yok, durum yok. Streaming yolu da bunu çağırıyor — bir vekil stream:true bayrağını yutup tek-atış JSON döndürdüğünde, elde OLAN gövdeyi çözümlemek ikinci bir faturalı çağrıdan iyidir (v0.8.404).

content[] birden çok text bloğu taşıyabilir (Anthropic uzun yanıtı bölebiliyor); text OLMAYAN bloklar (tool_use, thinking) atlanır.

func ParseGitHubChat added in v0.9.1124

func ParseGitHubChat(respBody []byte) (Response, error)

ParseGitHubChat, Copilot'un chat.completion gövdesini çözer. Kasıtlı olarak ParseOpenAIChat'ten ayrı — yukarıdaki (3).

func ParseOpenAIChat

func ParseOpenAIChat(respBody []byte) (Response, error)

ParseOpenAIChat, buffered bir chat.completion gövdesini çözer ve kurtarma zincirini uygular. Saf: ağ yok, durum yok — tablo testli.

func StreamAnthropic added in v0.9.1125

func StreamAnthropic(ctx context.Context, cfg Config, req Request, onDelta func(string)) (Response, error)

StreamAnthropic tek bir stream:true Messages çağrısı yapar. Sözleşme StreamOpenAI ile aynı (bkz. yukarısı).

Uç sabittir: Config.BaseURL bu yolda OKUNMAZ — buffered ikizindeki (DoAnthropic) kararın aynısı.

func StreamOpenAI added in v0.9.1125

func StreamOpenAI(ctx context.Context, cfg Config, req Request, onDelta func(string)) (Response, error)

StreamOpenAI tek bir stream:true chat.completion çağrısı yapar ve içerik parçalarını onDelta ile yayınlar. onDelta nil olabilir.

Akış kurulamazsa *StreamFallbackError döner — geri düşme KARARI çağıranındır (bkz. dosya başı). Akış başladıktan SONRA kopan bağlantı geri düşüş DEĞİLDİR: parçalar istemciye ulaştı, hata düz döner.

type StreamFallbackError added in v0.9.1125

type StreamFallbackError struct {
	Verdict     StreamVerdict
	Stage       StreamStage
	Provider    string // "openai-compat" | "anthropic" — log/hata öneki
	Status      int    // StageHead dışında 0
	ContentType string
	Body        []byte
	Err         error // bağlanma / okuma hatası, varsa
}

StreamFallbackError — "akış olmadı". Service errors.As ile okur, Verdict + Stage'e bakıp kararı verir.

Body, taşımanın ZATEN okuduğu gövdedir: VerdictParseBuffered'da tam tek-atış cevabı (Service onu buffered çözümleyiciye verir — ikinci faturalı çağrı YOK), diğerlerinde log için kırpılmış parçadır.

func (*StreamFallbackError) Error added in v0.9.1125

func (e *StreamFallbackError) Error() string

func (*StreamFallbackError) Unwrap added in v0.9.1125

func (e *StreamFallbackError) Unwrap() error

type StreamStage added in v0.9.1125

type StreamStage int

StreamStage — geri düşüşün hangi aşamada olduğunu söyler. Service'in log satırı üçünü ayrı cümlelerle yazıyor ve operatör bu cümlelerle teşhis koyuyor (bağlanamadı mı, baş mı reddetti, akış boş mu geldi).

const (
	// StageConnect — istek hiç kurulamadı (DNS/TCP/TLS/timeout).
	StageConnect StreamStage = iota
	// StageHead — yanıt başı geldi ve akış DEĞİL (statü/content-type).
	StageHead
	// StageEmptyStream — SSE başlıkları geldi ama gövde TEK bir olay
	// bile üretmeden bitti. Hâlâ ilk-bayt bölgesi: bir kez geri düş,
	// karar YAZMA.
	StageEmptyStream
)

type StreamVerdict added in v0.9.1125

type StreamVerdict int

StreamVerdict — stream:true yoklamasının yanıt BAŞINA verilen karar. Yalnız "bu istek şekli kabul edilmiyor" diyen statüler kalıcı karar üretir; geçici olan her şey YALNIZ bu çağrı için geri düşer ve bir dahakine yeniden yoklanır.

const (
	// VerdictStream — 200 + text/event-stream: akışı tüket.
	VerdictStream StreamVerdict = iota
	// VerdictParseBuffered — 200 + SSE-olmayan gövde: sunucu stream:true
	// bayrağını yuttu ve tek atışta cevapladı. Gövde ZATEN cevaptır —
	// ikinci (faturalı) çağrı yapmadan çözümlenmeli.
	VerdictParseBuffered
	// VerdictFallbackCache — bayrağın kesin reddi (bazı vLLM sürümleri
	// stream:true'ya 400 döner): buffered'a BİR kez düş + kararı
	// önbelleğe yaz.
	VerdictFallbackCache
	// VerdictFallbackOnce — geçici ya da akışa özgü olmayan hata (429
	// kota, 5xx, auth): buffered'a BİR kez düş ama önbelleğe YAZMA.
	VerdictFallbackOnce
)

func ClassifyStreamResponse added in v0.9.1125

func ClassifyStreamResponse(status int, contentType string) StreamVerdict

ClassifyStreamResponse, stream:true yoklamasının yanıt BAŞINI bir karara eşler. Saf + tablo testli.

type ToolCall added in v0.9.1125

type ToolCall struct {
	ID    string          // sağlayıcı üretimi id, sonuçta geri yollanır
	Name  string          // tool adı
	Input json.RawMessage // argümanlar (JSON)
	// Raw, openai-compat sağlayıcısının döndürdüğü TAM tool_call
	// nesnesidir (v0.8.373, operatör-bildirimi). Gemini'nin uyumluluk
	// ucu ek alanlar iliştiriyor (extra_content → thought_signature) ve
	// tekrar oynatılan functionCall onları taşımıyorsa sonraki turu 400
	// INVALID_ARGUMENT ile REDDEDİYOR — nesneyi yukarıdaki kırpılmış
	// alanlardan yeniden kurmak bilinmeyen her şeyi sessizce düşürüyordu.
	// Doluysa tekrar kodlayıcısı Raw'ı BİREBİR gönderir; ID/Name/Input
	// yürütücünün çözümlenmiş görüşü olarak kalır. Anthropic yolunda ve
	// eski mesajlarda nil.
	Raw json.RawMessage `json:",omitempty"`
}

ToolCall, modelin istediği tek bir fonksiyon çağrısı.

type ToolResult added in v0.9.1125

type ToolResult struct {
	CallID  string
	Name    string
	Content string // JSON'a çevrilmiş tool çıktısı (ya da hata metni)
	IsError bool
}

ToolResult, bir ToolCall'ın yürütülmüş çıktısı; model okuyabilsin diye sonraki tura geri beslenir.

type ToolSpec added in v0.9.1125

type ToolSpec struct {
	Name        string
	Description string
	InputSchema map[string]any
}

ToolSpec, LLM'e verilen sağlayıcı-nötr fonksiyon tanımı. InputSchema JSON Schema'dır (draft 2020-12) — MCP tool'larının zaten bildirdiği şekil, böylece API katmanı mcp.Tool → ToolSpec'i 1:1 eşler.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL