Notes pratiques : RAG sans devinette : LangGraph standardisé +
Guide opérationnel des notes pratiques : RAG sans devinette – LangGraph + standardisé, avec des contrats, des vérifications et des emplacements de code prêts à l’emploi pour les équipes qui utilisent ce modèle.
Ce guide reconstitue le parcours allant des matières premières à un système fonctionnel pour : RAG Sans devinette : Un modèle standardisé LangGraph + LlamaIndex. L’accent est mis sur des étapes opérationnelles, des vérifications explicites et du code que vous pouvez intégrer directement dans un dépôt sans devoir deviner l’intention. Pour une vue d’ensemble, définissez les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans avoir à deviner l’état caché. Documentez conjointement le parcours normal et celui de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non traités font partie intégrante du produit, et non d’une mise en forme ultérieure.
Pourquoi cet article existe
Lorsque vous travaillez sur « Pourquoi cet article existe », notez d’abord les éléments requis : les entrées nécessaires, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un processus embrouillé. Évaluez le taux de rappel sur un ensemble de questions fixe avant d’ajuster les prompts. Un changement fréquent des prompts ne résout que rarement un système de récupération insuffisant.
Partie A : Comprendre LlamaIndex (d’abord le concept)
Lorsque vous travaillez sur la partie A : Comprendre LlamaIndex (d’abord le concept), notez d’abord les conditions prévues : les entrées requises, le signal de succès, ainsi que ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux éléments générés, définez des vérifications de succès, et refusez les complétions partielles silencieuses. Évaluez le taux de rappel sur un ensemble de questions fixe avant d’ajuster les prompts. Changer fréquemment les prompts ne résout que rarement un système de récupération insuffisant.
Que fait réellement LlamaIndex
Lorsque vous travaillez sur le document « What LlamaIndex Actually Does », notez d’abord les exigences : entrées requises, signal de succès et conséquences en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Enregistrez les temps d’exécution ainsi que le coût en tokens ou en requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le système passe de l’environnement de démonstration à des environnements partagés. Mesurez le taux de rappel sur un ensemble de questions fixe avant d’ajuster les prompts. Changer fréquemment les prompts ne résout que rarement un système de récupération insuffisant. Lorsque vous travaillez sur le document « What LlamaIndex Actually Does », notez d’abord les exigences : entrées requises, signal de succès et conséquences en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Documentez à la fois le parcours normal et les scénarios de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non traités font partie intégrante du produit, et non d’améliorations apportées ultérieurement.
Le pipeline RAG en cinq étapes
Le pipeline RAG en cinq étapes fonctionne le mieux lorsqu’il est considéré comme une surface mesurable. Capturez un transcript idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’erreur doit pointer vers une seule responsabilité plutôt que vers un pipeline embrouillé. Séparez la politique de segmentation des données de la politique de récupération. Modifier l’une ne doit pas obliger à réécrire l’autre lorsque les métriques de qualité changent.
1. LOAD → Read raw files (PDF, Word, web pages, databases) into Documents
2. CHUNK → Split Documents into small, retrievable Nodes
3. EMBED → Convert each Node's text into a vector (a list of numbers
representing meaning)
4. STORE → Save those vectors in a Vector Index for fast lookup
5. RETRIEVE → At query time, embed the user's question, find the most
similar Nodes, and return them as context
Les mots-clés essentiels que vous devez connaître
« Les mots-clés essentiels que vous devez connaître » fonctionnent le mieux lorsqu’ils sont considérés comme une surface mesurable. Recueillez un exemple exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des critères de succès et refusez toute mise en œuvre partielle silencieuse. Séparez la politique de segmentation de la politique de récupération. Modifier l’une ne doit pas obliger à réécrire l’autre lorsque les métriques de qualité évoluent.
Partie B : Création d’une base de connaissances LlamaIndex autonome
Partie B : La création d’une base de connaissances LlamaIndex autonome fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Enregistrez les temps d’exécution ainsi que le coût en tokens ou en requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le système passe d’un environnement de démonstration à des environnements partagés. Séparez la politique de segmentation des données de la politique de récupération. Modifier l’une ne doit pas obliger à réécrire l’autre lorsque les métriques de qualité évoluent. Partie B : La création d’une base de connaissances LlamaIndex autonome fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Documentez ensemble le parcours optimal et le parcours de récupération. Les tentatives de réessai, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’une mise en forme ultérieure.
Étape 1 : Installation
Pour l’Étape 1 : Installation, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Préférez des unités petites et testables à des scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un processus embrouillé. Citez les passages qui ont réellement servi de base à la réponse. Sans citations, les opérateurs ne peuvent pas distinguer une hallucination d’un manque d’indexation.
# Core package + OpenAI LLM and embedding integrations (the common starting setup)
pip install llama-index-core llama-index-llms-openai llama-index-embeddings-openai
# Readers for common file types (PDF, Word, etc.)
pip install llama-index-readers-file pypdf
Étape 2 : Configuration globale avec Settings
Pour l’Étape 2 : Configuration globale via Settings, définissez les entrées, le responsable de l’étape ainsi que les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché.
Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définites des vérifications de succès et refusez toute exécution partielle silencieuse.
Citez les passages qui justifient réellement la réponse. Sans citations, les opérateurs ne peuvent pas distinguer une hallucination d’un manque dans l’indexation.
# ── llamaindex_config.py ─────────────────────────────────────
import os
from llama_index.core import Settings
from llama_index.llms.openai import OpenAI
from llama_index.embeddings.openai import OpenAIEmbedding
# Settings is global - configure once, used everywhere in LlamaIndex
Settings.llm = OpenAI(
model="gpt-4o-mini", # Used for generating final answers from retrieved context
temperature=0.1, # Low temperature: factual, not creative
)
Settings.embed_model = OpenAIEmbedding(
model="text-embedding-3-small", # Used to convert text into vectors
)
# Controls how documents are split into Nodes (chunks)
Settings.chunk_size = 512 # Max tokens per chunk
Settings.chunk_overlap = 50 # Overlap between consecutive chunks, to preserve context across boundaries
Étape 3 : Chargement → Indexation → Requête (Le pipeline autonome)
Pour l’étape 3 : Chargement → Indexation → Requête (le pipeline autonome), définissez les entrées, le responsable de l’étape ainsi que les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Enregistrez les temps d’exécution ainsi que le coût en tokens ou en requêtes à côté des résultats fonctionnels. Une visibilité précoce du coût permet d’éviter des factures inattendues lorsque le processus passe de l’environnement de démonstration à des environnements partagés. Citez les passages qui ont réellement servi de base à la réponse. Sans citations, les opérateurs ne peuvent pas distinguer une hallucination d’un manque d’indexation.
# ── build_knowledge_base.py ──────────────────────────────────
from llama_index.core import SimpleDirectoryReader, VectorStoreIndex
# ── LOAD: Read all files in a folder into Document objects ──
documents = SimpleDirectoryReader("./data").load_data()
print(f"Loaded {len(documents)} documents")
# ── CHUNK + EMBED + STORE: all three happen inside this one call ──
# VectorStoreIndex automatically:
# 1. Splits each Document into Nodes (using Settings.chunk_size)
# 2. Embeds each Node (using Settings.embed_model)
# 3. Stores the vectors in an in-memory index
index = VectorStoreIndex.from_documents(documents, show_progress=True)
# ── RETRIEVE + GENERATE: ask a question ──────────────────────
query_engine = index.as_query_engine(
similarity_top_k=3, # Retrieve the 3 most relevant chunks for each query
)
response = query_engine.query("What is our refund policy for enterprise customers?")
print(response)
Pour l’étape 3 : Chargement → Indexation → Requête (Le pipeline autonome), définissez les entrées, le responsable de l’étape ainsi que les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Documentez conjointement le parcours normal et les scénarios de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’améliorations ultérieures.
Étape 4 : Persister l’index (Ne le réinsérez pas à chaque fois)
Lorsque vous travaillez sur l’Étape 4 : Persister l’index (Ne pas réinsérer à chaque fois), notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Préférez des unités petites et testables plutôt que des scripts volumineux. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité et non un processus embrouillé. Évaluez le taux de rappel sur un ensemble de questions fixe avant d’ajuster les prompts. Un changement fréquent des prompts ne résout que rarement un système de récupération insuffisant.
# ── Save the index after building it ─────────────────────────
index.storage_context.persist(persist_dir="./storage")
# ── Load it back later without re-embedding anything ──────────
from llama_index.core import StorageContext, load_index_from_storage
storage_context = StorageContext.from_defaults(persist_dir="./storage")
index = load_index_from_storage(storage_context)
Étape 5 : Utiliser une base de données vectorielle externe (Chroma)
Lorsque vous travaillez sur l’Étape 5 : Utilisation d’une base de données vectorielle externe (Chroma), notez d’abord les conditions préalables : les entrées requises, le signal de succès, ainsi que ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des vérifications de succès, et refusez les terminations partielles silencieuses. Mesurez le taux de rappel sur un ensemble de questions fixe avant d’ajuster les prompts. Le simple changement de prompts ne résout que rarement un système de récupération insuffisant.
# ── Using Chroma as a persistent, production-grade vector store ──
# pip install llama-index-vector-stores-chroma chromadb
import chromadb
from llama_index.vector_stores.chroma import ChromaVectorStore
from llama_index.core import StorageContext, VectorStoreIndex
chroma_client = chromadb.PersistentClient(path="./chroma_db")
chroma_collection = chroma_client.get_or_create_collection("my_knowledge_base")
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
# Build the index directly into Chroma
index = VectorStoreIndex.from_documents(
documents,
storage_context=storage_context
)
# Later, in a different process, reconnect without re-indexing:
index = VectorStoreIndex.from_vector_store(vector_store=vector_store)
Partie C : Connexion de LlamaIndex à LangGraph
Lorsque vous travaillez sur la partie C : connexion de LlamaIndex à LangGraph, notez d’abord les spécifications requises : entrées obligatoires, signal de succès et conséquences en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Enregistrez les temps d’exécution ainsi que le coût en tokens ou en requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le système passe d’un environnement de démonstration à des environnements partagés. Mesurez le taux de rappel sur un ensemble de questions fixe avant d’ajuster les prompts. Changer fréquemment les prompts ne résout que rarement un système de récupération insuffisant. Lorsque vous travaillez sur la partie C : connexion de LlamaIndex à LangGraph, notez d’abord les spécifications requises : entrées obligatoires, signal de succès et conséquences en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Documentez à la fois le parcours normal et les scénarios de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non traités font partie intégrante du produit, et non d’améliorations apportées ultérieurement.
The Bridge : Envelopper le moteur de requêtes en tant qu’outil
The Bridge : Envelopper le moteur de requêtes en tant qu’outil fonctionne le mieux lorsqu’il est considéré comme une surface mesurable. Capturez un exemple exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’échec doit pointer vers une seule responsabilité plutôt que vers un processus embrouillé. Séparez la politique de segmentation de la politique de récupération. Modifier l’une ne doit pas obliger à réécrire l’autre lorsque les métriques de qualité changent.
# ── MODULE 3: TOOLS (LlamaIndex-backed) ─────────────────────
from langchain_core.tools import tool
# The query_engine built in Part B - created once, at startup
# (In a real app, you'd load this from persisted storage, not rebuild it every time)
@tool
def search_knowledge_base(query: str) -> str:
"""Search the internal knowledge base for company policies, product
documentation, and internal procedures. Use this whenever the user asks
a question that might be answered by internal company documents rather
than general knowledge.
Args:
query: A natural-language question to search for.
Returns:
A synthesized answer based on the most relevant retrieved documents.
"""
response = query_engine.query(query)
return str(response)
L’intégration complète : Modules 1 à 7
L’Intégration complète : Modules 1 à 7 fonctionne le mieux lorsqu’il est considéré comme une surface mesurable. Capturez un transcript parfait, un cas d’échec et la note de réversion avant d’élargir le périmètre. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des critères de succès et refusez toute mise en œuvre partielle silencieuse. Séparez la politique de segmentation de la politique de récupération. Modifier l’une ne doit pas obliger à réécrire l’autre lorsque les métriques de qualité évoluent.
# ============================================================
# LANGGRAPH + LLAMAINDEX RAG AGENT — COMPLETE TEMPLATE
# Extends: Part 1 (core structure)
# ============================================================
# ── MODULE 1: IMPORTS & CONFIGURATION ───────────────────────
import os
from typing import Literal
# LangChain / LangGraph imports (the orchestration layer)
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, SystemMessage, BaseMessage
from langchain_core.tools import tool
from langgraph.graph import StateGraph, MessagesState, START, END
from langgraph.prebuilt import ToolNode
from langgraph.checkpoint.memory import MemorySaver
# LlamaIndex imports (the retrieval / data layer)
from llama_index.core import (1
Settings, SimpleDirectoryReader, VectorStoreIndex,
StorageContext, load_index_from_storage
)
from llama_index.llms.openai import OpenAI as LlamaOpenAI
from llama_index.embeddings.openai import OpenAIEmbedding
# LangGraph's chat model - used by the agent's reasoning
llm = ChatOpenAI(model="gpt-4o", temperature=0)
# LlamaIndex's model config - used internally by the query engine
# Note: these are SEPARATE from the LangGraph llm above. Each framework
# manages its own model instances; they don't share state.
Settings.llm = LlamaOpenAI(model="gpt-4o-mini", temperature=0.1)
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")
Settings.chunk_size = 512
# ── MODULE 2: STATE ──────────────────────────────────────────
class State(MessagesState):
pass # messages field inherited; extend if your agent needs more
# ── MODULE 3: TOOLS (RAG-backed) ─────────────────────────────
# Build or load the LlamaIndex knowledge base ONCE, at startup
PERSIST_DIR = "./storage"
if os.path.exists(PERSIST_DIR):
# Reload existing index - no re-embedding, fast startup
storage_context = StorageContext.from_defaults(persist_dir=PERSIST_DIR)
index = load_index_from_storage(storage_context)
else:
# First run - build the index and persist it
documents = SimpleDirectoryReader("./data").load_data()
index = VectorStoreIndex.from_documents(documents, show_progress=True)
index.storage_context.persist(persist_dir=PERSIST_DIR)
query_engine = index.as_query_engine(similarity_top_k=3)
@tool
def search_knowledge_base(query: str) -> str:
"""Search internal company documents for policies, product specs,
procedures, and other domain-specific information. Use this for any
question that requires knowledge specific to this organization rather
than general world knowledge."""
response = query_engine.query(query)
return str(response)
tools = [search_knowledge_base]
llm_with_tools = llm.bind_tools(tools)
tool_node = ToolNode(tools)
# ── MODULE 4: NODES ──────────────────────────────────────────
def agent_node(state: State) -> dict:
"""The reasoning node. Decides whether to answer directly or
search the knowledge base first."""
system_prompt = SystemMessage(content=(
"You are a helpful assistant with access to an internal knowledge base. "
"Use the search_knowledge_base tool when the user asks about company-specific "
"information. For general questions, answer directly."
))
messages = [system_prompt] + state["messages"]
response = llm_with_tools.invoke(messages)
return {"messages": [response]}
# ── MODULE 5: ROUTING ────────────────────────────────────────
def should_continue(state: State) -> Literal["tools", "__end__"]:
last_message = state["messages"][-1]
if hasattr(last_message, "tool_calls") and last_message.tool_calls:
return "tools"
return "__end__"
# ── MODULE 6: GRAPH ASSEMBLY ─────────────────────────────────
graph_builder = StateGraph(State)
graph_builder.add_node("agent", agent_node)
graph_builder.add_node("tools", tool_node)
graph_builder.add_edge(START, "agent")
graph_builder.add_conditional_edges(
"agent", should_continue,
{"tools": "tools", "__end__": END}
)
graph_builder.add_edge("tools", "agent")
graph = graph_builder.compile(checkpointer=MemorySaver())
# ── MODULE 7: ENTRYPOINT ──────────────────────────────────────
if __name__ == "__main__":
config = {"configurable": {"thread_id": "session-001"}}
print("RAG agent ready. Ask about your documents, or anything else.\n")
while True:
user_text = input("You: ").strip()
if not user_text or user_text.lower() == "exit":
break
response = graph.invoke(
{"messages": [HumanMessage(content=user_text)]},
config=config
)
print(f"Agent: {response['messages'][-1].content}\n")
Que se passe-t-il réellement lorsque vous exécutez ceci
Que se passe-t-il réellement lorsque vous exécutez ceci fonctionne le mieux lorsqu’il est considéré comme une surface mesurable. Capturez un exemple idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe de la démonstration aux environnements partagés. Séparez la politique de segmentation de la politique de récupération. Modifier l’une ne doit pas obliger à réécrire l’autre lorsque les métriques de qualité évoluent. Que se passe-t-il réellement lorsque vous exécutez ceci fonctionne le mieux lorsqu’il est considéré comme une surface mesurable. Capturez un exemple idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Documentez ensemble le parcours réussi et le parcours de récupération. Les tentatives de réessai, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’une mise en forme ultérieure.
User: "What's our policy on remote work?"
↓
[agent_node] — LangGraph's LLM reads the message, recognizes this needs
internal info, decides to call search_knowledge_base
↓
[tools] — ToolNode executes search_knowledge_base("What's our policy on remote work?")
↓
Inside the tool: query_engine.query(...) runs —
this is 100% LlamaIndex, invisible to LangGraph:
1. Embeds the query
2. Searches the vector index for the 3 closest chunks
3. Feeds those chunks + the question to Settings.llm
4. Returns a synthesized answer string
↓
[agent_node] — LangGraph's LLM receives the tool's string result,
and crafts the final response shown to the user
↓
Response to user
Partie D : Un niveau de plus — Mode uniquement récupérateur (meilleure maîtrise)
Pour la Partie D : Un niveau de plus — Mode uniquement récupérateur (meilleure maîtrise), il convient de définir les entrées, le responsable de l’étape ainsi que les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité et non un processus embrouillé. Citez les passages qui justifient réellement la réponse. Sans citations, les opérateurs ne peuvent pas distinguer une hallucination d’un manque d’indexation.
# ── Retriever-only tool: returns raw chunks, not a synthesized answer ──
retriever = index.as_retriever(similarity_top_k=3)
@tool
def retrieve_documents(query: str) -> str:
"""Retrieve relevant document excerpts from the internal knowledge base.
Returns raw excerpts for you to read and reason over yourself -
use this when you need to cite specific sources or combine information
from multiple documents."""
nodes = retriever.retrieve(query)
# Format each retrieved chunk with its source for transparency
formatted_chunks = []
for i, node in enumerate(nodes):
source = node.metadata.get("file_name", "unknown source")
formatted_chunks.append(f"[Excerpt {i+1} from {source}]\n{node.text}")
return "\n\n---\n\n".join(formatted_chunks)
Quand utiliser QueryEngine plutôt que Retriever
Pour déterminer quand utiliser QueryEngine plutôt que Retriever, il faut définir les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché.
Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définites des vérifications de succès et refusez les terminaisons partielles silencieuses.
Citez les passages qui ont réellement servi de base à la réponse. Sans citations, les opérateurs ne peuvent pas distinguer une hallucination d’un manque d’indexation.
La carte de référence des mots-clés mise à jour
Pour la carte de référence des mots-clés mise à jour, définissez les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Enregistrez les temps d’exécution ainsi que le coût des jetons ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce du coût permet d’éviter des factures inattendues lorsque le parcours passe de l’environnement de démonstration à des environnements partagés. Citez les passages qui ont réellement servi de base à la réponse. Sans citations, les opérateurs ne peuvent pas distinguer une hallucination d’un manque d’indexation. Pour la carte de référence des mots-clés mise à jour, définissez les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Documentez ensemble le parcours optimal et les procédures de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non traités font partie intégrante du produit, et non d’une mise en forme ultérieure.
Le guide de décision : quand en avez-vous vraiment besoin ?
Lorsque vous travaillez avec le Guide de décision : quand en avez-vous vraiment besoin ?, notez d’abord les éléments requis pour le contrat : les données nécessaires, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Préférez des unités petites et testables plutôt que des scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité et non un processus embrouillé. Évaluez le taux de rappel sur un ensemble fixe de questions avant d’ajuster les prompts. Un changement fréquent des prompts ne résout que rarement un système de récupération insuffisant.
Conclusion : deux frameworks, une cohérence
Lorsque vous travaillez sur « Conclusion : Deux cadres, une intégration », notez d’abord les conditions requises : les entrées nécessaires, le signal de succès, ainsi que ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des vérifications de succès, et refusez les terminaisons partielles silencieuses. Évaluez le taux de rappel sur un ensemble fixe de questions avant d’ajuster les prompts. Un changement fréquent des prompts ne résout que rarement un système de récupération insuffisant.
Liste de contrôle opérationnelle
Cette liste fonctionne le mieux lorsqu’elle est considérée comme un indicateur mesurable. Capturez une transcription exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre.
Gardez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système.
Séparez la politique de segmentation de la politique de récupération. Modifier l’une ne doit pas obliger à réécrire l’autre lorsque les métriques de qualité changent.
Imposez une approbation humaine pour les opérations qui entraînent des dépenses ou modifient des données de production. Une connexion en temps de compilation ne garantit pas une couverture complète des besoins métier.
Rédigez un guide de procédures succinct : comment rotationner les clés, comment vider la file d’attente, comment annuler la dernière ingestion.
Considérez cette étape comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définez des vérifications de succès, et refusez toute mise à jour partielle silencieuse.
Au préalable de promouvoir l’ensemble du système, figez les versions, conservez une transcription exemplaire pour le parcours critique, et confirmez les étapes de rollback. Les environnements partagés nécessitent des limites de fréquence, des vérifications d’affectation, ainsi qu’un responsable clair pour la rotation des secrets. Préférez une fiabilité solide à des démonstrations brillantes mais ponctuelles.
Note de lot pour bcaf14f9c811 : ne pas inclure les clés du fournisseur dans le répertoire, fixer une limite pour les tokens par session, et stocker les transcriptions à côté des fichiers d’évaluation afin que les remplacements ultérieurs de modèles restent comparables.