> ## Documentation Index
> Fetch the complete documentation index at: https://langchain-zh.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# 评估聊天机器人

在本指南中，我们将为聊天机器人设置评估。这些评估允许您在一组数据上衡量应用程序的性能表现。能够快速可靠地获得这种洞察，将使您能够自信地进行迭代。

从高层次来看，本教程将涵盖以下内容：

* *创建初始的黄金数据集以衡量性能*
* *定义用于衡量性能的指标*
* *在几个不同的提示或模型上运行评估*
* *手动比较结果*
* *随时间跟踪结果*
* *设置在 CI/CD 中运行的自动化测试*

有关 LangSmith 支持的评估工作流的更多信息，请查看[操作指南](/langsmith/evaluation)，或参阅 [evaluate](https://reference.langchain.com/python/langsmith/client/Client/evaluate) 及其异步对应方法 [aevaluate](https://reference.langchain.com/python/langsmith/client/Client/aevaluate) 的参考文档。

内容很多，让我们开始吧！

## 设置

首先安装本教程所需的依赖项。我们这里使用 OpenAI，但 LangSmith 可以与任何模型一起使用：

<CodeGroup>
  ```bash pip theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  pip install -U langsmith openai
  ```

  ```bash uv theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  uv add langsmith openai
  ```
</CodeGroup>

并设置环境变量以启用 LangSmith 追踪：

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
export LANGSMITH_TRACING="true"
export LANGSMITH_API_KEY="<您的 LangSmith API 密钥>"
export OPENAI_API_KEY="<您的 OpenAI API 密钥>"
```

## 创建数据集

准备测试和评估应用程序的第一步是定义要评估的数据点。这里有几个方面需要考虑：

* 每个数据点的模式应该是什么？
* 我应该收集多少个数据点？
* 我应该如何收集这些数据点？

**模式：** 每个数据点至少应包含应用程序的输入。如果可能，定义预期输出也很有帮助——这些代表了您期望一个正常运行的应用程序会输出的内容。通常您无法定义完美的输出——这没关系！评估是一个迭代过程。有时您可能还想为每个示例定义更多信息——例如 RAG 中预期的检索文档，或作为代理预期的执行步骤。LangSmith 数据集非常灵活，允许您定义任意模式。

**数量：** 没有硬性规定应该收集多少。主要的是确保您能充分覆盖可能想要防范的边缘情况。即使是 10-50 个示例也能提供很多价值！开始时不必担心数量少——您可以（也应该）随时添加！

**如何获取：** 这可能是最棘手的部分。一旦您知道要收集数据集……实际上该如何进行？对于大多数开始新项目的团队，我们通常看到他们先手动收集前 10-20 个数据点。从这些数据点开始后，这些数据集通常是*动态*的，会随时间增长。它们通常在看到真实用户如何使用您的应用程序、发现存在的痛点后，将其中一些数据点移入此集合。也有像合成生成数据这样的方法可以用来扩充您的数据集。开始时，我们建议不必担心这些，只需手动标注大约 10-20 个示例。

一旦您有了数据集，有几种不同的方法可以将它们上传到 LangSmith。对于本教程，我们将使用客户端，但您也可以通过 UI 上传（甚至可以在 UI 中创建它们）。

对于本教程，我们将创建 5 个数据点进行评估。我们将评估一个问答应用程序。输入将是一个问题，输出将是一个答案。由于这是一个问答应用程序，我们可以定义预期的答案。让我们展示如何创建此数据集并将其上传到 LangSmith！

```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
from langsmith import Client

client = Client()

# 定义数据集：这些是您的测试用例
dataset_name = "问答示例数据集"
dataset = client.create_dataset(dataset_name)

client.create_examples(
    dataset_id=dataset.id,
    examples=[
        {
            "inputs": {"question": "什么是 LangChain？"},
            "outputs": {"answer": "一个用于构建 LLM 应用程序的框架"},
        },
        {
            "inputs": {"question": "什么是 LangSmith？"},
            "outputs": {"answer": "一个用于观察和评估 LLM 应用程序的平台"},
        },
        {
            "inputs": {"question": "什么是 OpenAI？"},
            "outputs": {"answer": "一家创建大语言模型的公司"},
        },
        {
            "inputs": {"question": "什么是 Google？"},
            "outputs": {"answer": "一家以搜索闻名的科技公司"},
        },
        {
            "inputs": {"question": "什么是 Mistral？"},
            "outputs": {"answer": "一家创建大语言模型的公司"},
        }
    ]
)
```

现在，如果我们转到 LangSmith UI 并在 `数据集与测试` 页面中查找 `问答示例数据集`，点击进入后应该会看到五个新示例。

<img src="https://mintcdn.com/hhh-8c10bf0c/BCyPqRNhtAjzdCmk/langsmith/images/testing-tutorial-dataset.png?fit=max&auto=format&n=BCyPqRNhtAjzdCmk&q=85&s=53f168a5ac220a917d55c1a0887e9683" alt="测试教程数据集" width="1251" height="560" data-path="langsmith/images/testing-tutorial-dataset.png" />

## 定义指标

创建数据集后，我们现在可以定义一些指标来评估我们的响应。由于我们有预期的答案，我们可以将其作为评估的一部分进行比较。然而，我们不期望我们的应用程序输出那些**完全相同的**答案，而是期望输出类似的内容。这使得我们的评估稍微复杂一些。

除了评估正确性，我们还希望确保答案简短精炼。这会容易一些——我们可以定义一个简单的 Python 函数来测量响应的长度。

让我们继续定义这两个指标。

对于第一个指标，我们将使用 LLM 来**判断**输出是否正确（相对于预期输出）。这种 **LLM 作为评判者** 对于过于复杂而无法用简单函数测量的情况相对常见。我们可以在这里定义自己的提示词和用于评估的 LLM：

```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
import openai
from langsmith import wrappers

openai_client = wrappers.wrap_openai(openai.OpenAI())

eval_instructions = "您是一位专门为学生的答案评分的专家教授。"

def correctness(inputs: dict, outputs: dict, reference_outputs: dict) -> bool:
    user_content = f"""您正在为以下问题评分：
{inputs['question']}
这是真实答案：
{reference_outputs['answer']}
您正在为以下预测答案评分：
{outputs['response']}
请回答 CORRECT 或 INCORRECT：
评分："""
    response = openai_client.chat.completions.create(
        model="gpt-4.1-mini",
        temperature=0,
        messages=[
            {"role": "system", "content": eval_instructions},
            {"role": "user", "content": user_content},
        ],
    ).choices[0].message.content
    return response == "CORRECT"
```

对于评估响应长度，这要容易得多！我们可以只定义一个简单的函数，检查实际输出是否小于预期结果长度的 2 倍。

```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
def concision(outputs: dict, reference_outputs: dict) -> bool:
    return int(len(outputs["response"]) < 2 * len(reference_outputs["answer"]))
```

## 运行评估

太好了！现在我们如何运行评估？现在我们有了数据集和评估器，我们需要的只是我们的应用程序！我们将构建一个简单的应用程序，它只有一个包含如何响应的指令的系统消息，然后将其传递给 LLM。我们将直接使用 OpenAI SDK 构建这个应用程序：

```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
default_instructions = "以简短、精炼的方式（一个短句）回答用户的问题。"

def my_app(question: str, model: str = "gpt-4.1-mini", instructions: str = default_instructions) -> str:
    return openai_client.chat.completions.create(
        model=model,
        temperature=0,
        messages=[
            {"role": "system", "content": instructions},
            {"role": "user", "content": question},
        ],
    ).choices[0].message.content
```

在通过 LangSmith 评估运行此程序之前，我们需要定义一个简单的包装器，将数据集中的输入键映射到我们要调用的函数，然后将函数的输出映射到我们期望的输出键。

```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
def ls_target(inputs: str) -> dict:
    return {"response": my_app(inputs["question"])}
```

很好！现在我们准备好运行评估了。开始吧！

```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
experiment_results = client.evaluate(
    ls_target, # 您的 AI 系统
    data=dataset_name, # 用于预测和评分的数据
    evaluators=[concision, correctness], # 用于评分结果的评估器
    experiment_prefix="openai-4o-mini", # 实验名称的前缀，便于识别
)
```

这将输出一个 URL。如果我们点击它，应该会看到评估结果！

<img src="https://mintcdn.com/hhh-8c10bf0c/BCyPqRNhtAjzdCmk/langsmith/images/testing-tutorial-run.png?fit=max&auto=format&n=BCyPqRNhtAjzdCmk&q=85&s=f245705b3e2e45da1b6f75a22da81999" alt="测试教程运行" width="3022" height="1128" data-path="langsmith/images/testing-tutorial-run.png" />

如果我们返回数据集页面并选择 `实验` 选项卡，现在可以看到我们一次运行的摘要！

<img src="https://mintcdn.com/hhh-8c10bf0c/BCyPqRNhtAjzdCmk/langsmith/images/testing-tutorial-one-run.png?fit=max&auto=format&n=BCyPqRNhtAjzdCmk&q=85&s=32e7aa426a449bb4aa34a4a2b89bfd9f" alt="测试教程一次运行" width="3022" height="1532" data-path="langsmith/images/testing-tutorial-one-run.png" />

现在让我们用不同的模型试试！试试 `gpt-4-turbo`

```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
def ls_target_v2(inputs: str) -> dict:
    return {"response": my_app(inputs["question"], model="gpt-4-turbo")}

experiment_results = client.evaluate(
    ls_target_v2,
    data=dataset_name,
    evaluators=[concision, correctness],
    experiment_prefix="openai-4-turbo",
)
```

现在让我们使用 GPT-4，同时更新提示词，要求答案更简短。

```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
instructions_v3 = "以简短、精炼的方式（一个短句）回答用户的问题。不要使用超过十个词。"

def ls_target_v3(inputs: str) -> dict:
    response = my_app(
        inputs["question"],
        model="gpt-4-turbo",
        instructions=instructions_v3
    )
    return {"response": response}

experiment_results = client.evaluate(
    ls_target_v3,
    data=dataset_name,
    evaluators=[concision, correctness],
    experiment_prefix="strict-openai-4-turbo",
)
```

如果我们返回数据集页面的 `实验` 选项卡，应该会看到所有三次运行都显示出来了！

<img src="https://mintcdn.com/hhh-8c10bf0c/BCyPqRNhtAjzdCmk/langsmith/images/testing-tutorial-three-runs.png?fit=max&auto=format&n=BCyPqRNhtAjzdCmk&q=85&s=6d9181c584ed04354ab1cdcdd9076b3d" alt="测试教程三次运行" width="3020" height="1540" data-path="langsmith/images/testing-tutorial-three-runs.png" />

## 比较结果

太棒了，我们已经评估了三种不同的运行。但是我们如何比较结果呢？第一种方法是查看 `实验` 选项卡中的运行。如果我们这样做，可以看到每次运行指标的高级视图：

<img src="https://mintcdn.com/hhh-8c10bf0c/BCyPqRNhtAjzdCmk/langsmith/images/testing-tutorial-compare-metrics.png?fit=max&auto=format&n=BCyPqRNhtAjzdCmk&q=85&s=20526664f7d139e5deb74e439ec9c847" alt="测试教程比较指标" width="3020" height="1540" data-path="langsmith/images/testing-tutorial-compare-metrics.png" />

我们可以看出 GPT-4 在了解公司信息方面比 GPT-3.5 更好，并且严格的提示词在长度控制上有很大帮助。但是如果我们想更详细地探索呢？

为了做到这一点，我们可以选择所有要比较的运行（在本例中是全部三个），并在比较视图中打开它们。我们立即看到所有三个测试并排显示。一些单元格被颜色编码——这显示了*某个指标*相对于*某个基线*的回归。我们自动为基线和指标选择默认值，但您可以自己更改这些。您还可以使用 `显示` 控件选择要查看的列和指标。您还可以通过点击顶部的图标自动筛选，只显示有改进/回归的运行。

<img src="https://mintcdn.com/hhh-8c10bf0c/BCyPqRNhtAjzdCmk/langsmith/images/testing-tutorial-compare-runs.png?fit=max&auto=format&n=BCyPqRNhtAjzdCmk&q=85&s=a1ab857e78e64225f09d7a0ec90bc61f" alt="测试教程比较运行" width="3022" height="1548" data-path="langsmith/images/testing-tutorial-compare-runs.png" />

如果我们想查看更多信息，还可以将鼠标悬停在一行上时出现的 `展开` 按钮，打开一个侧边面板，显示更详细的信息：

<img src="https://mintcdn.com/hhh-8c10bf0c/BCyPqRNhtAjzdCmk/langsmith/images/testing-tutorial-side-panel.png?fit=max&auto=format&n=BCyPqRNhtAjzdCmk&q=85&s=c692ad90e8d3d449bd59206a971bfd7e" alt="测试教程侧边面板" width="2824" height="1546" data-path="langsmith/images/testing-tutorial-side-panel.png" />

## 设置在 CI/CD 中运行的自动化测试

既然我们已经以一次性方式运行了此测试，我们可以将其设置为以自动化方式运行。我们可以很容易地通过将其包含在 CI/CD 中运行的 pytest 文件中来实现。作为此过程的一部分，我们可以只记录结果，或者设置一些标准来确定它是否通过。例如，如果我想确保我们生成的响应中至少有 80% 通过 `长度` 检查，我们可以设置如下测试：

```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
def test_length_score() -> None:
    """测试长度得分至少为 80%。"""
    experiment_results = evaluate(
        ls_target, # 您的 AI 系统
        data=dataset_name, # 用于预测和评分的数据
        evaluators=[concision, correctness], # 用于评分结果的评估器
    )
    # 这将在下一个版本中清理：
    feedback = client.list_feedback(
        run_ids=[r.id for r in client.list_runs(project_name=experiment_results.experiment_name)],
        feedback_key="concision"
    )
    scores = [f.score for f in feedback]
    assert sum(scores) / len(scores) >= 0.8, "总分应至少为 .8"
```

## 随时间跟踪结果

既然我们已经以自动化方式运行了这些实验，我们希望随时间跟踪这些结果。我们可以从数据集页面的整体 `实验` 选项卡中做到这一点。默认情况下，我们显示随时间变化的评估指标（以红色高亮显示）。我们还自动跟踪 git 指标，以便轻松地将其与您的代码分支关联起来（以黄色高亮显示）。

<img src="https://mintcdn.com/hhh-8c10bf0c/BCyPqRNhtAjzdCmk/langsmith/images/testing-tutorial-over-time.png?fit=max&auto=format&n=BCyPqRNhtAjzdCmk&q=85&s=18f982bb9bb00cf863c11fccb49ca0c6" alt="测试教程随时间变化" width="3020" height="1544" data-path="langsmith/images/testing-tutorial-over-time.png" />

## 结论

本教程到此结束！

我们已经介绍了如何创建初始测试集、定义一些评估指标、运行实验、手动比较它们、设置 CI/CD 以及随时间跟踪结果。这可以帮助您自信地进行迭代。

这只是一个开始。如前所述，评估是一个持续的过程。例如——您想要评估的数据点可能会随时间继续变化。您可能希望探索许多类型的评估器。有关此信息，请查看[操作指南](/langsmith/evaluation)。

此外，除了这种“离线”方式外，还有其他评估数据的方法（例如，您可以评估生产数据）。有关在线评估的更多信息，请查看[设置 LLM 作为评判者的在线评估器](/langsmith/online-evaluations-llm-as-judge)。

## 参考代码

<Accordion title="点击查看整合后的代码片段">
  ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  import openai
  from langsmith import Client, wrappers

  # 应用程序代码
  openai_client = wrappers.wrap_openai(openai.OpenAI())

  default_instructions = "以简短、精炼的方式（一个短句）回答用户的问题。"

  def my_app(question: str, model: str = "gpt-4.1-mini", instructions: str = default_instructions) -> str:
      return openai_client.chat.completions.create(
          model=model,
          temperature=0,
          messages=[
              {"role": "system", "content": instructions},
              {"role": "user", "content": question},
          ],
      ).choices[0].message.content

  client = Client()

  # 定义数据集：这些是您的测试用例
  dataset_name = "问答示例数据集"
  dataset = client.create_dataset(dataset_name)

  client.create_examples(
      dataset_id=dataset.id,
      examples=[
          {
              "inputs": {"question": "什么是 LangChain？"},
              "outputs": {"answer": "一个用于构建 LLM 应用程序的框架"},
          },
          {
              "inputs": {"question": "什么是 LangSmith？"},
              "outputs": {"answer": "一个用于观察和评估 LLM 应用程序的平台"},
          },
          {
              "inputs": {"question": "什么是 OpenAI？"},
              "outputs": {"answer": "一家创建大语言模型的公司"},
          },
          {
              "inputs": {"question": "什么是 Google？"},
              "outputs": {"answer": "一家以搜索闻名的科技公司"},
          },
          {
              "inputs": {"question": "什么是 Mistral？"},
              "outputs": {"answer": "一家创建大语言模型的公司"},
          }
      ]
  )

  # 定义评估器
  eval_instructions = "您是一位专门为学生的答案评分的专家教授。"

  def correctness(inputs: dict, outputs: dict, reference_outputs: dict) -> bool:
      user_content = f"""您正在为以下问题评分：
  {inputs['question']}
  这是真实答案：
  {reference_outputs['answer']}
  您正在为以下预测答案评分：
  {outputs['response']}
  请回答 CORRECT 或 INCORRECT：
  评分："""
      response = openai_client.chat.completions.create(
          model="gpt-4.1-mini",
          temperature=0,
          messages=[
              {"role": "system", "content": eval_instructions},
              {"role": "user", "content": user_content},
          ],
      ).choices[0].message.content
      return response == "CORRECT"

  def concision(outputs: dict, reference_outputs: dict) -> bool:
      return int(len(outputs["response"]) < 2 * len(reference_outputs["answer"]))

  # 运行评估
  def ls_target(inputs: str) -> dict:
      return {"response": my_app(inputs["question"])}

  experiment_results_v1 = client.evaluate(
      ls_target, # 您的 AI 系统
      data=dataset_name, # 用于预测和评分的数据
      evaluators=[concision, correctness], # 用于评分结果的评估器
      experiment_prefix="openai-4o-mini", # 实验名称的前缀，便于识别
  )

  def ls_target_v2(inputs: str) -> dict:
      return {"response": my_app(inputs["question"], model="gpt-4-turbo")}

  experiment_results_v2 = client.evaluate(
      ls_target_v2,
      data=dataset_name,
      evaluators=[concision, correctness],
      experiment_prefix="openai-4-turbo",
  )

  instructions_v3 = "以简短、精炼的方式（一个短句）回答用户的问题。不要使用超过十个词。"

  def ls_target_v3(inputs: str) -> dict:
      response = my_app(
          inputs["question"],
          model="gpt-4-turbo",
          instructions=instructions_v3
      )
      return {"response": response}

  experiment_results_v3 = client.evaluate(
      ls_target_v3,
      data=dataset_name,
      evaluators=[concision, correctness],
      experiment_prefix="strict-openai-4-turbo",
  )
  ```
</Accordion>

***

<div className="source-links">
  <Callout icon="edit">
    [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/i18n\zh-CN\langsmith\evaluate-chatbot-tutorial.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose).
  </Callout>

  <Callout icon="terminal-2">
    [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers.
  </Callout>
</div>
