LangSmith 与 LangChain(Python 和 JavaScript)无缝集成,后者是用于构建 LLM 应用程序的流行开源框架。
安装
为 Python 或 JS 安装以下依赖(代码示例使用 OpenAI 集成)。
有关可用包的完整列表,请参阅 LangChain 文档.
pip install langchain_openai
yarn add @langchain/openai @langchain/core
npm install @langchain/openai @langchain/core
pnpm add @langchain/openai @langchain/core
快速入门
1. 配置您的环境
# This example uses OpenAI, but you can use any LLM provider of choice
# For LangSmith API keys linked to multiple workspaces, set the LANGSMITH_WORKSPACE_ID environment variable to specify which workspace to use.
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-5.4-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})
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-5.4-mini" });
const outputParser = new StringOutputParser();
const chain = prompt.pipe(model).pipe(outputParser);
const question = "Can you summarize this morning's meetings?"
const context = "During this morning's meeting, we solved all world conflict."
await chain.invoke({ question: question, context: context });
3. 查看您的追踪
默认情况下,追踪将记录到名称为 default的项目中。您可以在 LangSmith 中公开查看使用上述代码记录的追踪示例 公开查看.
选择性追踪
上一节 展示了如何通过设置单个环境变量来追踪应用程序内所有 LangChain runnable 的调用。虽然这是入门的一种便捷方式,但您可能只想追踪特定的调用或应用程序的某些部分。
在 Python 中有两种方式可以做到这一点:手动传入一个 LangChainTracer 实例作为 回调,或者使用 tracing_context 上下文管理器.
In JS/TS, you can pass a LangChainTracer 实例作为回调。
# You can opt-in to specific invocations..
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"})
// You can configure a LangChainTracer instance to trace a specific invocation.
const tracer = new LangChainTracer();
await chain.invoke(
{
question: "Am I using a callback?",
context: "I'm using a callback"
},
{ callbacks: [tracer] }
);
记录到特定项目
静态方式
如 追踪概念指南 中所述,LangSmith 使用项目概念对追踪进行分组。如果未指定,追踪器项目将设置为 default。您可以设置 LANGSMITH_PROJECT 环境变量来为整个应用程序运行配置自定义项目名称。这应该在执行应用程序之前完成。
动态方式
这主要基于 上一节 构建,允许您为特定的 LangChainTracer 实例设置项目名称,或作为 Python 中 tracing_context 上下文管理器的参数。
# You can set the project name using the project_name parameter.
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"})
// You can set the project name for a specific tracer instance:
const tracer = new LangChainTracer({ projectName: "My Project" });
await chain.invoke(
{
question: "Am I using a callback?",
context: "I'm using a callback"
},
{ callbacks: [tracer] }
);
为追踪添加元数据和标签
您可以通过在 RunnableConfig这对于将附加信息与跟踪关联非常有用,例如执行环境或启动它的用户。有关如何按元数据和标签查询跟踪和运行的信息,请参见 查询跟踪 (SDK)
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"}})
const prompt = ChatPromptTemplate.fromMessages([
["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
const model = new ChatOpenAI().withConfig({ tags: ["model-tag"], metadata: { "model-key": "model-value" } });
const outputParser = new StringOutputParser();
// Tags and metadata can be configured with RunnableConfig
const chain = (prompt.pipe(model).pipe(outputParser)).withConfig({"tags": ["config-tag"], "metadata": {"config-key": "top-level-value"}});
// Tags and metadata can also be passed at runtime
await chain.invoke({input: "What is the meaning of life?"}, {tags: ["invoke-tag"], metadata: {"invoke-key": "invoke-value"}})
自定义运行名称
你可以在调用或流式传输 LangChain 代码时通过在 Config中提供来自定义给定运行的名称。这个名称用于在 LangSmith 中识别该运行,并可用于过滤和分组运行。该名称也用作 LangSmith UI 中运行的标题。 run_name 通过在 RunnableConfig 对象中设置一个 run_name in the invocation parameters in 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"})
// When tracing within LangChain, run names default to the class name of the traced object (e.g., 'ChatOpenAI').
const configuredChain = chain.withConfig({ runName: "MyCustomChain" });
await configuredChain.invoke({ input: "What is the meaning of life?" });
// You can also configure the run name at invocation time, like below
await chain.invoke({ input: "What is the meaning of life?" }, {runName: "MyCustomChain"})
在跟踪中覆盖模型名称
在跟踪 LangChain 模型调用时,LangSmith 会自动捕获 API 调用中使用的模型标识符。但是,出于组织目的或区分不同模型配置,你可能希望在跟踪中显示不同的、更具描述性的名称。你可以通过在 ls_model_name 元数据参数 构造或配置 LangChain 模型时传递
来实现此目的。这在以下情况下特别有用:
- - 使用自托管或本地模型时,模型 ID 可能不够描述性。
- - 使用相同模型的不同配置并希望在跟踪中区分它们。
- - 为模型创建别名,使跟踪对你的团队更具可读性。
- - 跨不同部署环境标准化模型名称。
from langchain_openai import ChatOpenAI
from langchain_ollama import ChatOllama
# Override model name for a local model
llm = ChatOllama(
model="llama2:13b-chat", # Actual model ID
metadata={"ls_model_name": "llama2-13b-production"} # Name shown in LangSmith
)
# Or with OpenAI to distinguish configurations
llm_creative = ChatOpenAI(
model="gpt-5.5",
temperature=0.9,
metadata={"ls_model_name": "gpt-5.4-creative"}
)
llm_factual = ChatOpenAI(
model="gpt-5.5",
temperature=0.1,
metadata={"ls_model_name": "gpt-5.4-factual"}
)
# The metadata is inherited when the model is used in a chain
result = llm.invoke("What is the meaning of life?")
// Override model name for a local model
const llm = new ChatOllama({
model: "llama2:13b-chat", // Actual model ID
metadata: { ls_model_name: "llama2-13b-production" } // Name shown in LangSmith
});
// Or with OpenAI to distinguish configurations
const llmCreative = new ChatOpenAI({
modelName: "gpt-5.5",
temperature: 0.9,
metadata: { ls_model_name: "gpt-5.4-creative" }
});
const llmFactual = new ChatOpenAI({
modelName: "gpt-5.5",
temperature: 0.1,
metadata: { ls_model_name: "gpt-5.4-factual" }
});
// The metadata is inherited when the model is used in a chain
const result = await llm.invoke("What is the meaning of life?");
当你在模型的元数据中传递 ls_model_name 时,此名称将出现在 LangSmith UI 中涉及该模型实例的所有跟踪中。这适用于任何 LangChain 聊天模型或 LLM,并被使用该模型的所有运行继承,包括当它作为链的一部分时。
自定义运行 ID
你可以在调用或流式传输 LangChain 代码时通过在 Config. 此 ID 用于在 LangSmith 中唯一标识该运行,可用于查询特定运行。ID 可用于跨不同系统链接运行或实现自定义跟踪逻辑。可以通过设置一个 run_id 在 RunnableConfig 对象时在构造函数中设置,或通过传递一个 run_id 在调用参数中传递。
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})
const myUuid = crypto.randomUUID();
// You can configure the run ID at invocation time, like below
await chain.invoke({ input: "What is the meaning of life?" }, { runId: myUuid });
请注意,如果在 **根** 级别执行此操作(即顶级运行),该运行 ID 将被用作 trace_id).
访问 LangChain 调用的运行 (span) ID
调用 LangChain 对象时,可以手动指定调用的运行 ID。此运行 ID 可用于在 LangSmith 中查询运行。
In JS/TS, you can use a RunCollectorCallbackHandler 实例来访问运行 ID。
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-5.4-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)
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}\n\nContext: {context}"],
]);
const model = new ChatOpenAI({ modelName: "gpt-5.4-mini" });
const outputParser = new StringOutputParser();
const chain = prompt.pipe(model).pipe(outputParser);
const runCollector = new RunCollectorCallbackHandler();
const question = "Can you summarize this morning's meetings?"
const context = "During this morning's meeting, we solved all world conflict."
await chain.invoke(
{ question: question, context: context },
{ callbacks: [runCollector] }
);
const runId = runCollector.tracedRuns[0].id;
console.log(runId);
确保在退出前提交所有追踪
在 LangChain Python 中,LangSmith 的追踪在后台线程中执行,以避免阻塞您的生产应用程序。这意味着在所有追踪成功发送到 LangSmith 之前,您的进程可能会结束。这在无服务器环境中尤为常见,因为一旦您的链或代理完成,VM 可能会立即被终止。
您可以通过设置 LANGCHAIN_CALLBACKS_BACKGROUND 环境变量来使回调同步 "false".
对于两种语言,LangChain 都公开了等待追踪提交后再退出应用程序的方法。以下是一个示例:
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()
try {
const llm = new ChatOpenAI();
const response = await llm.invoke("Hello, World!");
} catch (e) {
// handle error
} finally {
await awaitAllCallbacks();
}
在不设置环境变量的情况下追踪
如其他指南所述,以下环境变量允许您配置追踪启用、API 端点、API 密钥和追踪项目:
- *
LANGSMITH_TRACING - *
LANGSMITH_API_KEY - *
LANGSMITH_ENDPOINT - *
LANGSMITH_PROJECT
但是,在某些环境中,无法设置环境变量。在这种情况下,您可以以编程方式设置追踪配置。
这主要基于 上一节.
# 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", # Self-hosted, GCP EU (`eu.api...`), GCP APAC (`apac.api...`), or AWS US (`aws.api...`) as needed
)
# 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"})
// You can create a client instance with an api key and api url
const client = new Client(
{
apiKey: "YOUR_API_KEY",
apiUrl: "https://api.smith.langchain.com", // Self-hosted, GCP EU (`eu.api...`), GCP APAC (`apac.api...`), or AWS US (`aws.api...`) as needed
}
);
// You can pass the client and project_name to the LangChainTracer instance
const tracer = new LangChainTracer({client, projectName: "test-no-env"});
await chain.invoke(
{
question: "Am I using a callback?",
context: "I'm using a callback",
},
{ callbacks: [tracer] }
);
LangChain (Python) 的分布式追踪
LangSmith 支持使用 LangChain Python 进行分布式追踪。这允许您跨不同服务和应用程序链接运行 (span)。原理类似于 LangSmith SDK 的 分布式追踪指南
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 对象将被追踪,并作为 traceable function.
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-5.4-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.")
这将产生以下追踪树: !追踪树 Python 互操作
LangChain.JS 与 LangSmith SDK 之间的互操作性
在 traceable (仅限 JS)
从 langchain@0.2.x开始,LangChain 对象在使用时会被自动追踪 @traceable 函数,并继承该可追踪函数的客户端、标签、元数据和项目名称。
对于低于 0.2.x的旧版本 LangChain,您需要手动传递一个实例 LangChainTracer 从以下位置找到的追踪上下文创建 @traceable.
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-5.4-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" }
);
通过以下方式追踪 LangChain 子运行 traceable / RunTree API (JS only)
在某些用例中,您可能想要运行 traceable 函数作为 RunnableSequence 的一部分,或通过以下方式命令式地追踪 LangChain 的子运行 RunTree API. Starting with LangSmith 0.1.39 and @langchain/core 0.2.18, you can directly invoke traceable在 RunnableLambda 中使用 -包装的函数。
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);
},
});
!追踪树
或者,您可以通过使用将 LangChain 的 RunnableConfig 转换为等效的 RunTree 对象,或者将 @[ RunTree.fromRunnableConfig ] 作为第一个参数传递给RunnableConfig-包装的函数。 traceable-wrapped function.
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;
},
});
const parrot = new RunnableLambda({
func: async (input: { text: string }, config?: RunnableConfig) => {
// create the RunTree from the RunnableConfig of the RunnableLambda
const childRunTree = RunTree.fromRunnableConfig(config, {
name: "Child Run",
});
childRunTree.inputs = { input: input.text };
await childRunTree.postRun();
childRunTree.outputs = { output: `Child Run: ${input.text}` };
await childRunTree.patchRun();
return input.text;
},
});
如果您更喜欢视频教程,请查看 追踪替代方法视频 选自 LangSmith 入门课程。