跳到正文
北京时间
原文
LangChain:Blog·· 2025-01-23精选AI 评分60

LangSmith 推出 Pytest 和 Vitest/Jest 评测集成(beta)

Introducing Pytest and Vitest integrations for LangSmith Evaluations

AI 导读

LangChain 发布 LangSmith 的 Pytest 与 Vitest/Jest 集成,随 Python 和 TypeScript SDK v0.3.0 以 beta 提供,让开发者沿用现有测试框架运行 LLM 评测并记录到 LangSmith。

推荐理由

原文介绍了将 LLM 评测接入 Pytest/Vitest 的具体用法和与 evaluate() 的差异,开发者可直接对照迁移现有测试流程。

正文 · AI 翻译

评估(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。

从左到右,从上到下:1. 给定测试套件的运行表,2. 测试套件运行的结果,3. 测试用例的追踪,4. 测试用例反馈的追踪。

请访问我们的 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