Documentation
¶
Overview ¶
Package ai provides a unified, provider-agnostic client for large language model APIs.
It speaks the native wire protocols of OpenAI (both the Chat Completions and Responses APIs), Anthropic (Messages API), and Google Gemini (generateContent) without depending on any vendor SDK. A single request and response model covers text generation, streaming, vision input, tool calling, structured output, reasoning ("thinking"), image generation, and embeddings.
The core abstraction is LanguageModel. Provider subpackages (openai, anthropic, gemini) return implementations bound to a specific model:
model := openai.New("gpt-6-astra", openai.WithAPIKey(key))
resp, err := model.Generate(ctx, ai.Request{
Messages: ai.Messages{ai.UserText("Hello!")},
})
Streaming uses Go iterators; breaking out of the loop cancels the underlying request:
for ev, err := range model.Stream(ctx, req) {
if err != nil {
break
}
if ev.Type == ai.StreamTextDelta {
fmt.Print(ev.Text)
}
}
Bare provider clients never retry. Cross-cutting behavior (retries, rate limiting, observability) is added by wrapping a LanguageModel with middleware from the middleware and observability subpackages.
The package has no third-party runtime dependencies beyond golang.org/x.
Example (Generate) ¶
Generate makes a blocking call and returns the normalized response.
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/rsbin1178/pips/ai"
"github.com/rsbin1178/pips/ai/openai"
)
func main() {
model := openai.New("gpt-6-astra", openai.WithAPIKey(os.Getenv("OPENAI_API_KEY")))
resp, err := model.Generate(context.Background(), ai.Request{
Messages: ai.Messages{ai.SystemText("You are terse."), ai.UserText("Capital of France?")},
Temperature: ai.Ptr(0.2),
})
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.Text(), resp.Usage.OutputTokens)
}
Output:
Example (Stream) ¶
Streaming with an iterator; breaking out cancels the request.
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/rsbin1178/pips/ai"
"github.com/rsbin1178/pips/ai/openai"
)
func main() {
model := openai.New("gpt-6-astra", openai.WithAPIKey(os.Getenv("OPENAI_API_KEY")))
for ev, err := range model.Stream(context.Background(), ai.Request{
Messages: ai.Messages{ai.UserText("Tell me a haiku.")},
}) {
if err != nil {
log.Fatal(err)
}
if ev.Type == ai.StreamTextDelta {
fmt.Print(ev.Text)
}
}
}
Output:
Index ¶
- Variables
- func ClassifyStatus(status int) error
- func IsRetryable(err error) bool
- func JoinSystemText(messages []SystemMessage) string
- func MarshalParts(parts []Part) ([]byte, error)
- func Ptr[T any](v T) *T
- func ValidateMessage(message Message) error
- func ValidateRequestBodyExtension(extra map[string]any, reserved ...string) error
- type AssistantMessage
- type AssistantPart
- type Capabilities
- type CapabilityDeclaration
- type CapabilityOverride
- func (o CapabilityOverride) Apply(base Capabilities) Capabilities
- func (o CapabilityOverride) Clone() CapabilityOverride
- func (o CapabilityOverride) Declarations() []CapabilityDeclaration
- func (o CapabilityOverride) IsZero() bool
- func (o CapabilityOverride) Overlay(child CapabilityOverride) CapabilityOverride
- type Citation
- type EmbeddedResourcePart
- type EmbeddingEncodingFormat
- type EmbeddingModel
- type EmbeddingRequest
- type EmbeddingResponse
- type EmbeddingTaskType
- type Error
- type FilePart
- type FinishReason
- type GeneratedImage
- type GroundingMetadata
- type ImageEditRequest
- type ImageEditor
- type ImageModel
- type ImagePart
- type ImageRequest
- type ImageResponse
- type ImageStream
- type ImageStreamEvent
- type ImageStreamEventType
- type ImageStreamer
- type ImageUsage
- type ImageVariationRequest
- type ImageVariator
- type JSON
- type LanguageModel
- type LogProbsConfig
- type MediaSource
- type Message
- type Messages
- type Middleware
- type Part
- type Provider
- type ReasoningConfig
- type ReasoningEffort
- type ReasoningMode
- type ReasoningPart
- type Request
- type RerankModel
- type RerankRequest
- type RerankResponse
- type RerankResult
- type ResourceLinkPart
- type Response
- type ResponseFormat
- type Schema
- type Stream
- type StreamEvent
- type StreamEventType
- type StructuredContentPart
- type SystemMessage
- type SystemPart
- type TextPart
- type TextRange
- type TokenCounter
- type Tool
- type ToolCallPart
- type ToolChoice
- type ToolChoiceMode
- type ToolKind
- type ToolMessage
- type ToolResultPart
- type Usage
- type UserMessage
- type UserPart
- type Warning
- type WarningType
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrUnsupported means the model or provider does not support the // requested capability (for example image generation on Anthropic). ErrUnsupported = errors.New("ai: capability not supported") // ErrAuth means authentication failed (HTTP 401/403). ErrAuth = errors.New("ai: authentication failed") // ErrRateLimited means the provider rate-limited the request (HTTP 429). ErrRateLimited = errors.New("ai: rate limited") // ErrOverloaded means the provider is temporarily overloaded (HTTP // 500-599, or Anthropic's 529). ErrOverloaded = errors.New("ai: provider overloaded") // ErrInvalidRequest means the provider rejected the request as malformed // (HTTP 400/404/422). ErrInvalidRequest = errors.New("ai: invalid request") // ErrInvalidMessage means a portable message has an unsupported concrete // form, role-specific content, or sequence position. ErrInvalidMessage = errors.New("ai: invalid message") )
Sentinel errors for common failure classes. Provider adapters wrap these so callers can branch with errors.Is regardless of provider:
if errors.Is(err, ai.ErrRateLimited) { ... }
Functions ¶
func ClassifyStatus ¶
ClassifyStatus maps an HTTP status code to the matching sentinel error, or nil for 2xx. Anthropic's 529 is treated as overload.
func IsRetryable ¶
IsRetryable reports whether err is worth retrying: rate limits, overload, request timeouts, and transport-level errors. Invalid-request and auth errors are not retryable. A nil error is not retryable.
Retryability is orthogonal to whether a retry is safe mid-stream; the retry middleware only replays requests that have not yet produced output.
func JoinSystemText ¶
func JoinSystemText(messages []SystemMessage) string
JoinSystemText concatenates a validated sequence of system messages. Text parts within one message are adjacent; separate messages are joined with a newline so their instruction boundaries do not disappear.
func MarshalParts ¶
MarshalParts encodes a role-neutral part list using the stable Part envelope shared by message and durable projection codecs.
func Ptr ¶
func Ptr[T any](v T) *T
Ptr returns a pointer to v. It keeps request literals terse:
ai.Request{Temperature: ai.Ptr(0.2), MaxTokens: ai.Ptr(1024)}
func ValidateMessage ¶
ValidateMessage checks that message is a supported concrete value and that its content belongs to that role.
func ValidateRequestBodyExtension ¶
ValidateRequestBodyExtension validates a bounded raw JSON object against reserved dotted paths without sending a request. Provider adapters enforce the same rules again while merging into their typed wire body.
Types ¶
type AssistantMessage ¶
type AssistantMessage struct {
Parts []AssistantPart
}
AssistantMessage contains model output. It may combine text, reasoning, and tool calls.
func Assistant ¶
func Assistant(parts ...AssistantPart) AssistantMessage
Assistant returns an assistant message from the given parts. Use it to replay prior model turns in a conversation.
func AssistantText ¶
func AssistantText(text string) AssistantMessage
AssistantText returns an assistant message containing a single text part.
func (AssistantMessage) MarshalJSON ¶
func (m AssistantMessage) MarshalJSON() ([]byte, error)
MarshalJSON implements json.Marshaler.
func (*AssistantMessage) UnmarshalJSON ¶
func (m *AssistantMessage) UnmarshalJSON(data []byte) error
UnmarshalJSON implements json.Unmarshaler.
func (AssistantMessage) Validate ¶
func (m AssistantMessage) Validate() error
Validate checks that an assistant message uses only text, reasoning, and tool-call content.
type AssistantPart ¶
type AssistantPart interface {
Part
// contains filtered or unexported methods
}
AssistantPart is content accepted by AssistantMessage.
type Capabilities ¶
type Capabilities struct {
// Text reports whether the model generates text.
Text bool
// Vision reports whether the model accepts image input.
Vision bool
// Documents reports whether the model accepts document/file input.
Documents bool
// AudioInput reports whether the model accepts audio input.
AudioInput bool
// VideoInput reports whether the model accepts video input.
VideoInput bool
// Tools reports whether the model supports tool / function calling.
Tools bool
// StructuredOutput reports whether the model supports schema-constrained
// JSON output.
StructuredOutput bool
// Reasoning reports whether the model exposes reasoning ("thinking")
// controls and content.
Reasoning bool
// ImageGeneration reports whether the model can generate images.
ImageGeneration bool
// Embeddings reports whether the model produces embeddings.
Embeddings bool
// Reranking reports whether the model performs document reranking.
Reranking bool
// PromptCaching reports whether the provider supports prompt-cache reuse
// or cache-usage reporting for this model. Caching may be automatic or
// explicitly controlled by the request.
PromptCaching bool
// TokenCounting reports whether the model exposes a server-side token-count
// operation without running inference.
TokenCounting bool
// WebSearch reports whether the model natively supports provider-executed
// web search.
WebSearch bool
// CodeExecution reports whether the model natively supports server-side
// code execution.
CodeExecution bool
}
Capabilities reports, best effort, what a specific model supports. It is derived from static per-provider model tables; unknown models report pessimistic values but calls are never blocked based on capabilities.
type CapabilityDeclaration ¶
type CapabilityDeclaration struct {
// Name is the stable field name, for example "vision" or "audio_input".
Name string
// Value is the declared value.
Value bool
}
CapabilityDeclaration is one declared capability field.
type CapabilityOverride ¶
type CapabilityOverride struct {
// Text reports whether the model generates text.
Text *bool
// Vision reports whether the model accepts image input.
Vision *bool
// Documents reports whether the model accepts document/file input.
Documents *bool
// AudioInput reports whether the model accepts audio input.
AudioInput *bool
// VideoInput reports whether the model accepts video input.
VideoInput *bool
// Tools reports whether the model supports tool / function calling.
Tools *bool
// StructuredOutput reports whether the model supports schema-constrained
// JSON output.
StructuredOutput *bool
// Reasoning reports whether the model exposes reasoning controls/content.
Reasoning *bool
// ImageGeneration reports whether the model can generate images.
ImageGeneration *bool
// Embeddings reports whether the model produces embeddings.
Embeddings *bool
// Reranking reports whether the model performs document reranking.
Reranking *bool
// PromptCaching reports whether the provider supports prompt-cache reuse
// or cache-usage reporting for this model.
PromptCaching *bool
// TokenCounting reports whether the model exposes server-side token
// counting without running inference.
TokenCounting *bool
// WebSearch reports whether the model supports provider-executed web
// search.
WebSearch *bool
// CodeExecution reports whether the model supports server-side code
// execution.
CodeExecution *bool
}
CapabilityOverride is a field-level, tri-state overlay on Capabilities. A nil field means "inherit"; a non-nil field is an explicit declaration, so an explicit false stays distinguishable from "not declared".
It mirrors every Capabilities field so a capability added to the base type becomes visible here.
func (CapabilityOverride) Apply ¶
func (o CapabilityOverride) Apply(base Capabilities) Capabilities
Apply returns base with every declared field replaced by its declaration. Undeclared fields keep the base value.
func (CapabilityOverride) Clone ¶
func (o CapabilityOverride) Clone() CapabilityOverride
Clone returns a detached copy sharing no pointer with o.
func (CapabilityOverride) Declarations ¶
func (o CapabilityOverride) Declarations() []CapabilityDeclaration
Declarations returns the declared fields in a stable order. It lets callers report exactly what was declared without repeating the field list.
func (CapabilityOverride) IsZero ¶
func (o CapabilityOverride) IsZero() bool
IsZero reports whether no field is declared.
func (CapabilityOverride) Overlay ¶
func (o CapabilityOverride) Overlay(child CapabilityOverride) CapabilityOverride
Overlay returns o with every field declared in child taking precedence. The receiver is the base layer and child wins, matching the layering used by the coding configuration.
type Citation ¶
type Citation struct {
// URL is the web address of the referenced source.
URL string `json:"url"`
// Title is the human-readable title of the document or webpage.
Title string `json:"title,omitempty"`
// Snippet is the extracted content snippet that grounded the answer.
Snippet string `json:"snippet,omitempty"`
// Index is the reference index corresponding to citation markers in the text.
Index int `json:"index,omitempty"`
// TextRange is the character offset span in the generated text supported by
// this citation.
TextRange *TextRange `json:"text_range,omitempty"`
}
Citation represents an attribution or source reference produced by a search or grounding tool.
type EmbeddedResourcePart ¶
type EmbeddedResourcePart struct {
// URI locates the originating resource. It is required.
URI string
// MIMEType describes Text or Blob. It is required for Blob.
MIMEType string
// Text is the body of a textual resource.
Text string
// Blob is the raw body of a binary resource.
Blob []byte
}
EmbeddedResourcePart carries a resource inline together with the identity it had at its source. Text and Blob are mutually exclusive: Text holds the body of a textual resource (possibly empty), Blob the raw body of a binary one.
type EmbeddingEncodingFormat ¶
type EmbeddingEncodingFormat string
EmbeddingEncodingFormat specifies the transfer encoding format of the output vectors.
const ( // EmbeddingEncodingFormatFloat returns vectors as standard JSON arrays of floats (default). EmbeddingEncodingFormatFloat EmbeddingEncodingFormat = "float" // EmbeddingEncodingFormatBase64 requests base64-encoded binary vectors from providers // that support it (OpenAI, Mistral) to reduce wire payload size and serialization overhead. // Adapters transparently decode base64 back into []float32. EmbeddingEncodingFormatBase64 EmbeddingEncodingFormat = "base64" )
Supported embedding encoding formats.
type EmbeddingModel ¶
type EmbeddingModel interface {
Embed(ctx context.Context, req EmbeddingRequest) (*EmbeddingResponse, error)
Provider() Provider
ModelID() string
}
EmbeddingModel converts text into embedding vectors.
type EmbeddingRequest ¶
type EmbeddingRequest struct {
// Input is the texts to embed. Order is preserved in the response.
Input []string
// Dimensions optionally requests reduced-dimension vectors on models that
// support it. Nil uses the model default.
Dimensions *int
// TaskType optionally specifies downstream task optimization for models that
// support asymmetric embeddings (such as Gemini). Empty leaves task optimization
// to provider default.
TaskType EmbeddingTaskType
// Title optionally specifies the document title when TaskType is
// [EmbeddingTaskTypeDocument]. Providers that do not use document titles ignore this.
Title string
// EncodingFormat optionally requests a compact transfer format (such as Base64)
// on providers that support it. Regardless of transfer format, the returned
// [EmbeddingResponse.Embeddings] are decoded as [][]float32.
EncodingFormat EmbeddingEncodingFormat
// ProviderOptions passes provider-specific extensions, keyed like
// [Request.ProviderOptions].
ProviderOptions map[Provider]any
}
EmbeddingRequest asks an EmbeddingModel to embed one or more inputs.
type EmbeddingResponse ¶
EmbeddingResponse carries one vector per input, in input order.
type EmbeddingTaskType ¶
type EmbeddingTaskType string
EmbeddingTaskType selects downstream task optimization for embedding generation, especially for asymmetric retrieval tasks (such as search and RAG).
const ( EmbeddingTaskTypeQuery EmbeddingTaskType = "query" EmbeddingTaskTypeDocument EmbeddingTaskType = "document" EmbeddingTaskTypeSimilarity EmbeddingTaskType = "similarity" EmbeddingTaskTypeClassification EmbeddingTaskType = "classification" EmbeddingTaskTypeClustering EmbeddingTaskType = "clustering" EmbeddingTaskTypeQuestionAnswer EmbeddingTaskType = "question_answering" EmbeddingTaskTypeFactCheck EmbeddingTaskType = "fact_verification" EmbeddingTaskTypeCodeQuery EmbeddingTaskType = "code_retrieval_query" )
Known embedding task types.
type Error ¶
type Error struct {
// Provider is the adapter that produced the error.
Provider Provider
// StatusCode is the HTTP status, or 0 for transport/decoding errors.
StatusCode int
// Type is the provider's error type string (for example
// "rate_limit_error"), when present.
Type string
// Code is the provider's error code, when present.
Code string
// Message is the human-readable error message.
Message string
// RetryAfter is the delay requested by a Retry-After header, when present.
RetryAfter time.Duration
// Raw is the provider's error body, when available.
Raw []byte
// contains filtered or unexported fields
}
Error is a structured provider error. Adapters return it (wrapped around a sentinel) for non-2xx responses. Extract it with errors.As:
var apiErr *ai.Error
if errors.As(err, &apiErr) { log.Print(apiErr.StatusCode) }
func NewError ¶
NewError builds an Error for the given provider and HTTP status, selecting the wrapped sentinel from the status code via ClassifyStatus.
func (*Error) Unwrap ¶
Unwrap returns the wrapped sentinel error so errors.Is matches ErrAuth, ErrRateLimited, and the other class errors.
func (*Error) WithSentinel ¶
WithSentinel returns a copy of e wrapping the given sentinel. Adapters use it when they can classify an error more precisely than ClassifyStatus does.
type FilePart ¶
type FilePart struct {
Source MediaSource
// Name is an optional human-readable filename, forwarded to providers that
// accept one.
Name string
}
FilePart is a non-image document (for example a PDF) supplied as model input.
type FinishReason ¶
type FinishReason string
FinishReason is why generation stopped, normalized across providers.
const ( // FinishStop means the model completed its turn normally (including by // hitting a stop sequence). FinishStop FinishReason = "stop" // FinishLength means generation hit the max-token limit. FinishLength FinishReason = "length" // FinishToolCalls means the model stopped to request tool invocations. FinishToolCalls FinishReason = "tool_calls" // FinishContentFilter means the provider suppressed output for safety // reasons. FinishContentFilter FinishReason = "content_filter" // FinishOther covers provider-specific reasons with no portable meaning; // consult [Response.Raw] for details. FinishOther FinishReason = "other" )
Normalized finish reasons.
type GeneratedImage ¶
type GeneratedImage struct {
// Data is the inline image bytes; empty when the provider returned a URL.
Data []byte
// MIMEType is the image's media type (for example "image/webp"). It is
// empty when the provider reported no usable format.
MIMEType string
// URL is the provider-hosted link to the image. It is temporary (OpenAI
// keeps it valid for 60 minutes). The adapter never downloads it; fetch it
// yourself if you need bytes.
URL string
// RevisedPrompt is the prompt the provider reports having actually used,
// when it does (OpenAI's dall-e-3). It is empty for providers that do not
// report one.
RevisedPrompt string
}
GeneratedImage is one produced image. Data and URL are mutually exclusive: a provider returns inline bytes or a hosted link, not both.
type GroundingMetadata ¶
type GroundingMetadata struct {
// WebSearchQueries lists queries formulated by the model during generation.
WebSearchQueries []string `json:"web_search_queries,omitempty"`
// Raw preserves provider-specific grounding structures.
Raw any `json:"raw,omitempty"`
}
GroundingMetadata carries query-level grounding details from search tools.
type ImageEditRequest ¶
type ImageEditRequest struct {
// Prompt describes the desired edit.
Prompt string
// Images are the source images, each carrying inline bytes, a URL, or a
// provider file ID. Providers cap the count (OpenAI: 1 to 16).
Images []ImagePart
// Mask is an optional PNG whose transparent pixels mark the region to
// edit. It applies to Images[0].
Mask *ImagePart
// N is how many images to generate; zero means one.
N int
// Size is the provider-specific dimensions string. Empty uses the provider
// default.
Size string
// Quality is the provider-specific quality tier. Empty uses the provider
// default.
Quality string
// OutputFormat is the desired encoding ("png", "jpeg", or "webp"). Empty
// uses the provider default. Providers that emit a single format ignore
// it.
OutputFormat string
// ProviderOptions passes provider-specific extensions, keyed like
// [Request.ProviderOptions].
ProviderOptions map[Provider]any
}
ImageEditRequest asks an ImageEditor to edit source images. Providers apply the prompt to Images, or to the region a Mask selects within the first image.
type ImageEditor ¶
type ImageEditor interface {
// EditImage applies an edit request and returns the completed response.
EditImage(ctx context.Context, req ImageEditRequest) (*ImageResponse, error)
}
ImageEditor is the optional ability to edit existing images. Discover it by type assertion, like TokenCounter.
type ImageModel ¶
type ImageModel interface {
GenerateImages(ctx context.Context, req ImageRequest) (*ImageResponse, error)
Provider() Provider
ModelID() string
}
ImageModel generates images from text prompts. Implemented by the openai, gemini, and agnes adapters; absent capabilities surface as ErrUnsupported.
type ImagePart ¶
type ImagePart struct {
Source MediaSource
}
ImagePart is image input for a vision-capable model.
type ImageRequest ¶
type ImageRequest struct {
// Prompt describes the desired image.
Prompt string
// N is how many images to generate; zero means one.
N int
// Size is the provider-specific dimensions string (for example
// "1024x1024"). Empty uses the provider default.
Size string
// Quality is the provider-specific quality tier (for example "high").
// Empty uses the provider default.
Quality string
// OutputFormat is the desired encoding ("png", "jpeg", or "webp"). Empty
// uses the provider default. Providers that emit a single format ignore
// it.
OutputFormat string
// ProviderOptions passes provider-specific extensions, keyed like
// [Request.ProviderOptions].
ProviderOptions map[Provider]any
}
ImageRequest asks an ImageModel to generate images.
type ImageResponse ¶
type ImageResponse struct {
// Images are the produced images, in provider order.
Images []GeneratedImage
// Usage is the token accounting for the request; zero when unreported.
Usage ImageUsage
// CreatedAt is when the provider created the response. The zero time means
// the provider did not report it.
CreatedAt time.Time
// OutputFormat is the format the provider reports having produced (for
// example "webp"); empty when unreported.
OutputFormat string
// Size is the produced dimensions string the provider reports (for example
// "1024x1536"); empty when unreported.
Size string
// Quality is the effective quality tier the provider reports; empty when
// unreported.
Quality string
// Background is the effective background the provider reports (for example
// "transparent"); empty when unreported.
Background string
// Raw is the provider's response body, untouched. Providers that return
// inline image payloads in the body keep them here as well, so Raw is
// larger than the decoded images.
Raw JSON
}
ImageResponse is the result of an image request.
type ImageStream ¶
type ImageStream = iter.Seq2[ImageStreamEvent, error]
ImageStream is a sequence of [ImageStreamEvent]s. Errors surface through the sequence; a pre-first-event failure is retryable, a failure after output was produced is terminal.
type ImageStreamEvent ¶
type ImageStreamEvent struct {
// Type identifies the event.
Type ImageStreamEventType
// Index is the 0-based index of the partial image. It is always 0 on the
// completed event, which carries no index of its own.
Index int
// Image is the event's image: inline bytes for partials and for the final
// image of providers that stream data (OpenAI never streams URLs).
Image GeneratedImage
// Usage is the request's token accounting. It is non-nil only on the
// completed event, and only when the provider reported it.
Usage *ImageUsage
}
ImageStreamEvent is one event of an ImageStream.
type ImageStreamEventType ¶
type ImageStreamEventType string
ImageStreamEventType identifies one kind of ImageStreamEvent.
const ( // ImageStreamPartial is a partial image produced while the request is // still running. ImageStreamPartial ImageStreamEventType = "partial_image" // ImageStreamCompleted is the final image of the request. It is the last // event of a well-formed stream. ImageStreamCompleted ImageStreamEventType = "completed" )
Image stream event types.
type ImageStreamer ¶
type ImageStreamer interface {
// StreamImages streams a generation request.
StreamImages(ctx context.Context, req ImageRequest) ImageStream
// StreamImageEdits streams an edit request.
StreamImageEdits(ctx context.Context, req ImageEditRequest) ImageStream
}
ImageStreamer is the optional ability to stream images as they are produced. Discover it by type assertion, like TokenCounter:
if streamer, ok := model.(ai.ImageStreamer); ok {
for event, err := range streamer.StreamImages(ctx, req) { ... }
}
type ImageUsage ¶
type ImageUsage struct {
Usage
// TotalTokens is the provider-reported total for the call.
TotalTokens int
// InputTextTokens is the input text portion, when the provider breaks it
// out.
InputTextTokens int
// InputImageTokens is the input image portion, when the provider breaks it
// out.
InputImageTokens int
// OutputTextTokens is the output text portion, when the provider breaks it
// out.
OutputTextTokens int
// OutputImageTokens is the output image portion, when the provider breaks
// it out.
OutputImageTokens int
}
ImageUsage is token accounting for an image request, normalized across providers. The embedded Usage keeps InputTokens, OutputTokens, and the other generic counters readable exactly as on chat responses.
type ImageVariationRequest ¶
type ImageVariationRequest struct {
// Image is the source image. Providers that require inline bytes reject
// other sources.
Image ImagePart
// N is how many images to generate; zero means one.
N int
// Size is the provider-specific dimensions string. Empty uses the provider
// default.
Size string
// ProviderOptions passes provider-specific extensions, keyed like
// [Request.ProviderOptions].
ProviderOptions map[Provider]any
}
ImageVariationRequest asks an ImageVariator for variations of one image.
type ImageVariator ¶
type ImageVariator interface {
// CreateVariations applies a variation request and returns the completed
// response.
CreateVariations(ctx context.Context, req ImageVariationRequest) (*ImageResponse, error)
}
ImageVariator is the optional ability to create variations of an existing image. Discover it by type assertion, like TokenCounter.
type JSON ¶
type JSON = json.RawMessage
JSON is raw JSON bytes. It aliases json.RawMessage, so values convert freely between the two.
type LanguageModel ¶
type LanguageModel interface {
// Generate performs a blocking request and returns the completed response.
Generate(ctx context.Context, req Request) (*Response, error)
// Stream performs a streaming request. Errors — including connection
// failures — surface through the returned sequence on first iteration.
// Breaking out of the range loop cancels the request.
Stream(ctx context.Context, req Request) Stream
// Provider identifies the adapter.
Provider() Provider
// ModelID is the model this instance is bound to.
ModelID() string
// Capabilities reports, best effort, what the bound model supports.
Capabilities() Capabilities
}
LanguageModel is a chat-capable model bound to a specific provider and model ID. Implementations are safe for concurrent use.
Bare implementations perform exactly one attempt per call and never retry; wrap them with middleware for resilience.
func Chain ¶
func Chain(model LanguageModel, middlewares ...Middleware) LanguageModel
Chain applies middlewares to model so that the first middleware is the outermost layer:
m := ai.Chain(base, retry.New(), ratelimit.New(lim)) // request flow: retry → ratelimit → base
Example ¶
Chain layers middleware around a bare provider.
package main
import (
"context"
"os"
"github.com/rsbin1178/pips/ai"
"github.com/rsbin1178/pips/ai/middleware/retry"
"github.com/rsbin1178/pips/ai/openai"
)
func main() {
base := openai.New("gpt-6-astra", openai.WithAPIKey(os.Getenv("OPENAI_API_KEY")))
model := ai.Chain(base, retry.New(retry.WithMaxAttempts(3)))
_, _ = model.Generate(context.Background(), ai.Request{
Messages: ai.Messages{ai.UserText("Hi")},
})
}
Output:
type LogProbsConfig ¶
LogProbsConfig controls portable token log-probability output.
type MediaSource ¶
type MediaSource struct {
// ID references a file already uploaded to the target provider. IDs are
// provider-scoped opaque values.
ID string
// URL is a remote location for the media. Providers that only accept
// inline bytes will reject a URL source. Provider file URIs also use this
// field (for example a Gemini Files API URI).
URL string
// Data is the raw media bytes, used when the media is inlined rather than
// referenced by URL.
Data []byte
// MIMEType is the IANA media type of Data (for example "image/jpeg"). It
// is required for a Data source and optional for a URL source.
MIMEType string
}
MediaSource locates binary media for an ImagePart or FilePart. Exactly one of ID, URL, or Data should be set. When Data is set, MIMEType must describe it (for example "image/png").
func (MediaSource) IsID ¶
func (s MediaSource) IsID() bool
IsID reports whether the source references a provider-uploaded file.
func (MediaSource) IsURL ¶
func (s MediaSource) IsURL() bool
IsURL reports whether the source references media by URL rather than carrying inline bytes.
type Message ¶
type Message interface {
Validate() error
// contains filtered or unexported methods
}
Message is one role-specific turn in a conversation. It is a sealed union: the only implementations are SystemMessage, UserMessage, AssistantMessage, and ToolMessage. The concrete type identifies the author and constrains the content kinds that may appear in the turn.
func CloneMessage ¶
CloneMessage returns a deep copy of a supported concrete message.
func UnmarshalMessage ¶
UnmarshalMessage decodes one stable provider-independent message envelope and dispatches it to the matching concrete message type.
type Messages ¶
type Messages []Message
Messages is a conversation ordered from oldest to newest. System messages, when present, must form a prefix; call Messages.SplitSystem to validate and project that prefix for a provider adapter.
func (Messages) MarshalJSON ¶
MarshalJSON implements json.Marshaler.
func (Messages) SplitSystem ¶
func (messages Messages) SplitSystem() ([]SystemMessage, Messages, error)
SplitSystem validates messages and separates the leading system prefix from the provider conversation. Returned slices are shallow projections intended for immediate read-only adapter use.
func (*Messages) UnmarshalJSON ¶
UnmarshalJSON implements json.Unmarshaler.
type Middleware ¶
type Middleware func(LanguageModel) LanguageModel
Middleware wraps a LanguageModel with cross-cutting behavior (retries, rate limiting, observability) and returns a value that is itself a LanguageModel, so layers compose.
type Part ¶
type Part interface {
// contains filtered or unexported methods
}
Part is one piece of content within a Message. It is a sealed interface: the only implementations are the Part types in this package (TextPart, ImagePart, FilePart, ReasoningPart, ToolCallPart, ToolResultPart, StructuredContentPart, ResourceLinkPart, EmbeddedResourcePart). This lets provider adapters exhaustively switch over the concrete types when translating to and from wire formats. Structured content, resource links, and embedded resources occur only as tool-result content; the role-specific part sets do not accept them.
func CloneParts ¶
CloneParts returns a deep, cycle-safe copy of a supported role-neutral part graph.
func MessageParts ¶
MessageParts returns a role-neutral snapshot of a message's parts. The snapshot recursively owns mutable byte and JSON data.
func ProviderParts ¶
ProviderParts rewrites tool-result content into the part kinds every provider transport carries natively: text, image, and file. Structured content becomes its JSON object text so the model still receives the payload; resource links become a deterministic JSON description and are never fetched; embedded resources project their text, or their blob as an image or file. The public Part taxonomy stays lossless; this view exists for provider I/O and consumers that have not learned the newer kinds.
func UnmarshalParts ¶
UnmarshalParts decodes a stable role-neutral Part envelope list.
type Provider ¶
type Provider string
Provider identifies an LLM API vendor. Provider values appear in errors, capability lookups, and the ProviderOptions escape hatch on Request.
const ( ProviderOpenAI Provider = "openai" ProviderAnthropic Provider = "anthropic" ProviderGemini Provider = "gemini" ProviderAgnes Provider = "agnes" ProviderDeepSeek Provider = "deepseek" ProviderGroq Provider = "groq" ProviderXAI Provider = "xai" ProviderOpenRouter Provider = "openrouter" ProviderCerebras Provider = "cerebras" ProviderTogether Provider = "together" ProviderMistral Provider = "mistral" ProviderCohere Provider = "cohere" ProviderJina Provider = "jina" ProviderSiliconFlow Provider = "siliconflow" ProviderZhipu Provider = "zhipu" ProviderKimi Provider = "kimi" ProviderQwen Provider = "qwen" ProviderMiniMax Provider = "minimax" )
Known providers.
type ReasoningConfig ¶
type ReasoningConfig struct {
// Mode controls whether and how the provider enables reasoning.
Mode ReasoningMode
// Effort is the portable knob; prefer it for cross-provider code.
Effort ReasoningEffort
// BudgetTokens optionally pins an explicit thinking-token budget for
// providers that accept one (Anthropic, Gemini). Zero leaves budget
// selection to the effort mapping or provider default.
BudgetTokens int
// IncludeSummary asks providers that can return a reasoning summary
// (OpenAI Responses) to include it. Providers that always stream reasoning
// content ignore this.
IncludeSummary bool
}
ReasoningConfig requests and tunes model reasoning. BudgetTokens is explicit; adapters may translate Effort to their native level or documented default budget when the protocol has no effort field.
type ReasoningEffort ¶
type ReasoningEffort string
ReasoningEffort selects how much reasoning ("thinking") a model does before answering. It maps to each provider's native control: OpenAI Responses reasoning.effort, Anthropic adaptive effort or enabled-thinking budget, and Gemini thinkingConfig.thinkingLevel.
const ( ReasoningNone ReasoningEffort = "none" ReasoningMinimal ReasoningEffort = "minimal" ReasoningLow ReasoningEffort = "low" ReasoningMedium ReasoningEffort = "medium" ReasoningHigh ReasoningEffort = "high" ReasoningXHigh ReasoningEffort = "xhigh" ReasoningMax ReasoningEffort = "max" )
Reasoning effort levels. The empty value leaves reasoning at the provider default.
type ReasoningMode ¶
type ReasoningMode string
ReasoningMode selects a provider strategy independently from the effort or explicit token budget.
const ( ReasoningModeAuto ReasoningMode = "auto" ReasoningModeEnabled ReasoningMode = "enabled" ReasoningModeAdaptive ReasoningMode = "adaptive" ReasoningModeDisabled ReasoningMode = "disabled" )
Portable reasoning modes.
type ReasoningPart ¶
type ReasoningPart struct {
// Text is the reasoning content. It is empty when Redacted is true.
Text string
// Signature is opaque provider continuation state for the reasoning block.
// Preserve it when echoing reasoning back to the same provider.
Signature string
// Redacted reports that the provider withheld the reasoning content while
// still requiring the block to be echoed back (via Signature) to continue
// the turn.
Redacted bool
}
ReasoningPart is model-produced reasoning ("thinking") content. It appears in assistant messages from reasoning-capable models.
type Request ¶
type Request struct {
// Messages is the conversation so far, oldest first.
Messages Messages
// Tools the model may call.
Tools []Tool
// ToolChoice constrains tool usage. The zero value is provider default.
ToolChoice ToolChoice
// Temperature controls randomness. Nil sends nothing.
Temperature *float64
// TopP is the nucleus-sampling cutoff. Nil sends nothing.
TopP *float64
// TopK limits sampling to the k most likely tokens. Nil sends nothing.
TopK *int
// Seed requests deterministic sampling when the provider supports it.
Seed *int64
// FrequencyPenalty discourages tokens based on occurrence frequency.
FrequencyPenalty *float64
// PresencePenalty discourages tokens that have already appeared.
PresencePenalty *float64
// LogProbs requests token log probabilities.
LogProbs *LogProbsConfig
// MaxTokens caps generated tokens. Nil lets the adapter choose: providers
// that require the field (Anthropic) get a sensible default; others get
// nothing.
MaxTokens *int
// Stop lists sequences that end generation.
Stop []string
// ResponseFormat requests schema-constrained JSON output. See
// [GenerateTyped] for the typed convenience wrapper.
ResponseFormat *ResponseFormat
// Reasoning requests and tunes model reasoning.
Reasoning *ReasoningConfig
// ProviderOptions passes provider-specific extensions that have no
// portable representation. Each adapter looks up its own [Provider] key
// and type-asserts the value to its documented options type; unknown keys
// are ignored.
ProviderOptions map[Provider]any
}
Request is a provider-agnostic generation request. The zero value of every optional field means "let the provider decide"; numeric knobs use pointers so that zero can be sent deliberately (see Ptr).
type RerankModel ¶
type RerankModel interface {
Rerank(ctx context.Context, req RerankRequest) (*RerankResponse, error)
Provider() Provider
ModelID() string
}
RerankModel re-orders candidate documents by semantic relevance to a query.
type RerankRequest ¶
type RerankRequest struct {
// Query is the search intent or reference text to rank candidate documents against.
Query string
// Documents is the list of candidate texts to rank. Order is indexed from 0
// and mapped to [RerankResult.Index].
Documents []string
// TopN optionally limits the number of returned results. If set, it must be
// greater than 0. If nil, all candidate documents are ranked and returned.
TopN *int
// ReturnDocuments optionally requests that original document texts be returned
// in [RerankResult.Document].
ReturnDocuments bool
// ProviderOptions passes provider-specific extensions, keyed like
// [Request.ProviderOptions].
ProviderOptions map[Provider]any
}
RerankRequest asks a RerankModel to score and rank candidate documents against a query.
type RerankResponse ¶
type RerankResponse struct {
Results []RerankResult
Usage Usage
Raw JSON
}
RerankResponse contains candidate documents sorted in descending order of relevance.
type RerankResult ¶
type RerankResult struct {
// Index is the zero-based position of the document in the original [RerankRequest.Documents].
Index int
// RelevanceScore is the relevance score assigned by the model (higher is more relevant).
RelevanceScore float64
// Document is the original document text, populated if ReturnDocuments was true
// or if the provider returns it.
Document string
}
RerankResult is a single candidate document scored and ranked against the query.
type ResourceLinkPart ¶
type ResourceLinkPart struct {
// URI locates the resource. It is required.
URI string
// Name is the machine-readable resource name supplied by the source.
Name string
// Title is a human-readable display name supplied by the source.
Title string
// Description describes the resource.
Description string
// MIMEType is the expected media type of the resource, when known.
MIMEType string
}
ResourceLinkPart references a resource by URI without embedding its content. It appears in ToolMessage results. Nothing fetches the resource automatically; consumers decide whether and how to access it.
type Response ¶
type Response struct {
// ID is the provider's response identifier, when supplied.
ID string
// Model is the model that actually served the request, as reported by the
// provider (it may be more specific than the requested alias).
Model string
// Provider identifies which adapter produced this response.
Provider Provider
// Message is the assistant turn: text, tool calls, and reasoning parts in
// model output order. Append it to the conversation to continue the turn.
Message AssistantMessage
// FinishReason is why generation stopped.
FinishReason FinishReason
// Usage is the token accounting for this request.
Usage Usage
// Citations lists source attributions produced by search or grounding tools.
Citations []Citation
// Grounding contains query-level grounding details when provided by the model.
Grounding *GroundingMetadata
// Warnings reports anything the adapter did not send exactly as
// configured, for example a field the endpoint does not implement. An
// empty slice means the request was encoded as written.
Warnings []Warning
// Raw is the provider's response body, untouched. It is an escape hatch
// for provider-specific fields; do not parse it in portable code.
Raw JSON
}
Response is a completed generation.
func Collect ¶
Collect drains a stream and assembles the complete Response, preserving part order (text, reasoning, and tool calls appear where they occurred). On mid-stream failure it returns the partial response together with the error.
Example ¶
Collect assembles a complete Response from a stream.
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/rsbin1178/pips/ai"
"github.com/rsbin1178/pips/ai/openai"
)
func main() {
model := openai.New("gpt-6-astra", openai.WithAPIKey(os.Getenv("OPENAI_API_KEY")))
resp, err := ai.Collect(model.Stream(context.Background(), ai.Request{
Messages: ai.Messages{ai.UserText("Hello!")},
}))
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.Text())
}
Output:
func GenerateTyped ¶
func GenerateTyped[T any](ctx context.Context, model LanguageModel, req Request) (T, *Response, error)
GenerateTyped calls Generate and decodes the schema-constrained JSON output into T. When req.ResponseFormat is nil, the schema is derived from T with SchemaFor. The raw Response is returned alongside the decoded value for usage accounting.
Example ¶
GenerateTyped derives a JSON schema from the Go type and decodes the model's structured output into it.
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/rsbin1178/pips/ai"
"github.com/rsbin1178/pips/ai/openai"
)
func main() {
type Weather struct {
City string `json:"city"`
TempC float64 `json:"temp_c"`
}
model := openai.New("gpt-6-astra", openai.WithAPIKey(os.Getenv("OPENAI_API_KEY")))
weather, _, err := ai.GenerateTyped[Weather](context.Background(), model, ai.Request{
Messages: ai.Messages{ai.UserText("Current weather in Paris?")},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(weather.City, weather.TempC)
}
Output:
func (*Response) ToolCalls ¶
func (r *Response) ToolCalls() []ToolCallPart
ToolCalls returns the tool invocations requested by the model, in order.
type ResponseFormat ¶
type ResponseFormat struct {
// Name labels the schema. Providers that require a name (OpenAI) get
// "output" when empty.
Name string
// Description optionally tells the model what the output represents.
Description string
// Schema constrains the output. It must describe a JSON object at the top
// level, which is what every provider requires.
Schema *Schema
// Strict requests provider-side exact-schema enforcement where available
// (OpenAI). Other providers ignore it.
Strict bool
}
ResponseFormat requests schema-constrained JSON output. Adapters translate it to the provider's native mechanism: OpenAI response_format/json_schema, Gemini responseJsonSchema, and a forced tool call on Anthropic. In every case the JSON text arrives as the response's text parts, so Response.Text (or GenerateTyped) yields the document.
type Schema ¶
type Schema struct {
// RawJSON is an opaque JSON Schema object or boolean. When set, it takes
// precedence over all typed fields during marshaling. Use ParseSchema for
// dynamic schemas that must be forwarded without normalization.
RawJSON json.RawMessage
// Type is a JSON Schema type: "object", "array", "string", "number",
// "integer", "boolean", or "null".
Type string
// Types represents a union of non-null JSON Schema types. When non-empty,
// it takes precedence over Type. Nullable adds "null" to either form.
Types []string
Description string
// Nullable widens Type to also accept null (serialized as
// ["<type>","null"]). OpenAI strict mode expresses optional fields this
// way.
Nullable bool
// Object schemas.
Properties map[string]*Schema
Required []string
// AdditionalProperties may be a bool or a *Schema. OpenAI strict mode
// requires it to be false on every object; adapters set that when the
// caller has not.
AdditionalProperties any
// Array schemas.
Items *Schema
// String/number constraints.
Enum []any
Format string
Pattern string
// Extra contains JSON Schema keywords without typed fields, such as
// oneOf, $defs, minimum, and default. Typed fields take precedence over
// entries with the same keyword.
Extra map[string]json.RawMessage
}
Schema represents JSON Schema (draft 2020-12). Common tool and structured output keywords have typed fields; Extra preserves other keywords during a JSON round trip. Zero-value typed fields are omitted from serialized schemas.
Schemas can be written as literals or derived from Go types with SchemaFor.
func ParseSchema ¶
ParseSchema validates and preserves a dynamic JSON Schema without normalizing its keywords or numeric values. JSON Schema permits an object or a boolean at every schema position.
func SchemaFor ¶
SchemaFor derives a Schema from T by reflection. T must be a struct (or pointer to one), since providers require a top-level JSON object.
Field rules: the json tag names and skips fields as usual; pointer fields become nullable; every field is listed as required, matching strict-mode expectations (express optionality with pointers). Supported field types are strings, booleans, integer and float kinds, structs, slices, arrays, maps with string keys, time.Time (string, date-time format), and json.RawMessage (any). Recursive types are rejected — write those schemas by hand.
Example ¶
SchemaFor reflects a JSON schema from a struct.
package main
import (
"fmt"
"log"
"github.com/rsbin1178/pips/ai"
)
func main() {
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
schema, err := ai.SchemaFor[Person]()
if err != nil {
log.Fatal(err)
}
fmt.Println(schema.Type, schema.Properties["age"].Type)
}
Output: object integer
func (*Schema) MarshalJSON ¶
MarshalJSON implements json.Marshaler, emitting standard JSON Schema.
func (*Schema) UnmarshalJSON ¶
UnmarshalJSON implements json.Unmarshaler. It accepts scalar and union forms of "type" and preserves unmodeled keywords in Extra.
type Stream ¶
type Stream = iter.Seq2[StreamEvent, error]
Stream is a sequence of streaming events. Iterate with range; breaking out of the loop cancels the underlying request and releases its connection:
for ev, err := range model.Stream(ctx, req) {
if err != nil { ... ; break }
...
}
After a non-nil error the sequence yields nothing further. Connection and pre-flight failures surface as an error on the first iteration.
type StreamEvent ¶
type StreamEvent struct {
Type StreamEventType
// Provider, ID, and Model are set on message_start.
Provider Provider
ID string
Model string
// Text is the fragment for text_delta and reasoning_delta.
Text string
// Signature carries opaque provider continuation state on reasoning_delta
// events (for example Anthropic signature_delta, Gemini thoughtSignature,
// or an OpenAI Responses reasoning item). It may arrive with an empty Text
// and applies to the reasoning part being accumulated.
Signature string
// ToolCallIndex orders concurrent tool calls within the response; it is
// set on all tool_call_* events.
ToolCallIndex int
// ToolCallID and ToolCallName are set on tool_call_start.
ToolCallID string
ToolCallName string
// ArgsDelta is the JSON-arguments fragment for tool_call_delta.
ArgsDelta string
// Citation is set on citation events.
Citation *Citation
// FinishReason and Usage are set on message_end. Usage is nil when the
// provider does not report it. Grounding carries search metadata when
// available. Warnings reports anything the adapter did not send exactly as
// configured; it is set on message_end and is empty when the request was
// encoded as written.
FinishReason FinishReason
Usage *Usage
Grounding *GroundingMetadata
Warnings []Warning
}
StreamEvent is one normalized increment of a streaming response. Only the fields documented for the event's Type are meaningful.
type StreamEventType ¶
type StreamEventType string
StreamEventType discriminates StreamEvent variants.
const ( // StreamMessageStart opens the response; it carries Provider, ID, and // Model. StreamMessageStart StreamEventType = "message_start" // StreamTextDelta carries a fragment of answer text in Text. StreamTextDelta StreamEventType = "text_delta" // StreamReasoningDelta carries a fragment of reasoning content in Text. StreamReasoningDelta StreamEventType = "reasoning_delta" // StreamToolCallStart announces a tool invocation; it carries // ToolCallIndex, ToolCallID, and ToolCallName. StreamToolCallStart StreamEventType = "tool_call_start" // StreamToolCallDelta carries a fragment of the call's JSON arguments in // ArgsDelta for the call identified by ToolCallIndex. StreamToolCallDelta StreamEventType = "tool_call_delta" // StreamToolCallEnd closes the arguments of the call identified by // ToolCallIndex. StreamToolCallEnd StreamEventType = "tool_call_end" // StreamCitation announces a source citation produced by a search or // grounding tool; it carries Citation. StreamCitation StreamEventType = "citation" // StreamMessageEnd closes the response; it carries FinishReason and, // when the provider reports it, Usage. It may also carry Grounding. StreamMessageEnd StreamEventType = "message_end" )
Stream event types, in the order a well-formed stream produces them: one message_start; any interleaving of text_delta, reasoning_delta, and tool_call_start/tool_call_delta/tool_call_end groups; one message_end.
type StructuredContentPart ¶
type StructuredContentPart struct {
// Data is the structured payload. It must be a complete JSON object.
Data JSON
}
StructuredContentPart is a tool-produced structured payload as a JSON object. It appears in ToolMessage results, alongside or instead of textual content. Use StructuredContent to build a validated value.
func StructuredContent ¶
func StructuredContent(data JSON) (StructuredContentPart, error)
StructuredContent returns a StructuredContentPart carrying data, which must be a complete JSON object.
type SystemMessage ¶
type SystemMessage struct {
Parts []SystemPart
}
SystemMessage contains model instructions. Only text is valid system content.
func System ¶
func System(parts ...SystemPart) SystemMessage
System returns a system message from the given text parts.
func SystemText ¶
func SystemText(text string) SystemMessage
SystemText returns a system message containing a single text part.
func (SystemMessage) MarshalJSON ¶
func (m SystemMessage) MarshalJSON() ([]byte, error)
MarshalJSON implements json.Marshaler.
func (*SystemMessage) UnmarshalJSON ¶
func (m *SystemMessage) UnmarshalJSON(data []byte) error
UnmarshalJSON implements json.Unmarshaler.
func (SystemMessage) Validate ¶
func (m SystemMessage) Validate() error
Validate checks that a system message uses its concrete value form and only contains supported system content.
type SystemPart ¶
type SystemPart interface {
Part
// contains filtered or unexported methods
}
SystemPart is content accepted by SystemMessage.
type TokenCounter ¶
TokenCounter is the optional ability to count a request's input tokens without running inference. Anthropic and Gemini expose dedicated endpoints; OpenAI does not (its tokenization is client-side only). Discover it by type assertion:
if tc, ok := model.(ai.TokenCounter); ok {
n, err := tc.CountTokens(ctx, req)
}
type Tool ¶
type Tool struct {
// Kind specifies the execution model of the tool. The zero value is
// [ToolKindFunction].
Kind ToolKind
// Name identifies the tool. Providers restrict names to
// letters/digits/underscores/dashes; stick to that subset for portability.
Name string
// Description tells the model what the tool does and when to use it.
Description string
// InputSchema describes the arguments object as JSON Schema. A nil schema
// means the tool takes no arguments.
InputSchema *Schema
// ProviderType is the wire type discriminator used by the provider
// (e.g. "web_search", "google_search", "code_execution").
ProviderType string
// ProviderData carries provider-specific tool configuration.
ProviderData any
// Disabled when true causes the tool to be omitted from the request.
Disabled bool
}
Tool declares a function or provider-executed capability the model may call. For ToolKindFunction, the model returns invocation requests as [ToolCallPart]s; the application executes the call and replies with a ToolResultPart. For ToolKindProviderExecuted, execution occurs server-side on provider infrastructure.
func (Tool) EffectiveInputSchema ¶
EffectiveInputSchema returns the JSON Schema Provider adapters should advertise for the tool. A nil InputSchema means the tool takes no arguments, which is represented on the wire as an explicit empty object schema. Non-nil schemas are returned unchanged.
func (Tool) IsClientExecuted ¶
IsClientExecuted reports whether the tool requires client execution.
func (Tool) IsProviderExecuted ¶
IsProviderExecuted reports whether the tool is executed server-side by the provider.
type ToolCallPart ¶
type ToolCallPart struct {
// ID uniquely identifies this call within the conversation. Gemini does
// not supply IDs on the wire; its adapter synthesizes stable ones.
ID string
// Name is the tool being called.
Name string
// Args is the raw JSON arguments object produced by the model.
Args JSON
}
ToolCallPart is a request from the model to invoke a tool. It appears in assistant messages.
type ToolChoice ¶
type ToolChoice struct {
Mode ToolChoiceMode
// Name is the tool to force when Mode is [ToolChoiceTool].
Name string
}
ToolChoice constrains the model's tool usage for a request.
type ToolChoiceMode ¶
type ToolChoiceMode string
ToolChoiceMode controls whether the model may, must, or must not call tools.
const ( // ToolChoiceAuto lets the model decide whether to call a tool. ToolChoiceAuto ToolChoiceMode = "auto" // ToolChoiceNone forbids tool calls. ToolChoiceNone ToolChoiceMode = "none" // ToolChoiceRequired forces the model to call some tool. ToolChoiceRequired ToolChoiceMode = "required" // ToolChoiceTool forces the model to call the specific tool named in // [ToolChoice.Name]. ToolChoiceTool ToolChoiceMode = "tool" )
Tool choice modes. The zero value defers to the provider default (equivalent to auto when tools are present).
type ToolKind ¶
type ToolKind string
ToolKind identifies who executes the tool.
const ( // ToolKindFunction is a standard user-defined tool executed by the client // application. The zero value of ToolKind defaults to this. ToolKindFunction ToolKind = "" // ToolKindProviderExecuted is a tool provided and executed autonomously by // the model provider in the cloud (e.g. Google Search Grounding, Gemini // Code Execution, OpenAI Web Search). ToolKindProviderExecuted ToolKind = "provider_executed" )
type ToolMessage ¶
type ToolMessage struct {
Parts []ToolResultPart
}
ToolMessage carries one or more results for prior assistant tool calls.
func ToolResultError ¶
func ToolResultError(toolCallID, name, errText string) ToolMessage
ToolResultError returns a tool message telling the model the call failed.
func ToolResultText ¶
func ToolResultText(toolCallID, name, text string) ToolMessage
ToolResultText returns a tool message answering the given call with plain text output.
func ToolResults ¶
func ToolResults(results ...ToolResultPart) ToolMessage
ToolResults returns a tool message containing the given results.
func (ToolMessage) MarshalJSON ¶
func (m ToolMessage) MarshalJSON() ([]byte, error)
MarshalJSON implements json.Marshaler.
func (*ToolMessage) UnmarshalJSON ¶
func (m *ToolMessage) UnmarshalJSON(data []byte) error
UnmarshalJSON implements json.Unmarshaler.
func (ToolMessage) Validate ¶
func (m ToolMessage) Validate() error
Validate checks the nested content of every result in a tool message.
type ToolResultPart ¶
type ToolResultPart struct {
// ToolCallID matches the [ToolCallPart.ID] this result answers.
ToolCallID string
// Name is the tool that produced the result. Some providers require it;
// others ignore it.
Name string
// Content is the tool output. Text is the common case, but results may be
// multi-modal (for example an image returned by a tool).
Content []Part
// IsError reports that the tool failed; the model is told the call errored.
IsError bool
}
ToolResultPart carries the outcome of a tool invocation back to the model. It appears in ToolMessage.
type Usage ¶
type Usage struct {
// InputTokens is the prompt size, including cached tokens.
InputTokens int
// OutputTokens is the generated size, including reasoning tokens where
// the provider counts them there.
OutputTokens int
// ReasoningTokens is the portion of output spent on reasoning, when
// reported separately.
ReasoningTokens int
// CachedInputTokens is the portion of input served from a prompt cache,
// when reported.
CachedInputTokens int
// CacheWriteTokens is the portion of input written to a prompt cache
// (Anthropic cache_creation), when reported.
CacheWriteTokens int
}
Usage is token accounting for a request, normalized across providers. Fields a provider does not report stay zero.
type UserMessage ¶
type UserMessage struct {
Parts []UserPart
}
UserMessage contains input supplied by a user. It may combine text, images, and files.
func User ¶
func User(parts ...UserPart) UserMessage
User returns a user message from the given parts.
Example ¶
Building a multi-modal conversation with the message constructors.
package main
import (
"fmt"
"github.com/rsbin1178/pips/ai"
)
func main() {
msg := ai.User(
ai.Text("What's in this picture?"),
ai.ImageURL("https://example.com/cat.png"),
)
fmt.Printf("%T %d\n", msg, len(msg.Parts))
}
Output: ai.UserMessage 2
func UserText ¶
func UserText(text string) UserMessage
UserText returns a user message containing a single text part.
func (UserMessage) MarshalJSON ¶
func (m UserMessage) MarshalJSON() ([]byte, error)
MarshalJSON implements json.Marshaler.
func (*UserMessage) UnmarshalJSON ¶
func (m *UserMessage) UnmarshalJSON(data []byte) error
UnmarshalJSON implements json.Unmarshaler.
func (UserMessage) Validate ¶
func (m UserMessage) Validate() error
Validate checks that a user message uses only text, image, and file content.
type UserPart ¶
type UserPart interface {
Part
// contains filtered or unexported methods
}
UserPart is content accepted by UserMessage.
type Warning ¶
type Warning struct {
// Type classifies the notice.
Type WarningType
// Feature names the field or capability the notice is about, for example
// "reasoning_effort", "response_format", or a provider tool name.
Feature string
// Details explains what happened and why, in one sentence.
Details string
}
Warning is one structured notice about a request whose configuration did not reach the wire exactly as written. Adapters emit it instead of silently dropping a configured field, so a caller can tell whether its request took effect: an empty Warnings slice means everything asked for was sent as asked.
type WarningType ¶
type WarningType string
WarningType classifies a notice about how a request was encoded.
const ( // WarningUnsupported means the provider or protocol does not support what // was requested, so it was not sent. WarningUnsupported WarningType = "unsupported" // WarningCompatibility means the value was sent, but encoded differently // from what was requested to fit the endpoint. WarningCompatibility WarningType = "compatibility" // WarningDeprecated means the requested field is deprecated in favor of // another one. WarningDeprecated WarningType = "deprecated" )
Warning types, mirroring the structured-warning contract of the wider ecosystem (for example the Vercel AI SDK): a warning is data the caller can read, not a log line.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package agnes implements ai.ImageModel against the Agnes Image API without the vendor SDK: text-to-image generation and multi-image editing through a single endpoint.
|
Package agnes implements ai.ImageModel against the Agnes Image API without the vendor SDK: text-to-image generation and multi-image editing through a single endpoint. |
|
Package anthropic implements ai.LanguageModel against Anthropic's Messages API (POST /v1/messages) without the vendor SDK.
|
Package anthropic implements ai.LanguageModel against Anthropic's Messages API (POST /v1/messages) without the vendor SDK. |
|
Package cerebras implements ai.LanguageModel against Cerebras ultra-fast inference APIs.
|
Package cerebras implements ai.LanguageModel against Cerebras ultra-fast inference APIs. |
|
Package cohere implements ai.RerankModel against the Cohere Rerank API and compatible endpoints without the vendor SDK.
|
Package cohere implements ai.RerankModel against the Cohere Rerank API and compatible endpoints without the vendor SDK. |
|
Package deepseek implements ai.LanguageModel against DeepSeek APIs.
|
Package deepseek implements ai.LanguageModel against DeepSeek APIs. |
|
Package gemini implements ai.LanguageModel against Google's Gemini API (generateContent / streamGenerateContent) without the vendor SDK.
|
Package gemini implements ai.LanguageModel against Google's Gemini API (generateContent / streamGenerateContent) without the vendor SDK. |
|
Package groq implements ai.LanguageModel against Groq's high-speed inference APIs.
|
Package groq implements ai.LanguageModel against Groq's high-speed inference APIs. |
|
internal
|
|
|
apierr
Package apierr decodes the OpenAI-shaped error envelope every OpenAI-dialect provider returns into an ai.Error.
|
Package apierr decodes the OpenAI-shaped error envelope every OpenAI-dialect provider returns into an ai.Error. |
|
clientopts
Package clientopts provides shared option types and converters for provider facades.
|
Package clientopts provides shared option types and converters for provider facades. |
|
httpx
Package httpx is the shared HTTP plumbing for provider adapters: a tuned transport, JSON request/response execution, SSE stream setup, an SSRF guard, and Retry-After parsing.
|
Package httpx is the shared HTTP plumbing for provider adapters: a tuned transport, JSON request/response execution, SSE stream setup, an SSRF guard, and Retry-After parsing. |
|
imagewire
Package imagewire maps the Images-shaped response items shared by the image adapters onto portable images and derives media types from wire format names.
|
Package imagewire maps the Images-shaped response items shared by the image adapters onto portable images and derives media types from wire format names. |
|
jsonx
Package jsonx is the ai module's single JSON encode/decode seam and owns bounded request-body extension merging shared by all provider adapters.
|
Package jsonx is the ai module's single JSON encode/decode seam and owns bounded request-body extension merging shared by all provider adapters. |
|
sse
Package sse parses Server-Sent Events streams from LLM provider responses.
|
Package sse parses Server-Sent Events streams from LLM provider responses. |
|
Package kimi implements ai.LanguageModel against Moonshot AI's Kimi platform.
|
Package kimi implements ai.LanguageModel against Moonshot AI's Kimi platform. |
|
middleware
|
|
|
capability
Package capability provides a middleware that overrides a model's reported ai.Capabilities with a declarative, field-level ai.CapabilityOverride.
|
Package capability provides a middleware that overrides a model's reported ai.Capabilities with a declarative, field-level ai.CapabilityOverride. |
|
ratelimit
Package ratelimit provides a client-side rate-limiting ai.LanguageModel middleware with two token buckets: requests per minute (RPM) and estimated input tokens per minute (TPM), the two quota dimensions LLM providers enforce.
|
Package ratelimit provides a client-side rate-limiting ai.LanguageModel middleware with two token buckets: requests per minute (RPM) and estimated input tokens per minute (TPM), the two quota dimensions LLM providers enforce. |
|
retry
Package retry provides a retrying ai.LanguageModel middleware with exponential backoff and full jitter.
|
Package retry provides a retrying ai.LanguageModel middleware with exponential backoff and full jitter. |
|
Package minimax implements ai.LanguageModel against MiniMax.
|
Package minimax implements ai.LanguageModel against MiniMax. |
|
Package mistral implements ai.LanguageModel and ai.EmbeddingModel against Mistral AI APIs.
|
Package mistral implements ai.LanguageModel and ai.EmbeddingModel against Mistral AI APIs. |
|
Package observability turns cross-cutting instrumentation into an ai.Middleware via a set of callback hooks.
|
Package observability turns cross-cutting instrumentation into an ai.Middleware via a set of callback hooks. |
|
Package openai implements ai.LanguageModel against OpenAI's wire protocols without the vendor SDK.
|
Package openai implements ai.LanguageModel against OpenAI's wire protocols without the vendor SDK. |
|
compat
Package compat provides service profiles for providers that expose an OpenAI-shaped Chat Completions or Responses API.
|
Package compat provides service profiles for providers that expose an OpenAI-shaped Chat Completions or Responses API. |
|
Package openrouter implements ai.LanguageModel against the OpenRouter gateway.
|
Package openrouter implements ai.LanguageModel against the OpenRouter gateway. |
|
Package qwen implements ai.LanguageModel and ai.EmbeddingModel against Alibaba Cloud Model Studio / DashScope (Qwen).
|
Package qwen implements ai.LanguageModel and ai.EmbeddingModel against Alibaba Cloud Model Studio / DashScope (Qwen). |
|
Package siliconflow implements ai.LanguageModel, ai.EmbeddingModel, and ai.RerankModel against SiliconFlow (硅基流动) APIs.
|
Package siliconflow implements ai.LanguageModel, ai.EmbeddingModel, and ai.RerankModel against SiliconFlow (硅基流动) APIs. |
|
Package together implements ai.LanguageModel, ai.EmbeddingModel, and ai.RerankModel against Together AI APIs.
|
Package together implements ai.LanguageModel, ai.EmbeddingModel, and ai.RerankModel against Together AI APIs. |
|
Package xai implements ai.LanguageModel against xAI (Grok) APIs.
|
Package xai implements ai.LanguageModel against xAI (Grok) APIs. |
|
Package zhipu implements ai.LanguageModel, ai.EmbeddingModel, and ai.RerankModel against Zhipu AI (GLM / BigModel) APIs.
|
Package zhipu implements ai.LanguageModel, ai.EmbeddingModel, and ai.RerankModel against Zhipu AI (GLM / BigModel) APIs. |