compat_oai

package
v1.12.0 Latest Latest
Warning

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

Go to latest
Published: Aug 17, 2026 License: Apache-2.0 Imports: 24 Imported by: 11

README

OpenAI-Compatible Plugin Package

This directory contains a package for building plugins that are compatible with the OpenAI API specification, along with plugins built on top of this package.

Package Overview

The compat_oai package provides a base implementation (OpenAICompatible) that handles:

  • Model and embedder registration
  • Message handling
  • Tool support
  • Configuration management

Usage Example

Here's how to implement a new OpenAI-compatible plugin. A plugin defines a config type for its models that declares every field the provider's API accepts, embedding compat_oai.RequestConfig for the settings Genkit owns (the per-request API key, the model version, and the extra passthrough). SDK-modeled fields are written directly and anything else goes through the request's extra fields. The framework validates every request against the schema inferred from the config type, and that schema is what the Dev UI offers, so declare what the provider's API reference lists and nothing more. Give every field a jsonschema_description for the Dev UI, and put the ranges and enums the provider documents as hard limits in a jsonschema tag, where validation rejects a violation before it is sent and billed; leave per-model limits to the descriptions, since the schema is shared by every model the plugin serves.

A provider field the config does not declare yet is not stranded: callers can send it through the config's extra map, which the framework forwards verbatim (keys in the provider's wire names) after the declared fields, so a plugin never declares a passthrough of its own.

// ChatConfig is the plugin's per-request model config.
type ChatConfig struct {
    compat_oai.RequestConfig

    // Temperature controls the degree of randomness, from 0 to 1.
    Temperature  *float64 `json:"temperature,omitempty" jsonschema:"minimum=0,maximum=1" jsonschema_description:"Controls the degree of randomness in token selection, from 0 to 1."`
    EnableSearch *bool    `json:"enableSearch,omitempty" jsonschema_description:"Lets the model consult web search, sent as the API's enable_search."`
}

func (c ChatConfig) ApplyToChatCompletion(params *openai.ChatCompletionNewParams) {
    c.ApplyVersion(params)
    if c.Temperature != nil {
        params.Temperature = openai.Float(*c.Temperature)
    }
    if c.EnableSearch != nil {
        compat_oai.AddExtraFields(params, map[string]any{"enable_search": *c.EnableSearch})
    }
}

type MyPlugin struct {
    // Models overrides what the plugin knows about a model, keyed by model ID,
    // bare or provider-prefixed. Fields left at their zero value keep what the
    // plugin resolves.
    Models map[string]ai.ModelOptions

    openAICompatible compat_oai.OpenAICompatible
    // define other plugin-specific fields
}

// Capability sets shared by the entries below.
var (
    textOnly = ai.ModelSupports{
        Multiturn: true, Tools: true, SystemRole: true,
        Media: false, ToolChoice: true,
        Output: []string{"text", "json"},
        Constrained: ai.ConstrainedSupportAll,
    }
    multimodal = ai.ModelSupports{
        Multiturn: true, Tools: true, SystemRole: true,
        Media: true, ToolChoice: true,
        Output: []string{"text", "json"},
        Constrained: ai.ConstrainedSupportAll,
    }
)

// supportedModels curates capabilities for well-known models. It is not the
// set of usable models: any model resolves on demand and takes
// [dynamicModelOptions], so an ID absent here still works.
//
// Catalog: https://myprovider.example/docs/models
var supportedModels = map[string]ai.ModelOptions{
    "my-model":       {Label: "My Model", Supports: &textOnly},
    "my-model-vision": {Label: "My Model Vision", Supports: &multimodal},
}

// dynamicModelOptions is advertised for models that resolve dynamically rather
// than appearing in supportedModels.
var dynamicModelOptions = ai.ModelOptions{
    Supports: &multimodal,
    Versions: []string{},
    Stage:    ai.ModelStageStable,
}

// modelOptions is the one source of model capabilities, shared by Init,
// ListActions and ResolveAction, which is what makes a caller's Models entry
// authoritative no matter which path describes the model first.
func (p *MyPlugin) modelOptions(id string) ai.ModelOptions {
    return compat_oai.ModelOptionsFor("myprovider", id, supportedModels, dynamicModelOptions, p.Models)
}

func (p *MyPlugin) Name() string {
    return "myprovider"
}

func (p *MyPlugin) Init(ctx context.Context) []api.Action {
    // initialize the plugin with the common compatible package
    p.openAICompatible.Provider = p.Name()
    actions := p.openAICompatible.Init(ctx)

    // Define plugin-specific models
    for model := range supportedModels {
        actions = append(actions, compat_oai.NewChatModel[ChatConfig](&p.openAICompatible, model, p.modelOptions(model)))
    }

    // Define embedders, if applicable

    return actions
}

A plugin whose config is the raw OpenAI request (the openai plugin, or a proxy for the real OpenAI API) uses OpenAICompatible.NewModel instead, which takes the SDK's openai.ChatCompletionNewParams as the model config.

A typed config can also carry a per-request API key (RequestConfig.APIKey / EmbeddingConfig.APIKey) that overrides the plugin's key for that request alone. The key is a client credential: it never serializes, so it stays out of the advertised schema, recorded traces, and the request body, and it cannot be supplied through JSON or map configs.

Every plugin in this directory lays its catalog out the same way, so the shape above transfers: named capability sets, a documented supportedModels map of one-line entries, a dynamicModelOptions fallback, and a modelOptions method that overlays the caller's Models on whichever of the two applies. Where a provider publishes dated snapshots, fold them into the entry's Versions instead of registering a model per snapshot.

Route every path that describes a model through that one method. Init registers the curated models and cannot be undone afterwards, so a catalog the plugin got wrong is only correctable if Init reads the caller's overrides too.

Models is the whole mechanism, and a plugin exposes no way to register a model itself. An application never needs one: an ID the plugin does not curate resolves on demand, and an entry in Models describes it. This is why the plugins here take no RegisterModel, matching googlegenai and the native anthropic plugin. A registration call would only be able to add IDs that already work, while the models most likely to need correcting are exactly the ones Init has already registered and nothing can register twice.

Fields Genkit owns are not part of a model's config. messages, tools, tool_choice, response_format, and the deprecated functions/function_call pair are built from the Genkit request, so the SDK-typed models hide them from the advertised schema and reject a config that sets one, naming the Genkit option to use instead (ai.WithTools(), ai.WithOutputType(), and so on); n is rejected the same way because the response carries the first candidate only. A curated config type simply omits them. The rest of the SDK schema carries descriptions from OpenAI's API reference, so the Dev UI's config sidebar documents each field.

Constrained is the one capability worth checking against the provider's docs rather than copying. Genkit sends response_format as json_schema whenever the request carries a schema, but it only skips injecting schema instructions into the prompt when the model advertises constrained support. Set ConstrainedSupportAll only where the provider documents response_format with type: json_schema; a provider offering json_object alone (DashScope, DeepSeek, Z.ai) or ignoring response_format outright (Anthropic's compatible endpoint) must leave it unset, or structured output loses the prompt instructions that were the only thing enforcing the schema. Use ConstrainedSupportNoTools where the provider supports schemas but not alongside tools, as xAI does outside the Grok 4 family.

Model IDs are string literals rather than exported constants. An exported ModelMyModel outlives the model it names: the ID churns every few months, but the constant cannot be removed without a breaking change. The map key is already the single source of truth that modelOptions looks up, and a model on its way out is marked with Stage: ai.ModelStageDeprecated, which is data rather than API surface.

Plugins declare their generation fields rather than inheriting them because providers disagree about which ones exist and what they are called: DeepSeek dropped the frequency and presence penalties, Z.ai caps temperature at 1, Kimi's K-series takes neither, and maxOutputTokens is max_tokens on some providers and max_completion_tokens on others. Use the same camelCase name other plugins use for the same setting; conformance_test.go enforces that across the package.

Not every provider is a model vendor. openrouter fronts a gateway serving hundreds of models from dozens of vendors, so it curates no supportedModels map at all: it registers nothing at Init, returns no descriptors from ListActions (a descriptor carries full request and response schemas, so listing that catalog would put megabytes on every reflection poll), and describes every model it resolves with one permissive capability set. Models is how a caller narrows one. Follow that shape for a gateway, and the curated shape above for a vendor.

See the openai, anthropic, dashscope, deepseek, kimi, openrouter, xai, and zai directories for complete implementations.

Running Tests

Set your API keys:

export OPENAI_API_KEY=<your-openai-key>
export ANTHROPIC_API_KEY=<your-anthropic-key>
export DASHSCOPE_API_KEY=<your-dashscope-key>
export ZAI_API_KEY=<your-zai-key>
export KIMI_API_KEY=<your-kimi-key>
export XAI_API_KEY=<your-xai-key>
export DEEPSEEK_API_KEY=<your-deepseek-key>
export OPENROUTER_API_KEY=<your-openrouter-key>

Run all tests:

go test -v ./...

Run specific plugin tests:

# OpenAI tests
go test -v ./openai

# Anthropic tests
go test -v ./anthropic

# DashScope tests
go test -v ./dashscope

# Z.ai tests
go test -v ./zai

# Kimi tests
go test -v ./kimi

# xAI tests
go test -v ./xai

# DeepSeek tests
go test -v ./deepseek

# OpenRouter tests
go test -v ./openrouter

Note: Tests will be skipped if the required API keys are not set.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// BasicText describes model capabilities for text-only GPT models.
	BasicText = ai.ModelSupports{
		Multiturn:  true,
		Tools:      true,
		SystemRole: true,
		Media:      false,
	}

	// Multimodal describes model capabilities for multimodal GPT models.
	Multimodal = ai.ModelSupports{
		Multiturn:  true,
		Tools:      true,
		SystemRole: true,
		Media:      true,
		ToolChoice: true,
	}
)

Functions

func ActionName added in v1.12.0

func ActionName(provider, id string) string

ActionName builds the action name for a model or embedder ID under provider, taking the ID either bare or already provider-prefixed. The prefix is applied by concatenation, so without the trim an already-prefixed name would double up and name an action that resolves nowhere.

func AddExtraFields added in v1.12.0

func AddExtraFields(params *openai.ChatCompletionNewParams, fields map[string]any)

AddExtraFields merges fields into the extra request fields params carries, keeping any set earlier. openai.ChatCompletionNewParams.SetExtraFields alone replaces the map wholesale, which silently drops extras a config's embedded layers already set.

func DefaultModelOptions added in v1.12.0

func DefaultModelOptions() ai.ModelOptions

DefaultModelOptions is the capability set advertised for models that are discovered or resolved dynamically rather than curated by a plugin. Each call returns its own copy of the capabilities, so a caller that adjusts them adjusts one model's description rather than the package's default.

func ListChatActions added in v1.12.0

func ListChatActions[Config ChatConfig](ctx context.Context, o *OpenAICompatible, modelOptions func(id string) ai.ModelOptions) []api.ActionDesc

ListChatActions lists the models the provider's API reports, each described by modelOptions and the schema of the plugin's Config type. Plugins with curated capabilities pass the same options lookup their ResolveAction uses, so listing and resolving a model can never disagree.

func ListModelActions added in v1.12.0

func ListModelActions(ctx context.Context, o *OpenAICompatible, modelOptions func(id string) ai.ModelOptions) []api.ActionDesc

ListModelActions lists the models the provider's API reports, each described by modelOptions and the SDK config schema. It is ListChatActions for a plugin whose config is the SDK request type: the plugin passes the same options lookup its ResolveAction and its Init use, so no path can describe a model differently from the others.

OpenAICompatible.ListActions is the same listing for a plugin with no catalog of its own, describing every model with the generic defaults.

func ModelOptionsFor added in v1.12.0

func ModelOptionsFor(provider, id string, curated map[string]ai.ModelOptions, dynamic ai.ModelOptions, models map[string]ai.ModelOptions) ai.ModelOptions

ModelOptionsFor resolves the options a plugin describes a model with: curated capabilities for a known ID, dynamic ones for the rest, and a caller's own entry from models overlaid on whichever applies. Overlaying rather than replacing lets an entry pin one capability without restating the label, the versions and the rest.

This is how a plugin's catalog stays correctable. Every path that describes a model goes through it, so a caller's entry is authoritative no matter whether Init, ListActions or ResolveAction gets there first, and it applies to the models Init registers, which nothing can re-register afterwards.

id is the bare model ID; models is keyed either bare or provider-prefixed (see internal.LookupOverride).

func NewChatModel added in v1.12.0

func NewChatModel[Config ChatConfig](o *OpenAICompatible, id string, opts ai.ModelOptions) *ai.ModelAction

NewChatModel creates an unregistered model whose config is the provider's own Config type; the framework validates the request's config against the schema inferred from Config and deserializes it before the model function runs, and the config merges itself into the outgoing request through ChatConfig, with its RequestConfig.Extra fields forwarded after that merge so a collision resolves in their favor. A config Version pins the model version the request is served by, and a config carrying a request API key (see [ChatCompletionConfig.APIKey]) is served by a request-scoped client. An empty label is derived from the plugin's provider and the name.

Return the model from the plugin's Init for the framework to register, or register it with genkit.RegisterAction.

func ResolveChatAction added in v1.12.0

func ResolveChatAction[Config ChatConfig](o *OpenAICompatible, atype api.ActionType, id string, modelOptions func(id string) ai.ModelOptions) api.Action

ResolveChatAction resolves a model not registered up front, described by modelOptions and the schema of the plugin's Config type; see ListChatActions.

func ResolveModelAction added in v1.12.0

func ResolveModelAction(o *OpenAICompatible, atype api.ActionType, id string, modelOptions func(id string) ai.ModelOptions) api.Action

ResolveModelAction resolves a model not registered up front, described by modelOptions and the SDK config schema; see ListModelActions.

func WrapAPIError added in v1.12.0

func WrapAPIError(err error) error

WrapAPIError wraps an error the OpenAI SDK returned for an HTTP response in a status.Error carrying the status the server reported, so status-aware middleware (retry, fallback, ...) can tell a rate limit from a request the provider rejected. Without it every API failure is unclassified, which the retry middleware treats as retryable: a 401 would be reissued unchanged until the attempts ran out.

It is exported for the provider packages built on this one, which reach the SDK directly for model discovery.

Values that are not an SDK API error pass through untouched. The SDK returns transport failures unwrapped, and leaving those unclassified is the right answer: a dial timeout really is worth retrying.

Types

type ChatConfig added in v1.12.0

type ChatConfig interface {
	// ApplyToChatCompletion merges the config into params. Only fields the
	// config carries are written, so the zero config leaves params untouched.
	ApplyToChatCompletion(params *openai.ChatCompletionNewParams)
	// RequestAPIKey returns the API key overriding the plugin's for this
	// request, or "" for none (see [RequestConfig.APIKey]). Configs embedding
	// RequestConfig inherit it.
	RequestAPIKey() string
	// RequestExtra returns the request body fields the config carries beyond
	// the ones it declares, or nil for none (see [RequestConfig.Extra]).
	// Configs embedding RequestConfig inherit it.
	RequestExtra() map[string]any
}

ChatConfig is the constraint for a provider's chat model config: a type that can merge itself into the outgoing OpenAI chat completion request. A plugin declares every field its provider accepts, embeds RequestConfig for the settings Genkit owns, and writes SDK-modeled fields directly and anything else through AddExtraFields:

type ChatConfig struct {
	compat_oai.RequestConfig

	Temperature  *float64 `json:"temperature,omitempty" jsonschema:"minimum=0,maximum=2" jsonschema_description:"Controls the degree of randomness in token selection, from 0 to 2."`
	EnableSearch *bool    `json:"enableSearch,omitempty" jsonschema_description:"Lets the model consult web search, sent as the API's enable_search."`
}

func (c ChatConfig) ApplyToChatCompletion(params *openai.ChatCompletionNewParams) {
	c.ApplyVersion(params)
	if c.Temperature != nil {
		params.Temperature = openai.Float(*c.Temperature)
	}
	if c.EnableSearch != nil {
		compat_oai.AddExtraFields(params, map[string]any{"enable_search": *c.EnableSearch})
	}
}

The schema inferred from the config type is what the model advertises and what every request's config is validated against, so a field a provider does not accept is a field the Dev UI offers and the provider rejects. Declare what the provider's API reference lists, and use the same camelCase names other plugins use for the same setting so one config JSON keeps its meaning across providers and runtimes.

Carry the provider's documentation on each field twice: a doc comment for Go readers, and a jsonschema_description tag with the same content for the Dev UI. Ranges, enums, and lengths the provider documents as hard limits belong in a jsonschema tag too, where validation rejects a violation before it is sent and billed. Leave a constraint out when the provider does not document one, and keep per-model limits (a context length, a level one model rejects) to the descriptions: the schema is shared by every model the plugin serves, so it may only say what holds for all of them.

None of this leaves a new provider field stranded until the plugin declares it: every config inherits RequestConfig.Extra, a passthrough NewChatModel forwards after the config's own merge, so a plugin never declares a passthrough of its own.

type EmbeddingConfig added in v1.12.0

type EmbeddingConfig struct {
	// Dimensions is the number of dimensions the output embeddings should
	// have, for models that support shortening.
	Dimensions int `` /* 167-byte string literal not displayed */
	// EncodingFormat selects the encoding of the returned embeddings, "float"
	// (the default) or "base64".
	EncodingFormat openai.EmbeddingNewParamsEncodingFormat `` /* 160-byte string literal not displayed */
	// APIKey overrides the plugin's API key for this request alone. Like
	// [RequestConfig.APIKey], it never serializes and can only be set from a
	// typed config in code.
	APIKey string `json:"-"`
	// User is an end-user identifier the provider can use for abuse
	// monitoring.
	User string `json:"user,omitempty" jsonschema_description:"End-user identifier the provider can use to monitor and detect abuse."`
	// Extra carries request body fields this config does not declare, sent
	// verbatim at the top level of the outgoing request; the contract is
	// [RequestConfig.Extra]'s, with the input the only field Genkit protects.
	Extra map[string]any `` /* 267-byte string literal not displayed */
}

EmbeddingConfig is the per-request config for OpenAI-compatible embedders.

Dimensions and EncodingFormat lead because they are the two fields the released openai.TextEmbeddingConfig had, in the order it had them: that type is now an alias for this one, and keeping the order makes the two interchangeable everywhere a keyed literal is used.

type ModelGenerator

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

ModelGenerator handles OpenAI generation requests

func NewModelGenerator

func NewModelGenerator(client *openai.Client, modelName string) *ModelGenerator

NewModelGenerator creates a new ModelGenerator instance

func (*ModelGenerator) Generate

func (g *ModelGenerator) Generate(ctx context.Context, req *ai.ModelRequest, handleChunk func(context.Context, *ai.ModelResponseChunk) error) (*ai.ModelResponse, error)

Generate executes the generation request

func (*ModelGenerator) GetRequest

GetRequest returns the request built so far, for tests and for plugins that need to inspect what will be sent.

func (*ModelGenerator) WithConfig deprecated

func (g *ModelGenerator) WithConfig(config any) *ModelGenerator

WithConfig adds configuration parameters from the model request see https://platform.openai.com/docs/api-reference/responses/create for more details on openai's request fields

Deprecated: use ModelGenerator.WithParams, which takes the SDK request params directly. A plugin with a config type of its own converts it once, in its ApplyToChatCompletion, instead of leaving every request to a runtime type switch that silently drops the keys it does not recognize.

func (*ModelGenerator) WithMessages

func (g *ModelGenerator) WithMessages(messages []*ai.Message) *ModelGenerator

WithMessages adds messages to the request

func (*ModelGenerator) WithOutputFormats added in v1.12.0

func (g *ModelGenerator) WithOutputFormats(formats []string) *ModelGenerator

WithOutputFormats declares the output formats the model serves natively on the wire. When the declaration leaves "json" out, a schema-less JSON request sends no response_format and rides on the injected format instructions instead. Nil declares nothing and keeps every format eligible.

func (*ModelGenerator) WithParams added in v1.12.0

WithParams uses params as the base the request is built on, carrying the request's config onto the wire. A model the params carry wins over the generator's: that is how a config pins the exact version the request is served by, matching the JS plugin's version handling. The generator's model fills in otherwise.

The fields Genkit manages are cleared out of params and refilled from the Genkit request by the other builders (see [clearManagedFields]). Clearing them is what keeps a config from smuggling in a tool: the builders only assign when the Genkit request carries something, so a tool set here and nowhere else would otherwise survive onto the wire and the model could answer with a call the framework has no handler for.

func (*ModelGenerator) WithToolChoice added in v1.12.0

func (g *ModelGenerator) WithToolChoice(toolChoice ai.ToolChoice) *ModelGenerator

WithToolChoice adds Genkit's tool choice setting to the OpenAI-compatible request.

func (*ModelGenerator) WithTools

func (g *ModelGenerator) WithTools(tools []*ai.ToolDefinition) *ModelGenerator

WithTools adds tools to the request

type OpenAICompatible

type OpenAICompatible struct {

	// Opts contains request options for the OpenAI client.
	// Required: Must include at least WithAPIKey for authentication.
	// Optional: Can include other options like WithOrganization, WithBaseURL, etc.
	Opts []option.RequestOption

	// Provider is a unique identifier for the plugin.
	// This will be used as a prefix for model names (e.g., "myprovider/model-name").
	// Should be lowercase and match the plugin's Name() method.
	Provider string

	// API key to use with the desired plugin.
	APIKey string

	// Base URL to use for custom endpoints.
	// This should be used if you are running through a proxy or
	// using a non-official endpoint
	BaseURL string

	// ListModels optionally overrides how the provider's model IDs are
	// listed, for providers whose models endpoint does not speak OpenAI's
	// pagination. It must return every model the provider serves; nil uses
	// the OpenAI-style listing.
	ListModels func(ctx context.Context, client *openai.Client) ([]string, error)
	// contains filtered or unexported fields
}

OpenAICompatible is a plugin that provides compatibility with OpenAI's Compatible APIs. It allows defining models and embedders that can be used with Genkit.

func (*OpenAICompatible) DefineEmbedder deprecated

func (o *OpenAICompatible) DefineEmbedder(provider, id string, embedOpts *ai.EmbedderOptions) ai.Embedder

DefineEmbedder creates an unregistered embedder.

Deprecated: use OpenAICompatible.NewEmbedder, which names what it does and takes the provider from the plugin. Define is the verb for a caller supplying the implementation, which this is not.

func (*OpenAICompatible) DefineModel deprecated

func (o *OpenAICompatible) DefineModel(provider, id string, opts ai.ModelOptions) ai.Model

DefineModel creates an unregistered model that takes its config untyped: the OpenAI SDK's request params, or a map of them whose unknown keys ride to the wire as JSON extras. Nothing is validated before the model function runs; a config the ModelGenerator.WithConfig type switch does not recognize fails the request instead.

Deprecated: use OpenAICompatible.NewModel, which names what it does, takes the provider from the plugin, and has the framework validate the config against the SDK schema before the model function runs.

func (*OpenAICompatible) Embedder deprecated

func (o *OpenAICompatible) Embedder(g *genkit.Genkit, name string) ai.Embedder

Embedder returns the ai.Embedder with the given name, the full action name with its provider prefix. It returns nil if the embedder was not defined.

Deprecated: Embedding resolves an embedder from its name, so passing ai.WithEmbedderName is usually enough; a plugin's EmbedderRef carries a typed config with it. Use genkit.LookupEmbedder when the action itself is what you need.

func (*OpenAICompatible) Init

func (o *OpenAICompatible) Init(ctx context.Context) []api.Action

Init implements genkit.Plugin.

func (*OpenAICompatible) IsDefinedEmbedder deprecated

func (o *OpenAICompatible) IsDefinedEmbedder(g *genkit.Genkit, name string) bool

IsDefinedEmbedder reports whether the named [Embedder] is defined by this plugin. name is the full action name, provider prefix included.

Deprecated: this existed to guard a registration call that panics on a duplicate. Embedder options now come from a plugin's Embedders field, which nothing has to register and no ordering can defeat, leaving this a question about registry state that applications do not need to ask.

func (*OpenAICompatible) IsDefinedModel deprecated

func (o *OpenAICompatible) IsDefinedModel(g *genkit.Genkit, name string) bool

IsDefinedModel reports whether the named [Model] is defined by this plugin. name is the full action name, provider prefix included.

Deprecated: this existed to guard a registration call that panics on a duplicate. Capabilities now come from a plugin's Models field, which nothing has to register and no ordering can defeat, leaving this a question about registry state that applications do not need to ask.

func (*OpenAICompatible) ListActions added in v0.6.1

func (o *OpenAICompatible) ListActions(ctx context.Context) []api.ActionDesc

ListActions lists the models the provider's API reports, described with the SDK config schema and generic multimodal capabilities. Plugins with a config type and curated capabilities of their own use ListChatActions.

func (*OpenAICompatible) Model deprecated

func (o *OpenAICompatible) Model(g *genkit.Genkit, name string) ai.Model

Model returns the ai.Model with the given name, the full action name with its provider prefix. It returns nil if the model was not defined.

Deprecated: Generation resolves a model from its name, so passing ai.WithModelName is usually enough; a plugin's ModelRef carries a typed config with it. Use genkit.LookupModel when the action itself is what you need.

func (*OpenAICompatible) Name

func (o *OpenAICompatible) Name() string

Name implements genkit.Plugin.

func (*OpenAICompatible) NewEmbedder added in v1.12.0

func (o *OpenAICompatible) NewEmbedder(id string, embedOpts *ai.EmbedderOptions) *ai.EmbedderAction

NewEmbedder creates an embedder that takes an EmbeddingConfig as its per-request config; a config carrying a request API key is served by a request-scoped client. The embedder is not registered: return it from a plugin's Init for the framework to register, or register it with genkit.RegisterAction.

func (*OpenAICompatible) NewModel added in v1.12.0

func (o *OpenAICompatible) NewModel(id string, opts ai.ModelOptions) *ai.ModelAction

NewModel creates a model that takes the OpenAI SDK's openai.ChatCompletionNewParams as its config, the raw request the plugin sends to the provider. The framework validates the request's config against the SDK schema and deserializes it before the model function runs. A Model set in the config pins the exact version the request is served by. Providers with a curated config of their own use NewChatModel instead.

The schema is the SDK's minus the fields Genkit owns (see [managedRequestFields]), so a config naming one of them is rejected rather than silently dropped.

The model is not registered: return it from a plugin's Init for the framework to register, or register it with genkit.RegisterAction.

func (*OpenAICompatible) ResolveAction added in v0.6.1

func (o *OpenAICompatible) ResolveAction(atype api.ActionType, id string) api.Action

ResolveAction resolves a model not registered up front, described with the SDK config schema and generic multimodal capabilities. Plugins with a config type and curated capabilities of their own use ResolveChatAction.

type RequestConfig added in v1.12.0

type RequestConfig struct {
	// APIKey overrides the plugin's API key for this request alone. It is a
	// client credential rather than a request parameter: it never serializes,
	// so it stays out of the advertised config schema, recorded traces, and
	// the outgoing request body, and it can only be set from a typed config in
	// code, never through a JSON or map config.
	APIKey string `json:"-"`
	// Version pins the exact model version the request is served by, e.g.
	// "gpt-4o-2024-11-20" for the "gpt-4o" family. It overrides the model ID
	// the request would otherwise carry.
	Version string `` /* 208-byte string literal not displayed */
	// Extra carries request body fields the config does not declare, sent
	// verbatim at the top level of the outgoing request. Keys are the
	// provider's wire names (usually snake_case), not the camelCase names
	// declared fields use, and a key that collides with anything the config
	// wrote wins, so a stale or missing mapping never blocks a request the
	// provider would accept. The fields Genkit builds from the request itself
	// (messages, tools and their variants) are rejected rather than forwarded.
	Extra map[string]any `` /* 294-byte string literal not displayed */
}

RequestConfig holds the per-request settings Genkit owns rather than the provider: the credential the request is served with, the model version it is served by, and the passthrough for request fields the config does not declare. Every OpenAI-compatible provider implements them identically, so provider configs embed it and declare the rest themselves; see ChatConfig.

Nothing the provider owns belongs here. Sampling settings differ between providers in availability, name, and range, so a shared struct of them would force every config to advertise fields some provider rejects.

func (RequestConfig) ApplyVersion added in v1.12.0

func (c RequestConfig) ApplyVersion(params *openai.ChatCompletionNewParams)

ApplyVersion writes Version onto the request's model, which is how a config pins the version it is served by. Provider configs call it first from their own ApplyToChatCompletion.

It is deliberately not named ApplyToChatCompletion: a config embedding a complete apply method would satisfy ChatConfig while silently dropping every field the provider declared, so the interface stays unsatisfied until the plugin writes its own.

func (RequestConfig) RequestAPIKey added in v1.12.0

func (c RequestConfig) RequestAPIKey() string

RequestAPIKey returns the API key the request overrides the plugin's with, or "" for none. Configs embedding RequestConfig inherit it, which is what makes the override reach NewChatModel.

func (RequestConfig) RequestExtra added in v1.12.0

func (c RequestConfig) RequestExtra() map[string]any

RequestExtra returns the request body fields the config carries beyond the ones it declares, or nil for none. Configs embedding RequestConfig inherit it, which is what makes the passthrough reach NewChatModel.

Directories

Path Synopsis
Package anthropic provides a Genkit plugin for Claude models through Anthropic's OpenAI-compatible endpoint.
Package anthropic provides a Genkit plugin for Claude models through Anthropic's OpenAI-compatible endpoint.
Package dashscope provides a Genkit plugin for Alibaba Cloud's Qwen models, served through DashScope's OpenAI-compatible mode.
Package dashscope provides a Genkit plugin for Alibaba Cloud's Qwen models, served through DashScope's OpenAI-compatible mode.
Package deepseek provides a Genkit plugin for DeepSeek's models.
Package deepseek provides a Genkit plugin for DeepSeek's models.
internal
livetest
Package livetest drives an OpenAI-compatible plugin through the core Genkit generate features against the provider's real API: generation, history, system prompts, streaming, tool calling, structured output, reasoning, vision, and the extra config passthrough.
Package livetest drives an OpenAI-compatible plugin through the core Genkit generate features against the provider's real API: generation, history, system prompts, streaming, tool calling, structured output, reasoning, vision, and the extra config passthrough.
Package kimi provides a Genkit plugin for Moonshot AI's Kimi models.
Package kimi provides a Genkit plugin for Moonshot AI's Kimi models.
Package openai provides a Genkit plugin for OpenAI's models and embedders.
Package openai provides a Genkit plugin for OpenAI's models and embedders.
Package openrouter provides a Genkit plugin for OpenRouter, a gateway that serves models from many providers behind one OpenAI-compatible endpoint.
Package openrouter provides a Genkit plugin for OpenRouter, a gateway that serves models from many providers behind one OpenAI-compatible endpoint.
Package xai provides a Genkit plugin for xAI's Grok models.
Package xai provides a Genkit plugin for xAI's Grok models.
Package zai provides a Genkit plugin for Z.ai's GLM models.
Package zai provides a Genkit plugin for Z.ai's GLM models.

Jump to

Keyboard shortcuts

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