Skip to content
LangSmith 文档版本 跟随上游 源快照 97be68c3 更新于 2026-10-18

Trajectory 视图集成

在 LangSmith Trajectory 视图中呈现的框架和 SDK,以及每个框架设置的元数据。

Trajectory 视图将追踪(即线程的追踪)呈现为轨迹:用户提示、模型响应、工具调用和工具结果,按顺序排列。Trajectory 视图需要两条运行元数据来呈现轨迹:

  • 线程分组:每个运行上的 thread_id 告诉 LangSmith 一组运行属于同一对话。
  • 运行分类:轮次顶层运行上的 ls_agent_type: "root" 将该运行标记为主对话的一部分。标记为 subagent 的运行在线程中显示为子 agent 操作,而标记为 middleware 或 compaction 的运行目前会被过滤掉。

对于大多数 LangSmith 集成,这两者都会为你设置。当你需要手动设置元数据时,以下示例涵盖链式模式下的 OpenAI Responses API以及标记自定义中间件或护栏。

支持的集成

以下集成会自动设置 thread_id 和 ls_agent_type:

链式模式下的 OpenAI Responses API(previous_response_id)会自动设置 ls_agent_type,但 thread_id 需要你自己设置。有关更多详细信息,请参阅带链式的 OpenAI Responses API示例。

有关完整的 ls_agent_type schema 以及官方集成在非根运行上设置的其他值(subagent、middleware、compaction),请参阅编码 agent 元数据契约。有关底层线程分组机制,请参阅配置线程。

带链式的 OpenAI Responses API

当你通过传递 previous_response_id 链式调用 OpenAI Responses API 时,OpenAI 会在服务器端存储对话状态,LangSmith 包装器没有用于将调用分组到线程的自然键。你需要自行设置 thread_id,可以按调用设置,也可以在包装器初始化时设置。

NOTE

为 thread_id 使用 UUID v7。LangSmith 的 SDK 导出了 uuid7 辅助函数,UUID v7 按创建时间排序,因此线程在列表视图中保持有序。

按调用设置元数据

在每次调用时设置 thread_id。当同一个被包装的客户端服务多个线程时(例如,每个进程一个客户端、多个并发对话)使用此方式。

python
import openai
from langsmith import uuid7
from langsmith.wrappers import wrap_openai

client = wrap_openai(openai.Client())
thread_id = str(uuid7())

res1 = client.responses.create(
    model="gpt-5.6",
    input="What is the capital of France?",
    store=True,
    langsmith_extra={"metadata": {"thread_id": thread_id}},
)

res2 = client.responses.create(
    model="gpt-5.6",
    input="And its population?",
    previous_response_id=resp1.id,
    store=True,
    langsmith_extra={"metadata": {"thread_id": thread_id}},
)
typescript
import OpenAI from "openai";
import { uuid7 } from "langsmith";
import { wrapOpenAI } from "langsmith/wrappers";

const client = wrapOpenAI(new OpenAI());
const threadId = uuid7();

const res1 = await client.responses.create({
  model: "gpt-5.6",
  input: "What is the capital of France?",
  metadata: { thread_id: threadId },
  store: true,
});

const res2 = await client.responses.create({
  model: "gpt-5.6",
  input: "And its population?",
  previous_response_id: res1.id,
  metadata: { thread_id: threadId },
  store: true,
});

初始化时设置元数据

在包装客户端时设置一次 thread_id。通过此包装器进行的每次调用都会标记为同一线程。当被包装的客户端在其生命周期内仅服务一个线程时(例如,每个对话一个 worker)使用此方式。

python
import openai
from langsmith import uuid7
from langsmith.wrappers import wrap_openai

thread_id = str(uuid7())

client = wrap_openai(
    openai.Client(),
    tracing_extra={"metadata": {"thread_id": thread_id}},
)

res1 = client.responses.create(
    model="gpt-5.6",
    input="What is the capital of France?",
    store=True,
)

res2 = client.responses.create(
    model="gpt-5.6",
    input="And its population?",
    previous_response_id=resp1.id,
    store=True,
)
typescript
import OpenAI from "openai";
import { uuid7 } from "langsmith";
import { wrapOpenAI } from "langsmith/wrappers";

const threadId = uuid7();

const client = wrapOpenAI(new OpenAI(), { metadata: { thread_id: threadId } });

const res1 = await client.responses.create({
  model: "gpt-5.6",
  input: "What is the capital of France?",
  store: true,
});

const res2 = await client.responses.create({
  model: "gpt-5.6",
  input: "And its population?",
  previous_response_id: res1.id,
  store: true,
});

隐藏自定义中间件或护栏

当你围绕 LLM 或工具调用编写自己的护栏、策略检查或中间件函数时,请用 @traceable 包装它,并在元数据上设置 ls_agent_type: "middleware"。Trajectory 视图会将这些运行从主对话中过滤掉。

python
from langsmith import traceable

@traceable(
    run_type="llm",
    metadata={"ls_agent_type": "middleware"},
)
def entry_guardrail(prompt: str) -> dict:
    # Your guardrail logic
    return {"decision": "allow"}
typescript
import { traceable } from "langsmith/traceable";

const entryGuardrail = traceable(
  async (prompt: string) => {
    // Your guardrail logic
    return { decision: "allow" };
  },
  { run_type: "llm", metadata: { ls_agent_type: "middleware" } },
);

从 Trajectory 视图中排除运行

在运行的元数据上设置 LS_MESSAGE_VIEW_EXCLUDE 会告诉 Trajectory 视图跳过该运行。重要的是键的存在,True 是常规值。该过滤器会在任何提取策略看到追踪之前运行,因此被排除的 LLM 或工具运行永远不会影响检测、消息提取或工具调用配对。

LS_MESSAGE_VIEW_EXCLUDE 是从 langsmith(Python 和 JS)导出的顶级常量,其值为字符串 "ls_message_view_exclude"。优先使用该常量以避免拼写错误;字面字符串仍然有效。

将其用于非对话轮次的 LLM 子 span,例如分类调用、嵌入查找、安全过滤器或路由/护栏决策,你仍然希望在 LangSmith 的其他位置看到它们,但不希望它们弄乱对话记录。

1. 在 @traceable 装饰器上:排除整个函数的运行。

python
from langsmith import LS_MESSAGE_VIEW_EXCLUDE, traceable

@traceable(run_type="llm", metadata={LS_MESSAGE_VIEW_EXCLUDE: True})
def classify_intent(query: str) -> str:
    # This LLM call is internal routing, not part of the chat
    return llm.predict(f"Classify the intent of: {query}")

2. 通过 trace 上下文管理器:排除临时 span。

python
from langsmith import LS_MESSAGE_VIEW_EXCLUDE, trace

with trace(
    "safety_check",
    run_type="llm",
    metadata={LS_MESSAGE_VIEW_EXCLUDE: True},
) as run:
    result = safety_model.score(text)
    run.end(outputs={"score": result})

3. 在运行中的函数内部:在运行被打补丁之前的任意时刻,在当前运行树上设置该键。

python
from langsmith import LS_MESSAGE_VIEW_EXCLUDE, get_current_run_tree, traceable

@traceable(run_type="llm")
def maybe_internal(query: str) -> str:
    result = llm.predict(query)
    if _looks_like_routing(query):
        rt = get_current_run_tree()
        if rt is not None:
            rt.add_metadata({LS_MESSAGE_VIEW_EXCLUDE: True})
    return result

4. 使用 wrap_openai / wrap_anthropic 时按调用设置:将 langsmith_extra 传递给被包装的客户端调用。

python
import openai
from langsmith import LS_MESSAGE_VIEW_EXCLUDE
from langsmith.wrappers import wrap_openai

client = wrap_openai(openai.Client())

resp = client.chat.completions.create(
    model="gpt-5.6",
    messages=[{"role": "user", "content": "Classify: ..."}],
    langsmith_extra={"metadata": {LS_MESSAGE_VIEW_EXCLUDE: True}},
)

5. LangChain RunnableConfig:排除链或聊天模型的单次调用。

python
from langchain_openai import ChatOpenAI
from langsmith import LS_MESSAGE_VIEW_EXCLUDE

llm = ChatOpenAI(model="gpt-5.6")
result = llm.invoke(
    "Classify this query",
    config={"metadata": {LS_MESSAGE_VIEW_EXCLUDE: True}},
)

注

  • 过滤器检查的是键是否存在,而不是真值。{LS_MESSAGE_VIEW_EXCLUDE: false} 仍会排除该运行。要包含该运行,请完全省略该键。
  • 在 @traceable(Python)或 traceable(JS)父级内执行的子运行会通过共享的追踪上下文继承排除设置:Python 的 _METADATA ContextVar 和 JS 的 AsyncLocalStorage。子级自身在装饰器时设置的元数据会叠加在继承值之上。
  • 被排除的运行仍会出现在常规追踪视图、运行浏览器和指标中。只有 Trajectory 视图会将它们过滤掉。

手动插桩

如果你在没有使用支持的集成中某个包装器的情况下进行追踪(例如,通过 RunTree、REST API 或围绕提供程序 SDK 的自定义包装器发出运行),请在每个 LLM 运行的元数据上设置 ls_message_format,以将追踪路由到正确的提取器:

追踪形态在元数据上设置
LangChain 消息(构造函数封装)ls_message_format: "langchain"
OpenAI Chat Completionsls_message_format: "completions"
OpenAI Responses APIls_message_format: "responses"
Anthropic Messages APIls_message_format: "anthropic"

相关


BytesRouter 是社区翻译站点,所有译文仅供参考,一切以官方英文原文为准。