LangSmith简介
LangSmith提供用于开发、调试和部署大型语言模型(LLM)应用程序的工具。它能帮助你在同一个平台中完成请求追踪、输出评估、提示词测试以及部署管理等操作。 LangSmith不依赖特定框架,因此无论你是否使用LangChain的开源库(langchain和langgraph),都可以正常使用该工具。你可以先在本地进行原型开发,随后无缝过渡到生产环境;同时,借助其集成的监控与评估功能,能够构建出更可靠的人工智能系统。
可观测性(Observability)
对于使用大模型(LLM)构建的应用程序而言,可观测性(Observability)是一项关键需求。LLM具有非确定性特征,这意味着相同的提示词可能会生成不同的响应。这种特性使得LLM应用的调试与监控工作,比传统软件更具挑战性。
LangSmith为解决这一问题提供了方案:它能让你端到端地掌握应用程序处理请求的完整过程。每一个请求都会生成一条追踪记录(trace),该记录会完整捕捉整个过程中发生的所有事件。一条追踪记录包含多个独立运行单元(runs)------ 即应用程序执行的具体操作,例如一次LLM调用或一个信息检索步骤。通过对这些运行单元进行追踪,你可以检查、调试并验证应用程序的运行行为。
本文将搭建一个最小化的RAG应用程序,并为其添加LangSmith追踪功能。具体操作步骤如下:
- 配置你的环境。
- 创建一个可检索上下文并调用LLM的应用程序。
- 启用追踪功能,以同时捕捉检索步骤和LLM调用过程。
- 在LangSmith界面中查看生成的追踪记录。
准备
你需要:
- 一个LangSmith账号:可在smith.langchain.com注册或登录。
- 一个LangSmith API密钥:请参考《创建API密钥指南》操作。
- 安装langsmith
bash
pip install -U langsmith
- 设置环境变量:
bash
export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY="<your-langsmith-api-key>"
export LANGSMITH_WORKSPACE_ID="<your-workspace-id>"
构建智能体应用
可以使用本步骤中列出的示例应用代码,为一个RAG应用程序添加埋点监测;也可以使用你自己包含大模型调用逻辑的应用代码。
以下是一个最小化的RAG应用程序,它直接使用OpenAI SDK,暂未添加任何LangSmith追踪功能。该应用包含三个核心部分:
- 检索器函数(Retriever function):模拟文档检索过程,且始终返回相同的字符串。
- OpenAI 客户端(OpenAI client):初始化一个基础的 OpenAI 客户端,用于发送聊天补全请求。
- RAG 函数(RAG function):将检索到的文档与用户的问题结合,构建系统提示词;调用 chat.completions.create() 接口;并返回助手的响应结果。
python
from openai import OpenAI
def retriever(query: str):
# Minimal example retriever
return ["Harrison worked at Kensho"]
# OpenAI client call (no wrapping yet)
client = OpenAI()
def rag(question: str) -> str:
docs = retriever(question)
system_message = (
"Answer the user's question using only the provided information below:\n"
+ "\n".join(docs)
)
# This call is not traced yet
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_message},
{"role": "user", "content": question},
],
)
return resp.choices[0].message.content
if __name__ == "__main__":
print(rag("Where did Harrison work?"))
追踪LLM调用
追踪所有的大模型调用,LangSmith提供了对应的包装器(wrapper):
- Python语言:wrap_openai
- TypeScript语言:wrapOpenAI
此代码片段会对OpenAI客户端进行包装,这样后续每一次模型调用都会被自动记录,并作为LangSmith中一条追踪记录的子运行单元。
python
from openai import OpenAI
from langsmith.wrappers import wrap_openai # traces openai calls
def retriever(query: str):
return ["Harrison worked at Kensho"]
client = wrap_openai(OpenAI()) # log traces by wrapping the model calls
def rag(question: str) -> str:
docs = retriever(question)
system_message = (
"Answer the user's question using only the provided information below:\n"
+ "\n".join(docs)
)
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_message},
{"role": "user", "content": question},
],
)
return resp.choices[0].message.content
if __name__ == "__main__":
print(rag("Where did Harrison work?"))
追踪整个应用
你也可以使用traceable装饰器,来追踪整个应用程序,而不只是仅仅追踪大型语言模型的调用。
python
from openai import OpenAI
from langsmith.wrappers import wrap_openai
from langsmith import traceable
def retriever(query: str):
return ["Harrison worked at Kensho"]
client = wrap_openai(OpenAI()) # keep this to capture the prompt and response from the LLM
@traceable
def rag(question: str) -> str:
docs = retriever(question)
system_message = (
"Answer the user's question using only the provided information below:\n"
+ "\n".join(docs)
)
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_message},
{"role": "user", "content": question},
],
)
return resp.choices[0].message.content
if __name__ == "__main__":
print(rag("Where did Harrison work?"))
追踪LangChain应用
- 自动追踪
LangSmith可与LangChain无缝集成,你只需要配置LangSmith的环境变量,即可自动追踪LangChain应用的运行。
- 选择性跟踪
有时候你并不需要追踪智能体所有的行为。你可能希望选择性的追踪一些行为。使用tracing_context上下文管理器可以实现选择性的追踪。
python
# You can opt-in to specific invocations..
import langsmith as ls
with ls.tracing_context(enabled=True):
chain.invoke({"question": "Am I using a callback?", "context": "I'm using a callback"})
# This will NOT be traced (assuming LANGSMITH_TRACING is not set)
chain.invoke({"question": "Am I being traced?", "context": "I'm not being traced"})
# This would not be traced, even if LANGSMITH_TRACING=true
with ls.tracing_context(enabled=False):
chain.invoke({"question": "Am I being traced?", "context": "I'm not being traced"})