Skip to main content
许多大语言模型应用都具有类似聊天机器人的界面,用户与大语言模型应用在其中进行多轮对话。为了追踪这些对话,你可以在 LangSmith 中使用线程

将追踪分组到线程中

要将追踪关联到一个线程中,你需要传入一个特殊的 metadata 键,其值是该线程的唯一标识符。键名应为以下之一:
  • session_id
  • thread_id
  • conversation_id
值可以是任何你想要的字符串,但我们建议使用 UUID v7 作为线程 ID。 LangSmith SDK 导出了一个 uuid7 辅助函数(Python v0.4.43+,JS v0.3.80+):
  • Pythonfrom langsmith import uuid7
  • JS/TSimport { uuid7 } from 'langsmith'
有关说明,请参阅向追踪添加元数据和标签
重要: 为确保过滤和令牌计数在整个线程中正常工作,你必须在所有运行上设置线程元数据(session_idthread_idconversation_id),包括追踪中的子运行。如果子运行没有 thread_id 元数据,它们将不会被包含在以下情况中:
  • 按线程过滤运行时。
  • 计算线程的令牌使用量时。
  • 聚合线程的成本时。
创建子运行时(例如,使用 @traceable 进行嵌套函数或创建子 span),请确保将线程元数据传播到所有子运行。

示例

此示例演示了如何使用结构化消息格式记录和检索对话历史,以维护长时间运行的聊天。 该示例使用 uuid7() 生成一个 THREAD_ID,并通过 metadata 将其传递给 @traceable,将该会话中的所有运行链接到 LangSmith 中的同一个线程。对话历史在轮次之间本地持久化——在生产环境中,请将基于文件的存储替换为数据库或缓存。get_chat_history 标志控制管道是继续现有线程还是开始一个新线程:
import os
import json
from dotenv import load_dotenv

# 从 .env 文件加载环境变量
load_dotenv()

import openai
from langsmith import traceable, Client, uuid7
from langsmith.wrappers import wrap_openai

# 初始化客户端
langsmith_client = Client()
client = wrap_openai(openai.Client())

# 配置
THREAD_ID = str(uuid7())

# 使用本地目录存储线程历史。生产环境中,请使用持久化存储解决方案。
THREADS_DIR = os.path.join(os.path.dirname(__file__), "threads")

# 获取线程中所有大语言模型调用的历史以构建对话历史
def get_thread_history(thread_id: str) -> list:
    path = os.path.join(THREADS_DIR, f"{thread_id}.json")
    if not os.path.exists(path):
        return []
    with open(path, "r") as f:
        return json.load(f)

def save_thread_history(thread_id: str, messages: list):
    os.makedirs(THREADS_DIR, exist_ok=True)
    with open(os.path.join(THREADS_DIR, f"{thread_id}.json"), "w") as f:
        json.dump(messages, f, indent=2, default=str)


@traceable(name="Chat Bot", metadata={"thread_id": THREAD_ID})
def chat_pipeline(messages: list, get_chat_history: bool = False):
    # 是继续现有线程还是开始新线程
    if get_chat_history:
        history_messages = get_thread_history(THREAD_ID)
        # 获取现有对话历史并追加新消息
        all_messages = history_messages + messages
    else:
        all_messages = messages

    # 调用模型
    chat_completion = client.chat.completions.create(
        model="gpt-5.4-mini", messages=all_messages
    )

    response_message = chat_completion.choices[0].message
    print("模型响应:", response_message)

    full_conversation = all_messages + [{"role": response_message.role, "content": response_message.content}]
    save_thread_history(THREAD_ID, full_conversation)

    return {"messages": full_conversation}


# 格式化消息
messages = [
    {
        "content": "你好,我叫萨莉",
        "role": "user"
    }
]

# 调用聊天管道
result = chat_pipeline(messages, get_chat_history=False)
进行以下调用以继续对话。通过传递 get_chat_history=True,/getChatHistory: true,你可以从上次中断的地方继续对话。这意味着大语言模型将接收整个消息历史并对其做出响应,而不仅仅是响应最新消息:
# 格式化消息
messages = [
    {
        "content": "我叫什么名字",
        "role": "user"
    }
]

# 调用聊天管道
result = chat_pipeline(messages, get_chat_history=True)
继续对话。由于包含了过去的消息,大语言模型将记住对话内容:
# 继续对话。
messages = [
    {
        "content": "我发给你的第一条消息是什么?",
        "role": "user"
    }
]

chat_pipeline(messages, get_chat_history=True)

查看线程

你可以通过在任何项目详情页面中点击 Threads 选项卡来查看线程。然后你将看到所有线程的列表,按最近活动排序。
显示线程表的 LangSmith UI。
在线程视图中使用 Polly 来分析对话线程、理解用户情绪、识别痛点并跟踪问题是否已解决。
然后你可以点击进入特定的线程。这将打开特定线程的历史记录:
显示线程表的 LangSmith UI。
你可以通过两种不同的方式查看线程: 你可以使用页面顶部的按钮在两种视图之间切换,或使用键盘快捷键 T 在两种视图之间切换。

线程概览

线程概览按顺序显示对话的每一轮,显示线程中每个追踪的输入和输出。你可以配置概览中显示输入和输出的哪些字段,或通过点击 Configure 按钮显示多个字段。 输入和输出的 JSON 路径支持负索引,因此你可以使用 -1 访问数组的最后一个元素。例如,inputs.messages[-1].content 将访问 messages 数组中的最后一条消息。

追踪视图

线程的追踪视图类似于查看单个运行时的追踪视图,不同之处在于你可以访问线程中每一轮的所有运行。

查看反馈

查看线程时,页面顶部会有一个名为 Feedback 的部分。你可以在这里查看构成线程的每个运行的反馈。此反馈是聚合的,因此如果你对线程的每个运行使用相同的标准进行评估,你将看到所有显示运行的平均分数。你还可以看到此处留下的线程级反馈

保存线程级过滤器

线程过滤器会查看所有运行,并在至少 1 个运行匹配过滤器时显示该线程。
与在项目级别保存过滤器类似,你也可以在线程级别保存常用过滤器。要在 Threads 表上保存过滤器,请使用 Add filter 按钮设置过滤器,然后点击 Save view 按钮。 你可以通过分别点击 AnnotateOpen trace 在侧面板中打开追踪或注释追踪。

相关内容