Skip to main content

LangSmith 简介

LangChain使得原型化LLM应用程序和代理变得简单。然而,将LLM应用程序交付到生产环境可能会出现意想不到的困难。您可能需要对提示、链和其他组件进行大量定制和迭代,以创建高质量的产品。

为了帮助您进行这个过程,我们推出了LangSmith,一个用于调试、测试和监控LLM应用程序的统一平台。

什么时候会派上用场?当您想要:

  • 快速调试新的链、代理或一组工具
  • 可视化组件(链、LLM、检索器等)之间的关系和使用方式
  • 评估单个组件的不同提示和LLMs
  • 在数据集上多次运行给定的链,以确保它始终达到质量标准
  • 捕获使用跟踪,并使用LLMs或分析管道生成洞察

先决条件

创建LangSmith账户并创建一个API密钥(参见左下角)。通过查看文档来熟悉平台。

请注意,LangSmith处于封闭测试阶段;我们正在将其推广给更多用户。但是,您可以在网站上填写表格以加快访问速度。

现在,让我们开始吧!

将运行记录到LangSmith

首先,配置您的环境变量以告诉LangChain记录跟踪。通过将LANGCHAIN_TRACING_V2环境变量设置为true来完成此操作。您可以通过设置LANGCHAIN_PROJECT环境变量来告诉LangChain要记录到哪个项目(如果未设置,运行将记录到default项目)。如果该项目不存在,它将自动为您创建。您还必须设置LANGCHAIN_ENDPOINTLANGCHAIN_API_KEY环境变量。

有关设置跟踪的其他方法的更多信息,请参考LangSmith文档

注意: 您还必须设置OPENAI_API_KEYSERPAPI_API_KEY环境变量,以便运行以下教程。

注意: 您只能在首次创建API密钥时访问它。请将其保存在安全的地方。

注意: 您还可以在Python中使用上下文管理器来记录跟踪

from langchain.callbacks.manager import tracing_v2_enabled  

with tracing_v2_enabled(project_name="My Project"):
agent.run("How many people live in canada as of 2023?")

API参考:

但是,在本示例中,我们将使用环境变量。

import os  
from uuid import uuid4

unique_id = uuid4().hex[0:8]
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_PROJECT"] = f"Tracing Walkthrough - {unique_id}"
os.environ["LANGCHAIN_ENDPOINT"] = "https://api.smith.langchain.com"
os.environ["LANGCHAIN_API_KEY"] = "" # 更新为您的API密钥

# 本教程中代理使用的
# os.environ["OPENAI_API_KEY"] = "<YOUR-OPENAI-API-KEY>"
# os.environ["SERPAPI_API_KEY"] = "<YOUR-SERPAPI-API-KEY>"

创建与API交互的LangSmith客户端

from langsmith import Client  

client = Client()

创建一个LangChain组件并将运行记录到平台。在本示例中,我们将创建一个具有Search和Calculator工具访问权限的ReAct风格代理。然而,无论您使用哪种类型的LangChain组件(LLMs、Chat Models、Tools、Retrievers、Agents都受支持),LangSmith都可以工作。

from langchain.chat_models import ChatOpenAI  
from langchain.agents import AgentType, initialize_agent, load_tools

llm = ChatOpenAI(temperature=0)
tools = load_tools(["serpapi", "llm-math"], llm=llm)
agent = initialize_agent(
tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=False
)

API参考:

我们同时在多个输入上并发运行代理以减少延迟。运行在后台记录到LangSmith,因此执行延迟不受影响。

import asyncio  

inputs = [
"How many people live in canada as of 2023?",
"who is dua lipa's boyfriend? what is his age raised to the .43 power?",
"what is dua lipa's boyfriend age raised to the .43 power?",
"how far is it from paris to boston in miles",
"what was the total number of points scored in the 2023 super bowl? what is that number raised to the .23 power?",
"what was the total number of points scored in the 2023 super bowl raised to the .23 power?",
"how many more points were scored in the 2023 super bowl than in the 2022 super bowl?",
"what is 153 raised to .1312 power?",
"who is kendall jenner's boyfriend? what is his height (in inches) raised to .13 power?",
"what is 1213 divided by 4345?",
]
results = []


async def arun(agent, input_example):
try:
return await agent.arun(input_example)
except Exception as e:
# 代理有时会犯错误!这些错误将被跟踪捕获。
return e


for input_example in inputs:
results.append(arun(agent, input_example))
results = await asyncio.gather(*results)



from langchain.callbacks.tracers.langchain import wait_for_all_tracers

# 日志在后台线程中提交,以避免阻塞执行。
# 出于本教程的目的,我们希望确保
# 它们已提交后再继续。这也是
# 对于无服务器部署很有用。
wait_for_all_tracers()

API参考:

假设您已成功设置环境,您的代理跟踪应该显示在应用程序Projects部分中。恭喜!

评估另一个代理实现

除了记录运行,LangSmith还允许您测试和评估LLM应用程序。

在本节中,您将利用LangSmith创建一个基准数据集,并在代理上运行AI辅助评估器。您将按照以下几个步骤进行操作:

  1. 从现有的运行输入和输出创建数据集
  2. 初始化一个新的代理进行基准测试
  3. 配置评估器以对代理的输出进行评分
  4. 在数据集上运行代理并评估结果

1. 创建一个LangSmith数据集

以下是使用LangSmith客户端根据您刚刚记录的代理运行创建数据集的步骤。您将在后面使用这些数据集来评估新代理的性能。这只是将运行的输入和输出保存为数据集中的示例。数据集是一组示例,它们只是您可以用作应用程序测试用例的输入-输出对。

注意:这只是一个简单的演示示例。在实际环境中,您应该在将其添加到基准数据集中用于评估其他代理之前,首先验证输出。

有关数据集的更多信息,包括如何从CSV或其他文件创建数据集以及如何在平台上创建数据集,请参阅LangSmith文档

dataset_name = f"calculator-example-dataset-{unique_id}"  

dataset = client.create_dataset(
dataset_name, description="一个计算器示例数据集"
)

runs = client.list_runs(
project_name=os.environ["LANGCHAIN_PROJECT"],
execution_order=1, # 只返回顶级运行
error=False, # 只返回成功的运行
)
for run in runs:
client.create_example(inputs=run.inputs, outputs=run.outputs, dataset_id=dataset.id)

2. 初始化一个新的代理以进行基准测试

你可以评估任何LLM、chain或agent。由于chains可以具有记忆功能,我们将传入一个chain_factory(也称为constructor)函数来初始化每次调用。

在这种情况下,我们将测试一个使用OpenAI的函数调用端点的agent。

from langchain.chat_models import ChatOpenAI  
from langchain.agents import AgentType, initialize_agent, load_tools

llm = ChatOpenAI(model="gpt-3.5-turbo-0613", temperature=0)
tools = load_tools(["serpapi", "llm-math"], llm=llm)

# 由于chains可以具有状态(例如,它们可以具有记忆功能),我们提供了一种方法来为数据集中的每一行初始化一个新的chain。这是通过传入一个工厂函数来实现的,该函数为每一行返回一个新的chain。
def agent_factory():
return initialize_agent(tools, llm, agent=AgentType.OPENAI_FUNCTIONS, verbose=False)

# 如果您的chain没有状态,您的工厂函数可以直接返回对象,以提高运行时性能。例如:
# chain_factory = lambda: agent

API参考:

3. 配置评估

手动比较UI中链的结果是有效的,但可能会耗费时间。使用自动化指标和AI辅助反馈来评估组件的性能会很有帮助。

下面,我们将创建一些预先实现的运行评估器,执行以下操作:

  • 将结果与真实标签进行比较(您在上面使用了调试输出)
  • 使用嵌入距离测量语义(不)相似性
  • 使用自定义标准以无参考方式评估代理的响应的“方面”

有关如何选择适当的评估器以及如何创建自定义评估器的更长讨论,请参阅LangSmith文档

from langchain.evaluation import EvaluatorType  
from langchain.smith import RunEvalConfig

evaluation_config = RunEvalConfig(
# 评估器可以是评估器类型(例如“qa”,“criteria”,“embedding_distance”等)或该评估器的配置
evaluators=[
# 根据参考答案判断QA响应是否“正确”
# 也可以通过原始字符串“qa”进行选择
EvaluatorType.QA,
# 测量输出和参考答案之间的嵌入距离
# 等同于:EvalConfig.EmbeddingDistance(embeddings=OpenAIEmbeddings())
EvaluatorType.EMBEDDING_DISTANCE,
# 评估输出是否满足所述标准。您可以选择默认的标准,如“helpfulness”,也可以提供自己的标准。
RunEvalConfig.LabeledCriteria("helpfulness"),
# 标准和LabeledCriteria评估器都可以配置自定义标准的字典。
RunEvalConfig.Criteria(
{
"fifth-grader-score": "回答这个问题需要比五年级学生聪明吗?"
}
),
],
# 您还可以在此处添加自定义的StringEvaluator或RunEvaluator对象,它们将自动应用于每个预测。请查看文档中的示例。
custom_evaluators=[],
)

API参考:

4. 运行代理和评估器

使用arun_on_dataset(或同步的run_on_dataset)函数来评估你的模型。这将会:

  1. 从指定的数据集中获取示例行。
  2. 在每个示例上运行你的llm或chain。
  3. 对生成的运行跟踪和相应的参考示例应用评估器以生成自动化反馈。

结果将在LangSmith应用中可见。

from langchain.smith import (
arun_on_dataset,
run_on_dataset, # 如果你的chain不支持异步调用,则可用。
)

chain_results = await arun_on_dataset(
client=client,
dataset_name=dataset_name,
llm_or_chain_factory=agent_factory,
evaluation=evaluation_config,
verbose=True,
tags=["testing-notebook"], # 可选,为生成的chain运行添加一个标签。
)

# 有时,由于解析问题、不兼容的工具输入等原因,代理会出错。
# 这些错误会在此处记录为警告,并在跟踪界面中捕获为错误。

API参考:

查看项目'2023-07-17-11-25-20-AgentExecutor'的评估结果:
https://dev.smith.langchain.com/projects/p/1c9baec3-ae86-4fac-9e99-e1b9f8e7818c?eval=true

处理的示例数:1

示例5a2ac8da-8c2b-4d12-acb9-5c4b0f47fe8a的chain失败。错误:LLMMathChain._evaluate("age_of_Dua_Lipa_boyfriend ** 0.43")引发错误:'age_of_Dua_Lipa_boyfriend'。请使用有效的数值表达式重试。

处理的示例数:4

示例91439261-1c86-4198-868b-a6c1cc8a051b的chain失败。错误:单输入工具Calculator的参数过多。参数:['height ^ 0.13', {'height': 68}]

处理的示例数:9

查看测试结果

以下是满足要求的测试结果跟踪界面的查看方式:

  1. 导航到“数据集和测试”页面;
  2. 选择"calculator-example-dataset-*"数据集;
  3. 点击Test Runs选项卡;
  4. 检查相应项目中的运行情况。

这将显示新的运行结果以及从选定的评估者那里记录的反馈。请注意,出错的运行将没有反馈。

导出数据集和运行结果

LangSmith允许您在Web应用程序中直接将数据导出为常见格式,如CSV或JSONL。您还可以使用客户端获取运行结果进行进一步分析,存储在自己的数据库中或与他人共享。让我们从评估运行中获取运行结果的跟踪。

runs = list(client.list_runs(dataset_name=dataset_name))
runs[0]
    Run(id=UUID('e39f310b-c5a8-4192-8a59-6a9498e1cb85'), name='AgentExecutor', start_time=datetime.datetime(2023, 7, 17, 18, 25, 30, 653872), run_type=<RunTypeEnum.chain: 'chain'>, end_time=datetime.datetime(2023, 7, 17, 18, 25, 35, 359642), extra={'runtime': {'library': 'langchain', 'runtime': 'python', 'platform': 'macOS-13.4.1-arm64-arm-64bit', 'sdk_version': '0.0.8', 'library_version': '0.0.231', 'runtime_version': '3.11.2'}, 'total_tokens': 512, 'prompt_tokens': 451, 'completion_tokens': 61}, error=None, serialized=None, events=[{'name': 'start', 'time': '2023-07-17T18:25:30.653872'}, {'name': 'end', 'time': '2023-07-17T18:25:35.359642'}], inputs={'input': 'what is 1213 divided by 4345?'}, outputs={'output': '1213 divided by 4345 is approximately 0.2792.'}, reference_example_id=UUID('a75cf754-4f73-46fd-b126-9bcd0695e463'), parent_run_id=None, tags=['openai-functions', 'testing-notebook'], execution_order=1, session_id=UUID('1c9baec3-ae86-4fac-9e99-e1b9f8e7818c'), child_run_ids=[UUID('40d0fdca-0b2b-47f4-a9da-f2b229aa4ed5'), UUID('cfa5130f-264c-4126-8950-ec1c4c31b800'), UUID('ba638a2f-2a57-45db-91e8-9a7a66a42c5a'), UUID('fcc29b5a-cdb7-4bcc-8194-47729bbdf5fb'), UUID('a6f92bf5-cfba-4747-9336-370cb00c928a'), UUID('65312576-5a39-4250-b820-4dfae7d73945')], child_runs=None, feedback_stats={'correctness': {'n': 1, 'avg': 1.0, 'mode': 1}, 'helpfulness': {'n': 1, 'avg': 1.0, 'mode': 1}, 'fifth-grader-score': {'n': 1, 'avg': 1.0, 'mode': 1}, 'embedding_cosine_distance': {'n': 1, 'avg': 0.144522385071361, 'mode': 0.144522385071361}})
client.read_project(project_id=runs[0].session_id).feedback_stats
    {'correctness': {'n': 7, 'avg': 0.5714285714285714, 'mode': 1},
'helpfulness': {'n': 7, 'avg': 0.7142857142857143, 'mode': 1},
'fifth-grader-score': {'n': 7, 'avg': 0.7142857142857143, 'mode': 1},
'embedding_cosine_distance': {'n': 7,
'avg': 0.11462010799473926,
'mode': 0.0130477459560272}}

结论

恭喜!您已成功跟踪和评估了使用LangSmith的代理程序!

这只是一个入门指南,但是LangSmith还有更多的用途,可以加快开发者的工作流程并产生更好的结果。

要了解如何充分利用LangSmith,请查阅LangSmith文档,如果有任何问题、功能请求或反馈,请通过support@langchain.dev联系我们。