Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ $openai = new OpenAI(
```

Available OpenAI Models:
- `MODEL_GPT_5_NANO`: GPT-5 Nano - Small GPT-5 variant optimized for low latency and cost-sensitive workloads
- `MODEL_GPT_4_5_PREVIEW`: GPT-4.5 Preview - OpenAI's most advanced model with enhanced reasoning, broader knowledge, and improved instruction following
- `MODEL_GPT_4_1`: GPT-4.1 - Advanced large language model with strong reasoning capabilities and improved context handling
- `MODEL_GPT_4O`: GPT-4o - Multimodal model optimized for both text and image processing with faster response times
Expand Down Expand Up @@ -143,14 +144,15 @@ use Utopia\Agents\Adapters\XAI;

$xai = new XAI(
apiKey: 'your-api-key',
model: XAI::MODEL_GROK_2_LATEST,
model: XAI::MODEL_GROK_3_MINI,
maxTokens: 2048,
temperature: 0.7
);
```

Available XAI Models:
- `MODEL_GROK_2_LATEST`: Latest Grok model
- `MODEL_GROK_3`: Latest Grok model
- `MODEL_GROK_3_MINI`: Mini version of Grok model
- `MODEL_GROK_2_IMAGE`: Latest Grok model with image support

### Managing Conversations
Expand Down Expand Up @@ -245,4 +247,4 @@ We truly ❤️ pull requests! If you wish to help, you can learn more about how

## Copyright and license

The MIT License (MIT) [http://www.opensource.org/licenses/mit-license.php](http://www.opensource.org/licenses/mit-license.php)
The MIT License (MIT) [http://www.opensource.org/licenses/mit-license.php](http://www.opensource.org/licenses/mit-license.php)
14 changes: 7 additions & 7 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ services:
- ./phpunit.xml:/usr/src/code/phpunit.xml
environment:
- TESTING=true
- LLM_KEY_ANTHROPIC=${LLM_KEY_ANTHROPIC}
- LLM_KEY_OPENAI=${LLM_KEY_OPENAI}
- LLM_KEY_DEEPSEEK=${LLM_KEY_DEEPSEEK}
- LLM_KEY_XAI=${LLM_KEY_XAI}
- LLM_KEY_PERPLEXITY=${LLM_KEY_PERPLEXITY}
- LLM_KEY_GEMINI=${LLM_KEY_GEMINI}
- LLM_KEY_ANTHROPIC=${LLM_KEY_ANTHROPIC:-}
- LLM_KEY_OPENAI=${LLM_KEY_OPENAI:-}
- LLM_KEY_DEEPSEEK=${LLM_KEY_DEEPSEEK:-}
- LLM_KEY_XAI=${LLM_KEY_XAI:-}
- LLM_KEY_PERPLEXITY=${LLM_KEY_PERPLEXITY:-}
- LLM_KEY_GEMINI=${LLM_KEY_GEMINI:-}
depends_on:
- ollama
networks:
Expand All @@ -41,4 +41,4 @@ volumes:
ollama_models:

networks:
utopia:
utopia:
68 changes: 56 additions & 12 deletions src/Agents/Adapters/OpenAI.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@

class OpenAI extends Adapter
{
/**
* GPT-5 Nano - Small GPT-5 variant optimized for low latency and cost-sensitive workloads
*/
public const MODEL_GPT_5_NANO = 'gpt-5-nano';

/**
* GPT-4.5 Preview - OpenAI's most advanced model with enhanced reasoning, broader knowledge, and improved instruction following
*/
Expand Down Expand Up @@ -76,6 +81,11 @@ class OpenAI extends Adapter
*/
protected int $timeout;

/**
* @var bool
*/
protected bool $hasWarnedTemperatureOverride = false;

/**
* Create a new OpenAI adapter
*
Expand Down Expand Up @@ -125,7 +135,8 @@ public function isSchemaSupported(): bool
*/
public function send(array $messages, ?callable $listener = null): Message
{
if ($this->getAgent() === null) {
$agent = $this->getAgent();
if ($agent === null) {
throw new \Exception('Agent not set');
}

Expand All @@ -147,11 +158,11 @@ public function send(array $messages, ?callable $listener = null): Message
}

$instructions = [];
foreach ($this->getAgent()->getInstructions() as $name => $content) {
foreach ($agent->getInstructions() as $name => $content) {
$instructions[] = '# '.$name."\n\n".$content;
}

$systemMessage = $this->getAgent()->getDescription().
$systemMessage = $agent->getDescription().
(empty($instructions) ? '' : "\n\n".implode("\n\n", $instructions));

if (! empty($systemMessage)) {
Expand All @@ -164,10 +175,14 @@ public function send(array $messages, ?callable $listener = null): Message
$payload = [
'model' => $this->model,
'messages' => $formattedMessages,
'temperature' => $this->temperature,
];
$temperature = $this->temperature;
if ($this->usesDefaultTemperatureOnly()) {
$temperature = 1.0;
}
$payload['temperature'] = $temperature;

$schema = $this->getAgent()->getSchema();
$schema = $agent->getSchema();
if ($schema !== null) {
$payload['response_format'] = [
'type' => 'json_schema',
Expand All @@ -187,13 +202,7 @@ public function send(array $messages, ?callable $listener = null): Message
$payload['stream'] = true;
}

// Use 'max_completion_tokens' for o-series models, else 'max_tokens'
$oSeriesModels = [
self::MODEL_O3,
self::MODEL_O3_MINI,
self::MODEL_O4_MINI,
];
if (in_array($this->model, $oSeriesModels)) {
if ($this->usesMaxCompletionTokens()) {
$payload['max_completion_tokens'] = $this->maxTokens;
} else {
$payload['max_tokens'] = $this->maxTokens;
Expand Down Expand Up @@ -306,6 +315,7 @@ protected function process(Chunk $chunk, ?callable $listener): string
public function getModels(): array
{
return [
self::MODEL_GPT_5_NANO,
self::MODEL_GPT_4_5_PREVIEW,
self::MODEL_GPT_4_1,
self::MODEL_GPT_4O,
Expand All @@ -315,6 +325,40 @@ public function getModels(): array
];
}

/**
* OpenAI expects max_completion_tokens for these models.
*/
protected function usesMaxCompletionTokens(): bool
{
return in_array($this->model, [
self::MODEL_GPT_5_NANO,
self::MODEL_O4_MINI,
self::MODEL_O3,
self::MODEL_O3_MINI,
], true);
}

/**
* Some models only accept the default temperature (1).
*/
protected function usesDefaultTemperatureOnly(): bool
{
$usesDefaultTemperatureOnly = in_array($this->model, [
self::MODEL_GPT_5_NANO,
], true);

if ($usesDefaultTemperatureOnly && $this->temperature !== 1.0 && ! $this->hasWarnedTemperatureOverride) {
$this->hasWarnedTemperatureOverride = true;
error_log(
"OpenAI adapter warning: model '{$this->model}' only supports temperature=1.0. "
."Overriding provided value {$this->temperature}. "
.'Set temperature to 1.0 to remove this warning.'
);
}

return $usesDefaultTemperatureOnly;
}

/**
* Get current model
*
Expand Down
16 changes: 11 additions & 5 deletions src/Agents/Adapters/XAI.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,19 @@ class XAI extends OpenAI
protected const ENDPOINT = 'https://api.x.ai/v1/chat/completions';

/**
* Grok 2 Latest - Latest Grok model
* Grok 3 - Latest Grok model
*/
public const MODEL_GROK_2_LATEST = 'grok-2-latest';
public const MODEL_GROK_3 = 'grok-3';

/**
* Grok 3 Mini - Mini version of grok 3
*/
public const MODEL_GROK_3_MINI = 'grok-3-mini';
Comment on lines +15 to +22
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

rg -n 'MODEL_GROK_2_LATEST' --type=php

Repository: utopia-php/agents

Length of output: 43


🏁 Script executed:

cat -n src/Agents/Adapters/XAI.php | head -100

Repository: utopia-php/agents

Length of output: 2780


🏁 Script executed:

git log --oneline -n 20 src/Agents/Adapters/XAI.php

Repository: utopia-php/agents

Length of output: 91


🏁 Script executed:

git show 430ad21:src/Agents/Adapters/XAI.php | head -100

Repository: utopia-php/agents

Length of output: 2080


🏁 Script executed:

git log --oneline --follow -- src/Agents/Adapters/XAI.php

Repository: utopia-php/agents

Length of output: 91


🏁 Script executed:

git log --all --diff-filter=A -- src/Agents/Adapters/XAI.php

Repository: utopia-php/agents

Length of output: 441


🏁 Script executed:

git show c22aa7a --name-status | grep -i xai

Repository: utopia-php/agents

Length of output: 142


🏁 Script executed:

git show c22aa7a:src/Agents/Adapters/XAI.php | head -100

Repository: utopia-php/agents

Length of output: 2070


🏁 Script executed:

git show c22aa7a -- src/Agents/Adapters/XAI.php | grep -A 5 -B 5 "MODEL_GROK_2_LATEST"

Repository: utopia-php/agents

Length of output: 901


🏁 Script executed:

git log --oneline --all -- src/Agents/Adapters/XAI.php

Repository: utopia-php/agents

Length of output: 178


Removal of MODEL_GROK_2_LATEST is a breaking change for downstream consumers.

The MODEL_GROK_2_LATEST constant was replaced as part of the Grok 2 to Grok 3 migration. Any external code referencing XAI::MODEL_GROK_2_LATEST will fail. If this library has external consumers, preserve backwards compatibility by keeping the old constant as a deprecated alias pointing to MODEL_GROK_3_MINI or MODEL_GROK_3.

Additionally, MODEL_GROK_2_IMAGE value changed from 'grok-2-image' to 'grok-2-image-1212', which is also a breaking change for external consumers relying on the old value.

🤖 Prompt for AI Agents
In `@src/Agents/Adapters/XAI.php` around lines 15 - 22, Restore backward
compatibility by reintroducing the removed constant MODEL_GROK_2_LATEST as a
deprecated alias that points to the new model constant (choose either
MODEL_GROK_3_MINI or MODEL_GROK_3 based on compatibility) and add a deprecation
doc comment; also revert or provide a deprecated alias for the changed
MODEL_GROK_2_IMAGE value so the original string 'grok-2-image' remains available
(e.g., keep existing MODEL_GROK_2_IMAGE with its new value and add
MODEL_GROK_2_IMAGE_DEPRECATED or reassign the original name to the old string
while marking it deprecated), updating PHPDoc comments for
XAI::MODEL_GROK_2_LATEST and XAI::MODEL_GROK_2_IMAGE to indicate deprecation and
mapping to the new constants.


/**
* Grok 2 Image - Latest Grok model with image support
*/
public const MODEL_GROK_2_IMAGE = 'grok-2-image';
public const MODEL_GROK_2_IMAGE = 'grok-2-image-1212';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

MODEL_GROK_2_IMAGE value changed — verify this is intentional.

The model string changed to 'grok-2-image-1212' (a date-pinned version). This silently changes behavior for anyone using XAI::MODEL_GROK_2_IMAGE without updating their code, which may be desirable for reproducibility but should be noted.

🤖 Prompt for AI Agents
In `@src/Agents/Adapters/XAI.php` at line 27, The constant XAI::MODEL_GROK_2_IMAGE
was changed to a date-pinned string ('grok-2-image-1212') which can silently
alter behavior; confirm whether this pin is intentional and either revert to the
generic identifier or explicitly document the pin and preserve
backward-compatibility by adding a clear alias (keep XAI::MODEL_GROK_2_IMAGE as
the canonical constant and, if needed, add a new XAI::MODEL_GROK_2_IMAGE_PINNED
constant or a comment next to MODEL_GROK_2_IMAGE explaining the pin and its
rationale) and update any places that depend on MODEL_GROK_2_IMAGE to use the
intended constant.


/**
* Create a new XAI adapter
Expand All @@ -35,7 +40,7 @@ class XAI extends OpenAI
*/
public function __construct(
string $apiKey,
string $model = self::MODEL_GROK_2_LATEST,
string $model = self::MODEL_GROK_3_MINI,
int $maxTokens = 1024,
float $temperature = 1.0,
?string $endpoint = null,
Expand Down Expand Up @@ -69,7 +74,8 @@ public function isSchemaSupported(): bool
public function getModels(): array
{
return [
self::MODEL_GROK_2_LATEST,
self::MODEL_GROK_3,
self::MODEL_GROK_3_MINI,
self::MODEL_GROK_2_IMAGE,
];
}
Expand Down
2 changes: 1 addition & 1 deletion tests/Agents/Conversation/ConversationXAITest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ protected function createAdapter(): Adapter

return new XAI(
$apiKey,
XAI::MODEL_GROK_2_LATEST,
XAI::MODEL_GROK_3_MINI,
1024,
1.0
);
Expand Down