Skip to content

Commit 285a1f0

Browse files
committed
Add a new bridge based on models.dev
1 parent 75746d6 commit 285a1f0

21 files changed

+1582
-0
lines changed

docs/components/platform.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ This requires to configure a :class:`Symfony\\AI\\Platform\\Bridge\\Generic\\Mod
166166
:class:`Symfony\\AI\\Platform\\Bridge\\Generic\\CompletionsModel` or :class:`Symfony\\AI\\Platform\\Bridge\\Generic\\EmbeddingsModel`,
167167
see `LiteLLM example`_ for more details.
168168

169+
Alternatively, use the :doc:`models.dev bridge <platform/models-dev>` to
170+
auto-discover model capabilities for many providers without manually curating
171+
model catalogs.
172+
169173
Options
170174
-------
171175

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
Models.dev Platform
2+
===================
3+
4+
The models.dev bridge provides auto-discovered model catalogs for many AI
5+
providers using data from the `models.dev`_ community registry. It leverages
6+
the Generic bridge under the hood, so any provider with an OpenAI-compatible
7+
API works out of the box.
8+
9+
Installation
10+
------------
11+
12+
.. code-block:: terminal
13+
14+
$ composer require symfony/ai-models-dev-platform
15+
16+
Authentication
17+
--------------
18+
19+
Each provider requires its own API key. Set it as an environment variable:
20+
21+
.. code-block:: bash
22+
23+
# Example for DeepSeek
24+
DEEPSEEK_API_KEY=your-api-key
25+
26+
# Example for Groq
27+
GROQ_API_KEY=your-api-key
28+
29+
Refer to each provider's documentation for how to obtain an API key.
30+
31+
Usage
32+
-----
33+
34+
Using the PlatformFactory
35+
~~~~~~~~~~~~~~~~~~~~~~~~~
36+
37+
The simplest way to get started is with ``PlatformFactory``, which auto-detects
38+
the API base URL from the models.dev data::
39+
40+
use Symfony\AI\Platform\Bridge\ModelsDev\PlatformFactory;
41+
use Symfony\AI\Platform\Message\Message;
42+
use Symfony\AI\Platform\Message\MessageBag;
43+
44+
// Auto-detect base URL from models.dev data
45+
$platform = PlatformFactory::create(
46+
provider: 'deepseek',
47+
apiKey: $_ENV['DEEPSEEK_API_KEY'],
48+
);
49+
50+
$messages = new MessageBag(
51+
Message::forSystem('You are a helpful assistant.'),
52+
Message::ofUser('What is the Symfony framework?'),
53+
);
54+
55+
$result = $platform->invoke('deepseek-chat', $messages);
56+
echo $result->asText();
57+
58+
For providers where models.dev does not publish an API base URL, you must provide it
59+
explicitly::
60+
61+
$platform = PlatformFactory::create(
62+
provider: 'groq',
63+
apiKey: $_ENV['GROQ_API_KEY'],
64+
baseUrl: 'https://api.groq.com/openai/v1',
65+
);
66+
67+
The factory accepts the same options as the Generic bridge factory, including
68+
custom HTTP clients, event dispatchers, and endpoint paths::
69+
70+
use Symfony\Component\HttpClient\HttpClient;
71+
72+
$platform = PlatformFactory::create(
73+
provider: 'deepseek',
74+
apiKey: $_ENV['DEEPSEEK_API_KEY'],
75+
httpClient: HttpClient::create(),
76+
completionsPath: '/v1/chat/completions',
77+
embeddingsPath: '/v1/embeddings',
78+
);
79+
80+
Embeddings
81+
~~~~~~~~~~
82+
83+
Embedding models are automatically detected from models.dev data and routed to the
84+
``EmbeddingsModel`` class. Use them like any other embedding model::
85+
86+
$platform = PlatformFactory::create(
87+
provider: 'openai',
88+
apiKey: $_ENV['OPENAI_API_KEY'],
89+
baseUrl: 'https://api.openai.com/v1',
90+
);
91+
92+
$result = $platform->invoke('text-embedding-3-small', 'What is Symfony?');
93+
$vectors = $result->asVectors();
94+
95+
Streaming
96+
~~~~~~~~~
97+
98+
All completions models include the ``OUTPUT_STREAMING`` capability. Enable
99+
streaming as you would with any other platform::
100+
101+
$result = $platform->invoke('deepseek-chat', $messages, [
102+
'stream' => true,
103+
]);
104+
105+
foreach ($result->getContent() as $chunk) {
106+
echo $chunk;
107+
}
108+
109+
Tool Calling
110+
~~~~~~~~~~~~
111+
112+
Models that support tool calling are automatically flagged with the
113+
``TOOL_CALLING`` capability::
114+
115+
use Symfony\AI\Platform\Bridge\ModelsDev\ModelCatalog;
116+
117+
$catalog = new ModelCatalog('deepseek');
118+
$model = $catalog->getModel('deepseek-chat');
119+
120+
// Check if the model supports tool calling
121+
if ($model->supports(\Symfony\AI\Platform\Capability::TOOL_CALLING)) {
122+
// Use with an Agent that has tools configured
123+
}
124+
125+
Adding Custom Models
126+
~~~~~~~~~~~~~~~~~~~~
127+
128+
If a model is missing from the data or you need to override its capabilities,
129+
pass additional models when creating the ``ModelCatalog``::
130+
131+
use Symfony\AI\Platform\Bridge\Generic\CompletionsModel;
132+
use Symfony\AI\Platform\Bridge\ModelsDev\ModelCatalog;
133+
use Symfony\AI\Platform\Capability;
134+
135+
$catalog = new ModelCatalog('deepseek', additionalModels: [
136+
'deepseek-custom-finetune' => [
137+
'class' => CompletionsModel::class,
138+
'capabilities' => [
139+
Capability::INPUT_MESSAGES,
140+
Capability::OUTPUT_TEXT,
141+
Capability::OUTPUT_STREAMING,
142+
Capability::TOOL_CALLING,
143+
],
144+
],
145+
]);
146+
147+
Additional models are merged with and take precedence over the bundled data.
148+
149+
Provider Registry
150+
~~~~~~~~~~~~~~~~~
151+
152+
The ``ProviderRegistry`` gives you access to provider metadata::
153+
154+
use Symfony\AI\Platform\Bridge\ModelsDev\ProviderRegistry;
155+
156+
$registry = new ProviderRegistry();
157+
158+
// List all available providers
159+
$providerIds = $registry->getProviderIds();
160+
// ['openai', 'anthropic', 'deepseek', 'groq', ...]
161+
162+
// Check if a provider exists
163+
$registry->has('deepseek'); // true
164+
165+
// Get provider name
166+
$registry->getProviderName('deepseek'); // "DeepSeek"
167+
168+
// Get API base URL (null if not published by models.dev)
169+
$registry->getApiBaseUrl('deepseek'); // "https://api.deepseek.com"
170+
171+
Symfony Bundle Configuration
172+
----------------------------
173+
174+
When using the AI Bundle, configure the models.dev bridge under the ``generic``
175+
platform section. The ``ModelCatalog`` replaces the manually curated model
176+
list:
177+
178+
.. code-block:: yaml
179+
180+
# config/packages/ai.yaml
181+
ai:
182+
platform:
183+
generic:
184+
deepseek:
185+
base_url: 'https://api.deepseek.com'
186+
api_key: '%env(DEEPSEEK_API_KEY)%'
187+
model_catalog: 'Symfony\AI\Platform\Bridge\ModelsDev\ModelCatalog'
188+
agent:
189+
deepseek:
190+
platform: 'ai.platform.generic.deepseek'
191+
model: 'deepseek-chat'
192+
tools: false
193+
194+
services:
195+
Symfony\AI\Platform\Bridge\ModelsDev\ModelCatalog:
196+
arguments:
197+
$providerId: 'deepseek'
198+
199+
Multiple Providers
200+
~~~~~~~~~~~~~~~~~~
201+
202+
Configure multiple providers in the same application:
203+
204+
.. code-block:: yaml
205+
206+
# config/packages/ai.yaml
207+
ai:
208+
platform:
209+
generic:
210+
deepseek:
211+
base_url: 'https://api.deepseek.com'
212+
api_key: '%env(DEEPSEEK_API_KEY)%'
213+
model_catalog: 'app.model_catalog.deepseek'
214+
groq:
215+
base_url: 'https://api.groq.com/openai/v1'
216+
api_key: '%env(GROQ_API_KEY)%'
217+
model_catalog: 'app.model_catalog.groq'
218+
219+
services:
220+
app.model_catalog.deepseek:
221+
class: 'Symfony\AI\Platform\Bridge\ModelsDev\ModelCatalog'
222+
arguments:
223+
$providerId: 'deepseek'
224+
225+
app.model_catalog.groq:
226+
class: 'Symfony\AI\Platform\Bridge\ModelsDev\ModelCatalog'
227+
arguments:
228+
$providerId: 'groq'
229+
230+
Supported Providers
231+
-------------------
232+
233+
The models.dev registry includes many providers. Use the ``ProviderRegistry``
234+
to list all available providers and check which have auto-detected base URLs::
235+
236+
$registry = new ProviderRegistry();
237+
foreach ($registry->getProviderIds() as $id) {
238+
$url = $registry->getApiBaseUrl($id) ?? '(manual)';
239+
echo sprintf("%s: %s\n", $id, $url);
240+
}
241+
242+
.. note::
243+
244+
Not all providers in the models.dev registry use the OpenAI-compatible API format.
245+
Providers like Anthropic and Google use their own API formats. The models.dev bridge
246+
works best with providers that are OpenAI-compatible, which is the majority.
247+
248+
Resources
249+
---------
250+
251+
* `Contributing <https://symfony.com/doc/current/contributing/index.html>`_
252+
* `Report issues <https://github.com/symfony/ai/issues>`_ and
253+
`send Pull Requests <https://github.com/symfony/ai/pulls>`_
254+
in the `main Symfony AI repository <https://github.com/symfony/ai>`_
255+
256+
.. _models.dev: https://models.dev/
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/Tests export-ignore
2+
/phpunit.xml.dist export-ignore
3+
/.git* export-ignore
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
vendor/
2+
composer.lock
3+
phpunit.xml
4+
.phpunit.result.cache
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# CHANGELOG
2+
3+
## 0.3
4+
5+
* Add models.dev bridge with auto-discovered model catalogs

0 commit comments

Comments
 (0)