Evaluer un pipeline de génération augmentée par récupération (RAG) avec RAGAS !
Les grands modèles de langage (LLM), pose un défi en termes d'évaluation de performance, particulièrement pour les cas d'utilisation de génération augmentée par récupération (RAG). Contrairement aux méthodes traditionnelles d'apprentissage automatique, il n'existe pas de métriques mathématiques précises pour évaluer ces modèles.
Dans le contexte des pipelines RAG, nous n'avons pas d'autres alternatives, contrairement aux métriques comme l'ROC AUC ou le RMSE pour l'apprentissage automatique traditionnel. Les seules options disponibles sont l'évaluation humaine ou celle par LLM.
Deux principales options d'évaluation disponibles :
Ragas est un cadre d'évaluation multifacette pour tester l'efficacité des pipelines RAG. Malgré sa complexité conceptuelle, sa mise en œuvre est relativement simple.
Une approche hybride combinant évaluation humaine et Ragas pourrait être recommandée pour une évaluation plus complète.
Génération d'un jeu de données synthétique de test
Ces quatre informations sont essentielles pour utiliser le cadre Ragas. Cependant, toutes ne sont pas strictement nécessaires pour effectuer les métriques Ragas,
Le prérequis pour utiliser ce générateur est d'avoir un corpus de documents qui sera utilisé dans une base vectorielle. J'ai synthétisé un jeu de données pour cet exemple, en simulant des éléments de connaissance pour une grande entreprise fictive.
df_kis = pd.read_csv('data/ragas/synthetic_knowledge_items.csv')
df_kis = df_kis[['ki_topic', 'ki_text']]
ki_doc_loader = DataFrameLoader(data_frame=df_kis, page_content_column='ki_text')
ki_docs = ki_doc_loader.load()
Le corpus est chargé comme un groupe de documents LangChain, prêts à générer l'ensemble de test, mais avant que fait Ragas ?
Dans le contexte de Ragas, une évolution signifie simplement la manière dont une question doit évoluer (ou ne pas évoluer) pour produire un autre type de question. Ragas offre la possibilité de produire 4 types de questions différentes :
Fonctionnement
La génération de jeux de tests dans Ragas, utilise deux modèles de langage (LLM) : un générateur et un critique. Le LLM générateur crée des questions et des réponses à partir de morceaux de documents, tandis que le LLM critique évalue la qualité des questions et des réponses produites. Si le critique juge que la qualité est insuffisante, le générateur réessaye.
Le processus de génération de tests comprend plusieurs étapes :
J'utilise ici le même LLM pour les deux rôles, bien que cela ne soit pas idéal...
chat_model = ChatOpenAI(model='gpt-4o-mini')
embeddings = OpenAIEmbeddings()
testset_generator = TestsetGenerator.from_langchain(
generator_llm=chat_model,
critic_llm=chat_model,
embeddings=embeddings
)
testset = testset_generator.generate_with_langchain_docs(
documents=ki_docs,
test_size=10,
distributions={
simple: 0.5,
reasoning: 0.2,
multi_context: 0.2,
conditional: 0.1
}
)
df_testset = testset.to_pandas()
La génération de test avec Ragas peut être longue en raison du grand nombre d'appels à l'API, et qu'il est possible de rencontrer des erreurs liées à la limite de taux. De plus, Ragas ne génère pas toutes les données nécessaires : il produit une question et une colonne "ground_truth", mais cette dernière est davantage une réponse générée par IA. je vais renommer cette "ground_truth" en "answer" et créer une nouvelle "ground_truth" en utilisant une invite personnalisée.
Dans le cas d'un RAG en production, ces étapes ne sont pas nécessaires car le jeu de données devrait fournir les réponses exact.
df_testset.rename(columns={'ground_truth': 'answer'}, inplace=True)
df_testset['ground_truth'] = ''
Recommandé par LinkedIn
Génération
GT_SIMULATION_PROMPT = '''vous êtes un évaluateur expert pour les systèmes de réponse aux questions. Votre tâche consiste à fournir la réponse idéale basée sur la vérité en fonction de la question et du contexte donnés. Veuillez suivre les lignes directrices suivantes:
1. Question: {question}
2. Context: {context}
3. Instructions:
- Analyser attentivement la question et le contexte fourni.
- Formulez une réponse complète et précise en vous basant uniquement sur les informations fournies dans le contexte.
- Veillez à ce que votre réponse réponde directement à la question.
- Incluez toutes les informations pertinentes du contexte, mais n'ajoutez pas de connaissances externes.
- Si le contexte ne contient pas suffisamment d'informations pour répondre entièrement à la question, indiquez-le clairement et donnez la meilleure réponse partielle possible.
- Utilisez un ton formel et objectif.
N'oubliez pas que votre objectif est de fournir la réponse idéale qui servira de référence pour évaluer les performances de l'IA.'''
# Create the prompt template
gt_generation_prompt = ChatPromptTemplate.from_messages(messages=[
HumanMessagePromptTemplate.from_template(template=GT_SIMULATION_PROMPT)
])
llama_model = Ollama(model='llama3.2')
# Create LLMChain to link the prompt and the model
gt_generation_chain = LLMChain(
llm=llama_model,
prompt=gt_generation_prompt
)
def generate_ground_truth_text(row):
'''
Génère un texte simulé en fonction de la question et du contexte fournis.
Inputs:
- row (Pandas DataFrame record): Un seul enregistrement du DataFrame Pandas
Returns:
- gt_text (str): Le texte généré par le modèle d'IA pour l'enregistrement
'''
if row['ground_truth'] == '':
gt_text = gt_generation_chain.predict(
question=row['question'],
context=row['contexts']
)
return gt_text.strip()
else:
return row['ground_truth']
df_testset['ground_truth'] = df_testset.apply(generate_ground_truth_text, axis=1)
df_testset.to_csv('data/ragas/df_testset.csv', index=False)
df_testset = pd.read_csv('data/ragas/df_testset.csv')
J'ai maintenant un DataFrame Pandas qui contient les quatre éléments d'information nécessaires au calcul des métriques Ragas !
Calcul des métriques de Ragas
Actuellement, le jeu de test est sous forme de DataFrame Pandas, mais Ragas ne peut pas traiter directement ces DataFrames. Nous devons donc les convertir dans un format compatible. Plus précisément, Ragas requiert que les données soient dans un format de jeu de données spécifique à Hugging Face.
def pandas_to_ragas(df):
'''
Convertit un DataFrame Pandas en un jeu de données compatible avec Ragas
Inputs:
- df (Pandas DataFrame): Le DataFrame d'entrée à convertir
Returns:
- ragas_testset (Hugging Face Dataset): Un jeu de données Hugging Face compatible avec Ragas
'''
text_columns = ['question', 'ground_truth', 'answer']
for col in text_columns:
df[col] = df[col].fillna('').astype(str)
df['contexts'] = df['contexts'].fillna('').astype(str).apply(lambda x: [x] if x else [])
data_dict = df[['question', 'contexts', 'answer', 'ground_truth']].to_dict('list')
ragas_testset = Dataset.from_dict(data_dict)
return ragas_testset
ragas_testset = pandas_to_ragas(df=df_testset)
Ragas est prêt à être lancé !
ragas_scores = evaluate(
dataset=ragas_testset,
llm=ChatOpenAI(model='gpt-4o-mini'),
metrics=[
faithfulness,
answer_relevancy,
context_precision,
context_recall,
context_entity_recall,
answer_similarity,
answer_correctness
]
)
df_ragas_scores = ragas_scores.to_pandas()
df_ragas_scores.to_csv('data/ragas/ragas_scores.csv', index=False)
df_ragas_scores = pd.read_csv('data/ragas/ragas_scores.csv')
# Display various Ragas scores
print(df_ragas_scores[['question', 'contexts', 'answer', 'faithfulness']])
print(df_ragas_scores[['answer', 'contexts', 'answer_relevancy']])
print(df_ragas_scores[['question', 'contexts', 'ground_truth', 'context_recall']])
print(df_ragas_scores[['question', 'contexts', 'answer', 'context_precision']])
print(df_ragas_scores[['question', 'contexts', 'answer']])
print(df_ragas_scores[['contexts', 'ground_truth', 'context_entity_recall']])
print(df_ragas_scores[['answer', 'ground_truth', 'answer_similarity']])
print(df_ragas_scores[['question', 'answer', 'ground_truth', 'answer_correctness']])
print(df_ragas_scores[['question', 'answer', 'contexts', 'ground_truth']])
Ragas regroupe les différentes métriques d'évaluation en trois grandes catégories :
Évaluation par composant :
Ces métriques évaluent des éléments spécifiques des données RAG. Elles incluent :
Évaluation de bout en bout :
Ces métriques mesurent l'efficacité de la réponse finale de l'IA à la question originale.
Critique d'aspects :
Bien que Ragas ne classe pas officiellement ces métriques dans une catégorie, elles évaluent différents aspects de la réponse, chaque aspect étant jugé par le LLM. Ces critiques incluent :
Chaque aspect est évalué indépendamment avec un score de 0 ou 1.
Conclusion
Il est bon de se rappeler que, bien qu'il ne soit pas idéal d'évaluer un modèle avec un autre modèle, il faut tirer le meilleur parti de la situation en utilisant les ressources disponibles. Ragas calcule de nombreuses métriques, ce qui évite de se fier uniquement à une seule mesure pouvant être ambiguë. La précision et le rappel du contexte, reflètent des métriques statistiques connues. Ragas est donc un cadre intéressant.