llm

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Sep 8, 2026 License: AGPL-3.0 Imports: 6 Imported by: 0

Documentation

Overview

Package llm is the platform's interface to language models: content blocks, tool calling, streaming, structured output, and token accounting, over Anthropic and OpenAI.

The interface is the product here. Both backing providers are reached through the same Provider, and the differences between them — where the system prompt goes, how a tool result is addressed, whether streamed tool arguments arrive whole or in fragments, what a 429 looks like — are this package's problem rather than the caller's.

Content blocks

A Message's content is a list of [Part]s rather than a string. A turn in which the model says something, calls a tool, and then says something else is three parts in order, and flattening it to text with the tool call hoisted into a sidecar field loses the order. The common cases stay one-liners:

req := &llm.CompletionRequest{
	Model:  "claude-sonnet-5",
	System: "You are terse.",
	Messages: []llm.Message{
		llm.UserText("What is the capital of France?"),
	},
}

resp, err := provider.Completion(ctx, req)
if err != nil {
	return err
}

fmt.Println(resp.Text())

There is no system role. CompletionRequest.System is a field because Anthropic takes the system prompt out-of-band and OpenAI takes it as a leading message, and hiding that difference is the point.

Tool calling

Declare tools on the request, and the model answers with StopReasonToolUse and one or more ToolUse parts. Run them, and send the answers back as a single tool message:

resp, err := provider.Completion(ctx, req)
if err != nil {
	return err
}

uses := resp.ToolUses()
if len(uses) == 0 {
	return nil // the model is done
}

results := make([]llm.ToolResult, 0, len(uses))
for _, use := range uses {
	output, err := run(ctx, use)
	results = append(results, llm.ToolResult{
		ToolUseID: use.ID,
		Content:   output,
		IsError:   err != nil,
	})
}

req.Messages = append(req.Messages,
	llm.Message{Role: llm.RoleAssistant, Content: resp.Content},
	llm.ToolResultMessage(results...),
)

Appending the assistant's whole Content, rather than its text, is what keeps the tool call in the transcript — without it the next turn sees results for calls it has no record of making.

ToolUse.Input is model output and therefore untrusted. It may not validate against the tool's schema, and a response that stopped at StopReasonMaxTokens may leave it invalid JSON outright.

Streaming

Provider.Stream returns a Stream, which must be closed. See Stream for the loop shape and for why it is an explicit iterator rather than an iter.Seq2.

Streamed tool calls are the one place where the underlying providers disagree outright, and where this package earns its keep. OpenAI streams tool arguments as raw fragments, with the call's ID and name present only on the first; Anthropic accumulates internally and re-emits the whole call each time. A consumer written against either one is wrong on the other. This package emits EventToolUse only once a call is complete, so the same loop works on both.

Errors

Every provider error matches one of this package's sentinels under errors.Is — ErrRateLimited, ErrContextTooLong, ErrAuthentication, ErrModelNotFound, ErrContentFiltered, ErrInvalidRequest, ErrUnsupportedFeature — or none of them, when the failure has no platform-level meaning. Callers never need the client library underneath:

resp, err := provider.Completion(ctx, req)

var rateLimited *llm.RateLimitError
switch {
case errors.As(err, &rateLimited):
	time.Sleep(rateLimited.RetryAfter)
case errors.Is(err, llm.ErrContextTooLong):
	return errors.Wrap(err, "prompt is too long to retry")
case err != nil:
	return err
}

No method here retries. Rate limits are reported, not absorbed, because the right backoff belongs to the caller's own budget; wrap the call with the platform's retry package to get one.

Capabilities

Provider.Capabilities reports what a provider supports, so a caller can degrade deliberately instead of finding out mid-conversation. It describes the provider and not the model: a provider that supports images still has models that do not.

Choosing a provider

The llm/config subpackage builds a Provider from configuration, and the provider name is required: an unset or unrecognized one wraps errors.ErrUnknownProvider rather than standing something up. The llm/noop provider is selectable, by naming it, and a service that wants to run without LLM credentials has to say so — because a provider that quietly answers from a canned response looks like a healthy deployment whose answers have become useless.

Why the provider files look alike

The openai and anthropic implementations are near-identical files, and that is deliberate. Each is a translation between this package's request and response types and one vendor's SDK, so the shape they share is the shape of the interface — request in, translate, call, translate back, instrument — and the lines that differ are precisely the ones a reader came to see.

Factoring the common half out would produce a base type holding the instrumentation and the error mapping, with each vendor supplying a handful of translation hooks. That trades a file a reader can hold in their head for two files they must hold at once, and it does it at the seam most likely to move: every vendor difference that shows up next — a new content block type, a streaming protocol that frames differently, a usage field one of them omits — arrives as a hook the base type did not anticipate. The generic machinery around three implementations is not obviously cheaper than three implementations.

What was extracted is what is genuinely one decision rather than one shape: the instrument trio (observability/metrics.OperationSet), the latency timing (observability.Operation.Time), and the float narrowing every embeddings provider needs (embeddings.ToFloat32). The rule those share is that a second copy could be *wrong* — a different suffix, a bypassed clock, a different precision. A second copy of "decode the response, build a Completion" cannot be wrong in that way; it can only be different, and different is what it is for.

Example
package main

import (
	"context"
	"fmt"

	"github.com/primandproper/primitives-go/llm"
	llmnoop "github.com/primandproper/primitives-go/llm/noop"
)

func main() {
	provider := llmnoop.NewProvider()

	resp, err := provider.Completion(context.Background(), &llm.CompletionRequest{
		Model:  "example-model",
		System: "You are terse.",
		Messages: []llm.Message{
			llm.UserText("Hello!"),
		},
	})
	if err != nil {
		panic(err)
	}

	fmt.Printf("provider: %s\n", provider.Name())
	fmt.Printf("text: %q\n", resp.Text())
	fmt.Printf("tool uses: %d\n", len(resp.ToolUses()))
}
Output:
provider: noop
text: ""
tool uses: 0

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrRateLimited means the provider refused the request for rate reasons.
	// Errors matching it are usually a *RateLimitError, which may carry how
	// long to wait.
	ErrRateLimited = platformerrors.New("llm provider rate limited the request")
	// ErrContextTooLong means the prompt did not fit in the model's context
	// window. Retrying unchanged will fail the same way.
	ErrContextTooLong = platformerrors.New("llm request exceeded the model's context window")
	// ErrAuthentication means the provider rejected the credentials.
	ErrAuthentication = platformerrors.New("llm provider rejected the credentials")
	// ErrModelNotFound means the requested model does not exist, or the account
	// cannot reach it.
	ErrModelNotFound = platformerrors.New("llm model not found")
	// ErrContentFiltered means the provider's safety filter refused the
	// request or the response.
	ErrContentFiltered = platformerrors.New("llm provider filtered the content")
	// ErrInvalidRequest means the request was malformed. This covers requests
	// this package rejects before sending as well as ones the provider
	// rejected.
	ErrInvalidRequest = platformerrors.New("llm request was invalid")
	// ErrUnsupportedFeature means the provider or model does not support
	// something the request asked for. Provider.Capabilities reports the coarse
	// version of this ahead of time.
	ErrUnsupportedFeature = platformerrors.New("llm provider does not support the requested feature")
)

The conditions a provider can report. Every error a Provider returns matches one of these under errors.Is, or none of them when the failure has no platform-level meaning — a transport error, say. They exist so that callers can react to a rate limit or a context overflow without importing, or even knowing about, whichever client library the provider is built on.

Functions

This section is empty.

Types

type Capabilities

type Capabilities struct {
	// Streaming reports whether Provider.Stream produces real incremental
	// output. It is false for providers whose Stream is a formality.
	Streaming bool
	// Tools reports whether CompletionRequest.Tools is honored.
	Tools bool
	// Images reports whether PartImage is honored.
	Images bool
	// Reasoning reports whether CompletionRequest.ReasoningEffort is honored
	// and PartThinking parts come back.
	Reasoning bool
	// StructuredOutput reports whether CompletionRequest.ResponseFormat is
	// honored.
	StructuredOutput bool
}

Capabilities is what a provider can do, reported ahead of time so that a caller can degrade deliberately instead of discovering the gap as an ErrUnsupportedFeature mid-conversation.

It describes the provider, not the model. A provider that supports images still has models that do not, and only the request will find that out.

type CompletionRequest

type CompletionRequest struct {
	// Temperature controls randomness, conventionally in [0, 2].
	Temperature *float64
	// TopP controls nucleus sampling, in [0, 1]. Setting it alongside
	// Temperature is accepted but rarely what anyone wants.
	TopP *float64
	// MaxTokens caps the response length. Anthropic requires one and the
	// provider layer supplies a default when this is nil.
	MaxTokens *int
	// Seed asks for reproducible sampling. Best-effort everywhere.
	Seed *int
	// ParallelToolCalls allows the model to request several tools at once.
	ParallelToolCalls *bool
	// ResponseFormat constrains the response to a JSON schema.
	ResponseFormat *ResponseFormat
	// ToolChoice constrains which of Tools the model may call.
	ToolChoice *ToolChoice
	// Model is the provider's model identifier. Empty means the provider's
	// configured default.
	Model string
	// System is the system prompt. See Role for why it is a field rather than a
	// message.
	System string
	// ReasoningEffort asks for extended thinking.
	ReasoningEffort ReasoningEffort
	// Messages is the conversation so far, oldest first. At least one is
	// required.
	Messages []Message
	// Tools are the tools the model may call.
	Tools []Tool
	// StopSequences are strings that end generation when produced.
	StopSequences []string
}

CompletionRequest is one request for a completion.

The pointer-typed fields are the ones where "unset" and "zero" differ: Temperature 0 is a meaningful temperature, and so is a MaxTokens the caller never chose. A nil field is left off the wire so the provider's own default applies.

type CompletionResponse

type CompletionResponse struct {
	// Usage is the token accounting for the request, when the provider
	// reported it.
	Usage *Usage
	// ID is the provider's identifier for the response.
	ID string
	// Model is the model that actually answered, which can differ from the one
	// requested when the provider resolves an alias.
	Model string
	// StopReason is why generation ended.
	StopReason StopReason
	// Content is what the model produced, in order. See Part.
	Content []Part
}

CompletionResponse is one completion.

func (*CompletionResponse) Text

func (r *CompletionResponse) Text() string

Text concatenates the response's text parts, ignoring reasoning and tool calls. A nil receiver returns the empty string, so a caller can chain it off a call it has not error-checked.

func (*CompletionResponse) ToolUses

func (r *CompletionResponse) ToolUses() []ToolUse

ToolUses returns the tool calls the model requested, in order. It returns nil when there are none, which is the signal that a tool-calling loop has reached its end.

type Event

type Event struct {
	ToolUse    *ToolUse
	Usage      *Usage
	Type       EventType
	Text       string
	StopReason StopReason
}

Event is one item from a Stream. Type says which of the remaining fields is meaningful.

type EventType

type EventType string

EventType discriminates the union in Event.

const (
	// EventTextDelta is a fragment of the response text, in Event.Text.
	// Fragments arrive in order and concatenate to the full response.
	EventTextDelta EventType = "text_delta"
	// EventThinkingDelta is a fragment of the model's reasoning, in
	// Event.Text.
	EventThinkingDelta EventType = "thinking_delta"
	// EventToolUse is a complete tool call, in Event.ToolUse. It is never a
	// fragment: the arguments have been accumulated in full before the event
	// is yielded, whatever the underlying provider streamed.
	EventToolUse EventType = "tool_use"
	// EventDone is the final event, carrying Event.StopReason and, when the
	// provider reported one, Event.Usage. Exactly one is yielded per
	// successfully completed stream, and none when the stream fails.
	EventDone EventType = "done"
)

The kinds of event a Stream yields.

type Image

type Image struct {
	// URL is an http(s) URL or a data: URI the provider fetches or decodes.
	URL string
	// MediaType is the IANA media type of Data, e.g. "image/png". It is
	// required with Data and ignored with URL, whose own media type is either
	// implied by the server or already inside the data URI.
	MediaType string
	// Data is the raw image bytes, which the provider layer encodes as a data
	// URI. MediaType must be set alongside it.
	Data []byte
}

Image is an image attached to a message. Exactly one of Data or URL carries the image; when both are set, Data wins.

type Message

type Message struct {
	Role    Role
	Content []Part
}

Message is one turn in a conversation.

func AssistantText

func AssistantText(text string) Message

AssistantText returns an assistant message holding a single run of text.

func ToolResultMessage

func ToolResultMessage(results ...ToolResult) Message

ToolResultMessage returns the tool message answering one or more tool calls. Answering every call from a single assistant turn in one message is the shape both providers expect.

Example

ExampleToolResultMessage shows one turn of a tool-calling loop: the model's whole content goes back into the transcript, then the results.

package main

import (
	"encoding/json"
	"fmt"

	"github.com/primandproper/primitives-go/llm"
)

func main() {
	resp := &llm.CompletionResponse{
		StopReason: llm.StopReasonToolUse,
		Content: []llm.Part{
			{Type: llm.PartText, Text: "Let me look that up."},
			{Type: llm.PartToolUse, ToolUse: &llm.ToolUse{
				ID:    "call_1",
				Name:  "get_weather",
				Input: json.RawMessage(`{"city":"Paris"}`),
			}},
		},
	}

	uses := resp.ToolUses()

	results := make([]llm.ToolResult, 0, len(uses))
	for i := range uses {
		results = append(results, llm.ToolResult{ToolUseID: uses[i].ID, Content: "17C and raining"})
	}

	messages := []llm.Message{
		llm.UserText("What is the weather in Paris?"),
		{Role: llm.RoleAssistant, Content: resp.Content},
		llm.ToolResultMessage(results...),
	}

	for i := range messages {
		fmt.Printf("%s: %d part(s)\n", messages[i].Role, len(messages[i].Content))
	}
}
Output:
user: 1 part(s)
assistant: 2 part(s)
tool: 1 part(s)

func UserText

func UserText(text string) Message

UserText returns a user message holding a single run of text, which is the common case.

func (Message) Text

func (m Message) Text() string

Text concatenates the message's text parts, ignoring images, tool calls, tool results, and reasoning. It is the "just give me the words" accessor; a caller that cares about the other parts should range over Content.

type Part

type Part struct {
	Image      *Image
	ToolUse    *ToolUse
	ToolResult *ToolResult
	Type       PartType
	Text       string
}

Part is one piece of a message's content. Type says which of the remaining fields is meaningful; the others are nil or zero.

Content is a list of parts rather than a string with sidecar fields because order matters. A model that emits text, then a tool call, then more text has said three things in sequence, and replaying that turn with the tool call hoisted into a separate field loses the sequence.

type PartType

type PartType string

PartType discriminates the union in Part.

const (
	// PartText is a run of plain text, in Part.Text.
	PartText PartType = "text"
	// PartImage is an image, in Part.Image.
	PartImage PartType = "image"
	// PartToolUse is the model's request to call a tool, in Part.ToolUse.
	PartToolUse PartType = "tool_use"
	// PartToolResult is the outcome of such a call, in Part.ToolResult.
	PartToolResult PartType = "tool_result"
	// PartThinking is the model's reasoning, in Part.Text.
	PartThinking PartType = "thinking"
)

The kinds of content a Part can hold.

type Provider

type Provider interface {
	// Name identifies the provider, e.g. "anthropic". It is stable and safe to
	// use as a metric label or a persisted discriminator.
	Name() string
	// Capabilities reports what the provider supports.
	Capabilities() Capabilities
	// Completion answers the request in full.
	Completion(ctx context.Context, req *CompletionRequest) (*CompletionResponse, error)
	// Stream answers the request incrementally. The returned Stream must be
	// closed. The error is for failures that happen before the stream starts;
	// failures during it surface from Stream.Err.
	Stream(ctx context.Context, req *CompletionRequest) (Stream, error)
}

Provider is a language model that answers completions.

Both methods take the same request, and the difference is only in delivery: Completion waits for the whole answer, Stream yields it as it arrives. Streaming is on the interface rather than behind an optional one because every real provider streams, and a caller that has to type-assert for it ends up writing the non-streaming path anyway.

type RateLimitError

type RateLimitError struct {
	// RetryAfter is how long the provider asked the caller to wait. It is zero
	// when the provider did not say, which is not the same as "retry
	// immediately" — a caller with no advice should fall back to its own
	// backoff.
	RetryAfter time.Duration
}

RateLimitError is the rate limit condition with the provider's advice about when to try again attached. It matches ErrRateLimited under errors.Is, so a caller that only wants to know "was I throttled" need not reach for errors.As.

func (*RateLimitError) Error

func (e *RateLimitError) Error() string

Error implements error.

func (*RateLimitError) Unwrap

func (e *RateLimitError) Unwrap() error

Unwrap returns ErrRateLimited, so that errors.Is matches the sentinel.

type ReasoningEffort

type ReasoningEffort string

ReasoningEffort asks the model to spend more or less effort thinking before it answers. Providers implement it differently — Anthropic turns it into a thinking token budget, OpenAI passes it through to reasoning models — and providers or models that do not support it ignore it rather than failing.

const (
	// ReasoningEffortNone disables reasoning. It is also the zero value's
	// meaning: an unset ReasoningEffort leaves the parameter off the request
	// entirely, which lets the provider apply its own default.
	ReasoningEffortNone ReasoningEffort = "none"
	// ReasoningEffortLow spends the least effort.
	ReasoningEffortLow ReasoningEffort = "low"
	// ReasoningEffortMedium is the middle setting.
	ReasoningEffortMedium ReasoningEffort = "medium"
	// ReasoningEffortHigh spends the most effort.
	ReasoningEffortHigh ReasoningEffort = "high"
	// ReasoningEffortAuto lets the provider decide.
	ReasoningEffortAuto ReasoningEffort = "auto"
)

The reasoning effort levels.

type ResponseFormat

type ResponseFormat struct {
	// Schema is the JSON Schema the response must satisfy, as a decoded object.
	Schema map[string]any
	// Name identifies the schema to the provider. Required.
	Name string
	// Strict asks the provider to guarantee conformance rather than merely
	// prompt for it, where it can.
	Strict bool
}

ResponseFormat constrains the response to match a JSON schema, for callers that want to unmarshal the answer rather than read it.

type Role

type Role string

Role identifies who produced a Message.

There is deliberately no system role. A system prompt is CompletionRequest.System, because the providers disagree about what it is: Anthropic takes it out-of-band as a top-level request parameter, OpenAI takes it as a leading message in the conversation. Modeling it as a role would make callers responsible for a difference this package exists to hide.

const (
	// RoleUser marks input from the caller's end user.
	RoleUser Role = "user"
	// RoleAssistant marks output the model produced, replayed back to it on a
	// later turn.
	RoleAssistant Role = "assistant"
	// RoleTool marks the results of tool calls the model asked for. A tool
	// message carries only PartToolResult parts.
	RoleTool Role = "tool"
)

The roles a Message can carry.

type SliceStream

type SliceStream struct {
	// contains filtered or unexported fields
}

SliceStream is the Stream over a fixed slice of events. It is exported, and returned by NewSliceStream, so a caller can depend on the stream it built rather than on the Stream seam.

func NewSliceStream

func NewSliceStream(events ...Event) *SliceStream

NewSliceStream returns a Stream that yields the given events and then stops. It is what a Provider with nothing to say returns, and it saves consumers' tests from standing up an HTTP server to exercise their event handling.

func (*SliceStream) Close

func (s *SliceStream) Close() error

func (*SliceStream) Current

func (s *SliceStream) Current() Event

func (*SliceStream) Err

func (*SliceStream) Err() error

func (*SliceStream) Next

func (s *SliceStream) Next() bool

type StopReason

type StopReason string

StopReason is why the model stopped generating.

const (
	// StopReasonEndTurn means the model finished what it had to say.
	StopReasonEndTurn StopReason = "end_turn"
	// StopReasonMaxTokens means the response hit CompletionRequest.MaxTokens
	// and is truncated. Any tool call in a truncated response may carry
	// incomplete JSON.
	StopReasonMaxTokens StopReason = "max_tokens"
	// StopReasonStopSequence means one of CompletionRequest.StopSequences was
	// produced.
	StopReasonStopSequence StopReason = "stop_sequence"
	// StopReasonToolUse means the model is waiting on tool results. The
	// response's ToolUses are the calls to run.
	StopReasonToolUse StopReason = "tool_use"
	// StopReasonContentFilter means the provider's safety filter stopped the
	// response.
	StopReasonContentFilter StopReason = "content_filter"
)

The reasons a model stops.

type Stream

type Stream interface {
	// Next advances to the next event, reporting whether there is one.
	Next() bool
	// Current returns the event Next advanced to. It is only valid after Next
	// returned true.
	Current() Event
	// Err returns the error that stopped the stream, or nil if it ended
	// cleanly or is still running.
	Err() error
	// Close releases the stream's resources. It is idempotent.
	Close() error
}

Stream is a completion arriving incrementally.

It is an explicit iterator rather than an iter.Seq2 or a channel because it has to be closed. A stream holds an HTTP response body open, and a consumer that stops early — because it has the tool call it wanted, because its own caller cancelled — has to be able to release it. Close is also what makes abandonment cheap: a range-over-func has no way to say "I am done with this" beyond breaking, and a channel has no way to say it at all.

The usage is the familiar bufio.Scanner shape:

stream, err := provider.Stream(ctx, req)
if err != nil {
	return err
}
defer func() { _ = stream.Close() }()

for stream.Next() {
	switch event := stream.Current(); event.Type {
	case llm.EventTextDelta:
		fmt.Print(event.Text)
	case llm.EventToolUse:
		calls = append(calls, *event.ToolUse)
	}
}

return stream.Err()

Next returning false means either the stream ended or it failed, and Err distinguishes them. Close is always safe to call, including after a failure and more than once. A Stream is not safe for concurrent use.

type Tool

type Tool struct {
	// Schema is the JSON Schema describing the tool's input, as a decoded
	// object. It reaches the provider unchanged.
	Schema map[string]any
	// Name is what the model names in a ToolUse.
	Name string
	// Description tells the model when to call the tool. It is prompt text and
	// carries most of the weight of getting tool use right.
	Description string
}

Tool is one tool the model may call.

type ToolChoice

type ToolChoice struct {
	// Name is the tool to call. It is required when Mode is
	// ToolChoiceSpecific and ignored otherwise.
	Name string
	// Mode is how the choice is constrained. The zero value is not a valid
	// mode; leave ToolChoice nil rather than sending an empty one.
	Mode ToolChoiceMode
}

ToolChoice constrains the model's choice of tool.

type ToolChoiceMode

type ToolChoiceMode string

ToolChoiceMode is how strongly the model is steered toward calling a tool.

const (
	// ToolChoiceAuto lets the model decide whether to call a tool.
	ToolChoiceAuto ToolChoiceMode = "auto"
	// ToolChoiceRequired obliges the model to call some tool.
	ToolChoiceRequired ToolChoiceMode = "required"
	// ToolChoiceNone forbids tool calls for this turn.
	ToolChoiceNone ToolChoiceMode = "none"
	// ToolChoiceSpecific obliges the model to call the named tool.
	ToolChoiceSpecific ToolChoiceMode = "specific"
)

The tool choice modes.

type ToolResult

type ToolResult struct {
	// ToolUseID is the ID of the ToolUse this answers.
	ToolUseID string
	// Content is what the tool produced, as text. Structured results should be
	// marshaled to JSON by the caller.
	Content string
	// IsError reports that the tool failed. The providers' normalized wire
	// shape has no flag for this, so it is conveyed to the model by prefixing
	// Content with "error: " — the model still learns the call failed, which is
	// the point, but the transport is a convention rather than a field.
	IsError bool
}

ToolResult is the outcome of one tool call, sent back to the model.

type ToolUse

type ToolUse struct {
	// ID correlates this call with the ToolResult that answers it.
	ID string
	// Name is the Tool.Name the model chose.
	Name string
	// Input is the tool's arguments as JSON, shaped by the Tool's Schema. It is
	// the model's output and therefore untrusted: it may not validate against
	// the schema, and it may not be valid JSON at all if the model was cut off.
	Input json.RawMessage
}

ToolUse is the model's request to call one tool.

type Usage

type Usage struct {
	// InputTokens is what the prompt cost.
	InputTokens int
	// OutputTokens is what the response cost, including reasoning tokens where
	// the provider bills them that way.
	OutputTokens int
	// ReasoningTokens is the reasoning portion, when the provider breaks it
	// out.
	ReasoningTokens int
	// TotalTokens is the provider's own total. It is reported rather than
	// derived, because a provider that discounts or surcharges some tokens
	// disagrees with InputTokens + OutputTokens on purpose.
	TotalTokens int
}

Usage is the token accounting for one request.

Directories

Path Synopsis
Package anthropic is the Anthropic-backed llm.Provider.
Package anthropic is the Anthropic-backed llm.Provider.
Package llmcfg selects and builds an llm.Provider from configuration: OpenAI, Anthropic, or the noop provider.
Package llmcfg selects and builds an llm.Provider from configuration: OpenAI, Anthropic, or the noop provider.
internal
bridge
Package bridge translates between the platform's llm types and any-llm-go's.
Package bridge translates between the platform's llm types and any-llm-go's.
Package llmmock provides mock implementations of the llm package's interfaces.
Package llmmock provides mock implementations of the llm package's interfaces.
Package noop is the llm.Provider that spends nothing: Completion returns an empty response that stopped at llm.StopReasonEndTurn, and Stream returns a stream carrying only llm.EventDone.
Package noop is the llm.Provider that spends nothing: Completion returns an empty response that stopped at llm.StopReasonEndTurn, and Stream returns a stream carrying only llm.EventDone.
Package openai is the OpenAI-backed llm.Provider.
Package openai is the OpenAI-backed llm.Provider.

Jump to

Keyboard shortcuts

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