Skip to main content
The Inference class is the main facade for interacting with LLM APIs. It provides a clean, immutable interface for chat completions, tool calling, JSON output generation, and streaming — all through a consistent API regardless of the underlying provider.

Quick Start

The simplest way to generate text is with a single chained call:
The using() static method resolves a named preset from your configuration, while withMessages() accepts a Messages object. Use Messages::fromString() to wrap a plain text prompt, or Messages::fromArray() to convert an array of role/content pairs. The get() method executes the request and returns the response content as a string.

Creating an Inference Instance

For more control over the lifecycle, create an instance directly. Without arguments, Inference uses a sensible default configuration:
You may also use the with() method, which accepts all request parameters at once:

Core Request Fields

The with() method and its individual with...() counterparts allow you to set every aspect of the inference request:

Execution Paths

Once you have configured a request, choose how to execute it:

Multi-Turn Conversations

For multi-turn conversations, pass an array of messages with role annotations:

Customizing Request Options

Provider-specific parameters such as temperature, max_tokens, or top_p are passed through the options array. Most providers follow the OpenAI-compatible parameter conventions:
You can also set all parameters at once via the with() convenience method:

Streaming Responses

Streaming lets you display partial output as it arrives from the model, creating a more responsive user experience. Call stream() to get an InferenceStream, then iterate over deltas:
Each PartialInferenceDelta exposes the contentDelta string for the incremental text fragment. The stream also provides functional-style helpers — map(), filter(), and reduce() — for processing deltas inline. You can also register a callback to handle each delta as it arrives:
After the stream completes, call final() to retrieve the assembled InferenceResponse with full content and usage statistics.

Working with the Full Response

When you need more than just text, use response() to access the complete InferenceResponse object:
The response object provides access to content, reasoning content (for models that support chain-of-thought), tool calls, token usage statistics, and the raw HTTP response data.

Switching Between Providers

Polyglot ships with YAML-based presets for many providers. Switching between them is a single method call:
Available presets include openai, anthropic, gemini, mistral, groq, ollama, fireworks, together, openrouter, cohere, deepseek, xai, azure, perplexity, sambanova, and others. Each preset is defined in a YAML file under resources/config/llm/presets/.

Configuring Presets

Each preset is a YAML file that defines the connection parameters for a provider. For example, the OpenAI preset:
Polyglot resolves presets from several locations, searched in order:
  1. config/llm/presets/ (your project root)
  2. packages/polyglot/resources/config/llm/presets/ (monorepo)
  3. vendor/cognesy/instructor-php/packages/polyglot/resources/config/llm/presets/
  4. vendor/cognesy/instructor-polyglot/resources/config/llm/presets/
To customize a provider, copy the relevant YAML file into config/llm/presets/ at your project root and modify it as needed. Environment variables are referenced with the ${VAR_NAME} syntax.

Selecting a Model

Each preset defines a default model, but you can override it per-request:

Immutability

Inference is immutable from the caller’s perspective. Every with...() method returns a new instance, leaving the original unchanged. This makes it safe to build a base configuration and derive specialized variants from it:
Both $precise and $fast inherit the temperature setting without affecting each other or the $base instance.