AI Agent 的评估需要全面考虑其完整的生命周期,从开发阶段到生产部署。评估过程应当涵盖多个关键维度:最终输出的事实准确性和实用价值、推理过程中工具选择的合理性和路径效率、结构化响应生成能力(如 JSON 格式)、多轮对话的上下文维持能力,以及在真实用户流量下的持续性能表现和错误监控能力。

为了有效监控和评估 Agent 生命周期的各个组件,LangSmith 作为最具影响力和广泛应用的工具平台之一,提供了强大的评估框架。本文将深入探讨十二种不同的智能体评估技术,详细阐述每种技术的适用场景和实施方法。这些技术涵盖了从传统的预测答案与标准答案比较,到先进的实时反馈评估等多个层面,其中标准答案会随时间动态变化。

评估技术体系架构

基于标准答案的评估方法

这类方法包括环境配置、精确匹配评估、非结构化问答评估、结构化数据比较以及动态标准答案等技术。

程序性评估(过程分析)

此类别涵盖轨迹评估、工具选择精度分析、组件级 RAG 评估、基于 RAGAS 的 RAG 评估以及实时反馈机制。

观察性与自主评估

包括成对比较、基于仿真的评估、算法反馈以及技术总结等方法。

环境配置与初始化

评估工作的首要步骤是建立 LangSmith 环境。需要从官方仪表板获取 API 密钥,这是后续通过仪表板跟踪 Agent 进度的关键步骤。以下为 API 密钥的初始化配置:

 import os  
 from langchain_openai import ChatOpenAI  
 import langsmith  
   
 # 设置 LangSmith 端点(使用云版本时请勿修改)  
 os.environ["LANGCHAIN_ENDPOINT"] = "https://api.smith.langchain.com"  
   
 # 配置 LangSmith API 密钥  
 os.environ["LANGCHAIN_API_KEY"] = "YOUR_LANGSMITH_API_KEY"  
   
 # 配置 OpenAI API 密钥  
 os.environ["OPENAI_API_KEY"] = "YOUR_OPENAI_API_KEY"

虽然本文使用 OpenAI 模型作为示例,但 LangChain 支持广泛的开源和闭源大语言模型。开发者可以根据需求切换到其他模型 API 提供商或本地部署的 Hugging Face 模型。

LangSmith API 端点负责在 Web 仪表板中存储所有评估指标,这将在后续分析中发挥重要作用。接下来需要初始化 LangSmith 客户端,作为整个评估流程的核心组件:

 # 初始化 LangSmith 客户端  
 client = langsmith.Client()

1、精确匹配评估方法

精确匹配评估是最基础但至关重要的评估方法之一。该方法通过比较模型输出与预定义的正确答案来验证一致性。

该评估流程的核心机制包括:建立标准答案作为预期响应的基准;向模型提供输入并获取基于该输入的输出;执行逐字符精确匹配检验,若匹配则赋值 1 分,不匹配则为 0 分;最后对所有样本的得分进行平均计算,得出模型的整体精确匹配性能指标。

为了在 LangSmith 中有效实施这种方法,首先需要构建评估数据集。在 LangSmith 框架中,数据集是由示例集合构成,每个示例包含输入和相应的预期输出(参考或标签)。这些数据集构成了模型测试和评估的基础架构。

以下示例创建了包含两个问题的数据集,并为每个问题提供了期望的精确输出:

 # 创建数据集作为问答示例的容器  
 ds = client.create_dataset(  
     dataset_name=dataset_name,  
     description="A dataset for simple exact match questions."  
 )  
   
 # 每个示例由输入字典和相应的输出字典组成
 # 输入和输出在独立列表中提供,维持相同的顺序  
 client.create_examples(  
     # 输入列表,每个输入都是字典格式  
     inputs=[  
         {  
             "prompt_template": "State the year of the declaration of independence. Respond with just the year in digits, nothing else"  
         },  
         {  
             "prompt_template": "What's the average speed of an unladen swallow?"  
         },  
     ],  
     # 对应的输出列表  
     outputs=[  
         {"output": "1776"},  # 第一个提示的预期输出  
         {"output": "5"}      # 第二个提示的预期输出(陷阱问题)  
     ],  
     # 示例将被添加到的数据集 ID  
     dataset_id=ds.id,  
 )

数据准备完成后,需要定义评估组件。首要组件是待评估的模型或链。本示例中创建了

predict_result

函数,该函数接收提示,将其发送至 OpenAI 的

gpt-3.5-turbo

模型,并返回模型响应:

 # 定义待测试模型  
 model = "gpt-3.5-turbo"  
   
 # 被测试系统:接收输入字典,调用指定的 ChatOpenAI 模型,返回字典格式的输出  
 def predict_result(input_: dict) -> dict:  
     # 输入字典包含 "prompt_template" 键,与数据集输入中定义的键一致  
     prompt = input_["prompt_template"]  
       
     # 初始化并调用模型  
     response = ChatOpenAI(model=model, temperature=0).invoke(prompt)  
       
     # 输出键 "output" 与数据集输出中的键匹配,用于比较  
     return {"output": response.content}

评估器是对系统性能进行评分的核心函数。LangSmith 提供多种内置评估器,同时支持自定义评估器的创建。内置的

exact_match

评估器是预构建的字符串评估器,用于检查预测与参考输出之间的完全字符匹配。自定义

compare_label

评估器则演示了如何实现自定义逻辑,通过

@run_evaluator

装饰器使 LangSmith 能够在评估过程中识别和使用该函数。

 from langsmith.evaluation import EvaluationResult, run_evaluator  
   
 # @run_evaluator 装饰器将函数注册为自定义评估器  
 @run_evaluator  
 def compare_label(run, example) -> EvaluationResult:  
     """
     用于检查精确匹配的自定义评估器
       
     Args:  
         run: LangSmith 运行对象,包含模型输出  
         example: LangSmith 示例对象,包含参考数据  
       
     Returns:  
         包含键和分数的 EvaluationResult 对象  
     """  
     # 从运行输出字典获取模型预测
     # 键 'output' 必须与 `predict_result` 函数返回内容匹配  
     prediction = run.outputs.get("output") or ""  
       
     # 从示例输出字典获取参考答案
     # 键 'output' 必须与数据集中定义内容匹配  
     target = example.outputs.get("output") or ""  
       
     # 执行比较操作  
     match = prediction == target  
       
     # 返回结果,键值为结果中分数的命名方式
     # 精确匹配分数通常为二进制(匹配为 1,不匹配为 0)  
     return EvaluationResult(key="matches_label", score=int(match))

配置完成所有组件后,可以执行评估。

RunEvalConfig

用于配置评估测试套件,指定内置的

"exact_match"

评估器和自定义的

compare_label

评估器,确保每个模型运行都被两个评估器评分。

client.run_on_dataset

作为主要协调函数,遍历指定数据集中的每个示例,对输入运行

predict_result

函数,然后应用

RunEvalConfig

中的评估器对结果进行评分。

 from langchain.smith import RunEvalConfig  
   
 # 定义评估运行的配置  
 eval_config = RunEvalConfig(  
     # 通过字符串名称指定内置评估器  
     evaluators=["exact_match"],   
       
     # 在列表中直接传递自定义评估器函数  
     custom_evaluators=[compare_label],  
 )  
   
 # 触发评估执行
 # 对数据集中每个示例运行 `predict_result` 函数
 # 然后使用 `eval_config` 中的评估器对结果评分  
 client.run_on_dataset(  
     dataset_name=dataset_name,  
     llm_or_chain_factory=predict_result,  
     evaluation=eval_config,  
     verbose=True, # 打印进度条和链接  
     project_metadata={"version": "1.0.1", "model": model}, # 项目可选元数据  
 )

评估执行将在样本数据上启动基于精确匹配方法的评估并显示进度:

 View the evaluation results for project 'gregarious-doctor-77' at:  
 https://smith.langchain.com/o/your-org-id/datasets/some-dataset-uuid/compare?selectedSessions=some-session-uuid  
   
 View all tests for Dataset Oracle of Exactness at:  
 https://smith.langchain.com/o/your-org-id/datasets/some-dataset-uuid  
 [------------------------------------------------->] 2/2

结果展示了多种统计信息,包括评估数据中实体数量的

count

、正确预测实体比例的

mean

(0.5 表示一半实体被正确识别),以及其他统计信息。

LangSmith 精确匹配评估主要适用于需要确定性输出的 RAG 或 AI Agent 任务场景。基于事实的问答需要从上下文中获取单一正确事实答案;封闭式问题需要精确的是非判断或选择匹配;工具使用输出需要验证精确的工具调用结果;结构化输出需要检查精确的格式和键值对。

2、非结构化问答评估

由于大语言模型响应为非结构化文本,简单的字符串匹配往往无法满足评估需求。模型可以用多种不同表述方式提供事实正确的答案。为解决这一挑战,可以采用 LLM 辅助评估器来评估系统响应的语义和事实准确性。

该评估流程始于创建包含问题和参考答案(黄金标准)的数据集。基于 RAG 的问答系统随后使用检索到的文档回答每个问题。独立的 LLM(充当"评判者")将预测答案与参考答案进行比较。若答案在事实上正确,评判者给予 1 分;若答案错误或存在幻觉,则给予 0 分。评判者提供推理过程来解释评分依据。最终,开发者可以审查错误案例,改进系统并重新执行评估。

相比精确匹配方法,非结构化场景的关键区别在于"标准答案"现在是正确性的参考基准,而非精确匹配的模板。

 # 在 LangSmith 中创建数据集  
 dataset = client.create_dataset(  
     dataset_name=dataset_name,  
     description="Q&A dataset about LangSmith documentation."  
 )  
   
 # 问答示例,答案作为'标准答案'  
 qa_examples = [  
     (  
         "What is LangChain?",  
         "LangChain is an open-source framework for building applications using large language models. It is also the name of the company building LangSmith.",  
     ),  
     (  
         "How might I query for all runs in a project?",  
         "You can use client.list_runs(project_name='my-project-name') in Python, or client.ListRuns({projectName: 'my-project-name'}) in TypeScript.",  
     ),  
     (  
         "What's a langsmith dataset?",  
         "A LangSmith dataset is a collection of examples. Each example contains inputs and optional expected outputs or references for that data point.",  
     ),  
     (  
         "How do I move my project between organizations?",  
         "LangSmith doesn't directly support moving projects between organizations.",  
     ),  
 ]  
   
 # 将示例添加到数据集
 # 输入键为 'question',输出键为 'answer'
 # 这些键必须与 RAG 链期望和生成的内容匹配  
 for question, answer in qa_examples:  
     client.create_example(  
         inputs={"question": question},  
         outputs={"answer": answer},  
         dataset_id=dataset.id,  
     )

接下来构建使用 LangChain 和 LangSmith 文档的 RAG 管道问答系统。该系统包含四个主要步骤:加载文档(抓取 LangSmith 文档);创建检索器(嵌入文档并存储在 ChromaDB 中以查找相关片段);生成答案(使用 ChatOpenAI 和提示基于检索内容回答);组装链(使用 LangChain 表达语言将所有组件合并为单一管道)。

首先加载和处理文档以创建知识库:

 from langchain_community.document_loaders import RecursiveUrlLoader  
 from langchain_community.document_transformers import Html2TextTransformer  
 from langchain_community.vectorstores import Chroma  
 from langchain_text_splitters import TokenTextSplitter  
 from langchain_openai import OpenAIEmbeddings  
   
 # 1. 从网络加载文档  
 api_loader = RecursiveUrlLoader("https://docs.smith.langchain.com")  
 raw_documents = api_loader.load()  
   
 # 2. 将 HTML 转换为干净文本并分割为可管理的片段  
 doc_transformer = Html2TextTransformer()  
 transformed = doc_transformer.transform_documents(raw_documents)  
 text_splitter = TokenTextSplitter(model_name="gpt-3.5-turbo", chunk_size=2000, chunk_overlap=200)  
 documents = text_splitter.split_documents(transformed)  
   
 # 3. 创建向量存储检索器  
 embeddings = OpenAIEmbeddings()  
 vectorstore = Chroma.from_documents(documents, embeddings)  
 retriever = vectorstore.as_retriever(search_kwargs={"k": 4})

随后定义链的生成部分并组装完整的 RAG 管道:

 from operator import itemgetter  
 from langchain_core.output_parsers import StrOutputParser  
 from langchain_core.prompts import ChatPromptTemplate  
   
 # 定义发送给 LLM 的提示模板  
 prompt = ChatPromptTemplate.from_messages(  
     [  
         (  
             "system",  
             "You are a helpful documentation Q&A assistant, trained to answer"  
             " questions from LangSmith's documentation."  
             " LangChain is a framework for building applications using large language models."  
             "\nThe current time is {time}.\n\nRelevant documents will be retrieved in the following messages.",  
         ),  
         ("system", "{context}"), # 检索文档的占位符  
         ("human", "{question}"),  # 用户问题的占位符  
     ]  
 ).partial(time=str(datetime.now()))  
   
 # 初始化 LLM,使用大上下文窗口和低温度参数以获得更准确的响应  
 model = ChatOpenAI(model="gpt-3.5-turbo-16k", temperature=0)  
   
 # 定义生成链,将提示传递给模型再传递给输出解析器  
 response_generator = prompt | model | StrOutputParser()

准备好数据集和 RAG 链后,可以执行评估。此次使用内置的"qa"评估器替代"exact_match"。该评估器使用 LLM 根据数据集中的参考答案对生成答案的正确性进行评分:

 # 配置评估使用"qa"评估器,基于参考答案对"正确性"进行评分  
 eval_config = RunEvalConfig(  
     evaluators=["qa"],  
 )  
   
 # 在数据集上运行 RAG 链并应用评估器  
 client.run_on_dataset(  
     dataset_name=dataset_name,  
     llm_or_chain_factory=rag_chain,  
     evaluation=eval_config,  
     verbose=True,  
     project_metadata={"version": "1.0.0", "model": "gpt-3.5-turbo"},  
 )

评估执行将触发测试运行,输出中的链接可用于在 LangSmith 仪表板中实时查看结果:

 View the evaluation results for project 'witty-scythe-29' at:  
 https://smith.langchain.com/o/your-org-id/datasets/some-dataset-uuid/compare?selectedSessions=some-session-uuid  
   
 View all tests for Dataset Retrieval QA - LangSmith Docs at:  
 https://smith.langchain.com/o/your-org-id/datasets/some-dataset-uuid  
 [------------------------------------------------->] 5/5

运行完成后,LangSmith 仪表板提供结果分析界面。除了聚合分数外,更重要的是可以筛选失败案例进行调试。

通过筛选正确性分数为 0 的示例,可以隔离问题案例。例如,发现模型因检索到不相关文档而产生幻觉答案的情况。可以形成假设:"如果信息不在上下文中,模型需要明确被告知不要回答"。通过修改提示并重新运行评估来测试这一假设:

 # 定义改进的提示模板  
 prompt_v2 = ChatPromptTemplate.from_messages(  
     [  
         (  
             "system",  
             "You are a helpful documentation Q&A assistant, trained to answer"  
             " questions from LangSmith's documentation."  
             "\nThe current time is {time}.\n\nRelevant documents will be retrieved in the following messages.",  
         ),  
         ("system", "{context}"),  
         ("human", "{question}"),  
         # 新增防止幻觉的指令  
         (  
             "system",  
             "Respond as best as you can. If no documents are retrieved or if you do not see an answer in the retrieved documents,"  
             " admit you do not know or that you don't see it being supported at the moment.",  
         ),  
     ]  
 ).partial(time=lambda: str(datetime.now()))

仪表板显示的结果表明新链性能更优,通过了测试集中的所有示例。这种"测试-分析-改进"的迭代循环是改进大语言模型应用的强大方法论。

非结构化文本的 LLM 辅助评估对于生成输出具有细微差别且需要语义理解的任务至关重要。RAG 系统需要验证模型答案在事实上由检索上下文支持并避免幻觉;开放式问答在没有单一"精确"正确答案时评估正确性,允许措辞和风格变化;摘要任务需要检查生成摘要是否忠实于源文档并准确捕获要点;对话式 AI 和聊天机器人需要评估机器人在对话中逐轮响应的相关性、实用性和事实准确性。

3、结构化数据比较评估

大语言模型的一个重要且强大的应用场景是从非结构化文本(文档、邮件或合同)中提取结构化数据(如 JSON)。这种能力使我们能够填充数据库、使用正确参数调用工具或自动构建知识图谱。然而,评估这种提取质量存在挑战。对输出 JSON 进行简单精确匹配过于严格;模型可能产生完全有效且正确的 JSON,但如果键的顺序不同或存在细微空白变化,则无法通过字符串比较测试。因此需要更智能的方法来比较结构和内容。

该评估流程始于定义结构化模式(如 JSON 或 Pydantic 模型)作为模型必须填写的"表单"。随后构建包含非结构化输入和完美填写的 JSON 输出作为答案键的数据集。模型读取输入并填写表单,基于模式产生结构化输出。JSON 编辑距离评估器将预测的 JSON 与参考进行比较,规范化两个 JSON(如键顺序)并计算编辑距离(Levenshtein 距离)。基于预测与答案键的接近程度分配相似性分数(0.0-1.0)。最后,审查低分输出以找到薄弱环节并改进模型或提示。

Logo

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

更多推荐