mirror of
https://github.com/symfony/ai.git
synced 2026-03-23 23:42:18 +01:00
Fix outdated code references across documentation
- Fix class names: CachedPlatform→CachePlatform, OllamaApiCatalog→ModelCatalog, Indexer→DocumentIndexer/SourceIndexer, Store\Vector→Platform\Vector\Vector - Fix namespaces: TokenUsage, MemoryInputProcessor, ConfiguredSourceIndexer, SourceIndexer, DocumentIndexer, StructuredOutputSerializer - Fix method calls: asText()→getContent(), private property access→getters - Fix API signatures: StoreInterface::query() now requires QueryInterface, ChromaDb\Store constructor updated, Ollama PlatformFactory simplified - Remove unused imports: Gpt, Embeddings, VertexAi Model - Fix incorrect file reference: _model-listing.php→_model.php - Fix incorrect link target: Crawler Tool→firecrawl-crawl.php - Fix MessageBagInterface→MessageBag (interface doesn't exist)
This commit is contained in:
16
UPGRADE.md
16
UPGRADE.md
@@ -104,7 +104,7 @@ AI Bundle
|
||||
+$container->get('ai.toolbox.my_agent.subagent.research_agent');
|
||||
```
|
||||
|
||||
* An indexer configured with a `source`, now wraps the indexer with a `Symfony\AI\Store\ConfiguredSourceIndexer` decorator. This is
|
||||
* An indexer configured with a `source`, now wraps the indexer with a `Symfony\AI\Store\Indexer\ConfiguredSourceIndexer` decorator. This is
|
||||
transparent - the configured source is still used by default, but can be overridden by passing a source to `index()`.
|
||||
|
||||
* The `host_url` parameter for `Ollama` platform has been renamed `endpoint`.
|
||||
@@ -120,12 +120,12 @@ Store
|
||||
-----
|
||||
|
||||
* The `Symfony\AI\Store\Indexer` class has been replaced with two specialized implementations:
|
||||
- `Symfony\AI\Store\SourceIndexer`: For indexing from sources (file paths, URLs, etc.) using a `LoaderInterface`
|
||||
- `Symfony\AI\Store\DocumentIndexer`: For indexing documents directly without a loader
|
||||
- `Symfony\AI\Store\Indexer\SourceIndexer`: For indexing from sources (file paths, URLs, etc.) using a `LoaderInterface`
|
||||
- `Symfony\AI\Store\Indexer\DocumentIndexer`: For indexing documents directly without a loader
|
||||
|
||||
```diff
|
||||
-use Symfony\AI\Store\Indexer;
|
||||
+use Symfony\AI\Store\SourceIndexer;
|
||||
+use Symfony\AI\Store\Indexer\SourceIndexer;
|
||||
|
||||
-$indexer = new Indexer($loader, $vectorizer, $store, '/path/to/source');
|
||||
-$indexer->index();
|
||||
@@ -143,11 +143,11 @@ Store
|
||||
$indexer->index([$document1, $document2]);
|
||||
```
|
||||
|
||||
* The `Symfony\AI\Store\ConfiguredIndexer` class has been renamed to `Symfony\AI\Store\ConfiguredSourceIndexer`:
|
||||
* The `Symfony\AI\Store\ConfiguredIndexer` class has been renamed to `Symfony\AI\Store\Indexer\ConfiguredSourceIndexer`:
|
||||
|
||||
```diff
|
||||
-use Symfony\AI\Store\ConfiguredIndexer;
|
||||
+use Symfony\AI\Store\ConfiguredSourceIndexer;
|
||||
+use Symfony\AI\Store\Indexer\ConfiguredSourceIndexer;
|
||||
|
||||
-$indexer = new ConfiguredIndexer($innerIndexer, 'default-source');
|
||||
+$indexer = new ConfiguredSourceIndexer($sourceIndexer, 'default-source');
|
||||
@@ -260,7 +260,7 @@ Platform
|
||||
* Run `composer require symfony/ai-cache-platform`
|
||||
* Change `Symfony\AI\Platform\CachedPlatform` namespace usages to `Symfony\AI\Platform\Bridge\Cache\CachePlatform`
|
||||
* The `ttl` option can be used in the configuration
|
||||
* Adopt usage of class `Symfony\AI\Platform\Serializer\StructuredOuputSerializer` to `Symfony\AI\Platform\StructuredOutput\Serializer`
|
||||
* Adopt usage of class `Symfony\AI\Platform\Serializer\StructuredOutputSerializer` to `Symfony\AI\Platform\StructuredOutput\Serializer`
|
||||
|
||||
UPGRADE FROM 0.1 to 0.2
|
||||
=======================
|
||||
@@ -285,7 +285,7 @@ Agent
|
||||
* Constructor of `MemoryInputProcessor` now accepts an iterable of inputs instead of variadic arguments.
|
||||
|
||||
```php
|
||||
use Symfony\AI\Agent\InputProcessor\MemoryInputProcessor;
|
||||
use Symfony\AI\Agent\Memory\MemoryInputProcessor;
|
||||
|
||||
// Before
|
||||
$processor = new MemoryInputProcessor($input1, $input2);
|
||||
|
||||
@@ -798,7 +798,7 @@ Use the :class:`Symfony\\AI\\Agent\\Agent` service to leverage models and tools:
|
||||
Message::ofUser($message),
|
||||
);
|
||||
|
||||
return $this->agent->call($messages)->asText();
|
||||
return $this->agent->call($messages)->getContent();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -943,7 +943,7 @@ The token usage information can be accessed from the result metadata::
|
||||
use Symfony\AI\Agent\AgentInterface;
|
||||
use Symfony\AI\Platform\Message\Message;
|
||||
use Symfony\AI\Platform\Message\MessageBag;
|
||||
use Symfony\AI\Platform\Result\Metadata\TokenUsage\TokenUsage;
|
||||
use Symfony\AI\Platform\TokenUsage\TokenUsage;
|
||||
|
||||
final readonly class MyService
|
||||
{
|
||||
|
||||
@@ -16,10 +16,9 @@ Basic Usage
|
||||
-----------
|
||||
|
||||
To instantiate an agent, you need to pass a :class:`Symfony\\AI\\Platform\\PlatformInterface` and a
|
||||
:class:`Symfony\\AI\\Platform\\Model` instance to the :class:`Symfony\\AI\\Agent\\Agent` class::
|
||||
model name to the :class:`Symfony\\AI\\Agent\\Agent` class::
|
||||
|
||||
use Symfony\AI\Agent\Agent;
|
||||
use Symfony\AI\Platform\Bridge\OpenAi\Gpt;
|
||||
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory;
|
||||
|
||||
$platform = PlatformFactory::create($apiKey);
|
||||
@@ -27,7 +26,7 @@ To instantiate an agent, you need to pass a :class:`Symfony\\AI\\Platform\\Platf
|
||||
|
||||
$agent = new Agent($platform, $model);
|
||||
|
||||
You can then run the agent with a :class:`Symfony\\AI\\Platform\\Message\\MessageBagInterface` instance as input and an optional
|
||||
You can then run the agent with a :class:`Symfony\\AI\\Platform\\Message\\MessageBag` instance as input and an optional
|
||||
array of options::
|
||||
|
||||
use Symfony\AI\Agent\Agent;
|
||||
@@ -780,7 +779,7 @@ Code Examples
|
||||
.. _`Anthropic Toolbox Example`: https://github.com/symfony/ai/blob/main/examples/anthropic/toolcall.php
|
||||
.. _`Brave Tool`: https://github.com/symfony/ai/blob/main/examples/toolbox/brave.php
|
||||
.. _`Clock Tool`: https://github.com/symfony/ai/blob/main/examples/toolbox/clock.php
|
||||
.. _`Crawler Tool`: https://github.com/symfony/ai/blob/main/examples/toolbox/brave.php
|
||||
.. _`Crawler Tool`: https://github.com/symfony/ai/blob/main/examples/toolbox/firecrawl-crawl.php
|
||||
.. _`Mapbox Geocode Tool`: https://github.com/symfony/ai/blob/main/examples/toolbox/mapbox-geocode.php
|
||||
.. _`Mapbox Reverse Geocode Tool`: https://github.com/symfony/ai/blob/main/examples/toolbox/mapbox-reverse-geocode.php
|
||||
.. _`SerpAPI Tool`: https://github.com/symfony/ai/blob/main/examples/toolbox/serpapi.php
|
||||
|
||||
@@ -20,7 +20,6 @@ with a ``Symfony\AI\Agent\AgentInterface`` and a ``Symfony\AI\Chat\MessageStoreI
|
||||
use Symfony\AI\Agent\Agent;
|
||||
use Symfony\AI\Chat\Chat;
|
||||
use Symfony\AI\Chat\InMemory\Store as InMemoryStore;
|
||||
use Symfony\AI\Platform\Bridge\OpenAi\Gpt;
|
||||
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory;
|
||||
use Symfony\AI\Platform\Message\Message;
|
||||
|
||||
|
||||
@@ -28,8 +28,6 @@ OpenAI, Anthropic, Google, Replicate, and others.
|
||||
|
||||
For example, to use the OpenAI provider, you would typically do something like this::
|
||||
|
||||
use Symfony\AI\Platform\Bridge\OpenAi\Embeddings;
|
||||
use Symfony\AI\Platform\Bridge\OpenAi\Gpt;
|
||||
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory;
|
||||
|
||||
$platform = PlatformFactory::create(env('OPENAI_API_KEY'));
|
||||
@@ -37,7 +35,7 @@ For example, to use the OpenAI provider, you would typically do something like t
|
||||
With this :class:`Symfony\\AI\\Platform\\PlatformInterface` instance you can now interact with the LLM::
|
||||
|
||||
// Generate a vector embedding for a text, returns a Symfony\AI\Platform\Result\VectorResult
|
||||
$vectorResult = $platform->invoke($embeddings, 'What is the capital of France?');
|
||||
$vectorResult = $platform->invoke('text-embedding-3-small', 'What is the capital of France?');
|
||||
|
||||
// Generate a text completion with GPT, returns a Symfony\AI\Platform\Result\TextResult
|
||||
$result = $platform->invoke('gpt-4o-mini', new MessageBag(Message::ofUser('What is the capital of France?')));
|
||||
@@ -81,30 +79,18 @@ Custom models
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
For providers like Ollama, you can use custom models (built on top of ``Modelfile``), as those models are not listed in
|
||||
the default catalog, you can use the built-in ``OllamaApiCatalog`` to query the model information from the API rather
|
||||
than the default catalog::
|
||||
the default catalog. The ``ModelCatalog`` automatically queries the model information from the Ollama API::
|
||||
|
||||
use Symfony\AI\Platform\Bridge\Ollama\OllamaApiCatalog;
|
||||
use Symfony\AI\Platform\Bridge\Ollama\PlatformFactory;
|
||||
use Symfony\AI\Platform\Message\Message;
|
||||
use Symfony\AI\Platform\Message\MessageBag;
|
||||
|
||||
$platform = PlatformFactory::create('http://127.0.0.1:11434', HttpClient::create(), new OllamaApiCatalog(
|
||||
'http://127.0.0.1:11434',
|
||||
HttpClient::create(),
|
||||
));
|
||||
$platform = PlatformFactory::create('http://127.0.0.1:11434');
|
||||
|
||||
$platform->invoke('your_custom_model_name', new MessageBag(
|
||||
Message::ofUser(...)
|
||||
));
|
||||
|
||||
When using the bundle, the usage of ``OllamaApiCatalog`` is available via the ``api_catalog`` option::
|
||||
|
||||
ai:
|
||||
platform:
|
||||
ollama:
|
||||
api_catalog: true
|
||||
|
||||
Supported Models & Platforms
|
||||
----------------------------
|
||||
|
||||
@@ -131,7 +117,7 @@ Supported Models & Platforms
|
||||
* `OpenAI's Whisper`_ with `OpenAI`_ and `Azure`_ as Platform
|
||||
* `LM Studio Catalog`_ and `HuggingFace`_ Models with `LM Studio`_ as Platform.
|
||||
* All models provided by `HuggingFace`_ can be listed with a command in the examples folder,
|
||||
and also filtered, e.g. ``php examples/huggingface/_model-listing.php --provider=hf-inference --task=object-detection``
|
||||
and also filtered, e.g. ``php examples/huggingface/_model.php --provider=hf-inference --task=object-detection``
|
||||
* **Voice Models**
|
||||
* `ElevenLabs TTS`_ with `ElevenLabs`_ as Platform
|
||||
* `ElevenLabs STT`_ with `ElevenLabs`_ as Platform
|
||||
@@ -556,7 +542,7 @@ Embeddings
|
||||
|
||||
Creating embeddings of word, sentences, or paragraphs is a typical use case around the interaction with LLMs.
|
||||
|
||||
The standalone usage results in a :class:`Symfony\\AI\\Store\\Vector` instance::
|
||||
The standalone usage results in a :class:`Symfony\\AI\\Platform\\Vector\\Vector` instance::
|
||||
|
||||
use Symfony\AI\Platform\Bridge\OpenAi\Embeddings;
|
||||
|
||||
@@ -677,7 +663,7 @@ Cached Platform Calls
|
||||
Thanks to Symfony's Cache component, platform calls can be cached to reduce calls and resources consumption::
|
||||
|
||||
use Symfony\AI\Agent\Agent;
|
||||
use Symfony\AI\Platform\Bridge\Cache\CachedPlatform;
|
||||
use Symfony\AI\Platform\Bridge\Cache\CachePlatform;
|
||||
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory;
|
||||
use Symfony\AI\Platform\Message\Message;
|
||||
use Symfony\AI\Platform\Message\MessageBag;
|
||||
@@ -686,13 +672,13 @@ Thanks to Symfony's Cache component, platform calls can be cached to reduce call
|
||||
use Symfony\Component\HttpClient\HttpClient;
|
||||
|
||||
$platform = PlatformFactory::create($apiKey, HttpClient::create());
|
||||
$cachedPlatform = new CachedPlatform($platform, cache: new TagAwareAdapter(new ArrayAdapter()));
|
||||
$cachePlatform = new CachePlatform($platform, cache: new TagAwareAdapter(new ArrayAdapter()));
|
||||
|
||||
$firstResult = $cachedPlatform->invoke('gpt-4o-mini', new MessageBag(Message::ofUser('What is the capital of France?')));
|
||||
$firstResult = $cachePlatform->invoke('gpt-4o-mini', new MessageBag(Message::ofUser('What is the capital of France?')));
|
||||
|
||||
echo $firstResult->getContent().\PHP_EOL;
|
||||
|
||||
$secondResult = $cachedPlatform->invoke('gpt-4o-mini', new MessageBag(Message::ofUser('What is the capital of France?')));
|
||||
$secondResult = $cachePlatform->invoke('gpt-4o-mini', new MessageBag(Message::ofUser('What is the capital of France?')));
|
||||
|
||||
echo $secondResult->getContent().\PHP_EOL;
|
||||
|
||||
|
||||
@@ -46,7 +46,6 @@ Configure your Google Cloud project and location:
|
||||
|
||||
Basic usage example::
|
||||
|
||||
use Symfony\AI\Platform\Bridge\VertexAi\Gemini\Model;
|
||||
use Symfony\AI\Platform\Bridge\VertexAi\PlatformFactory;
|
||||
use Symfony\AI\Platform\Message\Message;
|
||||
use Symfony\AI\Platform\Message\MessageBag;
|
||||
|
||||
@@ -22,15 +22,18 @@ for documents.
|
||||
Indexing
|
||||
--------
|
||||
|
||||
One higher level feature is the :class:`Symfony\\AI\\Store\\Indexer`. The purpose of this service is to populate a store with documents.
|
||||
One higher level feature is the :class:`Symfony\\AI\\Store\\Indexer\\DocumentIndexer`. The purpose of this service is to populate a store with documents.
|
||||
Therefore it accepts one or multiple :class:`Symfony\\AI\\Store\\Document\\TextDocument` objects, converts them into embeddings and stores them in the
|
||||
used vector store::
|
||||
|
||||
use Symfony\AI\Store\Document\TextDocument;
|
||||
use Symfony\AI\Store\Indexer;
|
||||
use Symfony\AI\Store\Document\Vectorizer;
|
||||
use Symfony\AI\Store\Indexer\DocumentIndexer;
|
||||
use Symfony\AI\Store\Indexer\DocumentProcessor;
|
||||
|
||||
$indexer = new Indexer($platform, $model, $store);
|
||||
$document = new TextDocument('This is a sample document.');
|
||||
$vectorizer = new Vectorizer($platform, $model);
|
||||
$indexer = new DocumentIndexer(new DocumentProcessor($vectorizer, $store));
|
||||
$document = new TextDocument('id-1', 'This is a sample document.');
|
||||
$indexer->index($document);
|
||||
|
||||
You can find more advanced usage in combination with an Agent using the store for RAG in the examples folder.
|
||||
|
||||
@@ -14,10 +14,11 @@ InMemoryStore
|
||||
Stores vectors in a PHP array. Data is not persisted and is lost when the PHP process ends::
|
||||
|
||||
use Symfony\AI\Store\InMemory\Store;
|
||||
use Symfony\AI\Store\Query\VectorQuery;
|
||||
|
||||
$store = new Store();
|
||||
$store->add([$document1, $document2]);
|
||||
$results = $store->query($vector);
|
||||
$results = $store->query(new VectorQuery($vector));
|
||||
|
||||
CacheStore
|
||||
----------
|
||||
@@ -30,7 +31,7 @@ Stores vectors using a PSR-6 cache implementation. Persistence depends on the ca
|
||||
$cache = new FilesystemAdapter();
|
||||
$store = new Store($cache);
|
||||
$store->add([$document1, $document2]);
|
||||
$results = $store->query($vector);
|
||||
$results = $store->query(new VectorQuery($vector));
|
||||
|
||||
Distance Strategies
|
||||
-------------------
|
||||
@@ -70,7 +71,7 @@ candidates are kept, reducing peak memory from O(N) to O(maxItems + batchSize)::
|
||||
$store = new Store($calculator);
|
||||
|
||||
// Batch processing is activated when both batchSize and maxItems are set
|
||||
$results = $store->query($vector, [
|
||||
$results = $store->query($vectorQuery, [
|
||||
'maxItems' => 10,
|
||||
]);
|
||||
|
||||
@@ -87,34 +88,34 @@ Both stores support filtering search results based on document metadata using a
|
||||
|
||||
use Symfony\AI\Store\Document\VectorDocument;
|
||||
|
||||
$results = $store->query($vector, [
|
||||
'filter' => fn(VectorDocument $doc) => $doc->metadata['category'] === 'products',
|
||||
$results = $store->query($vectorQuery, [
|
||||
'filter' => fn(VectorDocument $doc) => $doc->getMetadata()['category'] === 'products',
|
||||
]);
|
||||
|
||||
You can combine multiple conditions::
|
||||
|
||||
$results = $store->query($vector, [
|
||||
$results = $store->query($vectorQuery, [
|
||||
'filter' => fn(VectorDocument $doc) =>
|
||||
$doc->metadata['price'] <= 100
|
||||
&& $doc->metadata['stock'] > 0
|
||||
&& $doc->metadata['enabled'] === true,
|
||||
$doc->getMetadata()['price'] <= 100
|
||||
&& $doc->getMetadata()['stock'] > 0
|
||||
&& $doc->getMetadata()['enabled'] === true,
|
||||
'maxItems' => 10,
|
||||
]);
|
||||
|
||||
Filter nested metadata::
|
||||
|
||||
$results = $store->query($vector, [
|
||||
$results = $store->query($vectorQuery, [
|
||||
'filter' => fn(VectorDocument $doc) =>
|
||||
$doc->metadata['options']['size'] === 'S'
|
||||
&& $doc->metadata['options']['color'] === 'blue',
|
||||
$doc->getMetadata()['options']['size'] === 'S'
|
||||
&& $doc->getMetadata()['options']['color'] === 'blue',
|
||||
]);
|
||||
|
||||
Use array functions for complex filtering::
|
||||
|
||||
$allowedBrands = ['Nike', 'Adidas', 'Puma'];
|
||||
$results = $store->query($vector, [
|
||||
$results = $store->query($vectorQuery, [
|
||||
'filter' => fn(VectorDocument $doc) =>
|
||||
\in_array($doc->metadata['brand'] ?? '', $allowedBrands, true),
|
||||
\in_array($doc->getMetadata()['brand'] ?? '', $allowedBrands, true),
|
||||
]);
|
||||
|
||||
.. note::
|
||||
@@ -131,7 +132,7 @@ Both stores support the following query options:
|
||||
|
||||
Example combining both options::
|
||||
|
||||
$results = $store->query($vector, [
|
||||
$results = $store->query($vectorQuery, [
|
||||
'maxItems' => 5,
|
||||
'filter' => fn(VectorDocument $doc) => $doc->metadata['active'] === true,
|
||||
'filter' => fn(VectorDocument $doc) => $doc->getMetadata()['active'] === true,
|
||||
]);
|
||||
|
||||
@@ -81,9 +81,10 @@ Query Similar Vectors
|
||||
::
|
||||
|
||||
use Symfony\AI\Platform\Vector\Vector;
|
||||
use Symfony\AI\Store\Query\VectorQuery;
|
||||
|
||||
$results = $store->query(
|
||||
vector: new Vector([0.1, 0.2, 0.3, ...]),
|
||||
query: new VectorQuery(new Vector([0.1, 0.2, 0.3, ...])),
|
||||
options: [
|
||||
'topK' => 5,
|
||||
'filter' => ['category' => 'documentation'],
|
||||
@@ -91,7 +92,7 @@ Query Similar Vectors
|
||||
);
|
||||
|
||||
foreach ($results as $result) {
|
||||
echo $result->metadata['title'] . ' (score: ' . $result->score . ')' . PHP_EOL;
|
||||
echo $result->getMetadata()['title'] . ' (score: ' . $result->getScore() . ')' . PHP_EOL;
|
||||
}
|
||||
|
||||
Remove Documents
|
||||
|
||||
@@ -94,7 +94,7 @@ The SQLite store supports filtering search results based on document metadata us
|
||||
use Symfony\AI\Store\Document\VectorDocument;
|
||||
|
||||
$results = $store->query($vectorQuery, [
|
||||
'filter' => fn(VectorDocument $doc) => $doc->metadata['category'] === 'products',
|
||||
'filter' => fn(VectorDocument $doc) => $doc->getMetadata()['category'] === 'products',
|
||||
]);
|
||||
|
||||
Query Options
|
||||
@@ -109,5 +109,5 @@ Example combining both options::
|
||||
|
||||
$results = $store->query($vectorQuery, [
|
||||
'maxItems' => 5,
|
||||
'filter' => fn(VectorDocument $doc) => $doc->metadata['active'] === true,
|
||||
'filter' => fn(VectorDocument $doc) => $doc->getMetadata()['active'] === true,
|
||||
]);
|
||||
|
||||
@@ -152,15 +152,17 @@ Querying Documents
|
||||
|
||||
$queryVector = new Vector([0.1, 0.2, 0.3, /* ... 768 dimensions */]);
|
||||
|
||||
$results = $store->query($queryVector, [
|
||||
use Symfony\AI\Store\Query\VectorQuery;
|
||||
|
||||
$results = $store->query(new VectorQuery($queryVector), [
|
||||
'max_items' => 10,
|
||||
'min_score' => 0.7
|
||||
]);
|
||||
|
||||
foreach ($results as $document) {
|
||||
echo "ID: " . $document->id . "\n";
|
||||
echo "Score: " . $document->score . "\n";
|
||||
echo "Metadata: " . json_encode($document->metadata->getArrayCopy()) . "\n";
|
||||
echo "ID: " . $document->getId() . "\n";
|
||||
echo "Score: " . $document->getScore() . "\n";
|
||||
echo "Metadata: " . json_encode($document->getMetadata()->getArrayCopy()) . "\n";
|
||||
}
|
||||
|
||||
Customization
|
||||
|
||||
@@ -168,13 +168,11 @@ Vector Store Selection
|
||||
|
||||
For production environments, use persistent vector stores like ChromaDB::
|
||||
|
||||
use Codewithkyrian\ChromaDB\ChromaDB;
|
||||
use Symfony\AI\Store\Bridge\ChromaDb\Store;
|
||||
|
||||
$store = new Store(
|
||||
$httpClient,
|
||||
'http://localhost:8000',
|
||||
'my_collection'
|
||||
);
|
||||
$client = ChromaDB::factory()->connect();
|
||||
$store = new Store($client, 'my_collection');
|
||||
|
||||
ChromaDB is a great choice for production RAG systems as it provides:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user