NAME
Langertha::Engine::Gemini - Google Gemini API
VERSION
version 0.503
SYNOPSIS
use Langertha::Engine::Gemini;
my $gemini = Langertha::Engine::Gemini->new(
api_key => $ENV{GEMINI_API_KEY},
model => 'gemini-3-flash-preview',
response_size => 4096,
temperature => 0.7,
);
# Simple chat
my $response = $gemini->simple_chat('Explain quantum computing in simple terms');
print $response;
# Streaming
$gemini->simple_chat_stream(sub {
my ($chunk) = @_;
print $chunk->content;
}, 'Write a poem about Perl');
# Async with Future::AsyncAwait
use Future::AsyncAwait;
async sub ask_gemini {
my $response = await $gemini->simple_chat_f(
'What are the benefits of functional programming?'
);
say $response;
}
# Embeddings (gemini-embedding-001 unless embedding_model is set)
my $vector = $gemini->simple_embedding('Some text to embed');
my $vectors = $gemini->simple_embedding([ 'first', 'second' ]);
DESCRIPTION
Provides access to Google's Gemini models via the Generative Language API. Gemini models support multimodal input (text, code, images) and long context windows.
Available models include the current stable Flash line gemini-3.8-flash and gemini-3.7-flash (thinkingLevel low|medium|high, no minimal), the gemini-3-flash-preview default (fast with thinking, and still accepts thinkingLevel=minimal), gemini-3.1-pro-preview (most capable), gemini-3.1-flash-lite (cost-efficient workhorse), and the image-generation models gemini-3.1-flash-image-preview and gemini-3-pro-image-preview. The gemini-2.5-* generation is still served but now classed as previous-generation. The default API endpoint is https://generativelanguage.googleapis.com.
Embeddings (Langertha::Role::Embedding) use gemini-embedding-001 by default; gemini-embedding-2 embeds into a different, incompatible vector space, so do not mix vectors of the two. See "embedding_request" for task_type and output_dimensionality.
THIS API IS WORK IN PROGRESS
api_key
The Google Generative Language API key. If not provided, reads from LANGERTHA_GEMINI_API_KEY environment variable. Get your key at https://aistudio.google.com/app/apikey. Required for the Developer API.
Pass api_key => undef explicitly to send no key at all (a keyless proxy or gateway in front of Gemini): the environment variable is then not read, no key query parameter is added to any URL, and nothing warns. Leaving api_key out keeps the default: environment variable, croak when unset.
cached_content
Optional Langertha::CachedContent resource bound to this engine. When set, every chat request (chat, chat_stream, simple_chat_f, …) injects cachedContent => '{name}' into the generateContent body so the model serves the request against the cached context.
A request that names a cache takes its system instruction, tools and tool configuration from the cache: Gemini rejects a generateContent request that sets systemInstruction, tools or toolConfig next to cachedContent (HTTP 400). While a cache is bound those three are therefore not sent, even when the engine's system_prompt, a system message, tools or tool_choice would set them, and the engine carps once. Put them into the cache when creating it ("system_instruction" in Langertha::CachedContent, "tools" in Langertha::CachedContent).
Lifecycle (create / get / list / update / delete) is on the role — "create_cached_content_f" in Langertha::Role::CachedContent and friends. Bind a freshly created resource with $engine->cached_content($cc).
Source URL: https://ai.google.dev/api/generate-content (the cachedContent field on a generateContent body).
gemini_api_version
The API version segment of every endpoint, v1beta for the Generative Language API. Override in a subclass serving a different version. Tool declarations are sent as parametersJsonSchema, which v1 does not have.
gemini_auth_query
The auth seam: returns the credential as a ( name => value ) query pair list, ( key => $self->api_key ) for the Developer API, or the empty list when api_key is undef or empty. A consumer that authenticates by header instead returns the empty list here and sets the header in update_request.
gemini_endpoint
Composes the credential-free endpoint {url}/{gemini_api_version}/{path}. This is the path half of the seam: a consumer whose resources live under an extra prefix (Vertex AI's projects/{p}/locations/{l}/) overrides this one method and every request URL follows. Callers that are about to issue a request want "gemini_url" instead — this one carries no credential.
gemini_url
Builds "gemini_endpoint" and appends the query string: first the pairs from "gemini_auth_query", then any ( name => value ) pairs passed by the caller (e.g. alt => 'sse').
gemini_model_url
Builds the endpoint of one model method, models/{model}:{method}, via "gemini_url". The models/ prefix lives here so a consumer with a different resource path (Vertex AI's publishers/google/models/) overrides one method.
The chat routes pass chat_model as {model}, or a per-request model (from "chat_f" in Langertha::Role::Chat or "model" in Langertha::Chat) for that request; the override is not sent in the body.
embedding_request
my $request = $engine->embedding_request($text, %extra);
my $request = $engine->embedding_request(\@texts,
task_type => 'RETRIEVAL_DOCUMENT', output_dimensionality => 768);
Builds an embedding request with embedding_model (default gemini-embedding-001). A string goes to models/{model}:embedContent, an ArrayRef of strings to models/{model}:batchEmbedContents as one request per input. The optional task_type, title and output_dimensionality are placed in embedContentConfig (as taskType, title, outputDimensionality), merged with an embedContentConfig you pass yourself; any other key goes into each request unchanged. In a batch every input gets the same settings. "embedding_dimensions" in Langertha::Role::Embedding, when set, is sent as outputDimensionality unless the call passes one.
embedding_response
my $vector = $engine->embedding_response($http_response);
my $vectors = $engine->embedding_response($http_response, \@texts);
Parses an embedding answer; the parser built by "embedding_request" passes the input itself. For a string it returns embedding.values, for an ArrayRef input embeddings[].values, one vector per input in input order. A count that does not match the number of inputs croaks, and so does a body without a vector, naming the engine and any error it carries; it never returns undef.
chat_response
my $response = $engine->chat_response($http_response);
Parses a generateContent answer into a Langertha::Response from the first candidate; finish_reason is its finishReason as Gemini spells it. A blocked prompt (no candidate, promptFeedback.blockReason) is an answer with content '' and the blockReason as finish_reason (e.g. SAFETY). A body with neither croaks, naming the engine and any error it carries. On a stream, the blocked prompt's chunk is the final chunk, with content '' and the blockReason as finish_reason. A stream chunk with a top-level error object croaks "<engine> stream carried an error: <message> (<code>)", which fails the stream.
list_models
my $model_ids = $engine->list_models;
my $models = $engine->list_models(full => 1);
my $models = $engine->list_models(force_refresh => 1);
Fetches available models from the Gemini API using token pagination. Returns an ArrayRef of model ID strings (with the models/ prefix stripped) by default, or full model objects when full = 1> is passed. Results are cached for models_cache_ttl seconds (default: 3600).
SEE ALSO
https://aistudio.google.com/status - Google AI Studio service status
https://ai.google.dev/gemini-api/docs - Official Gemini API documentation
https://aistudio.google.com/ - Google AI Studio for testing
Langertha::Role::Chat - Chat interface methods
Langertha::Role::Tools - MCP tool calling interface
Langertha::Role::Streaming - Streaming support (SSE format)
Langertha::Role::Embedding - Embedding interface (
simple_embedding,simple_embedding_f)https://ai.google.dev/api/embeddings - embedContent / batchEmbedContents reference
Langertha::Engine::Anthropic - Another non-OpenAI-compatible engine
SUPPORT
Issues
Please report bugs and feature requests on GitHub at https://github.com/Getty/langertha/issues.
IRC
Join #langertha on irc.perl.org or message Getty directly.
CONTRIBUTING
Contributions are welcome! Please fork the repository and submit a pull request.
AUTHOR
Torsten Raudssus <getty@cpan.org>
COPYRIGHT AND LICENSE
This software is copyright (c) 2026 by Torsten Raudssus https://raudssus.de/.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.