LangSmith 与 LangChain(Python 和 JavaScript)无缝集成,LangChain 是用于构建 LLM 应用程序的流行开源框架。
为 Python 和 JS 安装核心库和 OpenAI 集成(我们在下面的代码片段中使用 OpenAI 集成)。
有关可用包的完整列表,请参阅 LangChain 文档。
pip install langchain_openai langchain_core
快速入门
1. 配置您的环境
export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=<your-api-key>
# 此示例使用 OpenAI,但您可以使用您选择的任何 LLM 提供商
export OPENAI_API_KEY=<your-openai-api-key>
# 对于链接到多个工作区的 LangSmith API 密钥,设置 LANGSMITH_WORKSPACE_ID 环境变量以指定要使用的工作区。
export LANGSMITH_WORKSPACE_ID=<your-workspace-id>
如果您在非无服务器环境中使用 LangChain.js 和 LangSmith,我们还建议显式设置以下内容以减少延迟:export LANGCHAIN_CALLBACKS_BACKGROUND=true如果您在无服务器环境中,我们建议设置相反的设置以允许跟踪在函数结束之前完成:export LANGCHAIN_CALLBACKS_BACKGROUND=false
2. 记录跟踪
不需要额外的代码即可将跟踪记录到 LangSmith。只需像往常一样运行您的 LangChain 代码。
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant. Please respond to the user's request only based on the given context."),
("user", "Question: {question}\nContext: {context}")
])
model = ChatOpenAI(model="gpt-4o-mini")
output_parser = StrOutputParser()
chain = prompt | model | output_parser
question = "Can you summarize this morning's meetings?"
context = "During this morning's meeting, we solved all world conflict."
chain.invoke({"question": question, "context": context})
3. View your trace
By default, the trace will be logged to the project with the name default. An example of a trace logged using the above code is made public and can be viewed here.
选择性记录
上一节 介绍了通过设置单个环境变量来记录所有 LangChain runnable 的运行。尽管简单易用,但你可能只想跟踪特定调用或某些部分。
在 Python 中有两种方式:显式传入 LangChainTracer 作为 callback,或使用 tracing_context 上下文管理器。
在 JS/TS 中,可以将 LangChainTracer 实例作为回调传入。
# 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"})
记录到特定项目
静态方式
如 跟踪概念指南 所述,LangSmith 使用 Project 来组织跟踪。若未指定,默认写入 default 项目。可在执行应用前设置 LANGSMITH_PROJECT 环境变量,使整个运行写入自定义项目。
export LANGSMITH_PROJECT=my-project
LANGSMITH_PROJECT 仅在 JS SDK >= 0.2.16 支持,旧版本请使用 LANGCHAIN_PROJECT。
动态方式
基于前文的做法,可为特定 LangChainTracer 实例或 tracing_context 参数设置项目名。
# You can set the project name using the project_name parameter.
import langsmith as ls
with ls.tracing_context(project_name="My Project", enabled=True):
chain.invoke({"question": "Am I using a context manager?", "context": "I'm using a context manager"})
为跟踪添加元数据与标签
可在 RunnableConfig 中指定任意元数据与标签,以记录执行环境、触发用户等信息。如何按元数据/标签查询请参阅 相关指南。
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful AI."),
("user", "{input}")
])
# The tag "model-tag" and metadata {"model-key": "model-value"} will be attached to the ChatOpenAI run only
chat_model = ChatOpenAI().with_config({"tags": ["model-tag"], "metadata": {"model-key": "model-value"}})
output_parser = StrOutputParser()
# Tags and metadata can be configured with RunnableConfig
chain = (prompt | chat_model | output_parser).with_config({"tags": ["config-tag"], "metadata": {"config-key": "config-value"}})
# Tags and metadata can also be passed at runtime
chain.invoke({"input": "What is the meaning of life?"}, {"tags": ["invoke-tag"], "metadata": {"invoke-key": "invoke-value"}})
自定义运行名称
在 RunnableConfig 中配置 run_name,可在调用或流式传输时自定义运行名称,便于在 LangSmith 中识别、过滤、分组,并作为 UI 标题。可以在构建 RunnableConfig 时指定,也可在 JS/TS 调用参数中传入。
# When tracing within LangChain, run names default to the class name of the traced object (e.g., 'ChatOpenAI').
configured_chain = chain.with_config({"run_name": "MyCustomChain"})
configured_chain.invoke({"input": "What is the meaning of life?"})
# You can also configure the run name at invocation time, like below
chain.invoke({"input": "What is the meaning of life?"}, {"run_name": "MyCustomChain"})
run_name 仅影响当前 runnable(如 chain/function),不会重命名由 LLM 对象(如 ChatOpenAI)自动生成的子运行。示例中外层显示为 MyCustomChain,嵌套 LLM 仍使用模型默认名。若需更有意义的 LLM 名称,可:1) 将模型包裹在新的 runnable 并设置 run_name;2) 使用 @traceable(Python)或 traceable(JS/TS)在模型调用外创建自定义运行。
自定义运行 ID
同样可在 RunnableConfig 中配置 run_id,用于唯一标识运行并查询特定记录,也便于跨系统关联。可以在 RunnableConfig 构造时或调用参数中设置。
当前尚未直接支持为 LLM 对象设置 run_id。
import uuid
my_uuid = uuid.uuid4()
# You can configure the run ID at invocation time:
chain.invoke({"input": "What is the meaning of life?"}, {"run_id": my_uuid})
请注意,如果您在跟踪的根节点(即顶级运行)执行此操作,那么该运行 ID 将会作为 trace_id 使用。
获取 LangChain 调用的运行 ID
调用 LangChain 对象时可以手动指定 run_id,用于后续在 LangSmith 中查询。
在 JS/TS 中,可借助 RunCollectorCallbackHandler 获取运行 ID。
import uuid
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant. Please respond to the user's request only based on the given context."),
("user", "Question: {question}\n\nContext: {context}")
])
model = ChatOpenAI(model="gpt-4o-mini")
output_parser = StrOutputParser()
chain = prompt | model | output_parser
question = "Can you summarize this morning's meetings?"
context = "During this morning's meeting, we solved all world conflict."
my_uuid = uuid.uuid4()
result = chain.invoke({"question": question, "context": context}, {"run_id": my_uuid})
print(my_uuid)
退出前确保提交所有跟踪
在 LangChain Python 中,跟踪在后台线程执行,为避免阻塞主流程。这意味着进程可能在所有跟踪发送完毕前结束,特别是在无服务器环境中链路完成后 VM 会立即回收。
可通过设置 LANGCHAIN_CALLBACKS_BACKGROUND="false" 让回调同步执行。
两种语言都提供等待机制,确保退出前提交完所有跟踪,例如:
from langchain_openai import ChatOpenAI
from langchain_core.tracers.langchain import wait_for_all_tracers
llm = ChatOpenAI()
try:
llm.invoke("Hello, World!")
finally:
wait_for_all_tracers()
无需环境变量进行跟踪
以下环境变量可配置是否启用跟踪、API 端点、API Key 及项目:
LANGSMITH_TRACING
LANGSMITH_API_KEY
LANGSMITH_ENDPOINT
LANGSMITH_PROJECT
若无法设置环境变量,可在代码中配置,做法与选择性记录 类似:
import langsmith as ls
# You can create a client instance with an api key and api url
client = ls.Client(
api_key="YOUR_API_KEY", # This can be retrieved from a secrets manager
api_url="https://api.smith.langchain.com", # Update appropriately for self-hosted installations or the EU region
)
# You can pass the client and project_name to the tracing_context
with ls.tracing_context(client=client, project_name="test-no-env", enabled=True):
chain.invoke({"question": "Am I using a callback?", "context": "I'm using a callback"})
LangChain(Python)中的分布式跟踪
LangSmith 支持 LangChain Python 的分布式跟踪,可将不同服务/应用的运行(span)串联起来。原理与 LangSmith SDK 分布式跟踪指南 类似。
import langsmith
from langchain_core.runnables import chain
from langsmith.run_helpers import get_current_run_tree
# -- This code should be in a separate file or service --
@chain
def child_chain(inputs):
return inputs["test"] + 1
def child_wrapper(x, headers):
with langsmith.tracing_context(parent=headers):
child_chain.invoke({"test": x})
# -- This code should be in a separate file or service --
@chain
def parent_chain(inputs):
rt = get_current_run_tree()
headers = rt.to_headers()
# ... make a request to another service with the headers
# The headers should be passed to the other service, eventually to the child_wrapper function
parent_chain.invoke({"test": 1})
LangChain(Python)与 LangSmith SDK 互操作
若应用同时使用 LangChain 与 LangSmith SDK(参见 此指南),仍可无缝记录全链路。
在 traceable 函数内部调用 LangChain 对象时,它们会作为该函数的子运行被记录。
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langsmith import traceable
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant. Please respond to the user's request only based on the given context."),
("user", "Question: {question}\nContext: {context}")
])
model = ChatOpenAI(model="gpt-4o-mini")
output_parser = StrOutputParser()
chain = prompt | model | output_parser
# The above chain will be traced as a child run of the traceable function
@traceable(
tags=["openai", "chat"],
metadata={"foo": "bar"}
)
def invoke_runnnable(question, context):
result = chain.invoke({"question": question, "context": context})
return "The response is: " + result
invoke_runnnable("Can you summarize this morning's meetings?", "During this morning's meeting, we solved all world conflict.")
效果示例如下:
LangChain.JS 与 LangSmith SDK 互操作
在 traceable 中跟踪 LangChain 对象(仅 JS)
自 langchain@0.2.x 起,@traceable 函数内部的 LangChain 对象会自动被跟踪,继承该函数的 client、标签、元数据与项目名。
若版本低于 0.2.x,需从 @traceable 的 tracing context 创建 LangChainTracer 并手动传入。
import { ChatOpenAI } from "@langchain/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { StringOutputParser } from "@langchain/core/output_parsers";
import { getLangchainCallbacks } from "langsmith/langchain";
const prompt = ChatPromptTemplate.fromMessages([
[
"system",
"You are a helpful assistant. Please respond to the user's request only based on the given context.",
],
["user", "Question: {question}\nContext: {context}"],
]);
const model = new ChatOpenAI({ modelName: "gpt-4o-mini" });
const outputParser = new StringOutputParser();
const chain = prompt.pipe(model).pipe(outputParser);
const main = traceable(
async (input: { question: string; context: string }) => {
const callbacks = await getLangchainCallbacks();
const response = await chain.invoke(input, { callbacks });
return response;
},
{ name: "main" }
);
通过 traceable / RunTree 跟踪子运行(仅 JS)
我们正在改进 traceable 与 LangChain 的互操作,当前存在以下限制:
- 修改
RunnableLambda 中 getCurrentRunTree() 返回的 RunTree 不会生效;
- 不建议遍历该 RunTree,因为它可能不包含所有节点;
- 不同子运行可能拥有相同的
execution_order 与 child_execution_order,极端情况下运行顺序可能受 start_time 影响。
在某些场景下,你可能希望在 RunnableSequence 中运行 traceable 函数,或通过 RunTree API 命令式跟踪 LangChain 子运行。从 LangSmith 0.1.39 和 @langchain/core 0.2.18 起,可在 RunnableLambda 中直接调用 traceable 包裹的函数。
import { traceable } from "langsmith/traceable";
import { RunnableLambda } from "@langchain/core/runnables";
import { RunnableConfig } from "@langchain/core/runnables";
const tracedChild = traceable((input: string) => `Child Run: ${input}`, {
name: "Child Run",
});
const parrot = new RunnableLambda({
func: async (input: { text: string }, config?: RunnableConfig) => {
return await tracedChild(input.text);
},
});
也可以使用 RunTree.fromRunnableConfig 将 RunnableConfig 转为 RunTree,或者将 RunnableConfig 作为 traceable 函数的首个参数传入。
import { traceable } from "langsmith/traceable";
import { RunnableLambda } from "@langchain/core/runnables";
import { RunnableConfig } from "@langchain/core/runnables";
const tracedChild = traceable((input: string) => `Child Run: ${input}`, {
name: "Child Run",
});
const parrot = new RunnableLambda({
func: async (input: { text: string }, config?: RunnableConfig) => {
// Pass the config to existing traceable function
await tracedChild(config, input.text);
return input.text;
},
});
若偏好视频教程,可参考 LangSmith 入门课程中的 Alternative Ways to Trace 视频。