Articles de blog

​​Construire un flux de travail RAG en utilisant LangGraph et Elasticsearch

Apprenez à configurer et à personnaliser un modèle d'agent de récupération LangGraph avec Elasticsearch afin de créer un flux de travail RAG pour une récupération efficace des données et des réponses basées sur l'IA.

Le modèle d'agent de recherche LangGraph est un projet de démarrage développé par LangChain pour faciliter la création de systèmes de réponse aux questions basés sur la recherche en utilisant LangGraph dans LangGraph Studio. Ce modèle est préconfiguré pour s'intégrer de manière transparente à Elasticsearch, ce qui permet aux développeurs de créer rapidement des agents capables d'indexer et d'extraire des documents de manière efficace.

Ce blog se concentre sur l'exécution et la personnalisation du modèle d'agent de récupération LangChain en utilisant LangGraph Studio et LangGraph CLI. Le modèle fournit un cadre pour la construction d'applications de génération augmentée de recherche (RAG), en tirant parti de divers backends de recherche tels qu'Elasticsearch.

Nous vous guiderons dans la mise en place, la configuration de l'environnement et l'exécution efficace du modèle avec Elastic tout en personnalisant le flux de l'agent.

Produits requis

Avant de poursuivre, assurez-vous que les éléments suivants sont installés :

  • Déploiement d'Elasticsearch Cloud ou déploiement d'Elasticsearch sur site (ou créer un essai gratuit de 14 jours sur Elastic Cloud) - Version 8.0.0 ou supérieure

  • Python 3.9+

  • Accès à un fournisseur de LLM tel que Cohere (utilisé dans ce guide), OpenAI, ou Anthropic/Claude

Création de l'application LangGraph

1. Installer l'interface de programmation LangGraph

pip install --upgrade "langgraph-cli[inmem]"

2. Créer une application LangGraph à partir de retrieval-agent-template

mkdir lg-agent-demo
cd lg-agent-demo
langgraph new lg-agent-demo

Un menu interactif vous permettra de choisir parmi une liste de modèles disponibles. Sélectionnez 4 pour Retrieval Agent et 1 pour Python, comme indiqué ci-dessous :

Modèle de recherche interactive.
  • Dépannage: Si vous rencontrez l'erreur "urllib.error.URLError : <urlopen error [SSL : CERTIFICATE_VERIFY_FAILED] certificate verify failed : unable to get local issuer certificate (_ssl.c:1000)> "

Veuillez exécuter la commande Install Certificate de Python pour résoudre le problème, comme indiqué ci-dessous.

Exécution de la commande Python Install Certificate.

3. Installer les dépendances

À la racine de votre nouvelle application LangGraph, créez un environnement virtuel et installez les dépendances en mode edit afin que vos modifications locales soient utilisées par le serveur :

#For Mac
python3 -m venv lg-demo
source lg-demo/bin/activate 
pip install -e .

#For Windows
python3 -m venv lg-demo
lg-demo\Scripts\activate 
pip install -e .

Mise en place de l'environnement

1. Créez un environnement . fichier

Le fichier .env contient les clés API et les configurations permettant à l'application de se connecter au fournisseur de LLM et de récupération que vous avez choisi. Générer un nouveau fichier .env en dupliquant l'exemple de configuration :

cp .env.example .env

2. Configurez le fichier .env fichier

Le fichier .env est livré avec un ensemble de configurations par défaut. Vous pouvez le mettre à jour en ajoutant les clés et valeurs API nécessaires en fonction de votre configuration. Les clés qui ne sont pas pertinentes pour votre cas d'utilisation peuvent être laissées inchangées ou supprimées.

# To separate your traces from other applications
LANGSMITH_PROJECT=retrieval-agent

# LLM choice (set the API key for your selected provider):
ANTHROPIC_API_KEY=your_anthropic_api_key
FIREWORKS_API_KEY=your_fireworks_api_key
OPENAI_API_KEY=your_openai_api_key

# Retrieval provider (configure based on your chosen service):

## Elastic Cloud:
ELASTICSEARCH_URL=https://your_elastic_cloud_url
ELASTICSEARCH_API_KEY=your_elastic_api_key

## Elastic Local:
ELASTICSEARCH_URL=http://host.docker.internal:9200
ELASTICSEARCH_USER=elastic
ELASTICSEARCH_PASSWORD=changeme

## Pinecone:
PINECONE_API_KEY=your_pinecone_api_key
PINECONE_INDEX_NAME=your_pinecone_index_name

## MongoDB Atlas:
MONGODB_URI=your_mongodb_connection_string

# Cohere API key:
COHERE_API_KEY=your_cohere_api_key
  • Exemple de fichier .env (avec Elastic Cloud et Cohere)

Vous trouverez ci-dessous un exemple de configuration .env pour l'utilisation d'Elastic Cloud en tant que fournisseur d'extraction et de Cohere en tant que LLM, comme démontré dans ce blog :

# To separate your traces from other applications
LANGSMITH_PROJECT=retrieval-agent
#Retrieval Provider
# Elasticsearch configuration
ELASTICSEARCH_URL=elastic-url:443
ELASTICSEARCH_API_KEY=elastic_api_key
# Cohere API key
COHERE_API_KEY=cohere_api_key

Note : Bien que ce guide utilise Cohere pour la génération de réponses et l'intégration, vous êtes libre d'utiliser d'autres fournisseurs LLM tels que OpenAI, Claude, ou même un modèle LLM local en fonction de votre cas d'utilisation. Assurez-vous que chaque clé que vous avez l'intention d'utiliser est présente et correctement définie dans le fichier.env.

3. Mise à jour du fichier de configuration -configuration.py

Après avoir configuré votre fichier .env avec les clés API appropriées, l'étape suivante consiste à mettre à jour la configuration du modèle par défaut de votre application. La mise à jour de la configuration garantit que le système utilise les services et les modèles que vous avez spécifiés dans votre fichier .env.

Accédez au fichier de configuration :

 cd src/retrieval_graph

Le fichier configuration.py contient les paramètres du modèle par défaut utilisés par l'agent de recherche pour trois tâches principales :

  • Modèle d'intégration - convertit les documents en représentations vectorielles

  • Modèle de requête - traite la requête de l'utilisateur en un vecteur

  • Modèle de réponse - génère la réponse finale

Par défaut, le code utilise les modèles d'OpenAI (par exemple, openai/text-embedding-3-small) et d'Anthropic (par exemple, anthropic/claude-3-5-sonnet-20240620 and anthropic/claude-3-haiku-20240307). Dans ce blog, nous passerons à l'utilisation des modèles Cohere. Si vous utilisez déjà OpenAI ou Anthropic, aucun changement n'est nécessaire.

Exemple de modifications (en utilisant Cohere) :

Ouvrez configuration.py et modifiez les valeurs par défaut du modèle comme indiqué ci-dessous :

…
 embedding_model: Annotated[
       str,
       {"__template_metadata__": {"kind": "embeddings"}},
   ] = field(
       default="cohere/embed-english-v3.0",
…
response_model: Annotated[str, {"__template_metadata__": {"kind": "llm"}}] = field(
       default="cohere/command-r-08-2024",
…
query_model: Annotated[str, {"__template_metadata__": {"kind": "llm"}}] = field(
       default="cohere/command-r-08-2024",
       metadata={

Exécution de l'agent de recherche avec LangGraph CLI

1. Lancer le serveur LangGraph

cd lg-agent-demo
langgraph dev

Cette opération permet de démarrer localement le serveur LangGraph API. Si l'opération se déroule correctement, vous devriez voir apparaître quelque chose comme :

 Le serveur LangGraph API fonctionne correctement.

URL de l'interface utilisateur d'Open Studio.

Deux graphiques sont disponibles :

  • Graphique de récupération: Récupère les données d'Elasticsearch et répond à la requête à l'aide d'un LLM.

  • Graphique d'indexation: Indexe les documents dans Elasticsearch et génère des embeddings à l'aide d'un LLM.

2. Configuration du graphe de l'indexeur

  • Ouvrez le graphique de l'indexeur.

  • Cliquez sur gérer les assistants.

    • Cliquez sur "Ajouter un nouvel assistant", entrez les détails de l'utilisateur comme spécifié, puis fermez la fenêtre.

{"user_id": "101"}

3. Indexation de documents types

  • Indexez les documents types suivants, qui représentent un rapport trimestriel hypothétique pour l'organisation NoveTech :

[
  {    "page_content": "NoveTech Solutions Q1 2025 Report - Revenue: $120.5M, Net Profit: $18.2M, EPS: $2.15. Strong AI software launch and $50M government contract secured."
  },
  {
    "page_content": "NoveTech Solutions Business Highlights - AI-driven analytics software gained 15% market share. Expansion into Southeast Asia with two new offices. Cloud security contract secured."
  },
  {
    "page_content": "NoveTech Solutions Financial Overview - Operating expenses at $85.3M, Gross Margin 29.3%. Stock price rose from $72.5 to $78.3. Market Cap reached $5.2B."
  },
  {
    "page_content": "NoveTech Solutions Challenges - Rising supply chain costs impacting hardware production. Regulatory delays slowing European expansion. Competitive pressure in cybersecurity sector."
  },
  {
    "page_content": "NoveTech Solutions Future Outlook - Expected revenue for Q2 2025: $135M. New AI chatbot and blockchain security platform launch planned. Expansion into Latin America."
  },
  {
    "page_content": "NoveTech Solutions Market Performance - Year-over-Year growth at 12.7%. Stock price increase reflects investor confidence. Cybersecurity and AI sectors remain competitive."
  },
  {
    "page_content": "NoveTech Solutions Strategic Moves - Investing in R&D to enhance AI-driven automation. Strengthening partnerships with enterprise cloud providers. Focusing on data privacy solutions."
  },
  {
    "page_content": "NoveTech Solutions CEO Statement - 'NoveTech Solutions continues to innovate in AI and cybersecurity. Our growth strategy remains strong, and we foresee steady expansion in the coming quarters.'"
  }
]

Une fois les documents indexés, un message de suppression apparaît dans le fil de discussion, comme indiqué ci-dessous.

LangGraph et Elasticsearch Indexation des documents de flux de travail RAG.

4. Exécution du graphe de recherche

  • Passez au graphique de recherche.

  • Saisissez la requête de recherche suivante :

What was NovaTech Solutions total revenue in Q1 2025?
Exécution du graphe de recherche LangGraph et Elasticsearch

Le système renvoie les documents pertinents et fournit une réponse exacte sur la base des données indexées.

Personnaliser l'agent de recherche

Pour améliorer l'expérience de l'utilisateur, nous introduisons une étape de personnalisation dans le graphe de recherche afin de prédire les trois prochaines questions que l'utilisateur pourrait poser. Cette prédiction est basée sur :

  • Contexte des documents extraits

  • Interactions avec les utilisateurs précédents

  • Dernière requête de l'utilisateur

Les modifications de code suivantes sont nécessaires pour mettre en œuvre la fonction de prédiction des requêtes :

1. Mettez à jour graph.py

  • Ajouter la fonction predict_query:

async def predict_query(
   state: State, *, config: RunnableConfig
) -> dict[str, list[BaseMessage]]:
   logger.info(f"predict_query predict_querypredict_query predict_query predict_query predict_query")  # Log the query

   configuration = Configuration.from_runnable_config(config)
   prompt = ChatPromptTemplate.from_messages(
       [
           ("system", configuration.predict_next_question_prompt),
           ("placeholder", "{messages}"),
       ]
   )
   model = load_chat_model(configuration.response_model)
   user_query = state.queries[-1] if state.queries else "No prior query available"
   logger.info(f"user_query: {user_query}")
   logger.info(f"statemessage: {state.messages}")
   #human_messages = [msg for msg in state.message if isinstance(msg, HumanMessage)]

   message_value = await prompt.ainvoke(
       {
           "messages": state.messages,
           "user_query": user_query,  # Use the most recent query as primary input
           "system_time": datetime.now(tz=timezone.utc).isoformat(),
       },
       config,
   )

   next_question = await model.ainvoke(message_value, config)
   return {"next_question": [next_question]}
  • Modifier la fonction respond pour qu'elle renvoie l'objet response au lieu du message :

async def respond(
   state: State, *, config: RunnableConfig
) -> dict[str, list[BaseMessage]]:
   """Call the LLM powering our "agent"."""
   configuration = Configuration.from_runnable_config(config)
   # Feel free to customize the prompt, model, and other logic!
   prompt = ChatPromptTemplate.from_messages(
       [
           ("system", configuration.response_system_prompt),
           ("placeholder", "{messages}"),
       ]
   )
   model = load_chat_model(configuration.response_model)

   retrieved_docs = format_docs(state.retrieved_docs)
   message_value = await prompt.ainvoke(
       {
           "messages": state.messages,
           "retrieved_docs": retrieved_docs,
           "system_time": datetime.now(tz=timezone.utc).isoformat(),
       },
       config,
   )
   response = await model.ainvoke(message_value, config)
   # We return a list, because this will get added to the existing list
   return {"response": [response]}
  • Mise à jour de la structure du graphe afin d'ajouter un nouveau nœud et une nouvelle arête pour predict_query :

builder.add_node(generate_query)
builder.add_node(retrieve)
builder.add_node(respond)
builder.add_node(predict_query)
builder.add_edge("__start__", "generate_query")
builder.add_edge("generate_query", "retrieve")
builder.add_edge("retrieve", "respond")
builder.add_edge("respond", "predict_query")

2. Mettez à jour prompts.py

  • Demande de devis pour la prédiction de guery dans prompts.py:

PREDICT_NEXT_QUESTION_PROMPT = """Given the user query and the retrieved documents, suggest the most likely next question the user might ask.

**Context:**
- Previous Queries:
{previous_queries}

- Latest User Query: {user_query}

- Retrieved Documents:
{retrieved_docs}

**Guidelines:**
1. Do not suggest a question that has already been asked in previous queries.
2. Consider the retrieved documents when predicting the next logical question.
3. If the user's query is already fully answered, suggest a relevant follow-up question.
4. Keep the suggested question natural and conversational.
5. Suggest at least 3 question

System time: {system_time}"""

3. Mettez à jour configuration.py

  • Ajouter predict_next_question_prompt:

predict_next_question_prompt: str = field(
       default=prompts.PREDICT_NEXT_QUESTION_PROMPT,
       metadata={"description": "The system prompt used for generating responses."},
   )

4. Mettez à jour state.py

  • Ajouter les attributs suivants :

response: Annotated[Sequence[AnyMessage], add_messages]
next_question : Annotated[Sequence[AnyMessage], add_messages]

5. Réexécutez le graphique de recherche

  • Saisissez à nouveau la requête de recherche suivante :

What was NovaTech Solutions total revenue in Q1 2025?

Le système traitera les données et prévoira trois questions connexes que les utilisateurs pourraient poser, comme indiqué ci-dessous.

Exécution du graphe de recherche avec 3 questions d'utilisateurs à l'aide de LangGraph et Elasticsearch

Conclusion

L'intégration du modèle Retrieval Agent dans LangGraph Studio et CLI offre plusieurs avantages :

  • Développement accéléré: Les modèles et les outils de visualisation rationalisent la création et le débogage des flux de recherche, réduisant ainsi le temps de développement.

  • Déploiement transparent: La prise en charge intégrée des API et de la mise à l'échelle automatique garantit un déploiement sans heurts dans tous les environnements.

  • Des mises à jour faciles : La modification des flux de travail, l'ajout de nouvelles fonctionnalités et l'intégration de nœuds supplémentaires sont simples, ce qui facilite l'évolution et l'amélioration du processus de recherche.

  • Mémoire persistante: Le système conserve les états et les connaissances des agents, ce qui améliore la cohérence et la fiabilité.

  • Modélisation flexible des flux de travail: Les développeurs peuvent personnaliser la logique de recherche et les règles de communication pour des cas d'utilisation spécifiques.

  • Interaction et débogage en temps réel: La possibilité d'interagir avec les agents en cours d'exécution permet de tester et de résoudre les problèmes de manière efficace.

En tirant parti de ces fonctionnalités, les organisations peuvent construire des systèmes de recherche puissants, efficaces et évolutifs qui améliorent l'accessibilité des données et l'expérience de l'utilisateur.

Le code source complet de ce projet est disponible sur GitHub.

Questions fréquentes

Qu'est-ce qu'un flux de travail RAG ?

Un flux de travail RAG (Retrieval-Augmented Generation) est un moyen de donner à un modèle d'IA l'accès à vos données privées afin qu'il puisse fournir des réponses précises et basées sur des faits au lieu de "halluciner."

Pourquoi utiliser Elasticsearch comme base de données pour un agent LangGraph ?

Elasticsearch fait office de mémoire à long terme "" pour l'agent. Contrairement à une base de données standard, elle est conçue pour la recherche hybride, qui combine la recherche vectorielle (compréhension du sens) et la recherche par mot-clé (recherche de termes exacts). Ainsi, que vous demandiez "Q1 revenue" ou "financial growth," Elasticsearch fournit les documents les plus pertinents à traiter par LangGraph.

Puis-je construire un système multi-utilisateurs avec le modèle d'agent de recherche LangGraph ?

Oui. L'article démontre ceci à travers la configuration du graphe de l'indexeur en utilisant un identifiant d'utilisateur (comme "101"). Cela vous permet de marquer les documents avec des propriétaires spécifiques, ce qui permet à l'agent de recherche de trouver uniquement les informations qu'un utilisateur spécifique est autorisé à voir.

Pour aller plus loin

Techniques avancées de RAG, partie 2 : Requêtes et tests

Han Xiang Choong

Résolution d'entités avec Elasticsearch, partie 4 : le défi ultime

Jessica Moszkowicz

Automatisation de l'analyse des logs dans Streams avec le ML

Nastia Havriushenko

Construire un agent d'IA pour les RH avec Elastic Agent Builder et GPT-OSS

Tomás Murúa

Techniques avancées de RAG partie 1 : Traitement des données

Han Xiang Choong

Prêt à créer des expériences de recherche d'exception ?

Une recherche suffisamment avancée ne se fait pas avec les efforts d'une seule personne. Elasticsearch est alimenté par des data scientists, des ML ops, des ingénieurs et bien d'autres qui sont tout aussi passionnés par la recherche que vous. Mettons-nous en relation et travaillons ensemble pour construire l'expérience de recherche magique qui vous permettra d'obtenir les résultats que vous souhaitez.

Jugez-en par vous-même