DeepEval TypeScript SDK 实战指南:用 Vitest 风格测试为 LLM 应用构建端到端评估
【免费下载链接】deepevalThe LLM Evaluation Framework项目地址: https://gitcode.com/GitHub_Trending/de/deepeval
DeepEval 是开源的 LLM 评估框架,其 TypeScript SDK 以 Vitest 测试运行器为载体,提供 G-Eval、任务完成度、答案相关性、幻觉检测等研究级指标,让开发者在本机本地化运行 LLM-as-a-judge 评估。本文从安装、编写第一条测试用例开始,完整讲解指标体系、Trace 追踪、框架集成、Judge 模型切换,并对照仓库源码深入每个配置项的含义与默认值,帮助你为 Agent、RAG 流水线和聊天机器人搭建可复现、可解释的自动化评估流程。
Quickstart:十分钟跑通第一条 LLM 评估测试
安装与登录
DeepEval TypeScript SDK 以开发依赖形式安装,包名与 Python 版一致:
npm install --save-dev deepeval登录 Confident AI 可以把评估结果同步到云端、跨多次运行对比效果。登录免费且无需额外写代码——即使不登录,评估结果也会照常打印到终端:
npx deepeval login登录命令由deepeval的 bin 入口提供(见 typescript/package.json 中的"bin": {"deepeval": "dist/cli/index.js"}),CLI 基于 commander 实现,子命令包括login、test run、inspect、settings以及一组set-<provider>/unset-<provider>命令。
编写第一条测试
指标默认使用 OpenAI 作为 Judge 模型,因此需要先设置OPENAI_API_KEY。SDK 会自动加载.env.local和.env文件(对应源码 typescript/src/config/dotenv-handler.ts)。
import { LLMTestCase, SingleTurnParams } from "deepeval/test-case"; import { GEval } from "deepeval/metrics"; import { it, expect } from "vitest"; import "deepeval/vitest"; it("gives a correct answer", async () => { const correctnessMetric = new GEval({ name: "Correctness", criteria: "Determine if the 'actual output' is correct based on the 'expected output'.", evaluationParams: [ SingleTurnParams.ACTUAL_OUTPUT, SingleTurnParams.EXPECTED_OUTPUT, ], threshold: 0.5, }); const testCase = new LLMTestCase({ input: "What if these shoes don't fit?", // Replace this with the actual output from your LLM application actualOutput: "You have 30 days to get a full refund at no extra cost.", expectedOutput: "We offer a 30-day full refund at no extra costs.", }); await expect(testCase).toPass([correctnessMetric]); });运行测试:
npx deepeval test run example.test.ts得分范围是 0 到 1,threshold决定测试是否通过;每个指标都会附带解释文本,失败时会告诉你失败的原因。
从源码看,import "deepeval/vitest"这一步做了三件事(见 typescript/src/integrations/vitest/index.mts):
- 调用
expect.extend({ toPass })注册toPass()匹配器; - 通过
beforeAll/afterAll在测试文件层面开启并结束一次评估运行(beginEvaluationRun/session.finish()),并记录遥测事件; - 通过
beforeEach/afterEach调用beginTraceCapture()/endTraceCapture()为每个测试用例捕获 Trace 数据,这样npx deepeval inspect才能回放测试执行轨迹。
此外它还为 Vitest 的Assertion接口补充了toPass(metrics, options)的类型声明(TypeScriptdeclare module "vitest"),让你在测试文件里获得完整的类型提示。
在原生 Vitest 下运行
npx deepeval test run会自动注入toPass匹配器和测试运行报告器。如果你希望用项目自己的vitest命令运行,需要在配置中手动注册:
import { defineConfig } from "vitest/config"; export default defineConfig({ test: { setupFiles: ["deepeval/vitest"], globalSetup: ["deepeval/vitest/global-setup"], testTimeout: 120_000, hookTimeout: 120_000, }, });globalSetup会在测试进程启动时分配本次运行的 run id(通过环境变量传递),保证同一会话内多个测试文件的事件被聚合为同一次运行。
指标体系:从通用 G-Eval 到专用指标
所有指标都是从deepeval/metrics导出的类,构造时接收一个 options 对象,调用后返回score和reason。仓库中每个指标一个目录(见 typescript/src/metrics),目录内通常包含index.ts、指标实现和schema.ts(输出 JSON Schema 校验)。
通用与自定义指标
GEval:用纯英文写出任意评估标准,让 LLM 按标准打分,是最灵活的全能型指标。其实现位于 typescript/src/metrics/g-eval/g-eval.ts,核心选项包括:
| 选项 | 类型 | 说明 |
|---|---|---|
name | string | 指标显示名,默认会附加[GEval]后缀 |
evaluationParams | SingleTurnParams[] | 参与评估的测试用例字段,必填且不能为空,否则构造器直接抛错 |
criteria | string | 评估标准(自然语言描述) |
evaluationSteps | string[] | 可选的评估步骤;不传时由模型基于 criteria 自动生成(generateEvaluationSteps) |
rubric | Rubric[] | 评分量表,用于替代 0-1 连续打分 |
threshold | number | 通过阈值,默认 0.5 |
model | 模型或字符串 | 指定 Judge 模型 |
strictMode | boolean | 严格模式:按整数分(Math.trunc)计分且阈值固定为 1 |
topLogprobs | number | 对支持 logprob 的模型加权备选得分 token,默认 20 |
flaky/verboseMode/showIndicator | boolean | 抖动标记、详细日志、进度指示 |
includeGEvalSuffix | boolean | 是否在指标名后加[GEval],默认 true |
SingleTurnParams枚举定义在 typescript/src/test-case/llm-test-case.ts,可选值包括INPUT、ACTUAL_OUTPUT、EXPECTED_OUTPUT、CONTEXT、RETRIEVAL_CONTEXT、TOOLS_CALLED、EXPECTED_TOOLS,以及 MCP 相关字段(MCP_SERVERS、MCP_TOOLS_CALLED、MCP_RESOURCES_CALLED、MCP_PROMPTS_CALLED)。
DAGMetric:当你需要可重复、确定性的判定结果时,用 DAGMetric 把多个 LLM 判定组织成一颗决策树,按树结构逐节点求值。对应实现位于 typescript/src/metrics/dag。
Agentic(智能体)指标
面向 Agent 完整决策轨迹的指标:
TaskCompletionMetric(任务是否完成)ToolCorrectnessMetric(工具调用是否正确)GoalAccuracyMetric(目标达成精度)StepEfficiencyMetric(步骤效率)PlanAdherenceMetric(是否遵循计划)PlanQualityMetric(计划质量)ToolUseMetric(工具使用)ArgumentCorrectnessMetric(论证正确性)
这些指标依赖LLMTestCase上的toolsCalled/expectedTools字段(类型为ToolCall[],见 typescript/src/test-case/llm-test-case.ts),ToolCall支持name、description、type(FUNCTION或MCP)、reasoning、output、inputParameters。
RAG 指标
检索增强生成场景下常用:
AnswerRelevancyMetric(答案相关性)FaithfulnessMetric(忠实度,答案是否忠实于检索上下文)ContextualRecallMetric(上下文召回)ContextualPrecisionMetric(上下文精确度)ContextualRelevancyMetric(上下文相关性)
它们依赖LLMTestCase.retrievalContext字段,该字段接受字符串数组或RetrievedContextData对象(含context与source两个属性,序列化后形如"source: context")。
多轮对话指标
KnowledgeRetentionMetric、ConversationCompletenessMetric、TurnRelevancyMetric、TurnFaithfulnessMetric、RoleAdherenceMetric、TopicAdherenceMetric、TurnContextualPrecisionMetric、TurnContextualRecallMetric、TurnContextualRelevancyMetric、ConversationalGEval、ConversationalDAGMetric。多轮指标配合ConversationalTestCase使用,后者内部包含turns数组。
MCP 指标
针对 Model Context Protocol 场景:MCPTaskCompletionMetric、MCPUseMetric、MultiTurnMCPUseMetric。它们对应LLMTestCase上的mcpServers、mcpToolsCalled、mcpResourcesCalled、mcpPromptsCalled字段,实现见 typescript/src/metrics/mcp。
多模态指标
TextToImageMetric、ImageEditingMetric、ImageCoherenceMetric、ImageHelpfulnessMetric、ImageReferenceMetric,位于 typescript/src/metrics/multimodal-metrics。多模态用例通过LLMTestCase中的图片 slug 自动检测(detectMultimodal),配合MLLMImage注册表使用。
安全、正确性与确定性指标
HallucinationMetric、SummarizationMetric、BiasMetric、ToxicityMetric、JsonCorrectnessMetric、PromptAlignmentMetric、PIILeakageMetric、NonAdviceMetric、MisuseMetric、RoleViolationMetric。
其中ExactMatchMetric和PatternMatchMetric完全不需要 LLM 参与,是零成本、零延迟的确定性指标,适合作为回归测试的第一道防线。
指标独立使用
指标可以脱离测试框架独立运行。先构造指标,再调用measure(testCase),随后读取score与reason:
import { AnswerRelevancyMetric } from "deepeval/metrics"; import { LLMTestCase } from "deepeval/test-case"; const metric = new AnswerRelevancyMetric({ threshold: 0.7 }); await metric.measure( new LLMTestCase({ input: "What if these shoes don't fit?", actualOutput: "We offer a 30-day full refund at no extra costs.", }), ); console.log(metric.score, metric.reason);对于脚本场景,可以用evaluate(testCases, metrics)(从deepeval主入口导出)一次批量打分,而不必套用测试套件。
Tracing:评估完整的 Agent 轨迹
用 observe() 包装函数
把任意函数包进observe(),DeepEval 会记录模型决策、工具调用和中间步骤的有序序列。有了 Trace,你评估的不再只是最终答案,而是完整的智能体轨迹,并能对轨迹中的单个组件单独打分:
import { observe, updateCurrentSpan } from "deepeval/tracing"; import { AnswerRelevancyMetric } from "deepeval/metrics"; import { LLMTestCase } from "deepeval/test-case"; const retrieve = observe({ type: "retriever", metrics: [new AnswerRelevancyMetric()], fn: async (query: string) => { const output = await search(query); updateCurrentSpan({ testCase: new LLMTestCase({ input: query, actualOutput: output }), }); return output; }, });observe、updateCurrentSpan、updateCurrentTrace、traceManager、getCurrentSpan、getCurrentTrace、SpanType等 API 统一从deepeval/tracing导出(见 typescript/src/tracing/index.ts)。span 类型包括 LLM、Agent、Tool、Retriever 等,每种都有对应的更新函数(updateLlmSpan、updateRetrieverSpan等)。
用 evalsIterator() 跑数据集
通过evalsIterator()把数据集送入被追踪的应用逐条执行。Trace 级指标评判整条轨迹;nextLlmSpan(以及nextAgentSpan、nextToolSpan、nextRetrieverSpan)则把指标挂载到下一个匹配的组件 span 上,实现组件级评分:
import { EvaluationDataset, Golden } from "deepeval/dataset"; import { TaskCompletionMetric } from "deepeval/metrics"; const dataset = new EvaluationDataset({ goldens: [new Golden({ input: "What's the weather in Tokyo?" })], }); for await (const golden of dataset.evalsIterator({ metrics: [new TaskCompletionMetric()], })) { await myAgent(golden.input); }Golden是最小粒度的数据单元,只需input即可创建,可选字段包括actualOutput、expectedOutput、context、retrievalContext、toolsCalled、expectedTools等(见 typescript/src/dataset/golden.ts)。EvaluationDataset同时支持单轮(Golden/LLMTestCase)与多轮(ConversationalGolden/ConversationalTestCase),两者不可混用,源码会在添加时做类型校验(见 typescript/src/dataset/dataset.ts)。
终端回放 Trace
运行:
npx deepeval inspect即可在终端以交互式 UI 回放 Trace 树。该命令对应 typescript/src/inspect 目录,底层基于 React + ink 构建终端界面,支持 span 树展开、详情查看等操作。
框架集成:免 observe 的自动追踪
如果你在使用成熟的 Agent 框架,可以完全跳过observe()——注册集成后,框架自身的 span 就会成为 DeepEval 的 Trace,其余代码保持不变。各框架仅初始化一行不同:
| 框架 | 初始化方式 |
|---|---|
| OpenAI | instrumentOpenAI(client),来自deepeval/openai |
| LangChain / LangGraph | new DeepEvalCallbackHandler({})作为 callback 传入 |
| OpenAI Agents | setTraceProcessors([new DeepEvalTracingProcessor()]) |
| Mastra | new DeepEvalExporter()作为 observability exporter |
| AI SDK | configureAiSdkTracing()作为experimental_telemetry.tracer |
| OpenInference | instrumentOpenInference() |
每个集成位于deepeval/integrations/<name>子路径下,与 typescript/package.json 中exports字段声明的入口一一对应。注意:AI SDK 和 OpenInference 集成需要开启isTestMode: true才能让 Trace 数据到达evalsIterator。
选择 Judge 模型
指标默认用 OpenAI 作为 Judge,因此多数场景只需OPENAI_API_KEY。切换模型有两种方式:
- 按指标指定:在指标 options 中传
model参数; - 全局默认:通过 CLI 设置:
npx deepeval set-anthropic --model claude-opus-5set-<provider>/unset-<provider>命令对每个 provider 生成完全一致的交互,其声明式配置集中在 typescript/src/cli/providers.ts,当前支持以下 provider:
| Provider | 关键环境变量 | 额外选项 |
|---|---|---|
| OpenAI | OPENAI_API_KEY、OPENAI_MODEL_NAME | 成本跟踪(OPENAI_COST_PER_INPUT_TOKEN等) |
| Azure OpenAI | AZURE_OPENAI_API_KEY、AZURE_MODEL_NAME | --base-url、--api-version、--model-version、--deployment-name |
| Anthropic | ANTHROPIC_API_KEY、ANTHROPIC_MODEL_NAME | 成本跟踪 |
| AWS Bedrock | AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY | --region |
| Ollama | OLLAMA_MODEL_NAME | --base-url(默认http://localhost:11434),自动写入占位 keyollama |
| Local model | LOCAL_MODEL_NAME、LOCAL_MODEL_BASE_URL | --format(默认json) |
| Grok | GROK_API_KEY、GROK_MODEL_NAME | 成本跟踪 |
| Moonshot | MOONSHOT_API_KEY、MOONSHOT_MODEL_NAME | --base-url |
| DeepSeek | DEEPSEEK_API_KEY、DEEPSEEK_MODEL_NAME | 成本跟踪 |
| Gemini | GOOGLE_API_KEY、GEMINI_MODEL_NAME | --project、--location、--service-account-file(Vertex AI) |
| Portkey | PORTKEY_API_KEY、PORTKEY_MODEL_NAME | --base-url、--provider |
| OpenRouter | OPENROUTER_API_KEY、OPENROUTER_MODEL_NAME | --base-url、--temperature |
从 typescript/src/cli/commands/providers.ts 可以看到,set-*命令执行时会做三件事:把其他 provider 的USE_*开关置空并只启用当前 provider(switchModelProvider)、写入模型名与密钥、支持-i/-o覆盖每 token 成本(用于未知模型的自定义成本跟踪)。-k/--prompt-api-key与-a/--prompt-credentials选项可以在终端以隐藏输入方式录入密钥(不适合 CI 环境)。
其它通用设置可通过npx deepeval settings查看与修改(支持--set KEY=VALUE、--unset、--list及大小写不敏感的部分匹配过滤),set-confident-region可切换 Confident AI 数据区域(US / EU / AU),set-debug/unset-debug负责日志级别、verbose 模式、gRPC 日志与 Trace 采样率等调试开关,详见 typescript/src/cli/commands/settings.ts。
Python 与 TypeScript SDK 的差异
两个 SDK 共享几乎全部指标,以及 Tracing、数据集、Prompt、CLI 和 Confident AI 集成,日常工作流一致。TypeScript 版独有的能力包括:Vitest 的toPass()匹配器(对应 Python 的assert_test)、npx deepeval inspectTrace 查看器,以及 Python 没有的 Mastra 与 AI SDK 集成。
目前仍仅限 Python 的能力:
- Synthesizer——合成数据集生成。TypeScript 需要手写 goldens 或从 Confident AI 拉取;
- Benchmarks——MMLU、HellaSwag、DROP、BIG-Bench Hard、TruthfulQA、HumanEval、GSM8K 等(对应 deepeval/benchmarks);
- 红队(Red teaming)与提示词优化;
- RAGAS 指标,以及
AgentLoopDetectionMetric、ToolPermissionMetric; - CrewAI、LlamaIndex、Pydantic AI、Google ADK、AWS AgentCore、Strands、Anthropic client 等集成。
两个 SDK 位于同一仓库:Python 包在 deepeval 目录,TypeScript 包在 typescript 目录;两者的 provider 环境变量命名相互对齐(typescript/src/cli/providers.ts 注释明确说明其镜像了 Python 的deepeval/key_handler.py),这意味着你可以放心地在同一套 CI 配置里维护两套语言的评估。
实战建议
- 从确定性指标起步:先加
ExactMatchMetric/PatternMatchMetric做零成本回归,再叠加 LLM-as-a-judge 指标控制质量上限; - 阈值按指标场景设置:G-Eval 默认阈值 0.5,严格场景可开启
strictMode(得分取整、阈值固定为 1);RAG 指标常用 0.6~0.7; - 用 Trace 定位问题组件:
evalsIterator()+ span 级指标可以把一次失败的 Agent 轨迹精确归因到检索、工具调用或某个 LLM 步骤; - 在 CI 中运行:
npx deepeval test run输出与 Vitest 兼容的测试报告,配合--save=dotenv让密钥与配置落盘到.env.local,避免在流水线里硬编码密钥; - 保持两端一致:如果团队同时维护 Python 与 TypeScript 服务,优先复用同一套数据与评估标准,利用两者共享的 Confident AI 数据集同步能力(
EvaluationDataset.pull/push,见 typescript/src/dataset/dataset.ts)维持双端口径统一。
【免费下载链接】deepevalThe LLM Evaluation Framework项目地址: https://gitcode.com/GitHub_Trending/de/deepeval
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考