OpenAI LLM provider

OpenAI provider for Piko's LLM service. It covers chat completions, server-sent streaming, native tool/function calling, structured output via JSON schemas, and embeddings. Works against OpenAI directly, Azure OpenAI, or any OpenAI-compatible proxy.

Overview

This provider implements both llm.ProviderPort against the OpenAI Chat Completions API and llm.EmbeddingProviderPort against the Embeddings API. A single WithLLMProvider("openai", provider) registration gives you completions, streaming, tool calling, structured output, and embeddings. The same adapter satisfies both ports, so piko auto-detects embedding support from the LLM provider. The model filter tracks the chat families OpenAI exposes through this API surface. It accepts the gpt-4, gpt-4o, and gpt-5 families, the o1, o3, and o4 reasoning models, and embedding models such as text-embedding-3-small and text-embedding-3-large.

Structured output uses OpenAI's native response_format JSON schema support instead of the tool-call translation Anthropic requires. This is the broadest model selection of the LLM providers.

The provider is API-compatible with anything that speaks the OpenAI HTTP shape. Point at Azure OpenAI, a local proxy (LiteLLM, openrouter), or a self-hosted vLLM or llama.cpp server exposing the OpenAI surface by setting BaseURL. The endpoint and organisation flow straight through to the OpenAI SDK, so you write no extra glue code.

The provider is concurrency-safe and lifecycle-aware. Close cancels in-flight streams and drains the active goroutines within a bounded timeout, so the provider slots into piko's run modes without extra handling.

Requirements

  • An OpenAI API key (or an Azure OpenAI key when BaseURL points at Azure).
  • Network egress to api.openai.com (or your BaseURL override).

Configuration

import (
    "os"

    "piko.sh/piko/wdk/llm/llm_provider_openai"
)

provider, err := llm_provider_openai.NewOpenAIProvider(llm_provider_openai.Config{
    APIKey:                os.Getenv("OPENAI_API_KEY"), // required
    BaseURL:               "",                          // empty for the official endpoint; set for Azure / proxies
    Organisation:          "",                          // optional OpenAI organisation ID
    DefaultModel:          "gpt-4.1",                   // optional; falls back to gpt-4.1
    DefaultEmbeddingModel: "text-embedding-3-small",    // optional; falls back to text-embedding-3-small
    EmbeddingDimensions:   0,                           // 0 = look up the model's default dimension
})
if err != nil {
    return err
}

Construction fails when the API key is empty. An unset DefaultModel falls back to gpt-4.1 and an unset DefaultEmbeddingModel falls back to text-embedding-3-small. When EmbeddingDimensions is zero, the provider resolves the dimension for the configured embedding model from a built-in table.

EmbeddingDimensions sets the vector size the provider reports to the LLM service, which the service uses to size the vector namespace for retrieval-augmented generation. It does not change the size of the vectors the OpenAI API returns. To request a shorter vector from a model that supports the dimensions parameter, set the per-request dimensions on the embedding call. Keep EmbeddingDimensions matched to the vectors the model produces so the namespace dimension lines up.

Bootstrap

ssr := piko.New(
    piko.WithLLMProvider("openai", provider),
    piko.WithDefaultLLMProvider("openai"),
)

This single registration covers completions and embeddings. The provider implements EmbeddingProviderPort, so piko detects embedding support from it. You do not need a separate WithEmbeddingProvider call for the OpenAI-only case.

Wire the provider in compiled main.go, as shown here. The provider is pure Go and needs no build tag or CGO. It is not exposed as an interpreted symbol, so register it from compiled code, not from interpreted dev scripts.

For mixed setups (OpenAI for chat, Voyage for embeddings) register both and pick defaults explicitly. WithDefaultEmbeddingProvider takes precedence over the embedding support auto-detected from the default LLM provider:

ssr := piko.New(
    piko.WithLLMProvider("openai", openaiProvider),
    piko.WithDefaultLLMProvider("openai"),
    piko.WithEmbeddingProvider("voyage", voyageProvider),
    piko.WithDefaultEmbeddingProvider("voyage"),
)

See also

Other LLM providers:

  • Anthropic Claude, long-context, strong tool use.
  • Gemini, cheapest competent option, multimodal-native.
  • Mistral, open-weight European provider.
  • Grok, xAI provider.
  • Ollama, local inference for offline or privacy-sensitive workloads.
  • Voyage, embeddings-only specialist.

Framework docs:

External: