欢迎来到吴恩达《LangChain LLM 应用开发》系列课程的第六讲。本节课我们将深入探讨 AI 应用开发中至关重要的一环:Evaluation (评估)

在构建了基于 LLM 的应用后,如何判断其回答的准确性?当修改了 Prompt 或更换了模型参数后,如何确保系统性能没有退化?这些都是评估阶段需要解决的问题。


1. 为什么需要评估 (Why)

场景示例

在传统的软件开发中,测试通常是确定性的。例如,1 + 1 必须等于 2。如果输出 3,则测试失败。

但在 AI 开发中,答案往往是开放的。例如:

  • 问题:“今天天气怎么样?”
  • 回答 A:“今天天气不错,阳光明媚。”
  • 回答 B:“是个大晴天,适合出去玩。”

这两个回答在语义上都是正确的,但传统的基于字符串匹配的测试方法(如 assert a == b)无法判断这种语义一致性。

核心痛点

如果完全依赖人工评估,会面临以下问题:

  1. 工作量大:随着测试集规模增加,人工逐条核对变得不可持续。
  2. 效率低下:每次系统迭代都需要重新评估,严重拖慢开发进度。
  3. 主观性强:不同的人(甚至同一个人在不同时间)对同一回答的评分可能不一致。

因此,我们需要一种自动化标准化的评估方法。


2. LangChain 评估框架 (What)

LangChain 提供了一套完整的评估工具,帮助开发者更高效地测试 LLM 应用。

2.1 手动评估 (Manual Evaluation) 👨‍🏫

这是最基础的评估方式,即人工查看输入和输出。LangChain 提供了 LangSmith 平台,可以可视化地追踪 LLM 的每一次调用、Token 消耗和中间结果,极大地方便了人工调试和标注。

2.2 AI 辅助评估 (LLM-assisted Evaluation) 🤖

这是一种利用 LLM 来评估 LLM 的方法(LLM-as-a-Judge)。
虽然我们无法预知标准答案的具体文字,但我们可以利用强大的 LLM(如 GPT-4)来判断“考生回答”是否符合“标准答案”的语义。

  • 输入:问题 + 标准答案 + 考生回答
  • 输出:CORRECT (正确) / INCORRECT (错误)

评估流程图 🗺️

[文档/知识库] --> (生成问题) --> [QAGenerateChain] --> (测试集: 问题+标准答案)
                                       |
                                       v
[AI 模型] <-- (做题: 回答问题) <--------+
    |
    v
(考生回答)
    |
    v
[QAEvalChain] <--(裁判: 对比标准答案与考生回答)--> [评分结果]

3. 实战代码详解 (How)

本节将演示如何构建一个完整的自动化评估流程:包括自动生成测试集自动回答以及自动评分

3.1 环境准备与数据加载 🛠️

首先,加载环境变量并准备测试数据。这里我们使用一个 CSV 文件作为知识库。

import os
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI
from langchain_community.document_loaders import CSVLoader
from langchain.indexes import VectorstoreIndexCreator
from langchain_community.vectorstores import DocArrayInMemorySearch
from langchain_openai import OpenAIEmbeddings
from dotenv import load_dotenv, find_dotenv

# 加载环境变量
_ = load_dotenv(find_dotenv())

# 1. 准备数据
csv_file = 'OutdoorClothingCatalog_1000.csv'
csv_content = """name,description
男士热带格纹短袖衬衫,"评级:防晒。由100%聚酯纤维制成,这款衬衫抗皱并具有UPF 50+的防晒功能。"
男士格纹热带衬衫,"评级:防晒。UPF 50+防晒。100%聚酯纤维。抗皱。"
女士防晒衬衫,"评级:防晒。吸湿排汗。UPF 50+。100%聚酯纤维。"
男士羊毛衫,"温暖舒适。100%羊毛。仅干洗。"
"""

# 写入本地文件
with open(csv_file, "w") as f:
    f.write(csv_content)

loader = CSVLoader(file_path=csv_file)
data = loader.load()

# 2. 创建向量索引
embeddings = OpenAIEmbeddings() 
index = VectorstoreIndexCreator(
    vectorstore_cls=DocArrayInMemorySearch,
    embedding=embeddings,
).from_loaders([loader])

print("✅ 数据加载与索引创建完成")

运行输出

✅ 已创建中文模拟数据文件: OutdoorClothingCatalog_1000.csv
✅ 数据加载与索引创建完成

3.2 步骤一:创建问答链 (RetrievalQA) 🔗

创建一个基于文档回答问题的检索问答链,作为我们要评估的对象(System Under Test)。

# 初始化 LLM
llm = ChatOpenAI(
    temperature=0.0,
    model_name="gpt-3.5-turbo", # 或 deepseek-chat
)

# 创建 RetrievalQA 链
qa = RetrievalQA.from_chain_type(
    llm=llm, 
    chain_type="stuff", 
    retriever=index.vectorstore.as_retriever(), 
    verbose=True,
    chain_type_kwargs = {
        "document_separator": "<<<<>>>>>"
    }
)
# 参数说明:
# - llm: 用于生成回答的大语言模型
# - chain_type="stuff": 将所有检索到的文档块拼接成一个 Context 发送给 LLM(适合短文档)
# - retriever: 检索器,负责从向量数据库中查找相关文档
# - verbose=True: 打印链执行的中间过程(如检索到的文档、使用的 Prompt)
# - chain_type_kwargs: 传递给内部链的额外参数,这里指定文档分隔符为 "<<<<>>>>>"
print("✅ 考生 (RetrievalQA) 已就位")

运行输出

✅ 考生 (RetrievalQA) 已就位

3.3 步骤二:手动评估 📝

先手动定义一些测试用例,验证系统是否正常工作。

# 手动定义测试集
examples = [
    {
        "query": "男士热带格纹短袖衬衫有什么功能?",
        "answer": "它具有防晒功能,UPF 50+,而且抗皱。"
    },
    {
        "query": "男士羊毛衫可以直接机洗吗?",
        "answer": "不可以,只能干洗。"
    }
]

# 运行测试
predictions = qa.apply(examples)

# 查看结果
print(predictions[0]['result'])

运行输出

这款衬衫具有防晒功能,UPF 50+,并且抗皱。

3.4 步骤三:引入自动评估 (QAEvalChain) ⚖️

使用 QAEvalChain 来自动对比标准答案和系统回答。

from langchain.evaluation.qa import QAEvalChain

# 初始化评估链
eval_chain = QAEvalChain.from_llm(llm)

# 运行评估
graded_outputs = eval_chain.evaluate(examples, predictions)

# 输出详细结果
for i, eg in enumerate(examples):
    print(f"\n📝 试题 {i+1}:")
    print(f"问题: {predictions[i]['query']}")
    print(f"标准答案: {predictions[i]['answer']}")
    print(f"考生回答: {predictions[i]['result']}")
    print(f"裁判评分: {graded_outputs[i]['text']}") 

运行输出

📝 试题 1:
问题: 男士热带格纹短袖衬衫有什么功能?
标准答案: 它具有防晒功能,UPF 50+,而且抗皱。
考生回答: 这款衬衫具有防晒功能,UPF 50+,并且抗皱。
裁判评分: CORRECT

📝 试题 2:
问题: 男士羊毛衫可以直接机洗吗?
标准答案: 不可以,只能干洗。
考生回答: 不可以,只能干洗。
裁判评分: CORRECT

3.5 步骤四:自动生成测试集 (Automated Generation) 🤖

为了扩大测试覆盖率,我们可以使用 QAGenerateChain 让 LLM 根据文档内容自动生成“问题-答案”对。

注意:由于 DeepSeek 等模型默认可能倾向于生成英文,我们需要通过自定义 Prompt 强制其使用中文出题。

from langchain.evaluation.qa import QAGenerateChain
from langchain.prompts import PromptTemplate

# 自定义 Prompt 模板,强制生成中文
template = """You are a teacher coming up with questions to ask on a quiz. 
Given the following document, please generate a question and answer based on that document.

Example Format:
<Begin Document>
...
<End Document>
QUESTION: question here
ANSWER: answer here

These questions should be detailed and be based explicitly on information in the document.
Please generate the question and answer in CHINESE (Simplified Chinese).

<Begin Document>
{doc}
<End Document>"""

prompt = PromptTemplate(
    input_variables=["doc"],
    template=template,
)

# 创建生成链
example_gen_chain = QAGenerateChain(
    llm=ChatOpenAI(model=model_name, base_url=base_url, api_key=api_key), prompt=prompt
)

# 自动生成试题
# 注意:DeepSeek 有时生成的格式可能不完全符合预期,需注意异常处理
try:
    new_examples = example_gen_chain.apply_and_parse(
        [{"doc": t} for t in data[:2]]
    )
    # 修复 QAGenerateChain 返回结构 (如果包含 qa_pairs 键)
    if new_examples and isinstance(new_examples[0], dict) and 'qa_pairs' in new_examples[0]:
        new_examples = [e['qa_pairs'] for e in new_examples]

    print(f"✅ AI 自动生成了 {len(new_examples)} 道新题目。")
    print(f"生成的题目示例: {new_examples[0]}")
except Exception as e:
    print(f"⚠️ 自动生成题目失败: {e}")

运行输出

✅ AI 自动生成了 2 道新题目。
生成的题目示例: {'query': '这款男士热带格纹短袖衬衫的防晒评级是什么?它是由什么材料制成的,这种材料带来了哪两个主要特点?', 'answer': '这款衬衫的防晒评级是“防晒”。它由100%聚酯纤维制成,这种材料使得衬衫具有抗皱以及提供UPF 50+防晒功能这两个主要特点。'}

3.6 步骤五:全自动评估闭环 🔄

将自动生成的试题输入到评估流程中,实现端到端的自动化测试。

# 1. 回答新生成的试题
predictions = qa.apply(new_examples)

# 2. 自动评分
graded_outputs = eval_chain.evaluate(new_examples, predictions)

# 3. 输出结果
for i, eg in enumerate(new_examples):
    print(f"\n📝 自动生成试题 {i+1}:")
    print(f"问题: {predictions[i]['query']}")
    print(f"标准答案: {predictions[i]['answer']}")
    print(f"考生回答: {predictions[i]['result']}")
    print(f"裁判评分: {graded_outputs[i]['text']}")

运行输出

📝 自动生成试题 1:
问题: 男士热带格纹短袖衬衫有什么特点?
标准答案: 这款衬衫防晒,由100%聚酯纤维制成,抗皱并具有UPF 50+的防晒功能。
考生回答: 这款衬衫防晒,由100%聚酯纤维制成,抗皱并具有UPF 50+的防晒功能。
裁判评分: CORRECT

📝 自动生成试题 2:
问题: 男士格纹热带衬衫有什么功能?
标准答案: 防晒,UPF 50+防晒,抗皱。
考生回答: 这款衬衫具有防晒功能,UPF 50+防晒,且抗皱。
裁判评分: CORRECT

3.7 Debug 模式 🐞

在开发过程中,如果发现评分不符合预期,可以开启 LangChain 的 Debug 模式,查看详细的 Prompt 和中间步骤。

import langchain
langchain.debug = True

qa.run("男士羊毛衫怎么洗?")

4. 总结

  1. 评估的重要性:自动化评估是保证 LLM 应用质量的关键,特别是在模型迭代和 Prompt 优化过程中。
  2. LLM-as-a-Judge:利用 LLM 来评估 LLM 的输出(语义一致性判断),是目前解决开放性问题评估的主流方案。
  3. 自动化工作流:通过 QAGenerateChain 自动生成测试集,配合 QAEvalChain 自动评分,可以构建高效的闭环测试系统。

创作不易,记得👇关注飞哥👇 ,点赞、收藏哦~~,下篇见👋

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐