Help us shape the future of Go! Take the 2026 Go Developer Survey

llm

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Sep 15, 2026 License: MIT Imports: 10 Imported by: 0

README

llm

Вызов языковой модели одним контрактом поверх нескольких плеч. Корень пакета — контракт, повторы, бюджет времени, классы отказа и наблюдатель; протокол поставщика — в подпакете. Сейчас есть ollama (нативный /api/chat), следом gigachat и yandex.

c := llm.New(ollama.New("http://localhost:11434"), 90*time.Second)

res, err := c.Chat(ctx, llm.Request{
	Task:  "receipt",
	Model: "gemma4:31b-cloud",
	Messages: []llm.Message{
		{Role: llm.RoleSystem, Text: prompt},
		{Role: llm.RoleUser, Text: "скриншот", Images: []llm.Image{{MIME: "image/png", Data: png}}},
	},
	Output: llm.Output{Mode: llm.ModeJSON},
})

Что делает клиент

  • Срок стоит на попытке, не на вызове: повтор после просрочки получает полный срок. Budget() считает худший случай — его обязана отвести себе джоба.
  • Классы отказа. immediate (сеть, 5xx, 408, просрочка) и after_delay (429) клиент повторяет сам с удвоением паузы и Retry-After. needs_configuration (401, 402, 403, 404: ключ, баланс, модель) и never (прочие 4xx) — не повторяет; первый при этом восстановим (llm.Recoverable) — чинит оператор, а не запрос.
  • Просьба подождать дольше MaxRetryAfter не ждётся: отказ уходит наверх со сроком как есть. Повторяет его очередь потребителя, а не клиент, заснувший на час.
  • Наблюдатель получает отчёт на каждую попытку и на вызов: исход, фаза, длительность, расход. Реализация под Prometheus или журнал — у потребителя; ядро от них не зависит.
  • Расход — по попыткам, Usage.Known отличает «ноль» от «не сообщили».

Что остаётся потребителю

Промпты и схемы, разбор ответа, пороги качества, тарифы и стоимость, журнал вызовов, квоты. llm.Fingerprint(...) даёт идентичность вызова до его выполнения — плечо, модель, ревизия, хеш промпта, схема, подготовка входа — чтобы дедупить прогоны и не смешивать плечи.

Documentation

Overview

Package llm — вызов языковой модели одним контрактом поверх нескольких плеч: повторы, бюджет времени, классы отказа и наблюдатель — здесь, протокол поставщика — в подпакете (ollama; gigachat и yandex следом).

Index

Constants

View Source
const (
	DefaultTimeout       = 90 * time.Second
	DefaultAttempts      = 3
	DefaultPause         = 2 * time.Second
	DefaultMaxPause      = time.Minute
	DefaultMaxRetryAfter = 30 * time.Second
)

Умолчания клиента. Attempts × Timeout + паузы — то, что вызывающий обязан себе отвести (Client.Budget), иначе очередь оборвёт последнюю попытку.

View Source
const (
	OutcomeOK          = "ok"
	OutcomeCancelled   = "cancelled"
	OutcomeTimeout     = "timeout"
	OutcomeHTTP4xx     = "http_4xx"
	OutcomeHTTP5xx     = "http_5xx"
	OutcomeBadResponse = "bad_response"
	OutcomeNetwork     = "network"
	OutcomeError       = "error"
)

Исходы попытки — про транспорт и годность конверта, а не про контракт модели.

Variables

This section is empty.

Functions

func Fingerprint

func Fingerprint(parts ...string) string

Fingerprint — короткий отпечаток набора строк, из которых складывается идентичность вызова: плечо, модель, ревизия, хеш промпта, схема, опции, подготовка входа. Считается до вызова — по нему дедупятся прогоны; порядок частей значим.

func Latency

func Latency(err error) time.Duration

Latency — сколько длился отказавший вызов; не наш отказ даёт ноль.

func Ptr

func Ptr[T any](v T) *T

Ptr — указатель на значение для необязательных полей запроса.

func Recoverable

func Recoverable(err error) bool

Recoverable отвечает, имеет ли смысл повторить вызов позже: всё, кроме RetryNever.

func RetryAfter

func RetryAfter(h http.Header) time.Duration

RetryAfter разбирает заголовок в обеих формах: секунды числом и HTTP-дата. Отсутствующий и непонятный — ноль, пауза остаётся за клиентом.

Types

type AttemptReport

type AttemptReport struct {
	Provider string
	Model    string
	Task     string
	Outcome  string
	Phase    Phase
	Duration time.Duration
	Usage    Usage
}

AttemptReport — одна попытка: исход, фаза, длительность и расход, если он известен.

type CallError

type CallError struct {
	Provider   string
	Model      string
	Phase      Phase
	Status     int // код HTTP; 0 — ответа не было (сеть, просрочка, отмена)
	Message    string
	Attempts   int
	RetryAfter time.Duration
	Latency    time.Duration
	Class      RetryClass
	Err        error
}

CallError — отказ вызова целиком, с решением о повторе и потраченным временем.

func (*CallError) Error

func (e *CallError) Error() string

func (*CallError) Unwrap

func (e *CallError) Unwrap() error

type CallReport

type CallReport struct {
	Provider string
	Model    string
	Task     string
	Outcome  string
	Class    RetryClass
	Attempts int
	Duration time.Duration
	Usage    Usage
}

CallReport — вызов целиком: исход, число попыток, суммарный расход попыток.

type Chat

type Chat interface {
	Chat(ctx context.Context, req Request) (Result, error)
}

Chat — узкий интерфейс потребителя: то, что делает Client.

type Client

type Client struct {
	Provider Provider
	// Timeout — на одну попытку, не на весь вызов: повтор после просрочки получает полный срок.
	Timeout  time.Duration
	Attempts int
	// Pause — базовая пауза между попытками, дальше удваивается до MaxPause.
	Pause    time.Duration
	MaxPause time.Duration
	// MaxRetryAfter — потолок просьбы подождать: дольше — отказ [RetryAfterDelay]
	// без ожидания, срок в нём исходный; повторяет его очередь потребителя.
	MaxRetryAfter time.Duration
	// Observe — приёмник отчётов; пустое поле не считает ничего.
	Observe Observer
}

Client — вызов с повторами поверх одного плеча. Поля открыты: бюджет сверяется с таймаутом джобы снаружи, а не прячется в константах.

func New

func New(p Provider, timeout time.Duration) *Client

New собирает клиента с умолчаниями бюджета.

func (*Client) Budget

func (c *Client) Budget() time.Duration

Budget — верхняя оценка времени вызова: все попытки со своими таймаутами плюс худшие паузы.

func (*Client) Chat

func (c *Client) Chat(ctx context.Context, req Request) (Result, error)

Chat вызывает модель, повторяя отказы классов RetryImmediate и RetryAfterDelay в пределах числа попыток и потолка ожидания.

type Image

type Image struct {
	MIME string
	Data []byte
}

Image — кадр при сообщении: байты и MIME, как их видит поставщик.

type Message

type Message struct {
	Role   Role
	Text   string
	Images []Image
}

Message — одно сообщение разговора; кадры едут при данных, а не при инструкции.

type Mode

type Mode string

Mode — форма ответа: свободный текст, любой JSON или JSON по схеме.

const (
	ModeText   Mode = "text"
	ModeJSON   Mode = "json"
	ModeSchema Mode = "schema"
)

Формы ответа. Схему соблюдают не все модели — контракт полей живёт и в промпте.

type Observer

type Observer interface {
	Attempt(AttemptReport)
	Call(CallReport)
}

Observer — приёмник отчётов; реализует его потребитель (Prometheus, журнал).

type Output

type Output struct {
	Mode   Mode
	Schema json.RawMessage
}

Output — требуемая форма ответа; Schema читается только при ModeSchema.

type Phase

type Phase string

Phase — где отказал вызов: у облачных плеч перед генерацией стоят вход и загрузка кадров.

const (
	PhaseAuth      Phase = "auth"
	PhaseUpload    Phase = "upload"
	PhaseInference Phase = "inference"
)

Фазы вызова.

type Provider

type Provider interface {
	Name() string
	Complete(ctx context.Context, req Request) (Result, error)
}

Provider — одна попытка вызова у конкретного плеча. Отказ HTTP возвращается *StatusError, негодный ответ — *ResponseError, сеть и контекст — как есть.

type Request

type Request struct {
	Task        string
	Model       string
	Messages    []Message
	Output      Output
	Temperature *float64
}

Request — один вызов модели. Task — имя задачи для метрик и журнала, не текст: набор значений ограничен конфигом потребителя.

type ResponseError

type ResponseError struct {
	Message string
}

ResponseError — поставщик ответил, но ответа модели в теле нет: отказ маршрута под кодом 200, битый конверт, пустое содержимое.

func (*ResponseError) Error

func (e *ResponseError) Error() string

type Result

type Result struct {
	// Model — имя из ответа поставщика; пустое у ответа заменяется запрошенным.
	Model        string
	Text         string
	FinishReason string
	Usage        Usage
	// ServerLatency — время на стороне поставщика, если он его сообщает; ноль — не сообщил.
	ServerLatency time.Duration
	// Latency — сколько ждал вызывающий: все попытки и паузы между ними.
	Latency  time.Duration
	Attempts int
}

Result — ответ модели с тем, что ложится в журнал вызова.

type RetryClass

type RetryClass string

RetryClass — что делать с отказом. Немедленный повтор и повтор после паузы делает клиент; NeedsConfiguration и Never клиент не повторяет, но первый остаётся восстановимым — его чинит оператор, а не запрос.

const (
	RetryImmediate          RetryClass = "immediate"
	RetryAfterDelay         RetryClass = "after_delay"
	RetryNeedsConfiguration RetryClass = "needs_configuration"
	RetryNever              RetryClass = "never"
)

Классы отказа.

type Role

type Role string

Role — роль сообщения. Инструкция и данные едут разными ролями: приехавшее с данными «забудь инструкции» иначе получило бы ту же роль, что правила.

const (
	RoleSystem    Role = "system"
	RoleUser      Role = "user"
	RoleAssistant Role = "assistant"
)

Роли сообщений.

type StatusError

type StatusError struct {
	Status     int
	Message    string
	RetryAfter time.Duration
	Phase      Phase
}

StatusError — не-2xx от поставщика вместе с просьбой подождать.

func (*StatusError) Error

func (e *StatusError) Error() string

type Usage

type Usage struct {
	InputTokens  int
	OutputTokens int
	Known        bool
}

Usage — расход токенов. Known ложно, когда поставщик расход не сообщил: неизвестный ноль в счёте неотличим от бесплатного вызова.

Directories

Path Synopsis
Package ollama — плечо Ollama поверх нативного `/api/chat`: кадры base64 в сообщении, `format` подсказкой или схемой, серверные длительности в ответе.
Package ollama — плечо Ollama поверх нативного `/api/chat`: кадры base64 в сообщении, `format` подсказкой или схемой, серверные длительности в ответе.

Jump to

Keyboard shortcuts

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