Intégration de Langchain-Chatchat avec TracingPlane pour l'observabilité des systèmes d'IA
Dans le domaine des modèles de langage de grande taille (LLM), l'aspect "boîte noire" pose des défis pour le débogage et la conformité, notamment dans des secteurs réglementés. La combinaison de Langchain-Chatchat, un framework de questions-réponses sur base de connaissances locale, avec TracingPlane, un outil de traçage distribué léger, offre une solution pour la transparence des opérations tout en préservant la souveraineté des données.
Fonctionnement de Langchain-Chatchat et l'architecture RAG
Langchain-Chatchat implémente un pipeline de RAG (Retrieval-Augmented Generation) entièrement local. Ce processus inclut le chargement de documents, la segmentation en morceaux, la vectorisation et l'interrogation assistée par un modèle local. Les étapes principales sont :
- Extraction et nettoyage des données : Utilisation de bibliothèques comme PyPDF2 pour lire les fichiers et appliquer des techniques de prétraitement.
- Création d'index vectoriels : Conversion des textes en vecteurs via des modèles d'embedding comme BGE-small-zh, stockés dans une base de données vectorielle locale telle que FAISS.
- Recherche sémantique et injection de contexte : Pour une requête utilisateur, récupération des fragments pertinents pour enrichir le prompt du modèle.
- Génération par modèle local : Utilisation de LLM open source comme ChatGLM3 pour produire des réponses sans échange de données externe.
Voici un exemple de code illustrant ce pipeline avec des noms de variables et une structure modifiés :
from langchain_community.document_loaders import PDFMinerLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.chains import ConversationalRetrievalChain
from langchain_community.llms import HuggingFaceEndpoint
# Chargement des documents source
doc_loader = PDFMinerLoader(file_path="data_source.pdf")
raw_docs = doc_loader.load()
# Découpage en segments
text_processor = CharacterTextSplitter(separator="\n", chunk_size=600, chunk_overlap=100)
processed_docs = text_processor.split_documents(raw_docs)
# Initialisation du modèle d'embedding
embedding_model = HuggingFaceEmbeddings(model_name="shibing624/text2vec-base-chinese")
# Construction de la base vectorielle
vector_db = Chroma.from_documents(documents=processed_docs, embedding=embedding_model)
# Configuration du LLM local
llm_engine = HuggingFaceEndpoint(endpoint_url="http://localhost:8080", model_kwargs={"temperature": 0.1})
# Création de la chaîne de récupération
retrieval_chain = ConversationalRetrievalChain.from_llm(
llm=llm_engine,
retriever=vector_db.as_retriever(search_type="similarity", search_kwargs={"k": 2}),
return_source_documents=True
)
# Exécution d'une requête
user_query = "Quelles sont les procédures de remboursement ?"
response = retrieval_chain({"question": user_query, "chat_history": []})
print(response["answer"])
Intégration de TracingPlane pour le suivi des performances
TracingPlane introduit un mécanisme de propagation de contexte léger appelé UCONTEXT, qui encapsule un identifiant de trace unique et des métadonnées de span. Cette approche permet d'instrumenter les appels sans modifier les protocoles de communication, avec un impact minimal sur les ressources.
L'intégration dans Langchain-Chatchat implique l'ajout de points d'entrée et de sortie pour marquer les opérations clés. Voici un exemple de code refactorisé :
import uuid
from tracingplane.context import UniversalContext, BlameTracker
# Initialisation du contexte de traçage pour une requête
def init_trace_context():
trace_identifier = uuid.uuid4().hex
span_identifier = uuid.uuid4().hex
uctx = UniversalContext.create(trace_id=trace_identifier, span_id=span_identifier)
BlameTracker.attach(uctx)
return uctx
# Fonction de récupération avec traçage
def fetch_documents_with_trace(user_question: str):
uctx = BlameTracker.current()
with uctx.start_span("document_retrieval") as span:
try:
# Simulation de la recherche vectorielle
relevant_docs = vector_db.similarity_search(user_question, k=2)
span.set_status("success")
return relevant_docs
except Exception as error:
span.record_error(error)
raise
# Exemple d'utilisation dans le flux principal
if __name__ == "__main__":
trace_ctx = init_trace_context()
try:
question = "Politique de congés annuels ?"
docs = fetch_documents_with_trace(question)
print("Documents récupérés:", len(docs))
except Exception as e:
print("Erreur lors de la requête:", e)
finally:
trace_summary = BlameTracker.current().generate_report()
print("Rapport de traçage:", trace_summary)
Le rapport généré inclut des détails tels que la durée des spans et leur statut, facilitant l'identification des goulots d'étranglement.
Architecture système et considérations d'ingénierie
L'architecture expérimentale se compose de plusieurs couches : une interface utilisateur pour les interactions, le noyau Langchain-Chatchat pour le traitement, un agent TracingPlane pour la collecte de données, et des services locaux pour les vecteurs et les modèles. Tous les composants fonctionnent au sein d'un réseau local, garantissant la confidentialité des données.
Lors de l'implémentation, plusieurs points ont été optimisés :
- Granularité du traçage : Focalisation sur les modules critiques comme la récupération et l'inférence, sans surcharger les opérations internes.
- Gestion des ressources : Utilisation d'une collecte asynchrone pour éviter d'affecter les performances principales.
- Sécurité des données : Les journaux de traçage excluent tout contenu sensible, avec des techniques comme le hachage des identifiants.
- Initialisation à froid : Ajout de balises pour distinguer les temps de chargement initiaux des requêtes normales.
Cette intégration permet de diagnostiquer efficacement les problèmes de performance, comme les retards dus à une segmentation inadéquate des documents. Elle ouvre la voie à une meilleure maintenabilité des systèmes d'IA locaux, avec des possibilités d'extension vers des outils de visualisation comme Grafana.