Documentation
¶
Overview ¶
Package gemini is a client for the Google Gemini API, built on the goloop/ai interface.
The Client implements ai.Client, so Generate and Stream work the same as with any other goloop AI provider. On top of that it exposes Gemini's native endpoints and their full options: generateContent, streamGenerateContent, image generation with Imagen (GenerateImage through the predict endpoint), embeddings, token counting and model listing.
c := gemini.New(os.Getenv("GEMINI_API_KEY"))
resp, err := c.Generate(ctx, &ai.Request{
Model: gemini.ModelGemini25Flash,
Messages: []ai.Message{ai.UserText("Say hello in one word.")},
})
Structured output ¶
ai.Request.Format maps onto responseMimeType, with ai.FormatJSONSchema sending the schema as responseJsonSchema beside it, so a request for JSON is enforced rather than merely asked for. ai.Response.JSON decodes the reply. The API has a second schema field, responseSchema, which takes an OpenAPI 3.0 subset rather than JSON Schema; it stays available on GenerationConfig for callers who mean that dialect.
Hosted web search ¶
ai.Request.Hosted maps onto grounding with Google Search, which goes in the tools list as an entry of its own beside the caller's functions:
resp, err := c.Generate(ctx, &ai.Request{
Model: gemini.ModelGemini25Flash,
Messages: []ai.Message{ai.UserText("What shipped this week?")},
Hosted: []ai.Hosted{{Kind: ai.HostedWebSearch}},
})
for _, c := range resp.Citations() { ... }
The search runs on the provider's side, so nothing new reaches a tool loop. The sources come back as ai.Citation values on the text they support, and this provider is unusual in reporting where: its offsets are byte offsets, so Citation.StartByte and Citation.EndByte cut ai.Text.Text exactly, and a caller can show which sentence each source backs. It never reports the source's own words, so Citation.CitedText stays empty here.
A stream is the exception: it carries the sources without a range. The provider measures a range against the finished answer, and there is no finished answer to measure against while it is still arriving.
Grounding takes no settings at all here: the provider decides how many searches to run and over what. A request that sets ai.HostedWeb.MaxUses, either domain list or a region is ai.ErrNoHosted rather than a search that quietly ignores what it was told.
A search and a structured Format cannot be asked for in the same call. This provider enforces a format by constraining what the model may emit, and that does not hold together with grounding, so a request that asks for both is ai.ErrFormatWithHosted before it leaves. Two calls do work: one that searches and answers in prose, one without Hosted that reshapes it into the schema.
Asking what this driver can do ¶
Capabilities describes this driver for the decision taken before a call: whether to offer a feature at all, and whether it needs one request or two.
if ai.SupportsHosted(c, ai.Hosted{Kind: ai.HostedWebSearch}) { ... }
It is a hint and not a permission - support also depends on the model, the account and the region - so ai.ErrNoHosted and ai.ErrNoFormat remain the source of truth and a caller still handles them. What changes is that a refusal the provider only reports as a 400 now arrives as those same sentinels, wrapped around the original ai.APIError, so one errors.Is covers a limitation this driver knew in advance and one it learned over the wire.
Gemini keys tool results by function name rather than by call ID, so this package synthesizes a unique ai.ToolUse ID per call (the function name plus a counter, so repeated calls to one function stay distinct) and resolves it back to the name on the way in. It depends only on goloop/ai and the standard library.
Index ¶
- Constants
- Variables
- type Blob
- type Candidate
- type Client
- func (c *Client) Capabilities() ai.Capabilities
- func (c *Client) CountTokens(ctx context.Context, model string, req *GenerateRequest) (int, error)
- func (c *Client) Embed(ctx context.Context, model string, texts ...string) ([][]float64, error)
- func (c *Client) EmbedContent(ctx context.Context, model string, req *EmbedRequest) (*Embedding, error)
- func (c *Client) Generate(ctx context.Context, req *ai.Request) (*ai.Response, error)
- func (c *Client) GenerateContent(ctx context.Context, model string, req *GenerateRequest) (*GenerateResponse, error)
- func (c *Client) GenerateImage(ctx context.Context, req *ImageRequest) (*ImageResponse, error)
- func (c *Client) GetModel(ctx context.Context, model string) (*Model, error)
- func (c *Client) Models(ctx context.Context) ([]Model, error)
- func (c *Client) Stream(ctx context.Context, req *ai.Request) iter.Seq2[ai.Chunk, error]
- func (c *Client) StreamGenerateContent(ctx context.Context, model string, req *GenerateRequest) iter.Seq2[*GenerateResponse, error]
- type Content
- type EmbedRequest
- type Embedding
- type FileData
- type FunctionCall
- type FunctionCallingConfig
- type FunctionDeclaration
- type FunctionResponse
- type GenerateRequest
- type GenerateResponse
- type GenerationConfig
- type GoogleSearch
- type GroundingChunk
- type GroundingMetadata
- type GroundingSupport
- type GroundingWeb
- type ImageData
- type ImageRequest
- type ImageResponse
- type ImageUsage
- type Model
- type Option
- type Part
- type PromptFeedback
- type Segment
- type ToolConfig
- type ToolDecls
- type UsageMetadata
Examples ¶
Constants ¶
const ( ModelGemini25Pro = "gemini-2.5-pro" ModelGemini25Flash = "gemini-2.5-flash" ModelGemini25FlashLite = "gemini-2.5-flash-lite" ModelGemini20Flash = "gemini-2.0-flash" ModelTextEmbedding004 = "text-embedding-004" )
Convenience model identifiers. Any model string is accepted; use Models to discover what the account can call.
const ( ModelImagen4 = "imagen-4.0-generate-001" ModelImagen3 = "imagen-3.0-generate-002" )
Imagen model identifiers. Any model string is accepted; a constant is just a documented name to reach for. Google versions these by date and retires old ones, so verify against the current catalog before pinning one for a release.
const DefaultBaseURL = "https://generativelanguage.googleapis.com/v1beta"
DefaultBaseURL is the Gemini API base URL, including the version segment.
Variables ¶
var ( // ErrNoImageRequest is returned by GenerateImage for a nil request. ErrNoImageRequest = errors.New("gemini: image request is nil") // ErrNoImagePrompt is returned by GenerateImage when the prompt is empty. // Imagen has nothing to draw from without one. ErrNoImagePrompt = errors.New("gemini: image request has no prompt") // ErrNoImageBytes is returned by ImageData.Bytes when there are no image // bytes to decode. Imagen answers with inline base64, so this only happens // on an empty result. ErrNoImageBytes = errors.New("gemini: no image bytes") )
Errors reported for an image request or its result. The names match the other goloop image drivers, so application code reads the same way whichever provider is behind it.
Functions ¶
This section is empty.
Types ¶
type Blob ¶
Blob is inline binary data, such as an image, with its MIME type. Data is base64-encoded.
type Candidate ¶
type Candidate struct {
Content Content `json:"content"`
FinishReason string `json:"finishReason,omitempty"`
Index int `json:"index"`
// GroundingMetadata is present when the answer was grounded in a search
// the provider ran. It is where the sources live.
GroundingMetadata *GroundingMetadata `json:"groundingMetadata,omitempty"`
}
Candidate is one generated response option.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a Gemini API client. It implements ai.Client and adds the provider's native endpoints.
func New ¶
New returns a Client for the given API key. Shared options (WithBaseURL, WithHTTPClient, WithTimeout, WithMaxRetries, WithHeader) configure it.
Example ¶
package main
import (
"fmt"
"github.com/goloop/gemini"
)
func main() {
c := gemini.New("AIza...")
_ = c // use c.Generate, c.Stream, c.GenerateContent, ...
fmt.Println(gemini.ModelGemini25Flash)
}
Output: gemini-2.5-flash
func (*Client) Capabilities ¶ added in v1.1.0
func (c *Client) Capabilities() ai.Capabilities
Capabilities describes what this driver can be asked for. It is a hint for the decision taken before a call - whether to offer a feature, and whether it needs one request or two - and never a substitute for handling ai.ErrNoHosted, ai.ErrNoFormat or ai.ErrFormatWithHosted, because support also depends on the model, the account and the region.
func (*Client) CountTokens ¶
func (c *Client) CountTokens( ctx context.Context, model string, req *GenerateRequest, ) (int, error)
CountTokens reports how many tokens the given content would consume for a model, without generating a response.
func (*Client) Embed ¶
Embed embeds one or more plain-text inputs and returns their vectors in order, using a single batchEmbedContents call.
func (*Client) EmbedContent ¶
func (c *Client) EmbedContent( ctx context.Context, model string, req *EmbedRequest, ) (*Embedding, error)
EmbedContent embeds a single request with the given model.
func (*Client) Generate ¶
Generate implements ai.Client. It maps the request onto generateContent and returns the first candidate as an ai.Response.
Example ¶
ExampleClient_Generate builds a request. Sending it needs a real API key, so this example only shows the shape.
package main
import (
"fmt"
"github.com/goloop/ai"
"github.com/goloop/gemini"
)
func main() {
req := &ai.Request{
Model: gemini.ModelGemini25Flash,
Messages: []ai.Message{
ai.UserText("Name the capital of France."),
},
}
fmt.Println(req.Model, len(req.Messages))
}
Output: gemini-2.5-flash 1
func (*Client) GenerateContent ¶
func (c *Client) GenerateContent( ctx context.Context, model string, req *GenerateRequest, ) (*GenerateResponse, error)
GenerateContent sends a native generateContent request for the given model.
func (*Client) GenerateImage ¶ added in v1.2.0
func (c *Client) GenerateImage( ctx context.Context, req *ImageRequest, ) (*ImageResponse, error)
GenerateImage generates images from a text prompt with Imagen, through the predict endpoint. Read each image with ImageData.Bytes.
The request is fitted first: Size is mapped to the nearest aspect ratio Imagen supports, unless AspectRatio names one directly. A nil or promptless request is refused before the network.
func (*Client) GetModel ¶
GetModel retrieves one model by name, with or without the "models/" prefix.
func (*Client) Stream ¶
Stream implements ai.Client. It maps the request onto streamGenerateContent and yields text deltas, completed tool calls and a final chunk carrying usage.
func (*Client) StreamGenerateContent ¶
func (c *Client) StreamGenerateContent( ctx context.Context, model string, req *GenerateRequest, ) iter.Seq2[*GenerateResponse, error]
StreamGenerateContent sends a native streaming request and yields each response chunk as it arrives.
type Content ¶
Content is one turn of a conversation: a role ("user" or "model") and its parts. System text is carried separately in GenerateRequest.SystemInstruction and leaves Role empty.
type EmbedRequest ¶
type EmbedRequest struct {
Content Content `json:"content"`
TaskType string `json:"taskType,omitempty"`
Title string `json:"title,omitempty"`
OutputDimensionality int `json:"outputDimensionality,omitempty"`
}
EmbedRequest is the native embedContent request body.
type Embedding ¶
type Embedding struct {
Values []float64 `json:"values"`
}
Embedding is a single embedding vector.
type FileData ¶
type FileData struct {
MIMEType string `json:"mimeType,omitempty"`
FileURI string `json:"fileUri"`
}
FileData references data by URI, such as an uploaded file or a supported remote resource.
type FunctionCall ¶
type FunctionCall struct {
Name string `json:"name"`
Args json.RawMessage `json:"args,omitempty"`
}
FunctionCall is a request from the model to call a declared function. Args is the JSON arguments object.
type FunctionCallingConfig ¶
type FunctionCallingConfig struct {
Mode string `json:"mode,omitempty"`
}
FunctionCallingConfig sets the tool-calling mode: "AUTO", "ANY" or "NONE".
type FunctionDeclaration ¶
type FunctionDeclaration struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
Parameters json.RawMessage `json:"parameters,omitempty"`
}
FunctionDeclaration describes a callable function. Parameters is a JSON Schema object describing its arguments.
type FunctionResponse ¶
type FunctionResponse struct {
Name string `json:"name"`
Response json.RawMessage `json:"response"`
}
FunctionResponse carries a function's result back to the model. Response is a JSON object.
type GenerateRequest ¶
type GenerateRequest struct {
Contents []Content `json:"contents"`
SystemInstruction *Content `json:"systemInstruction,omitempty"`
Tools []ToolDecls `json:"tools,omitempty"`
ToolConfig *ToolConfig `json:"toolConfig,omitempty"`
GenerationConfig *GenerationConfig `json:"generationConfig,omitempty"`
}
GenerateRequest is the native generateContent request body.
type GenerateResponse ¶
type GenerateResponse struct {
Candidates []Candidate `json:"candidates"`
UsageMetadata *UsageMetadata `json:"usageMetadata,omitempty"`
ModelVersion string `json:"modelVersion,omitempty"`
PromptFeedback *PromptFeedback `json:"promptFeedback,omitempty"`
}
GenerateResponse is the native generateContent (and stream chunk) response.
func (*GenerateResponse) Text ¶
func (r *GenerateResponse) Text() string
Text returns the concatenation of the text parts of the first candidate.
type GenerationConfig ¶
type GenerationConfig struct {
Temperature *float64 `json:"temperature,omitempty"`
TopP *float64 `json:"topP,omitempty"`
MaxOutputTokens int `json:"maxOutputTokens,omitempty"`
StopSequences []string `json:"stopSequences,omitempty"`
ResponseMIMEType string `json:"responseMimeType,omitempty"`
// ResponseSchema constrains the answer to a schema written in the
// OpenAPI 3.0 subset the API defines. It is not JSON Schema, and the two
// diverge as soon as a schema uses anything beyond type, properties and
// required.
ResponseSchema json.RawMessage `json:"responseSchema,omitempty"`
// ResponseJSONSchema constrains the answer to a JSON Schema. It is what
// ai.Format.Schema is, so that is where this driver puts it. The API
// rejects a request that sets both this and ResponseSchema; either one
// still needs ResponseMIMEType.
ResponseJSONSchema json.RawMessage `json:"responseJsonSchema,omitempty"`
}
GenerationConfig tunes generation. Temperature and TopP are pointers so an explicit zero is distinct from unset.
type GoogleSearch ¶ added in v1.0.0
type GoogleSearch struct{}
GoogleSearch asks the provider to ground its answer in a search it runs itself. It has no fields: this provider decides how many searches to run and over what, and offers nothing to narrow them with.
type GroundingChunk ¶ added in v1.0.0
type GroundingChunk struct {
Web *GroundingWeb `json:"web,omitempty"`
}
GroundingChunk is one source the search found.
type GroundingMetadata ¶ added in v1.0.0
type GroundingMetadata struct {
WebSearchQueries []string `json:"webSearchQueries,omitempty"`
GroundingChunks []GroundingChunk `json:"groundingChunks,omitempty"`
GroundingSupports []GroundingSupport `json:"groundingSupports,omitempty"`
}
GroundingMetadata reports the search behind a grounded answer: what was searched for, what was found, and which stretch of the answer each finding supports.
type GroundingSupport ¶ added in v1.0.0
type GroundingSupport struct {
Segment *Segment `json:"segment,omitempty"`
GroundingChunkIndices []int `json:"groundingChunkIndices,omitempty"`
}
GroundingSupport ties a stretch of the answer to the sources behind it. Sources are named by their position in GroundingMetadata.GroundingChunks.
type GroundingWeb ¶ added in v1.0.0
type GroundingWeb struct {
URI string `json:"uri,omitempty"`
Title string `json:"title,omitempty"`
Domain string `json:"domain,omitempty"`
}
GroundingWeb is a web page a search found.
type ImageData ¶ added in v1.2.0
type ImageData struct {
B64JSON string `json:"bytesBase64Encoded"`
MIMEType string `json:"mimeType,omitempty"`
}
ImageData is one generated image. Imagen returns bytes inline, so Bytes decodes them directly.
type ImageRequest ¶ added in v1.2.0
type ImageRequest struct {
Model string `json:"-"`
Prompt string `json:"-"`
// N is how many images to generate. Zero means one.
N int `json:"-"`
// AspectRatio is Imagen's native ratio, one of "1:1", "3:4", "4:3",
// "9:16", "16:9". Empty leaves it to the provider.
AspectRatio string `json:"-"`
// Size is a "WxH" pixel string (for example "1536x1024"). Google does not
// honor exact pixels, so it is mapped to the nearest supported aspect
// ratio. AspectRatio, when set, takes precedence.
Size string `json:"-"`
}
ImageRequest is an image generation request.
The field names match the other goloop image drivers where the meaning is the same (Model, Prompt, N). Imagen works in aspect ratios rather than exact pixels, so two size knobs are offered: Size takes a "WxH" string for cross-provider code and is mapped to the nearest aspect ratio, while AspectRatio sets Imagen's native knob directly. When both are set, AspectRatio wins.
type ImageResponse ¶ added in v1.2.0
type ImageResponse struct {
Data []ImageData
// Usage mirrors the field on the other drivers. Imagen's predict endpoint
// does not report token usage, so this is always nil here; it exists so
// accounting code reads the same across providers.
Usage *ImageUsage
}
ImageResponse is an image generation response.
type ImageUsage ¶ added in v1.2.0
type ImageUsage struct {
TotalTokens int `json:"total_tokens"`
InputTokens int `json:"input_tokens"`
OutputTokens int `json:"output_tokens"`
}
ImageUsage reports the tokens an image request consumed, in the shape the other goloop image drivers use. Imagen's predict endpoint reports none, so this is unused today; it keeps the type present for uniform accounting code.
type Model ¶
type Model struct {
Name string `json:"name"`
BaseModelID string `json:"baseModelId,omitempty"`
Version string `json:"version,omitempty"`
DisplayName string `json:"displayName,omitempty"`
Description string `json:"description,omitempty"`
InputTokenLimit int `json:"inputTokenLimit,omitempty"`
OutputTokenLimit int `json:"outputTokenLimit,omitempty"`
SupportedGenerationMethods []string `json:"supportedGenerationMethods,omitempty"`
}
Model describes a Gemini model as reported by the API.
type Option ¶
type Option func(*settings)
Option configures a Client in New.
func WithBaseURL ¶
WithBaseURL overrides the API base URL (proxies, gateways, mock servers, Gemini-compatible endpoints).
func WithHTTPClient ¶
WithHTTPClient sets the HTTP client used for requests.
func WithHeader ¶
WithHeader adds a header sent with every request.
func WithMaxRetries ¶
WithMaxRetries sets how many times a request is retried on 429 and 5xx.
func WithTimeout ¶
WithTimeout sets the per-request timeout when no custom HTTP client is set.
type Part ¶
type Part struct {
Text string `json:"text,omitempty"`
InlineData *Blob `json:"inlineData,omitempty"`
FileData *FileData `json:"fileData,omitempty"`
FunctionCall *FunctionCall `json:"functionCall,omitempty"`
FunctionResponse *FunctionResponse `json:"functionResponse,omitempty"`
}
Part is a single piece of a Content. Exactly one field is set: Text for plain text, InlineData for embedded bytes, FileData for a referenced file, FunctionCall for a model tool call, or FunctionResponse for a tool result.
type PromptFeedback ¶ added in v0.1.1
type PromptFeedback struct {
BlockReason string `json:"blockReason,omitempty"`
}
PromptFeedback reports why a prompt was rejected. BlockReason is empty for a prompt that was not blocked (for example "SAFETY" or "PROHIBITED_CONTENT").
type Segment ¶ added in v1.0.0
type Segment struct {
PartIndex int `json:"partIndex,omitempty"`
StartIndex int `json:"startIndex,omitempty"`
EndIndex int `json:"endIndex,omitempty"`
Text string `json:"text,omitempty"`
}
Segment is a stretch of the generated answer. StartIndex and EndIndex are byte offsets, which is what ai.Citation wants, so unlike most providers this one can say which sentence a source backs rather than only listing sources.
type ToolConfig ¶
type ToolConfig struct {
FunctionCallingConfig *FunctionCallingConfig `json:"functionCallingConfig,omitempty"`
}
ToolConfig controls tool calling for a request.
type ToolDecls ¶
type ToolDecls struct {
FunctionDeclarations []FunctionDeclaration `json:"functionDeclarations,omitempty"`
// GoogleSearch turns on grounding with Google Search, which the provider
// runs itself. It takes no settings, which is why it is an empty object.
GoogleSearch *GoogleSearch `json:"googleSearch,omitempty"`
}
ToolDecls is one entry of the tools list: either the caller's function declarations or one of the provider's own tools. A request that wants both sends two entries.
type UsageMetadata ¶
type UsageMetadata struct {
PromptTokenCount int `json:"promptTokenCount"`
CandidatesTokenCount int `json:"candidatesTokenCount"`
TotalTokenCount int `json:"totalTokenCount"`
}
UsageMetadata reports token counts for a request.