LangSmith 推出 Pytest 和 Vitest/Jest 评测集成(beta)
Introducing Pytest and Vitest integrations for LangSmith Evaluations
LangChain 发布 LangSmith 的 Pytest 与 Vitest/Jest 集成,随 Python 和 TypeScript SDK v0.3.0 以 beta 提供,让开发者沿用现有测试框架运行 LLM 评测并记录到 LangSmith。
原文介绍了将 LLM 评测接入 Pytest/Vitest 的具体用法和与 evaluate() 的差异,开发者可直接对照迁移现有测试流程。
评估(evals)是构建可靠且高质量 LLM 应用的重要组成部分。它们帮助你评估应用的性能,确保在你进行更新时质量保持一致。如果你有软件工程背景,你可能熟悉使用测试来实现这一目的。为了扩展这一熟悉的接口,我们很高兴地推出一种使用 LangSmith 的 Pytest 和 Vitest/Jest 集成来运行评估的新方式。
这些新集成现已在 LangSmith Python 和 Typescript SDK 的 v0.3.0 版本中以 beta 形式提供。

为什么使用测试框架进行 LLM 评估
如果你已经在使用 Pytest 或 Vitest/Jest 来测试你的应用,新的 LangSmith 集成让你能够获得 Pytest/Vitest 的灵活性、熟悉度和运行时行为,同时具备 LangSmith 的可观测性和共享功能。这些集成使用与你习惯的完全相同的开发者体验(DX),并具有以下优势:
在 LangSmith 中调试你的测试
使用 LLM 的应用由于其非确定性本质,在调试时具有额外的复杂性。LangSmith 会保存你的测试用例的输入/输出和堆栈跟踪,以帮助你精确定位问题的根本原因。
在 LangSmith 中记录指标(超越通过/失败)并跟踪随时间的变化
通常,测试框架只关注通过/失败结果,但测试 LLM 应用往往需要更细致的方法。你可能没有严格的通过/失败标准;相反,你想要记录结果并观察你的应用如何随时间改进。使用 LangSmith,你可以记录反馈并随时间比较结果,以防止回归并确保你始终部署最佳版本的应用。

与你的团队分享结果
使用 LLM 构建通常是团队协作。我们经常看到主题专家参与提示创建或创建评估的过程。LangSmith 允许你在团队中分享实验结果,使协作更容易。
内置评估函数
如果你使用 Python,LangSmith 提供了一些内置评估函数,用于检查你的 LLM 输出。例如,expect.edit_distance() 用于计算测试输出与提供的参考输出之间的字符串距离。有关内置评估函数的更多详细信息,请访问我们的 API 参考。
开始使用
以下是一个简单的测试用例,演示如何评估一个生成 SQL 查询的应用。此测试检查应用是否正确识别偏离主题的用户输入,并将结果记录到 LangSmith。当你运行测试套件时,LangSmith 中会创建/更新一个数据集,并创建一个新的实验。
开始使用 Pytest
要在 LangSmith 中跟踪测试,请添加 @pytest.mark.langsmith 装饰器。
# tests/test_sql.py
import openai
import pytest
from langsmith import wrappers
from langsmith import testing as t
oai_client = wrappers.wrap_openai(openai.OpenAI())
# Define your app logic elsewhere:
# @traceable
# def generate_sql(user_query: str) -> str: ...
@pytest.mark.langsmith
def test_offtopic_input() -> None:
# Log the test case inputs and reference outputs.
user_query = "whats up"
t.log_inputs({"user_query": user_query})
expected = "Sorry that is not a valid question."
t.log_reference_outputs({"response": expected})
actual = generate_sql(user_query)
t.log_outputs({"response": actual})
# Use this context manager to trace any steps used for
# generating evaluation feedback separately from the
# main application logic.
with t.trace_feedback():
instructions = (
"Return 1 if the ACTUAL and EXPECTED answers are semantically equivalent, "
"otherwise return 0. Return only 0 or 1 and nothing else."
)
grade = oai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": instructions},
{"role": "user", "content": f"ACTUAL: {actual}\nEXPECTED: {expected}"},
],
)
score = float(grade.choices[0].message.content)
t.log_feedback(key="correctness", score=score)
assert actual
assert score
像平常一样启动测试:
pytest tests
这将像任何其他 pytest 测试运行一样运行,同时将所有测试用例结果、应用追踪和反馈追踪记录到 LangSmith。




请访问我们的 Pytest 操作指南 查看完整示例。
Vitest 入门
要在 LangSmith 中跟踪测试,请将测试用例包裹在 ls.describe() 块中。
import * as ls from "langsmith/vitest";
import OpenAI from "openai";
import { traceable } from "langsmith/traceable";
import { wrapOpenAI } from "langsmith/wrappers/openai";
//Set OPENAI_API_KEY as an environment variable
const tracedClient = wrapOpenAI(new OpenAI());
const myEvaluator = async (params: {
outputs: { sql: string };
referenceOutputs: { sql: string };
}) => {
const { outputs, referenceOutputs } = params;
const instructions = [
"Return 1 if the ACTUAL and EXPECTED answers are semantically equivalent, ",
"otherwise return 0. Return only 0 or 1 and nothing else.",
].join("\n");
const grade = await tracedClient.chat.completions.create({
model: "gpt-4o-mini",
messages: [
{
role: "system",
content: instructions,
},
{
role: "user",
content: `ACTUAL: ${outputs.sql}\nEXPECTED: ${referenceOutputs.sql}`,
},
],
});
const score = parseInt(grade.choices[0].message.content ?? "");
return { key: "correctness", score };
};
ls.describe("generate sql demo", () => {
ls.test(
"offtopic input",
{
inputs: { userQuery: "whats up" },
referenceOutputs: { sql: "sorry that is not a valid query" },
},
async ({ inputs, referenceOutputs }) => {
const sql = await generateSql(inputs.userQuery); //generateSql is a function that given user input, generates an SQL query given
ls.logOutputs({ sql });
const wrappedEvaluator = ls.wrapEvaluator(myEvaluator);
// Will automatically log "correctness" as feedback
await wrappedEvaluator({
outputs: { sql },
referenceOutputs,
});
}
);
});
请访问我们的 Vitest/Jest 操作指南 查看完整示例。
测试框架与 evaluate() 的对比
大多数流行的评估库,例如 OpenAI Evals、Hugging Face 的 Evaluate 和 LangSmith 的 evaluate(),工作方式类似——你首先预先创建一个数据集,然后定义一个生成函数和一组评估器,在数据集上运行。这种方法通常适用于需要在数据集上运行同一组评估的用例,例如对智能体的输入和输出进行黑盒测试。然而,我们发现它在某些情况下存在不足。
我们已将新的 Pytest 和 Vitest/Jest 集成整合到我们构建的多个应用中(视频即将推出!),并发现它有三个主要优势:
针对每个测试用例的特定评估逻辑。
如果你想评估应用的特定部分,将示例和评估器定义为测试用例比使用 evaluate() 更灵活、更直观。例如,在测试一个可以访问多个工具的智能体时,你会想测试模型调用每个工具的能力。但评估两个工具的方式可能完全不同,这使得定义全局评估器函数变得繁琐。借助新的测试集成,你可以拥有单独的测试用例,并在每个用例中自定义评估逻辑。要了解实际效果,请查看我们的 教程。
实时本地反馈。
测试框架会实时反馈你的测试状态,这使得在过程中发现和修复问题变得更加容易。当你本地迭代应用(包括对应用的部分进行 mock)并需要快速测试评估时,这种快速反馈循环非常有用。
CI 流水线集成。
将评估作为 CI 流水线的一部分运行有助于尽早发现回归。测试框架天然支持定义通过/失败标准,并在 CI 工作流中引发断言错误。
在接下来的几周内,我们将发布一个 Github Action,使配置变得特别简单。
试一试吧!
我们很高兴分享使用 Pytest 和 Vitest/Jest 集成运行评估的新方法!请访问我们的开发者教程和操作指南(Python、TypeScript)开始使用,并查看我们的视频演示(Python、TypeScript)。
如果你有反馈或功能需求,请通过 LangChain Slack 社区与我们联系,或在 GitHub 上提交 issue,告诉我们你的想法。如果你还没有加入 Slack 社区,请在此处注册。
来源:LangChain:Blog · langchain.com