☰
LangChain 链路可观测性实战:用 TaoToken 统一 Key 打通 LangSmith 监控配置
2026/9/28 18:14:22 网站建设 项目流程

1. 多步链路跑通却查不到 trace,问题往往不在 LangSmith

LangChain 和 LangGraph 把 RAG、Agent、多步工具调用串起来之后,本地跑一遍能出结果,但一进 LangSmith 就发现:有的链路有 trace,有的链路是空的;CI 里跑批量回归,trace 全跑到别人的项目里;换台机器重新拉代码,同样的调用链却复现不出上一次的监控数据。这类“链路能跑、监控断档”的问题,在本地开发和 CI 联调阶段特别常见。

我这次要解决的核心场景是:用一套统一的 Key 和 API 通道,把 LangChain / LangGraph 的多步链路稳定地接到 LangSmith,让 RAG 调用链的 trace 可查、可复现。适合正在做 RAG 问答、Agent 编排、CI 回归测试的开发者,尤其是那种“代码没问题,但监控数据对不上”的情况。

整篇会围绕三件事展开:一是用 TaoToken 统一管理模型 Key 和 API 通道,避免每个环境各配一套;二是给出config.toml和settings.json的可复制骨架;三是用一个最小 RAG 链路演示 trace 上报和验证动作。你照着做,至少能把“监控盲区”缩到可定位的范围。

2. 前置准备:TaoToken 统一 Key 与 API 通道

在接 LangSmith 之前,先把模型调用这一层收口。很多 trace 断档的根因,是模型请求走了不同通道,LangSmith 只拦截了其中一部分。TaoToken 在这里的作用是提供一个统一的 API 入口和 Key 管理方式,让 LangChain / LangGraph 的模型调用走同一条通道,LangSmith 的追踪才能覆盖完整链路。

你需要先拿到两样东西:TaoToken 的 API Key,以及确认 API 地址。API 地址是https://taotoken.net/api,这个地址在配置里会作为base_url使用。Key 的获取入口在控制台的 API Keys 页面,建议单独建一个项目专用的 Key,不要和别的环境混用。

注意:LangSmith 的追踪是挂在 LangChain 回调体系上的,只要模型调用走的是 LangChain 封装的接口,trace 就会自动上报。但如果你的代码里混用了裸 HTTP 请求,那部分不会进 trace,这也是后面排查的重点之一。

统一 Key 的好处在于:本地开发、CI、预发三个环境用同一套通道配置,LangSmith 里的项目名通过环境变量区分,trace 不会串。下面先给配置骨架,再讲代码怎么接。

3. 可复制配置:config.toml 与 settings.json 骨架

先给config.toml,这个文件适合放在项目根目录,用来管理模型通道和 LangSmith 开关。注意base_url指向 TaoToken 的 API 地址,api_key从环境变量读取,不要硬编码。

# config.toml [llm] provider = "openai-compatible" base_url = "https://taotoken.net/api" api_key_env = "TAOTOKEN_API_KEY" model = "gpt-4o-mini" temperature = 0.0 [langsmith] tracing = true api_key_env = "LANGCHAIN_API_KEY" project = "rag-chain-dev" endpoint = "https://api.smith.langchain.com" [rag] chunk_size = 600 chunk_overlap = 80 retriever_k = 3

再给settings.json,这个适合 CI 或容器环境,用 JSON 覆盖默认值。两个文件字段名保持一致,方便代码里统一读取。

{ "llm": { "provider": "openai-compatible", "base_url": "https://taotoken.net/api", "api_key_env": "TAOTOKEN_API_KEY", "model": "gpt-4o-mini", "temperature": 0.0 }, "langsmith": { "tracing": true, "api_key_env": "LANGCHAIN_API_KEY", "project": "rag-chain-ci", "endpoint": "https://api.smith.langchain.com" }, "rag": { "chunk_size": 600, "chunk_overlap": 80, "retriever_k": 3 } }

环境变量这样设置,本地和 CI 用同一套逻辑:

export TAOTOKEN_API_KEY="你的 TaoToken Key" export LANGCHAIN_TRACING_V2="true" export LANGCHAIN_API_KEY="你的 LangSmith Key" export LANGCHAIN_PROJECT="rag-chain-dev"

提示:LANGCHAIN_PROJECT在 CI 里可以改成rag-chain-ci,这样本地调试和流水线的 trace 分开,不会互相覆盖。项目名建议带上环境后缀,排查时一眼能分清。

配置读取的代码可以写一个小的 loader,把 toml 和 json 合并,优先用环境变量覆盖。这样本地改 toml,CI 用 json,互不干扰。

import os import json import tomllib def load_config(path_toml="config.toml", path_json="settings.json"): cfg = {} if os.path.exists(path_toml): with open(path_toml, "rb") as f: cfg.update(tomllib.load(f)) if os.path.exists(path_json): with open(path_json, "r", encoding="utf-8") as f: cfg.update(json.load(f)) return cfg cfg = load_config()

到这里,通道和监控开关都收口了。接下来把 LangChain 的模型和 RAG 链接上,让 trace 真正跑起来。

4. 接入 LangChain:RAG 链路与 trace 上报

先装依赖,版本尽量对齐,避免回调接口不兼容。

pip install langchain langchain-openai langchain-community langsmith chromadb

模型初始化时,把base_url指向 TaoToken 的 API 地址,Key 从环境变量读。这样模型调用走统一通道,LangSmith 的回调能完整覆盖。

import os from langchain_openai import ChatOpenAI, OpenAIEmbeddings llm = ChatOpenAI( model="gpt-4o-mini", temperature=0.0, base_url="https://taotoken.net/api", api_key=os.environ["TAOTOKEN_API_KEY"], ) embeddings = OpenAIEmbeddings( base_url="https://taotoken.net/api", api_key=os.environ["TAOTOKEN_API_KEY"], )

构建一个最小 RAG 链路,用本地 Chroma 做向量库,文档就用几段文本模拟。重点是让检索和生成都在同一条链上,这样 trace 里能看到 retriever 和 llm 两个节点。

from langchain_core.documents import Document from langchain_community.vectorstores import Chroma from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_core.runnables import RunnablePassthrough from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate docs = [ Document(page_content="产品保修期为一年,支持全国联保。"), Document(page_content="退货需在签收后七天内发起,商品需保持完好。"), Document(page_content="发票可在订单详情页申请,电子发票三个工作日内发送。"), ] splitter = RecursiveCharacterTextSplitter( chunk_size=600, chunk_overlap=80, separators=["\n\n", "\n", "。", ","], ) splits = splitter.split_documents(docs) vectorstore = Chroma.from_documents( documents=splits, embedding=embeddings, persist_directory="./rag_kb", ) retriever = vectorstore.as_retriever(search_kwargs={"k": 3}) prompt = ChatPromptTemplate.from_template( "根据以下上下文回答问题:\n{context}\n\n问题:{question}" ) def format_docs(docs): return "\n".join(d.page_content for d in docs) rag_chain = ( {"context": retriever | format_docs, "question": RunnablePassthrough()} | prompt | llm | StrOutputParser() )

调用一次,触发 trace 上报:

result = rag_chain.invoke("保修期是多久?") print(result)

如果配置正确,这次调用会在 LangSmith 的rag-chain-dev项目里生成一条 trace,包含 retriever 和 llm 两个 span。你可以在 LangSmith 控制台看到输入、输出、耗时和 token 消耗。这一步是后面验证的基础。

5. 验证请求:确认 trace 可查、可复现

调用完成后,先看本地输出是否正常。正常会返回类似“产品保修期为一年,支持全国联保”的内容。然后去 LangSmith 控制台,进入对应项目,按时间排序,应该能看到刚才那条 trace。

验证 trace 是否完整,重点看三个地方:一是 trace 的根节点是不是RunnableSequence,二是里面有没有 retriever 的 span,三是 llm 的 span 里有没有 token 统计。如果只有根节点没有子 span,通常是回调没挂上,或者模型调用没走 LangChain 封装。

再验证可复现性:把LANGCHAIN_PROJECT改成rag-chain-ci,重新跑一次同样的调用,确认新 trace 出现在新项目里,且内容一致。这一步能确认环境变量切换有效,CI 和本地不会串数据。

export LANGCHAIN_PROJECT="rag-chain-ci" python rag_demo.py

如果要在 CI 里做批量回归,可以把问题列表循环调用,每条 trace 都会独立上报。建议在 CI 里固定temperature=0,减少非确定性带来的对比干扰。

questions = ["保修期是多久?", "退货要几天内?", "发票怎么申请?"] for q in questions: ans = rag_chain.invoke(q) print(q, "->", ans)

跑完后在 LangSmith 里按项目筛选,应该能看到三条独立 trace,每条都能展开到 retriever 和 llm。到这里,链路监控数据就是可查、可复现的了。

6. 本篇常见错排查

trace 为空或只有根节点:先确认LANGCHAIN_TRACING_V2=true是否生效,再检查模型调用是否走了 LangChain 封装。如果代码里混用了requests直接请求 TaoToken 的 API,那部分不会进 trace。统一走ChatOpenAI这类封装接口即可。

trace 跑到别人的项目里:多半是LANGCHAIN_PROJECT没设或设错。本地和 CI 用不同项目名,CI 里显式 export,不要依赖默认值。项目名建议带环境后缀,比如rag-chain-dev、rag-chain-ci。

Key 报 401 或 403:检查TAOTOKEN_API_KEY是否导出到当前 shell,CI 里是否配到 secrets。base_url要写https://taotoken.net/api,不要漏掉/api。如果用的是配置文件读取,确认环境变量优先级高于文件默认值。

retriever span 缺失:确认向量库检索走的是 LangChain 的 retriever 接口,而不是自己写的相似度计算。自己实现的检索不会自动进 trace,需要手动加回调或改成vectorstore.as_retriever()。

CI 里 trace 时有时无:检查网络出口是否稳定,LangSmith 上报是异步的,进程退出太快可能丢数据。可以在 CI 脚本末尾加一个短 sleep,或者用langsmith的 flush 接口确保上报完成。

token 统计对不上:TaoToken 通道返回的 usage 字段和 LangSmith 统计可能有细微差异,属于正常范围。重点看趋势和异常节点,不要纠结单次个位数差异。

排障时优先看 LangSmith 的 trace 详情页,里面有每个 span 的输入输出和耗时,比翻日志快得多。如果 trace 本身没生成,再回到环境变量和回调配置上查。

7. 统一 Key 之后,监控和编码可以分开推进

把模型通道收口到 TaoToken 之后,LangSmith 的 trace 覆盖会稳定很多,本地和 CI 的监控数据也能对齐。接下来如果你要长期跑编码类任务或 Agent 编排,可以了解 Coding Plan,适合需要持续调用和批量回归的场景;如果只是想先验证模型对话效果,可以直接在模型对话里试;接入过程中遇到 Key 或通道配置问题,API Keys 页面和接入文档里有更细的说明。

监控这件事,核心不是工具多,而是数据能对上。统一 Key、固定项目名、走同一条通道,这三步做完,trace 断档的问题基本就能定位到具体环节了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询