Guide de démarrage
Construisez un pipeline RAG en 5 minutes : importez des documents dans un dépôt vectoriel, puis interrogez-les.
Prérequis
- Python 3.12+
- Docker (pour exécuter Vespa localement)
- Une clé API Mistral AI depuis console.mistral.ai
Installation
Installez Search Toolkit avec le module Vespa à l’aide de uv :
uv add "mistralai-search-toolkit[vespa]"Configurer Vespa
Lancez une instance Vespa locale avec Docker :
docker run --detach \
--name vespa \
--hostname vespa-container \
--publish 8080:8080 \
--publish 19071:19071 \
vespaengine/vespaAttendez que Vespa soit opérationnelle :
curl --retry 10 --retry-delay 3 --retry-all-errors \
http://localhost:19071/state/v1/healthDéfinissez votre clé API Mistral :
export MISTRAL_API_KEY=your-api-keyDéfinir votre schéma
Créez une migration pour décrire la structure de vos documents :
mistral-vespa generate-migration \
--app-dir ./vespa/migrations \
initial_schemaRemplissez le fichier généré :
from mistralai.search.toolkit.plugins.vespa.app.schemas.app import FieldDefinition, IndexingMode, SearchMode
from mistralai.search.toolkit.plugins.vespa.migration import VespaMigration, create_schema, set_app_name
class InitialSchema(VespaMigration):
def migrate(self) -> None:
set_app_name("myquickstart")
create_schema(
name="quickstart_collection",
mode=SearchMode.INDEX,
embedding_dimensions=1024,
indexing_mode=IndexingMode.DOCUMENT_PER_CHUNK,
# The standard chunk fields (content, embedding, identity, metadata) are
# added automatically. `fields` only declares your extra fields.
fields=[
FieldDefinition.TextField(name="title"),
],
)Restrictions pour le nom de l’application : le nom passé à set_app_name() doit contenir uniquement des lettres minuscules (a-z). Les chiffres, traits de soulignement, traits d’union et autres caractères spéciaux ne sont pas autorisés.
Pour plus de détails sur la gestion et le déploiement des applications Vespa, consultez Gérer et déployer des applications Vespa.
Déployer à partir des migrations
Déployez le schéma vers votre instance Vespa locale :
mistral-vespa migrate \
--app-dir ./vespa/migrations \
--config-server http://localhost:19071 \
--query-port 8080Cela génère le package de l’application à partir de vos migrations en mémoire, le déploie, puis attend que l’application soit prête.
Importer des documents
Créez un pipeline qui charge des fichiers, extrait le texte, le divise en fragments, génère des incorporations et indexe dans Vespa :
import asyncio
from pathlib import Path
from mistralai.client import Mistral
from mistralai.search.toolkit.embedders import MistralEmbedder
from mistralai.search.toolkit.ingestion.extractors import PlainTextExtractor
from mistralai.search.toolkit.ingestion.loaders import FilesystemFileLoader
from mistralai.search.toolkit.ingestion.pipelines import Pipeline
from mistralai.search.toolkit.ingestion.text_splitters import CharacterTextSplitter
from mistralai.search.toolkit.plugins.vespa import VespaClientConfig
from vespa_app import app
async def main():
mistral_client = Mistral(api_key="your-api-key")
# Configure Vespa
config = VespaClientConfig(
endpoint="http://localhost:8080",
)
vector_store = app.get_search_index(config, collection_name="quickstart_collection")
# Create the pipeline
pipeline = Pipeline(
loader=FilesystemFileLoader(),
extractor=PlainTextExtractor(),
text_splitter=CharacterTextSplitter(chunk_size=500),
embedder=MistralEmbedder(client=mistral_client, model_name="mistral-embed"),
stores=vector_store,
)
# Ingest documents
await pipeline.run(documents=[Path("doc1.txt"), Path("doc2.txt")])
print("Documents ingested!")
asyncio.run(main())Le pipeline enchaîne cinq étapes :
FilesystemFileLoaderlit les octets bruts des fichiers depuis le disque.PlainTextExtractorextrait le contenu texte du fichier. Pour les PDF, utilisezMistralOCRExtractorà la place.CharacterTextSplitterdivise le texte en fragments de 500 caractères.MistralEmbeddergénère une incorporation vectorielle pour chaque fragment.vector_store(Vespa) indexe chaque fragment en stockant l’incorporation pour la recherche vectorielle.
Rechercher
Interrogez les documents indexés à l’aide de la recherche vectorielle :
import asyncio
from mistralai.client import Mistral
from mistralai.search.toolkit.embedders import MistralEmbedder
from mistralai.search.toolkit.plugins.vespa import VespaClientConfig
from mistralai.search.toolkit.retrieval import QueryEngine
from mistralai.search.toolkit.retrieval.retrievers import VectorRetriever
from vespa_app import app
async def main():
mistral_client = Mistral(api_key="your-api-key")
embedder = MistralEmbedder(client=mistral_client, model_name="mistral-embed")
# Configure Vespa for search
config = VespaClientConfig(
endpoint="http://localhost:8080",
)
vector_store = app.get_search_index(config, collection_name="quickstart_collection")
# Build query engine
query_engine = QueryEngine(
retriever=[VectorRetriever(client=vector_store, embedder=embedder)],
)
# Search
result = await query_engine.search(
query="What is RAG?",
top_k=5,
include_metadata=True,
include_content=True,
)
for i, r in enumerate(result.results, 1):
print(f"{i}. [Score: {r.score:.3f}] {r.chunk.content[:200]}...")
asyncio.run(main())Importer des PDF avec OCR
Pour les documents PDF, remplacez PlainTextExtractor par MistralOCRExtractor et utilisez MarkdownTextSplitter pour une division en fragments respectant la structure :
from mistralai.search.toolkit.ingestion.extractors import MistralOCRExtractor
from mistralai.search.toolkit.ingestion.text_splitters import (
MarkdownTextSplitter,
MarkdownTextSplitterConfig,
)
pipeline = Pipeline(
loader=FilesystemFileLoader(),
extractor=MistralOCRExtractor(client=mistral_client),
text_splitter=MarkdownTextSplitter(
MarkdownTextSplitterConfig(chunk_size=5048, chunk_overlap=50)
),
embedder=MistralEmbedder(client=mistral_client),
stores=vector_store,
)