Files
wiki_crawler/tests/rag_benchmark/evaluator.py

74 lines
3.1 KiB
Python
Raw Normal View History

2026-01-27 01:41:45 +08:00
import json
import logging
from backend.services.llm_service import llm_service
logger = logging.getLogger(__name__)
class RAGEvaluator:
def __init__(self):
self.llm = llm_service
def calculate_retrieval_metrics(self, retrieved_docs, dataset_item):
"""
计算检索阶段指标: Keyword Recall (关键词覆盖率)
检查 dataset 中的 keywords 有多少出现在了 retrieved_docs content
"""
required_keywords = dataset_item.get("keywords", [])
if not required_keywords:
return {"keyword_recall": 1.0, "hit": True} # 没有关键词要求,默认算对
# 将所有检索到的文本拼接并转小写
full_context = " ".join([doc['content'] for doc in retrieved_docs]).lower()
found_count = 0
for kw in required_keywords:
if kw.lower() in full_context:
found_count += 1
recall = found_count / len(required_keywords)
return {
"keyword_recall": recall,
# 只要召回率大于 0 就认为 Hit 了一部分;
# 严格一点可以要求 recall > 0.5,这里我们设定只要沾边就算 Hit
"hit": recall > 0
}
def evaluate_generation_quality(self, question, generated_answer, ground_truth_answer, q_type):
"""
使用 LLM 作为裁判评估生成质量 (1-5)
"""
prompt = f"""
你是一名RAG系统的自动化测试裁判请根据以下信息对系统回答进行评分1-5
测试类型: {q_type}
用户问题: {question}
标准答案 (Ground Truth): {ground_truth_answer}
系统回答: {generated_answer}
评分标准
- 5: 含义与标准答案完全一致逻辑正确无幻觉
- 4: 核心意思正确但缺少部分细节或废话较多
- 3: 回答了一部分正确信息但有遗漏或轻微错误
- 2: 包含大量错误信息或严重答非所问
- 1: 完全错误或产生了严重幻觉例如在负向测试中编造了不存在的功能
注意对于"negative_test"负向测试如果标准答案是不支持/文档未提及而系统回答诚实地说未找到相关信息不支持应给满分
请仅返回JSON格式: {{"score": 5, "reason": "理由..."}}
"""
try:
# 使用 system_prompt 强制约束格式
result_str = self.llm.chat(prompt, system_prompt="你是一个只输出JSON的评测机器人。")
# 清洗 Markdown 格式 (```json ... ```)
if "```" in result_str:
result_str = result_str.split("```json")[-1].split("```")[0].strip()
eval_result = json.loads(result_str)
return eval_result
except Exception as e:
logger.error(f"Eval LLM failed: {e}")
# 降级处理
return {"score": 0, "reason": "Evaluation Script Error"}