Skip to content
Draft
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
156 changes: 156 additions & 0 deletions src/platform/bin/generate-model-schema.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#!/usr/bin/env php
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

/**
* Generates models.schema.json from models.php for OpenAI bridge.
*
* This script extracts model definitions and generates a JSON Schema
* that can be used for validation and IDE support.
*/

// Bootstrap autoloader
$autoloadFiles = [
__DIR__.'/../vendor/autoload.php',
__DIR__.'/../../../../vendor/autoload.php',
];

$autoloaded = false;
foreach ($autoloadFiles as $autoloadFile) {
if (file_exists($autoloadFile)) {
require $autoloadFile;
$autoloaded = true;
break;
}
}

if (!$autoloaded) {
fwrite(STDERR, "Error: Could not find vendor/autoload.php\n");
exit(1);
}

$modelsFile = __DIR__.'/../src/Bridge/OpenAi/Resources/models.php';
$schemaFile = __DIR__.'/../src/Bridge/OpenAi/Resources/models.schema.json';

if (!file_exists($modelsFile)) {
fwrite(STDERR, "Error: models.php not found at: {$modelsFile}\n");
exit(1);
}

// Load the models array
$models = require $modelsFile;

if (!is_array($models)) {
fwrite(STDERR, "Error: models.php must return an array\n");
exit(1);
}

// Extract unique classes
$classes = [];
foreach ($models as $model) {
if (isset($model['class'])) {
$classes[$model['class']] = true;
}
}
$classes = array_keys($classes);
sort($classes);

// Define capability enum values
$capabilities = [
'INPUT_MESSAGES',
'INPUT_TEXT',
'INPUT_IMAGE',
'INPUT_AUDIO',
'OUTPUT_TEXT',
'OUTPUT_IMAGE',
'OUTPUT_STREAMING',
'OUTPUT_STRUCTURED',
'TOOL_CALLING',
];

// Create example from first few models
$exampleModels = array_slice($models, 0, 2, true);
$examples = [];
foreach ($exampleModels as $name => $config) {
$capabilityNames = [];
foreach ($config['capabilities'] as $capability) {
$capabilityNames[] = $capability->name;
}
$examples[$name] = [
'class' => $config['class'],
'capabilities' => $capabilityNames,
];
}

// Build the schema
$schema = [
'$schema' => 'http://json-schema.org/draft-07/schema#',
'$id' => 'https://symfony.com/schema/ai/openai-models.json',
'title' => 'OpenAI Model Catalog Schema',
'description' => 'JSON Schema for OpenAI model definitions in models.php',
'type' => 'object',
'patternProperties' => [
'^[a-z0-9.-]+$' => [
'$ref' => '#/definitions/model',
],
],
'additionalProperties' => false,
'definitions' => [
'model' => [
'type' => 'object',
'required' => ['class', 'capabilities'],
'properties' => [
'class' => [
'type' => 'string',
'enum' => $classes,
'description' => 'The fully qualified class name that handles this model type',
],
'capabilities' => [
'type' => 'array',
'items' => [
'$ref' => '#/definitions/capability',
],
'minItems' => 1,
'uniqueItems' => true,
'description' => 'Array of capabilities supported by this model',
],
],
'additionalProperties' => false,
],
'capability' => [
'type' => 'string',
'enum' => $capabilities,
'description' => 'A capability that the model supports',
],
],
'examples' => [$examples],
];

// Generate JSON with pretty printing
$json = json_encode($schema, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);

if (false === $json) {
fwrite(STDERR, "Error: Failed to encode JSON schema\n");
exit(1);
}

// Write to file
if (false === file_put_contents($schemaFile, $json."\n")) {
fwrite(STDERR, "Error: Failed to write schema file to: {$schemaFile}\n");
exit(1);
}

echo "✓ Successfully generated models.schema.json\n";
echo " Models: ".count($models)."\n";
echo " Classes: ".count($classes)."\n";
echo " Output: {$schemaFile}\n";

exit(0);
102 changes: 102 additions & 0 deletions src/platform/src/Bridge/OpenAi/Model.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\AI\Platform\Bridge\OpenAi;

/**
* OpenAI model identifiers.
*
* These constants provide IDE autocompletion and type safety when working with OpenAI models.
* Use these with ModelCatalog::getModel() for better developer experience.
*
* @author Oskar Stark <oskarstark@googlemail.com>
*/
final class Model
{
// GPT-3.5 Models
public const GPT_3_5_TURBO = 'gpt-3.5-turbo';
public const GPT_3_5_TURBO_INSTRUCT = 'gpt-3.5-turbo-instruct';

// GPT-4 Models
public const GPT_4 = 'gpt-4';
public const GPT_4_TURBO = 'gpt-4-turbo';
public const GPT_4O = 'gpt-4o';
public const GPT_4O_MINI = 'gpt-4o-mini';
public const GPT_4O_AUDIO_PREVIEW = 'gpt-4o-audio-preview';

// O1 Reasoning Models
public const O1_MINI = 'o1-mini';
public const O1_PREVIEW = 'o1-preview';

// O3 Reasoning Models
public const O3_MINI = 'o3-mini';
public const O3_MINI_HIGH = 'o3-mini-high';

// GPT-4.5 Preview Models
public const GPT_4_5_PREVIEW = 'gpt-4.5-preview';

// GPT-4.1 Models
public const GPT_4_1 = 'gpt-4.1';
public const GPT_4_1_MINI = 'gpt-4.1-mini';
public const GPT_4_1_NANO = 'gpt-4.1-nano';

// GPT-5 Models
public const GPT_5 = 'gpt-5';
public const GPT_5_CHAT_LATEST = 'gpt-5-chat-latest';
public const GPT_5_MINI = 'gpt-5-mini';
public const GPT_5_NANO = 'gpt-5-nano';

// Embedding Models
public const TEXT_EMBEDDING_ADA_002 = 'text-embedding-ada-002';
public const TEXT_EMBEDDING_3_LARGE = 'text-embedding-3-large';
public const TEXT_EMBEDDING_3_SMALL = 'text-embedding-3-small';

// Audio Models
public const WHISPER_1 = 'whisper-1';

// Image Generation Models
public const DALL_E_2 = 'dall-e-2';
public const DALL_E_3 = 'dall-e-3';

/**
* @return list<string>
*/
public static function all(): array
{
return [
self::GPT_3_5_TURBO,
self::GPT_3_5_TURBO_INSTRUCT,
self::GPT_4,
self::GPT_4_TURBO,
self::GPT_4O,
self::GPT_4O_MINI,
self::GPT_4O_AUDIO_PREVIEW,
self::O1_MINI,
self::O1_PREVIEW,
self::O3_MINI,
self::O3_MINI_HIGH,
self::GPT_4_5_PREVIEW,
self::GPT_4_1,
self::GPT_4_1_MINI,
self::GPT_4_1_NANO,
self::GPT_5,
self::GPT_5_CHAT_LATEST,
self::GPT_5_MINI,
self::GPT_5_NANO,
self::TEXT_EMBEDDING_ADA_002,
self::TEXT_EMBEDDING_3_LARGE,
self::TEXT_EMBEDDING_3_SMALL,
self::WHISPER_1,
self::DALL_E_2,
self::DALL_E_3,
];
}
}
Loading
Loading