BatchEvalRunner 是 LlamaIndex 中用于高效批量执行多项评估任务的核心工具。简单来说,它专为系统化测试 RAG 系统而设计——能将评估流程从“手动逐一检查”转变为“自动化流水线作业”。

? 为什么需要 BatchEvalRunner?
先思考一个问题:如果你的 RAG 应用需要回答几百甚至上千个问题,你打算如何评估效果?如果逐个手动查看答案、打分,效率极低。因此,BatchEvalRunner 的价值体现在以下几个方面:
- 自动化与批量化处理:无需针对单一问题反复测试,一次性运行整个测试集,成百上千的问题可同时处理。
- 并行化加速:采用异步机制,例如设置
workers=8即可同时发起 8 个并发任务,大幅缩短整体评估耗时。 - 多指标集成:忠实度、相关性、答案正确性等评估维度,可一次性配置完成。运行后输出结构化的统一报告,结果一目了然。
⚙️ 如何使用 BatchEvalRunner?
1. 准备评估器(Evaluators)
首先需要选择一个 LLM 作为“评委”,通常选用能力更强的模型(如 GPT-4)以确保评估结果更加客观。接着用它实例化具体的评估器,例如 FaithfulnessEvaluator(忠实度评估器)和 RelevancyEvaluator(相关性评估器)。
from llama_index.llms.openai import OpenAI
from llama_index.core.evaluation import FaithfulnessEvaluator, RelevancyEvaluator
# 初始化评委模型,temperature=0 确保评估结果一致性
gpt4 = OpenAI(temperature=0, model="gpt-4")
# 实例化忠实度评估器
faithfulness_evaluator = FaithfulnessEvaluator(llm=gpt4)
# 实例化相关性评估器
relevancy_evaluator = RelevancyEvaluator(llm=gpt4)
2. 创建并运行 Runner
将评估器以字典形式传入 BatchEvalRunner,然后调用它的 aevaluate_queries 方法(注意这是一个异步方法)。下面是一个完整的实战示例,包含从文档建索引、构造查询、并行评估到输出报告的全流程。
import asyncio
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.core.evaluation import FaithfulnessEvaluator, RelevancyEvaluator, BatchEvalRunner
from 加载模型 import get_llm
async def main():
# 1. 初始化模型设置 (全局配置)
llm, embed_model = get_llm()
# 2. 准备索引
print("正在构建索引...")
documents = SimpleDirectoryReader(input_files=[r".data小说.txt"]).load_data()
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()
# 3. 初始化评估器
# 建议:评估模型可以选比生成模型更强的(如 GPT-4),结果更客观
"""
忠实度:答案是否忠于检索上下文(有没有凭空捏造)。
答案相关性:答案是否针对用户所问的问题(有没有答非所问)。
"""
faith_evaluator = FaithfulnessEvaluator(llm=llm) # 忠实度评估器
rel_evaluator = RelevancyEvaluator(llm=llm) # 答案相关性评估器
# 4. 批量查询与评估 (核心优化点)
queries = [
"萧炎的爸爸是谁?", # 基础题(预期:1.0)
"萧炎最喜欢的现代流行歌手是谁?", # 跨时空无关(预期:Faithfulness 应该为 1.0,但回答应为“不知道”)
"萧炎在第一章里一共喝了几杯咖啡?",# 逻辑陷阱(玄幻小说没咖啡,看它是否产生幻觉)
"作者天蚕土豆的家庭住址在哪里?", # 外部元数据(文档里没写作者隐私,看它是否拒绝)
"萧炎用什么牌子的智能手机和药老联系?" # 严重干扰项
]
print(f"\n开始批量执行 {len(queries)} 组评估...")
# 使用 BatchEvalRunner 进行并行异步评估
# 相比于 for 循环逐个评估,BatchEvalRunner 能显著提高 Token 利用率和执行速度
runner = BatchEvalRunner({
"faithfulness": faith_evaluator,
"relevancy": rel_evaluator,
}, show_progress=True, workers=4) # 根据 API 限制调整并发数
# aevaluate_queries 会自动执行:查询 -> 获取 Response -> 调用各评估器
eval_results = await runner.aevaluate_queries(query_engine, queries=queries)
# 5. 格式化结果输出
print("\n" + "=" * 50)
print("评估报告汇总")
print("=" * 50)
for query in queries:
print(f"查询问题: {query}")
print("RAG最终的回复:", query_engine.query(query).response)
# 提取各个维度的结果
f_res = eval_results["faithfulness"][queries.index(query)]
r_res = eval_results["relevancy"][queries.index(query)]
# 打印详细打分
print(f"[忠实度 Faithfulness]: {'通过' if f_res.passing else '❌ 失败'} (得分: {f_res.score:.2f})")
if not f_res.passing:
print(f"└─ 反馈: {f_res.feedback}")
print(f"[相关性 Relevancy ]: {'通过' if r_res.passing else '❌ 失败'} (得分: {r_res.score:.2f})")
if not r_res.passing:
print(f"└─ 反馈: {r_res.feedback}")
print("\n" + "=" * 50)
if __name__ == "__main__":
asyncio.run(main())
⚡ 关键特性:异步与并发
BatchEvalRunner 最核心的优势在于其异步并发架构。通过 workers 参数控制并发数量,可以最大化利用 API 额度,将评估时间从“分钟级”压缩至“秒级”。
一个常见易错点:如果在同步环境(如普通 Python 脚本)中直接写 await runner.aevaluate_queries(),会遇到 SyntaxError: 'await' outside function。解决方法很简单——把调用放在一个异步协程内,就像上面示例所示。
? BatchEvalRunner 与其他框架对比
- Langfuse:通过
BatchEvaluationRunner对 Langfuse 平台已有的生产日志(Traces/Observations)进行事后批量分析。 - Ragas:没有直接的 Runner,核心入口是
evaluate()和aevaluate()函数,可批量运行EvaluationDataset。
? 典型应用场景
- 回归测试:将评估流程嵌入 CI/CD 中,每次代码变更后自动运行,通过指标变化检测性能下降(即“回归”)。
- 迭代优化:对测试集运行一次
BatchEvalRunner,生成详细评估报告,然后分析得分较低的案例,定位问题环节并针对性优化。
? 总结
BatchEvalRunner 是 RAG 应用从“能跑”迈向“好用”的关键一步。它帮助你建立定量评估体系,让每次迭代都有数据支撑,而非仅凭感觉。理解了这些之后,若想深入了解更具体的配置——例如如何集成自定义数据集——可查阅官方文档或社区中的实战案例,那里有更详尽的细节。
