// Package llm — провайдер LLM за интерфейсом (дискриминатор type). // // Реализация выбирается полем [llm].type (см. docs/specs/recognition.md). // Первый и пока единственный тип — "openai-compat": OpenAI-совместимый Chat // Completions API (локальные серверы LM Studio/llama.cpp/Ollama и облачные // совместимые провайдеры — DeepSeek, Qwen и др.). // // Пакет отвечает за один вызов модели и транспортную устойчивость (ретраи // на сетевые сбои, 429 и 5xx). Бюджет переразбора ответа со схемой-в-промпте // (llm.max_retries) принадлежит вызывающему recognize, а не провайдеру. package llm import ( "context" "errors" "fmt" "time" ) // Role — роль сообщения в диалоге. type Role string const ( RoleSystem Role = "system" RoleUser Role = "user" RoleAssistant Role = "assistant" ) // Message — одно сообщение запроса. type Message struct { Role Role Content string } // Request — запрос к модели. type Request struct { Messages []Message JSONMode bool // response_format: json_object (структурированный вывод) Temperature *float64 // nil — не передаём, у модели остаётся её дефолт MaxTokens int // 0 — не передаём } // Usage — расход токенов и стоимость (если провайдер их сообщает). type Usage struct { PromptTokens int CompletionTokens int TotalTokens int Cost float64 } // Response — ответ модели. type Response struct { Content string Model string Usage Usage } // Provider — абстракция доступа к LLM. recognize работает только с ним и не // знает про конкретный транспорт. type Provider interface { Complete(ctx context.Context, req Request) (Response, error) } // Config — параметры провайдера (подмножество [llm] из конфига). type Config struct { Type string BaseURL string APIKey string Model string Proxy string Timeout time.Duration } // ErrUnknownType — запрошенный [llm].type не поддерживается. var ErrUnknownType = errors.New("llm: unknown provider type") // New собирает провайдер по дискриминатору cfg.Type. func New(cfg Config) (Provider, error) { switch cfg.Type { case "openai-compat": return newOpenAICompat(cfg) case "": return nil, fmt.Errorf("%w: %q (укажите [llm].type)", ErrUnknownType, cfg.Type) default: return nil, fmt.Errorf("%w: %q", ErrUnknownType, cfg.Type) } }