Skip to main content
This guide walks you through installing Polyglot, configuring API keys, and choosing the right configuration strategy for your project.

Installation

Install Polyglot via Composer:
composer require cognesy/instructor-polyglot
# @doctest id="ed72"
Note: Polyglot ships as part of the Instructor PHP monorepo. If you already have cognesy/instructor-php installed, Polyglot is included automatically — there is no need to install it separately.

Requirements

  • PHP 8.3 or higher
  • Composer
  • A valid API key for at least one supported LLM provider

Setting Up API Keys

Polyglot authenticates with LLM providers through API keys. The simplest approach is to export them as environment variables:
export OPENAI_API_KEY=sk-your-openai-key
export ANTHROPIC_API_KEY=sk-ant-your-anthropic-key
export GEMINI_API_KEY=your-gemini-key
# @doctest id="5d57"
If your project uses a .env file, add the keys there instead and load them with a library such as vlucas/phpdotenv. Polyglot’s bundled preset files reference these variables using ${VAR_NAME} syntax, so the names above are the expected defaults.

Quick Start

Once an API key is available, a single call is all you need:
<?php
require 'vendor/autoload.php';

use Cognesy\Polyglot\Inference\Inference;
use Cognesy\Messages\Messages;

$text = Inference::using('openai')
    ->withMessages(Messages::fromString('Say hello.'))
    ->get();
// @doctest id="c61c"
If you see a friendly greeting, your installation is working correctly. The using() method loads a preset — a small YAML file that tells Polyglot which driver, API URL, endpoint, and model to use. Polyglot ships with presets for every supported provider, so you can swap 'openai' for 'anthropic', 'gemini', 'mistral', or any other supported name and it will just work (provided the matching API key is set).

Configuration Strategies

Polyglot offers three ways to configure connections, from simplest to most flexible.

1. Bundled Presets (Zero Configuration)

Polyglot ships with ready-made presets for all supported providers. Set the appropriate environment variable and call using():
<?php

use Cognesy\Polyglot\Inference\Inference;
use Cognesy\Messages\Messages;

// LLM inference
$text = Inference::using('anthropic')
    ->withMessages(Messages::fromString('Explain photosynthesis in one sentence.'))
    ->get();
// @doctest id="5506"
<?php

use Cognesy\Polyglot\Embeddings\Embeddings;

// Embeddings
$result = Embeddings::using('openai')
    ->withInputs('The quick brown fox.')
    ->create();
// @doctest id="e230"
Bundled presets live inside the package at resources/config/llm/presets/ and resources/config/embed/presets/. You never need to edit these files — override them with your own presets instead (see below).

2. Custom Presets (App-Owned YAML Files)

When you need to change a model, adjust token limits, or add metadata, create your own preset files. Polyglot checks the following directories in order and uses the first match:
PriorityPath
1config/llm/presets/ (or config/embed/presets/)
2packages/polyglot/resources/config/llm/presets/
3vendor/cognesy/instructor-php/packages/polyglot/resources/config/llm/presets/
4vendor/cognesy/instructor-polyglot/resources/config/llm/presets/
All paths are relative to your project root. A file placed in config/llm/presets/ takes precedence over the bundled default.

LLM Preset Example

Create config/llm/presets/openai.yaml:
driver: openai
apiUrl: 'https://api.openai.com/v1'
apiKey: '${OPENAI_API_KEY}'
endpoint: /chat/completions
model: gpt-4.1-nano
maxTokens: 1024
contextLength: 1000000
maxOutputLength: 16384
# @doctest id="0d31"
The driver field determines which Polyglot driver handles the request. The apiKey value supports ${ENV_VAR} interpolation so secrets never appear in plain text.

Embeddings Preset Example

Create config/embed/presets/openai.yaml:
driver: openai
apiUrl: 'https://api.openai.com/v1'
apiKey: '${OPENAI_API_KEY}'
endpoint: /embeddings
model: text-embedding-3-small
dimensions: 1536
maxInputs: 2048
# @doctest id="1cc9"
Once the file exists, Inference::using('openai') or Embeddings::using('openai') will resolve it automatically. You can also create entirely new presets for custom deployments. For example, to add a preset for a local vLLM server, create config/llm/presets/local-vllm.yaml:
driver: openai-compatible
apiUrl: 'http://localhost:8000/v1'
apiKey: 'not-needed'
endpoint: /chat/completions
model: meta-llama/Llama-3-8b
maxTokens: 2048
# @doctest id="57af"
Then use it like any other preset:
$text = Inference::using('local-vllm')
    ->withMessages(Messages::fromString('Say hello.'))
    ->get();
// @doctest id="d46b"

EmbeddingsConfig Reference

ParameterTypeDefaultDescription
driverstring'openai'Driver identifier
apiUrlstring''Base URL of the provider API
apiKeystring''Authentication key
endpointstring''API endpoint path (e.g., /embeddings)
modelstring''Embedding model identifier
dimensionsint0Output vector dimensions
maxInputsint0Maximum number of inputs per request
metadataarray[]Provider-specific metadata

3. Runtime Configuration (Programmatic)

When connection details come from a database, user input, or any other dynamic source, build the config object directly in PHP:
<?php

use Cognesy\Messages\Messages;
use Cognesy\Polyglot\Inference\Config\LLMConfig;
use Cognesy\Polyglot\Inference\Inference;

$inference = Inference::fromConfig(new LLMConfig(
    driver: 'openai',
    apiUrl: 'https://api.openai.com/v1',
    apiKey: (string) getenv('OPENAI_API_KEY'),
    endpoint: '/chat/completions',
    model: 'gpt-4.1-nano',
    maxTokens: 2048,
));

$text = $inference
    ->withMessages(Messages::fromString('What is the capital of France?'))
    ->get();
// @doctest id="3185"
The same approach works for embeddings:
<?php

use Cognesy\Polyglot\Embeddings\Config\EmbeddingsConfig;
use Cognesy\Polyglot\Embeddings\Embeddings;

$embeddings = Embeddings::fromConfig(new EmbeddingsConfig(
    driver: 'openai',
    apiUrl: 'https://api.openai.com/v1',
    apiKey: (string) getenv('OPENAI_API_KEY'),
    endpoint: '/embeddings',
    model: 'text-embedding-3-small',
    dimensions: 1536,
    maxInputs: 2048,
));
// @doctest id="599a"

LLMConfig Reference

ParameterTypeDefaultDescription
driverstring'openai-compatible'Driver identifier (see supported drivers below)
apiUrlstring''Base URL of the provider API
apiKeystring''Authentication key
endpointstring''API endpoint path
modelstring''Model identifier
maxTokensint1024Maximum tokens in the response
contextLengthint8000Context window size
maxOutputLengthint4096Maximum output length
queryParamsarray[]Additional query parameters
metadataarray[]Provider-specific metadata
optionsarray[]Additional driver options
pricingarray[]Token pricing configuration (per 1M tokens)

Overriding a Preset at Runtime

You can start from a preset and selectively override specific values using withOverrides():
<?php

use Cognesy\Polyglot\Inference\Config\LLMConfig;
use Cognesy\Polyglot\Inference\Inference;

$config = LLMConfig::fromPreset('openai')
    ->withOverrides([
        'model' => 'gpt-4.1',
        'maxTokens' => 4096,
    ]);

$inference = Inference::fromConfig($config);
// @doctest id="d082"
This is useful when you want to keep all the defaults from a preset but need to swap the model or adjust limits for a specific use case.

DSN Strings

For compact, inline configuration you can use a DSN (Data Source Name) string. This is useful when storing connection info in a single environment variable or database column:
<?php

use Cognesy\Polyglot\Inference\Config\LLMConfig;
use Cognesy\Polyglot\Inference\Inference;

$config = LLMConfig::fromDsn(
    'driver=openai,apiUrl=https://api.openai.com/v1,endpoint=/chat/completions,model=gpt-4.1-nano'
);

$inference = Inference::fromConfig($config);
// @doctest id="fd7a"
DSN strings are comma-separated key=value pairs. Nested keys use dot notation (e.g., metadata.apiVersion=2023-06-01).

Supported Providers

Polyglot includes built-in drivers for the following providers:
DriverProvider
openaiOpenAI
anthropicAnthropic
geminiGoogle Gemini (native API)
gemini-oaiGoogle Gemini (OpenAI-compatible)
azureAzure OpenAI
mistralMistral AI
cohereCohere
groqGroq
deepseekDeepSeek
fireworksFireworks AI
openrouterOpenRouter
togetherTogether AI
ollamaOllama (local)
perplexityPerplexity
cerebrasCerebras
sambanovaSambaNova
xaixAI (Grok)
a21AI21 Labs
metaMeta Llama API
minimaxiMiniMaxi
moonshotMoonshot (Kimi)
inceptionInception
huggingfaceHugging Face
qwenQwen
glmGLM
bedrock-openaiAWS Bedrock (OpenAI-compatible)
openai-responsesOpenAI Responses API
openresponsesOpen Responses API
openai-compatibleAny OpenAI-compatible API
Any provider that exposes an OpenAI-compatible chat completions endpoint can be used with the openai-compatible driver by pointing apiUrl to the provider’s base URL.

Troubleshooting

Composer dependency errors. Verify that you are running PHP 8.3 or higher (php -v) and that Composer is up to date (composer self-update). “No preset directory found” exception. This means Polyglot could not locate any preset YAML file for the name you passed to using(). Double-check the preset name and ensure your custom config directory (if any) follows the expected structure: config/llm/presets/<name>.yaml. API key not found. Make sure the environment variable is exported in the same shell session that runs your PHP script. You can verify with echo $OPENAI_API_KEY before launching PHP. Wrong model or endpoint. Create a custom preset (see above) to override the bundled defaults with the model and endpoint you need.