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

Prérequis

  • Python 3.12+
  • Docker (pour exécuter Vespa localement)
  • Une clé API Mistral AI depuis console.mistral.ai
Installation

Installation

Installez Search Toolkit avec le module Vespa à l’aide de uv :

uv add "mistralai-search-toolkit[vespa]"
Configurer 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/vespa

Attendez que Vespa soit opérationnelle :

curl --retry 10 --retry-delay 3 --retry-all-errors \
  http://localhost:19071/state/v1/health

Définissez votre clé API Mistral :

export MISTRAL_API_KEY=your-api-key
Définir votre schéma

Dé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_schema

Remplissez 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"),
            ],
        )
i
Information

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é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 8080

Cela 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

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 :

  1. FilesystemFileLoader lit les octets bruts des fichiers depuis le disque.
  2. PlainTextExtractor extrait le contenu texte du fichier. Pour les PDF, utilisez MistralOCRExtractor à la place.
  3. CharacterTextSplitter divise le texte en fragments de 500 caractères.
  4. MistralEmbedder génère une incorporation vectorielle pour chaque fragment.
  5. vector_store (Vespa) indexe chaque fragment en stockant l’incorporation pour la recherche vectorielle.

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

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,
)