完成RAG测试

This commit is contained in:
2026-01-27 01:41:45 +08:00
parent 155974572c
commit f78efc7125
16 changed files with 1434 additions and 66 deletions

View File

@@ -0,0 +1,74 @@
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"}