Onyx 评估框架Evals实战指南基于 Braintrust 的对话与工具调用自动化评测【免费下载链接】danswerOpen Source AI Platform - AI Chat with advanced features that works with every LLM项目地址: https://gitcode.com/GitHub_Trending/da/danswer本指南系统讲解 Onyx 内置评估框架backend/onyx/evals/的使用方法与底层原理它借助 Braintrust 对 Onyx 的聊天回复与检索系统进行自动化评测支持单轮与多轮对话场景、按测试用例配置工具强制调用与断言、跨模型如 gpt-4o、claude-3-5-sonnet横向对比以及本地免 Braintrust 的 CLI 调试模式。读完本文你将能够编写评估数据集、通过 CLI 或 VS Code 启动评估、读懂 Braintrust 仪表盘中的tool_assertion评分并理解评估背后的完整调用链。一、评估框架概览评估框架位于 backend/onyx/evals/用于测试和量化 Onyx 聊天与检索系统的表现。核心目标包括对 Onyx 聊天系统生成的回复质量进行自动化评测验证模型是否正确调用了预期工具如内部检索、联网搜索、Python 执行等长期追踪性能变化衡量迭代改进效果。框架目录结构如下backend/onyx/evals/ ├── README.md # 本文对应的官方文档 ├── eval.py # 评估核心执行逻辑单轮 / 多轮 ├── eval_cli.py # CLI 入口支持本地与远程两种运行方式 ├── models.py # 评估相关的数据模型与配置 ├── provider.py # 评估 Provider 工厂本地 / Braintrust ├── providers/ │ ├── braintrust.py # Braintrust 评估 Provider 与评分器 │ └── local.py # 纯本地评估 ProviderCLI 输出 └── one_off/ └── create_braintrust_dataset.py # 从 CSV 构建 Braintrust 数据集的辅助脚本从源码结构看框架采用Provider 抽象设计provider.py 中的get_provider(local_onlyFalse)会根据参数返回两种实现BraintrustEvalProvider默认调用 Braintrust 的Eval接口运行评估结果上报至 Braintrust 仪表盘LocalEvalProvider完全本地运行不需要 Braintrust 账号或外部服务结果直接打印到 CLI适合快速调试。两种 Provider 都实现同一个EvalProvider抽象基类定义见 models.py因此评估核心逻辑可以无缝切换后端。二、运行前置条件重要评估依赖 Onyx 的模型服务器model server它承载 Embedding 与 LLM 推理。确保模型服务器已启动并正常运行后再执行任何评估否则评测将无法工作。此外还需要准备搜索权限邮箱--search-permissions-email评估将以该邮箱对应用户的权限来执行检索与聊天因此该用户必须已存在于系统中且具备访问相应数据源的权限API Key远程评估时需要在 Onyx 管理后台admin panel创建 API Key用于触发远程评估任务环境变量远程评估的 API Key 可通过环境变量ONYX_EVAL_API_KEY提供配置在.env文件中即可这样无需在每次触发远程评估时手动指定。框架启动时会初始化数据库会话与日志eval_cli.py 中的setup_session_factory()调用SqlEngine.init_engine()建立数据库连接池eval_cli.py 中的configure_logging_for_evals()默认把日志级别压到WARNING以减少输出干扰--verbose可恢复详细日志。三、运行评估的三种方式1. 触发远程评估任务将评估作业发送到远程 Onyx 服务器执行onyx/backend$ python -m dotenv -f .vscode/.env run -- python onyx/evals/eval_cli.py --remote --api-key SUPER_CLOUD_USER_API_KEY --search-permissions-email email account to reference --remote-dataset-name Simple说明--remote表示触发远程评估流水线--api-key为远程服务器的认证 Key若省略则会读取环境变量ONYX_EVAL_API_KEY--search-permissions-email指定评估所模拟的用户邮箱--remote-dataset-name指定远程 Braintrust 数据集名称如示例中的Simple。远程模式的实际请求由 eval_cli.py 中的run_remote()完成它向{base_url}/api/evals/eval_run发送POST请求请求头携带Authorization: Bearer api_key并在 payload 中注入search_permissions_email与dataset_name字段。默认base_url为https://test.onyx.app可用--base-url覆盖。若请求失败如 Key 无效会抛出requests.RequestException并在 CLI 打印错误信息。2. 本地直接运行 CLI在本地直接执行评估数据来自本地 JSON 文件onyx$ python -m dotenv -f .vscode/.env run -- python backend/onyx/evals/eval_cli.py --local-data-path backend/onyx/evals/data/eval.json --search-permissions-email richardonyx.app该命令会通过load_data_local()读取 JSON 文件并校验其存在不存在时抛出ValueError见 eval_cli.py构建EvalConfigurationOptions配置dataset_name默认取local选择 Provider 并执行评估最终返回EvalationAck(success...)。若同时指定了--remote-dataset-name本地 CLI 会直接拉取该 Braintrust 数据集进行评测无需本地数据文件。3. 使用 VS Code 启动配置推荐用于本地调试框架推荐从 VS Code 启动配置运行本地评估以获得最佳调试体验在项目根目录打开 VS Code进入 Run and Debug 面板快捷键 Ctrl/Cmd Shift D从下拉列表选择Eval CLI配置点击播放按钮或按 F5。该配置默认使用以下设置使用本地数据文件evals/data/data.json开启 verbose 详细输出自动配置好环境变量与 Python 路径。四、CLI 选项全解析eval_cli.py基于argparse构建见 eval_cli.py支持的选项如下参数类型默认值说明--local-data-pathstr无包含测试数据的本地 JSON 文件路径--remote-dataset-namestr无远程 Braintrust 数据集名称--braintrust-projectstrOnyxBraintrust 项目名覆盖BRAINTRUST_PROJECT环境变量--verboseflag关闭开启详细日志输出--base-urlstrhttps://test.onyx.app远程评估服务器的基础 URL--api-keystrONYX_EVAL_API_KEY与远程服务器认证的 API Key--remoteflag关闭在远程服务器运行评估而非本地--search-permissions-emailstr无评估所模拟的用户邮箱本地评估必填--no-send-logsflag关闭不向 Braintrust 发送日志适合本地测试--local-onlyflag关闭完全本地运行评估不使用 Braintrust仅 CLI 输出使用注意事项源码级约束--local-only不能与--remote-dataset-name同时使用二者互斥见 eval_cli.py本地评估时--search-permissions-email为必填缺失会抛出ValueError见 eval_cli.py指定--remote-dataset-name时CLI 会先用braintrust.init_dataset()拉取数据集并打印其规模Dataset size便于执行前确认数据量。框架还支持以下 Braintrust 相关环境变量定义于 app_configs.pyBRAINTRUST_PROJECTBraintrust 项目名默认OnyxBRAINTRUST_API_KEYBraintrust API Key提供后启用 Braintrust 追踪BRAINTRUST_API_URL自定义 Braintrust API 地址自托管 / 非默认部署场景BRAINTRUST_MAX_CONCURRENCY评估最大并发数None表示不限制对应Eval调用中的max_concurrency参数。五、测试数据集格式评估的测试数据存放在本地 JSON 文件中如evals/data/data.json内容为一组测试用例test case的列表。每个测试用例至少包含一个input字段其核心是待测试的问题或提示词。最简单的基础用例{ input: { message: What is the capital of France? } }在 Braintrust 模式下每个测试用例还会被转换为EvalCaseinput中会透传force_tools、expected_tools、require_all_tools、model、model_provider、temperature等逐测试配置expected字段则对应EvalCase.expected见 braintrust.py。若数据集是远程的可使用--remote-dataset-name直接引用也可以使用仓库提供的辅助脚本 create_braintrust_dataset.py 从 CSV 文件批量创建 Braintrust 数据集。六、单轮测试的逐测试配置除input.message外每个测试用例还可以添加以下可选字段实现工具强制、断言与模型配置的按用例定制。工具配置字段类型默认值说明force_toolslist[str][]强制该测试调用指定的工具类型列表expected_toolslist[str][]预期会被调用的工具类型列表require_all_toolsboolfalse若为 true则expected_tools中所有工具都必须被调用模型配置字段类型默认值说明modelstrgpt-4o使用的模型版本如gpt-4o、claude-3-5-sonnetmodel_providerstr全局配置模型供应商如openai、anthropictemperaturefloat0.0模型采样温度框架的全局默认 LLM 配置在 models.py 的EvalConfigurationOptions中定义默认模型版本gpt-4o、默认温度0.0。逐测试的model/model_provider/temperature会通过构造新的LLMOverride覆盖全局配置未指定的字段回退到全局值具体逻辑见 eval.py。带工具与模型配置的完整示例[ { input: { message: Find information about Python programming }, expected_tools: [SearchTool], force_tools: [SearchTool], model: gpt-4o }, { input: { message: Search the web for recent news about AI }, expected_tools: [WebSearchTool], model: claude-3-5-sonnet, model_provider: anthropic }, { input: { message: Calculate 2 2 }, expected_tools: [PythonTool], temperature: 0.5 } ]关于工具断言的判定逻辑可参考 eval.py 中的evaluate_tool_assertions()未配置expected_tools时返回(None, None)表示“无断言”不参与通过/失败统计require_allTrue时expected_tools中任一工具未被调用即判定失败并输出缺失工具列表require_allFalse默认时只要expected_tools中至少有一个工具被调用即判定通过。force_tools的实现细节在 eval.py 中强制工具会通过BUILT_IN_TOOL_MAP映射为数据库中的工具 ID并作为SendMessageRequest.forced_tool_id传给聊天流水线多个强制工具取第一个从而约束模型只能调用该工具。七、多轮评估Multi-Turn Evaluations真实对话往往跨越多个来回且每一轮可能需要不同工具。为此框架支持messages数组格式替代单轮的message字段{ input: { messages: [ { message: Whats the latest news about OpenAI today?, expected_tools: [WebSearchTool, OpenURLTool] }, { message: Now search our internal docs for our OpenAI integration guide, expected_tools: [SearchTool] }, { message: Thanks, thats helpful!, expected_tools: [] } ] } }messages数组中的每个元素消息都可以携带自己的配置字段说明message用户消息文本必填expected_tools本轮预期调用的工具类型列表require_all_tools若为 true本轮所有预期工具必须全部被调用默认 falseforce_tools本轮强制调用的工具类型列表model本轮使用的模型版本覆盖model_provider本轮模型供应商覆盖temperature本轮采样温度覆盖多轮评估的关键特性是所有轮次在同一个聊天会话chat session中顺序执行因此模型在回复后续轮次时拥有前面所有轮次的完整上下文能够测试真实的连续对话能力。源码实现位于 eval.py 的_get_multi_turn_answer_with_tools()先为整个对话创建单个chat_session每轮消息通过parent_message_idAUTO_PLACE_AFTER_LATEST_MESSAGE自动接续在最新消息之后形成会话链每轮独立计算expected_tools断言结束时统计pass_count/fail_count/total_turns只要没有任何失败轮次即判定all_passed未配置断言的轮次不计为失败。多轮结果会返回MultiTurnEvalResult其评分按“通过断言数 / 已评估断言数”计算详见下一节。八、可用工具类型框架支持的内置工具类型对应BUILT_IN_TOOL_MAP完整注册表见 built_in_tools.py工具类型功能SearchTool内部文档检索WebSearchTool互联网 / Web 搜索ImageGenerationTool图像生成PythonToolPython 代码执行OpenURLTool打开并读取 URL除上述五种外BUILT_IN_TOOL_MAP中还注册了KnowledgeGraphTool知识图谱、FileReaderTool文件读取、MemoryTool记忆、CodingAgentTool编码 Agent等工具类型。其中ImageGenerationTool属于“停止类工具”调用后结束回复生成而SearchTool、WebSearchTool等属于“可引用类工具”回复可附带引用见 built_in_tools.py 的STOPPING_TOOLS_NAMES与CITEABLE_TOOLS_NAMES。评估配置中的allowed_tool_ids默认即为全部内置工具的 ID 集合由EvalConfigurationOptions.builtin_tool_types默认list(BUILT_IN_TOOL_MAP.keys())经数据库查询转换而来见 models.py 的get_configuration()。九、评估结果与 Braintrust 仪表盘评估完成后可在 Braintrust 仪表盘中查看结果。框架的评分器tool_assertion_scorer实现于 braintrust.py负责将每个用例的输出转换为分数单轮场景若断言通过或未配置断言tool_assertion得分为1.0若断言失败得分为0.0元数据包含tools_called、tools_called_count、assertion_passed、assertion_details与tool_call_details含工具名与参数。多轮场景得分 pass_count / (pass_count fail_count)若无任何断言则视为1.0元数据包含is_multi_turn、total_turns、pass_count、fail_count、all_passed以及每轮的turn_detailstools_called、assertion_passed、assertion_details。每个用例还会上报执行耗时EvalTimings总耗时、LLM 首 token 耗时、各工具执行耗时、流式处理耗时模型定义见 models.py便于定位性能瓶颈。评估的整体配置LLM 覆盖、数据集名、权限邮箱等会作为metadata写入 Braintrust 实验方便横向对比不同模型、不同配置下的表现。十、本地免 Braintrust 调试--local-only模式如果只想快速验证数据集或调试工具配置无需 Braintrust 账号可以使用--local-only模式python -m dotenv -f .vscode/.env run -- python backend/onyx/evals/eval_cli.py \ --local-data-path backend/onyx/evals/data/eval.json \ --search-permissions-email richardonyx.app \ --local-onlyLocalEvalProvider见 local.py会在终端逐条打印结果每条用例显示序号、消息预览、模型、工具调用轨迹含各阶段耗时、工具调用列表、断言状态PASS / FAIL / N/A以及截断到 200 字符的回复摘要最后输出汇总统计通过数、失败数、无断言数、通过率。所有输出带有 ANSI 颜色标记便于阅读。该模式不支持远程数据集--remote-dataset-name会报错并跳过 Braintrust 追踪初始化。值得注意的是评估过程运行在临时回滚事务中isolated_ephemeral_session_factory()见 eval.py为整个评估创建外层事务并在结束时整体回滚确保评估不会在数据库中留下副作用可安全地在开发环境反复运行。十一、评估的内部调用链原理速览一次本地评估的完整调用链如下便于排查问题或二次开发eval_cli.py main()解析参数决定本地 / 远程分支eval_cli.py本地分支调用run_local()初始化数据库与日志构建EvalConfigurationOptionseval_cli.pyrun_eval()校验数据来源本地数据与远程数据集互斥见 eval.py并把单轮任务_get_answer_with_tools与多轮任务_get_multi_turn_answer_with_tools包装成闭包传给 ProviderProvider 逐用例执行BraintrustEvalProvider通过dispatch_task依据input中是否含messages字段自动分派单轮 / 多轮braintrust.py每个用例内部解析工具强制与模型覆盖 → 通过handle_stream_message_objects进入聊天流水线 →gather_stream_full收集完整回复 →evaluate_tool_assertions判定断言eval.py结果交由tool_assertion_scorer评分并上报最终返回EvalationAck(success...)。掌握这条链路后你可以自由扩展新的评分器、新增内置工具断言类型或将评估数据源切换为自定义 CSV/JSON 格式把评估体系接入自己的 CI 流程长期跟踪 Onyx 对话质量的每一次迭代变化。【免费下载链接】danswerOpen Source AI Platform - AI Chat with advanced features that works with every LLM项目地址: https://gitcode.com/GitHub_Trending/da/danswer创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考