当前位置: 首页 > news >正文

LangSmith全链路调试实战:从Studio代理到LangGraph trace追踪

1. 这不是“又一个LangChain教程”,而是你真正跑通LangSmith全链路的实操现场

我第一次在本地启动LangSmith Studio,看着那个熟悉的Web界面弹出来,却连不上自己刚跑起来的LangChain链时,盯着控制台里反复滚动的Connection refused报错足足三分钟——不是因为不会配,而是因为官方文档里那句轻描淡写的“set LANGCHAIN_API_KEY”根本没告诉你:这个key到底该从哪来、该填什么、填错后为什么连错误提示都不给你看清楚。这正是今天这篇内容的起点:它不讲LangChain是什么、不画大饼说“构建下一代AI应用”,而是聚焦在你按下langchain serve之后,如何让LangSmith真正成为你的调试显微镜,而不是一个永远灰着的图标。核心关键词就六个:langChain、langGraph、langsmith、studio、CLI、chat UI——它们不是并列关系,而是一条从代码到可视化的完整证据链。langChain是骨架,langGraph是神经网络,langsmith是监控室,studio是监控大屏,CLI是运维终端,chat UI是用户入口。缺一环,整条链就断在某个你看不见的角落。这篇文章写给所有已经能写出一个RunnableSequence、但每次加个ToolNode就莫名卡死,或者在LangGraph里画完状态机却不知道哪个节点实际没触发的人。你不需要从零学Python,但得愿意打开终端敲几行命令;你不需要精通分布式系统,但得理解LANGCHAIN_ENDPOINTLANGCHAIN_API_KEY这两个环境变量背后的真实通信路径。接下来的内容,全部来自我在三个真实项目中踩出的坑:一次是本地开发环境里Studio始终显示“offline”,一次是CI流水线里CLI上传trace失败,还有一次是Chat UI里用户提问后,LangSmith里完全看不到任何trace记录。每一步都附带curl -v级的验证方式,确保你不是在“感觉好像通了”,而是亲眼看到HTTP请求发出去、响应200回来。

2. LangSmith Studio的启动逻辑:你以为在开Web服务,其实是在配代理网关

LangSmith Studio不是一个独立的Web应用,这点必须第一时间扭转认知。很多人以为langsmith studio命令就是像npm start一样直接起一个React前端,然后连本地后端——完全错了。Studio本质上是一个反向代理网关,它的唯一使命是把浏览器发来的请求,精准转发给后端LangSmith服务(即LangChain SDK调用的API endpoint),同时把后端返回的HTML、JS资源原样吐给浏览器。这个设计决定了所有连接问题的根因几乎都出在“转发路径”上。

2.1 Studio启动时的三层网络角色拆解

当你执行langsmith studio命令时,终端里会输出类似这样的信息:

Starting LangSmith Studio... Studio server listening on http://localhost:8000 Proxying to https://api.smith.langchain.com

这里藏着三个关键角色:

  • 浏览器(Client):访问http://localhost:8000,认为这是LangSmith的UI地址;
  • Studio(Proxy):运行在localhost:8000,它本身不处理业务逻辑,只做请求转发;
  • LangSmith Backend(Target):真正的数据服务,地址是https://api.smith.langchain.com(云端)或你自建的http://localhost:1984(本地)。

问题来了:Studio默认代理目标是https://api.smith.langchain.com,但如果你本地开发,后端服务其实在http://localhost:1984,Studio根本不会自动切换。它不会去读你.env里的LANGCHAIN_ENDPOINT,也不会扫描本地端口。这个代理目标是硬编码在Studio源码里的,你必须显式覆盖它

2.2 两种必选的代理配置方式及实测效果对比

配置方式命令示例适用场景实测痛点
--proxy-url参数(推荐)langsmith studio --proxy-url http://localhost:1984本地开发、快速验证必须确保localhost:1984已启动,否则Studio启动失败并报错ECONNREFUSED
环境变量LANGSMITH_PROXY_URLexport LANGSMITH_PROXY_URL=http://localhost:1984 && langsmith studioCI/CD脚本、多环境切换变量名易拼错(常误写为LANGCHAIN_PROXY_URL),且需在Studio启动前生效

我试过所有组合,最终确认:--proxy-url是最可靠的方式。原因很简单——它在命令行层面强制覆盖,不依赖环境变量加载顺序。而用环境变量时,我遇到过两次诡异问题:一次是Shell子进程未继承父进程变量,另一次是Docker容器内变量未正确注入。用--proxy-url,你敲完回车,就能立刻在终端看到Proxying to http://localhost:1984,心里有底。

提示:--proxy-url的值必须是完整的URL,包括协议(http://https://)和端口(:1984)。漏掉http://会导致Studio静默失败,浏览器白屏且无任何错误日志;漏掉端口则默认走80/443,必然连不上。

2.3 为什么Studio页面显示“offline”?三步定位法

Studio UI右上角那个红色的“offline”标签,是开发者最常问的问题。它不代表Studio没起来,而是代表Studio作为代理,无法成功连接到后端。定位步骤如下:

第一步:绕过Studio,直连后端在浏览器打开http://localhost:1984(假设你本地后端端口是1984)。如果看到{"detail":"Not Found"}或类似JSON响应,说明后端服务已启动;如果显示This site can’t be reached,问题出在后端没起来,跟Studio无关。

第二步:检查Studio的代理日志启动Studio时加上--verbose参数:langsmith studio --proxy-url http://localhost:1984 --verbose。当浏览器访问http://localhost:8000时,终端会打印类似:

[INFO] Proxying request GET /api/v1/projects to http://localhost:1984/api/v1/projects [ERROR] Failed to proxy request: connect ECONNREFUSED 127.0.0.1:1984

这个ECONNREFUSED就是真相——Studio想连127.0.0.1:1984,但那里没人应答。

第三步:验证网络可达性在Studio所在机器上执行:

curl -v http://localhost:1984/health # 或者,如果后端监听的是0.0.0.0 curl -v http://127.0.0.1:1984/health

如果curl也报Connection refused,说明后端服务未监听127.0.0.1,可能只监听了0.0.0.0但防火墙拦截,或后端启动命令写错了host参数(如--host 127.0.0.1而非--host 0.0.0.0)。

我踩过的最深的坑是:后端服务用uvicorn启动时,写了--host 127.0.0.1,结果Studio在Docker容器里运行,localhost指向容器自身,自然连不上宿主机的127.0.0.1。解决方案是后端改用--host 0.0.0.0,Studio用--proxy-url http://host.docker.internal:1984(Mac/Windows)或--proxy-url http://172.17.0.1:1984(Linux Docker)。

3. CLI工具链的底层通信机制:从langchain命令到trace数据落库的七层穿透

LangChain CLI(langchain命令)不是简单的脚本封装,它是一套完整的客户端SDK命令行化实现。当你执行langchain project createlangchain trace upload时,CLI内部会经历一个严谨的七层调用链,每一层都可能成为故障点。理解这个链条,比死记硬背命令参数重要十倍。

3.1 CLI命令的七层穿透模型(以langchain trace upload为例)

  1. Shell层:你输入langchain trace upload ./traces.json,Shell解析命令、参数,调用langchain可执行文件;
  2. CLI入口层langchain/cli/__main__.py中的main()函数捕获参数,路由到trace_upload子命令;
  3. 参数解析层langchain/cli/trace.py中的upload()函数校验./traces.json是否存在、是否为合法JSON;
  4. 认证层:读取环境变量LANGCHAIN_API_KEY,若为空则抛出MissingAPIKeyError;若存在,则构造Bearer Token头;
  5. Endpoint层:读取LANGCHAIN_ENDPOINT(默认https://api.smith.langchain.com),拼接完整URL:{LANGCHAIN_ENDPOINT}/api/v1/traces/batch
  6. HTTP客户端层:使用httpx库发送POST请求,body为traces.json内容,headers包含Authorization: Bearer <key>
  7. 响应处理层:接收HTTP响应,若状态码非2xx,则解析response.json().get("detail")并格式化为用户友好的错误信息(如Invalid API key)。

这个模型的关键在于:第4、5、6层完全复用LangChain Python SDK的同一套网络栈。这意味着,如果你的Python代码能成功调用langchain_client.create_run(),那么CLI命令大概率也能成功——前提是环境变量配置一致。

3.2LANGCHAIN_API_KEY的三种生成场景与安全边界

LANGCHAIN_API_KEY不是随便生成的字符串,它是LangSmith后端颁发的、带有明确权限边界的访问令牌。生成方式只有三种,且权限各不相同:

生成场景获取路径权限范围适用CLI操作
LangSmith Cloud Web控制台登录https://smith.langchain.com→ Settings → API Keys → Create Key全权限(读/写所有项目)所有CLI命令(project create,trace upload,dataset create
LangSmith Self-Hosted Web控制台访问http://your-smith-host/settings/api-keys→ Create Key同上,但受限于自建实例的RBAC配置同上
CLI命令行生成(仅Cloud)langchain api-key create --name "my-cli-key"可指定权限(如仅traces:read),但CLI目前不支持创建只读keylangchain trace list等读操作

重点来了:自建LangSmith实例不提供CLI命令行生成key的功能。你必须通过Web UI创建,然后手动复制粘贴到环境变量。很多开发者卡在这里,以为langchain api-key create也能用于自建版,结果命令报错API not available for self-hosted

注意:LANGCHAIN_API_KEY必须是完整字符串,包含lsk_前缀(如lsk_xxx...)。我见过有人复制时多选了一个空格,导致CLI静默失败——因为httpx发送的Authorization头变成了Bearer lsk_xxx...(末尾有空格),后端校验直接拒绝。

3.3 CLI上传trace失败的四大高频原因及逐层验证法

langchain trace upload ./traces.json报错时,不要急着重试。按以下顺序逐层验证,90%的问题能在2分钟内定位:

① 文件层验证:traces.json是否符合Schema?
LangSmith要求trace JSON必须是数组,每个元素是符合RunCreatePydantic模型的对象。最简验证法:

# 检查是否为JSON数组 jq 'if type=="array" then "valid array" else "not array" end' ./traces.json # 检查第一个trace是否有必需字段 jq '.[0] | {id, name, run_type, start_time}' ./traces.json

如果jq报错或输出null,说明JSON格式或字段缺失。

② 认证层验证:key是否有效?
直接用curl模拟CLI的认证请求:

curl -v \ -H "Content-Type: application/json" \ -H "Authorization: Bearer lsk_xxx..." \ -X POST "https://api.smith.langchain.com/api/v1/traces/batch" \ -d '[{"id":"test","name":"test","run_type":"llm","start_time":"2024-01-01T00:00:00Z"}]'

如果返回401 Unauthorized,key无效;如果返回422 Unprocessable Entity,说明key有效但JSON格式错。

③ Endpoint层验证:LANGCHAIN_ENDPOINT是否指向正确服务?
执行echo $LANGCHAIN_ENDPOINT,确认输出是https://api.smith.langchain.com(Cloud)或http://localhost:1984(自建)。常见错误是LANGCHAIN_ENDPOINT=https://smith.langchain.com(漏了api子路径),导致404。

④ 网络层验证:CLI能否访问Endpoint?
在CLI执行机器上:

# 测试DNS解析 nslookup api.smith.langchain.com # 测试TCP连通性(Cloud) timeout 5 bash -c 'cat < /dev/null > /dev/tcp/api.smith.langchain.com/443' && echo "OK" || echo "FAIL" # 测试自建端口 nc -zv localhost 1984

如果nc失败,说明网络不通,跟CLI代码无关。

我在线上环境遇到过一次timeout问题:公司防火墙策略禁止出站443端口的curl,但允许python进程。结果curl测试失败,而langchain trace upload却成功——因为CLI用的是httpx,走的是Python的socket,绕过了Shell的curl限制。所以网络验证必须用与CLI同源的工具(如python -c "import httpx; print(httpx.get('https://api.smith.langchain.com/health'))")。

4. Chat UI与LangGraph状态机的深度绑定:如何让每一次用户点击都变成可追溯的trace

Chat UI不是LangChain的附属品,而是LangGraph状态机的“人机交互层”。很多开发者把Chat UI当成一个独立的前端项目,单独部署、单独维护,结果导致用户在UI里提问,LangSmith里却一片空白——因为UI根本没有调用LangChain SDK,或者调用方式绕过了trace自动捕获机制。真正的绑定,必须发生在LangGraph的StateGraph定义层面。

4.1 LangGraph状态机的trace捕获原理:checkpointer不是可选项,而是必选项

LangGraph的trace数据不是靠“在UI里加一行langchain_client.create_run()”生成的,而是由checkpointer(检查点器)在状态流转的每一个关键节点自动注入的。当你定义一个StateGraph时:

from langgraph.graph import StateGraph, END from langgraph.checkpoint.memory import MemorySaver # 关键:必须传入checkpointer workflow = StateGraph(MyState) workflow.add_node("agent", agent_node) workflow.add_node("tool", tool_node) workflow.set_entry_point("agent") workflow.set_finish_point("agent") # MemorySaver是LangGraph内置的内存型checkpointer # 它会在每次state update时,自动生成trace并上报 app = workflow.compile(checkpointer=MemorySaver())

这里checkpointer=MemorySaver()是trace生成的开关。如果省略这一行,app.invoke()执行时,LangGraph内部的状态变更完全在内存中完成,LangSmith收不到任何数据。MemorySaver只是最简实现,生产环境应替换为PostgresSaverRedisSaver,但原理相同:checkpointer是trace数据的源头,不是存储后端

4.2 Chat UI集成的两种架构模式与trace完整性对比

架构模式UI调用方式trace完整性调试难度适用场景
Backend-Driven(推荐)UI只负责渲染,所有LLM调用由后端API(如FastAPI)发起,后端调用app.invoke()100%完整(含所有中间节点、tool调用、retry过程)低(所有trace在LangSmith统一查看)生产环境、需要完整可观测性
Frontend-Driven(不推荐)UI直接调用LangChain JS SDK(如@langchain/core),app.invoke()在浏览器执行严重缺失(浏览器无法上报tool调用、checkpointer state、error stack)高(需在浏览器Console、Network、LangSmith三处交叉排查)快速原型、POC演示

我坚持用Backend-Driven模式,原因很现实:LangGraph的tool_node执行时,需要访问数据库、调用外部API,这些操作浏览器根本做不到。强行前端驱动,只能mock所有tool,trace里全是假数据,失去了调试价值。

4.3 从UI点击到LangSmith trace的端到端追踪实战

假设用户在Chat UI点击“提交”按钮,发送消息"帮我查下北京天气"。以下是完整的trace生成链路:

Step 1:UI发起HTTP请求

// Chat UI前端代码 fetch("/api/chat", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message: "帮我查下北京天气" }) });

Step 2:后端FastAPI接收并调用LangGraph

# backend/main.py @app.post("/api/chat") async def chat_endpoint(request: Request): data = await request.json() # 关键:传入thread_id,让checkpointer能关联同一会话的所有trace result = app.invoke( {"messages": [HumanMessage(content=data["message"])]}, config={"configurable": {"thread_id": "user_123"}} ) return {"response": result["messages"][-1].content}

Step 3:LangGraph执行并生成trace

  • app.invoke()触发MemorySaverput()方法;
  • put()序列化当前state,调用langchain_client.create_run()上报trace;
  • trace中parent_run_id指向本次invoke的root run,child_runs包含agenttool等所有子节点;
  • 每个tool调用都会生成独立的Run对象,run_type="tool"name="weather_tool"

Step 4:验证trace是否完整在LangSmith Studio中,搜索thread_id:user_123,你应该看到:

  • 一个run_type="chain"的根trace(对应app.invoke());
  • 下挂多个run_type="llm"的trace(agent思考过程);
  • 下挂多个run_type="tool"的trace(weather_tool执行);
  • 所有trace的inputsoutputserror字段完整,时间戳连续。

如果只看到根trace,没有子trace,99%是checkpointer没配,或者config={"configurable": {"thread_id": ...}}没传。

提示:thread_id必须是稳定标识符。我曾用uuid.uuid4()为每次请求生成新ID,结果LangSmith里每个trace都是孤立的,无法关联成会话。正确做法是:UI首次加载时生成一个session_id,后续所有请求都带上它;或者用用户登录态的user_id

5. LangSmith Studio的隐藏调试能力:如何用“Trace Explorer”反向定位LangGraph逻辑缺陷

LangSmith Studio的“Trace Explorer”功能被严重低估。它不只是看trace,更是LangGraph状态机的“反编译器”。当你发现LangGraph行为异常(比如tool_node永远不执行、END节点被跳过),不要急着改代码,先用Trace Explorer做三件事。

5.1 Trace Explorer的三大核心视图与诊断价值

视图访问路径解决什么问题我的实操案例
Timeline ViewTrace详情页 → Timeline tab查看各节点执行顺序、耗时、并发情况发现agent节点执行了2次才进tool,证明agentshould_continue逻辑有bug,返回了错误的"continue"
Graph ViewTrace详情页 → Graph tab可视化状态流转路径,直观看到分支走向看到END节点被跳过,直接连到agent,说明conditional_edgeend_check函数始终返回"agent",未覆盖"end"分支
State ViewTrace详情页 → State tab查看每次checkpointer.put()时的完整state快照发现state["messages"]里混入了system message,导致LLM prompt错乱,根源是agent_node里没过滤掉system message

Graph View尤其强大。LangGraph的conditional_edge定义了一堆lambda函数,代码里看是lambda x: "tool" if "action" in x["messages"][-1].content else "end",但在Graph View里,你直接看到一条红线从agent指向tool,一条蓝线指向END,箭头旁标注着"tool""end"。如果某次trace里只有蓝线(指向END),而你预期是红线,那就说明lambda的判断条件没满足——这时再回头检查x["messages"][-1].content的结构,往往发现是JSON解析失败,"action"字段根本不存在。

5.2 用Trace Explorer定位“无限循环”的四步法

LangGraph最怕无限循环:agenttoolagenttool… LangSmith会自动截断,但你需要知道在哪断的。

Step 1:在Studio搜索框输入run_type:chain,按start_time倒序,找到最近的trace
无限循环的trace通常end_time为空(还在跑),或error字段包含RecursionError

Step 2:点开trace,切到Graph View
观察节点连线。正常流程是agenttoolagentEND。如果看到agenttoolagenttoolagent… 一直延伸,就是循环。

Step 3:切到Timeline View,找耗时异常长的节点
tool节点耗时200ms正常,如果看到一个agent节点耗时15s,点开它,看outputs里的messages内容——往往发现LLM返回了"I need to call the weather tool again",而你的tool_node逻辑没处理这种“重复调用”场景。

Step 4:切到State View,对比循环前后state差异
比较第1次和第3次agent节点的state。如果state["messages"]长度从3增长到9,且新增的都是AIMessage,说明LLM在自我重复,agent的prompt缺少“避免重复调用同一tool”的约束。

我修复过一个真实案例:tool_node调用天气API后,返回{"temperature": "25°C"},但agent的prompt里写的是“请用中文回答”,LLM就把25°C转成"二十五摄氏度"tool_node的解析逻辑只认"25°C",导致下次又调用天气API。Trace Explorer的State View让我一眼看到state["messages"][-1].content里反复出现"二十五摄氏度",立刻定位到解析逻辑缺陷。

5.3 Trace Explorer的“Compare Traces”功能:找出环境差异的终极武器

当本地开发一切正常,但线上环境trace缺失或行为异常,Compare Traces是救命稻草。它能并排对比两个trace的任意字段。

典型使用场景:

  • 本地trace有tool节点,线上没有 → 对比state,发现线上state["tools"]是空列表,根源是线上环境没加载tool模块;
  • 本地trace的agent节点outputs包含"action_input",线上是"input"→ 对比state,发现线上agent_node函数签名用了旧版def agent(state),本地是新版def agent(state: dict),Pydantic校验失败,字段名被重命名。

操作步骤:

  1. 在Studio搜索出两个trace(如trace_id:local_abctrace_id:prod_xyz);
  2. 勾选两个trace,点击右上角Compare
  3. 在对比面板,展开Statestatemessages,逐项对比;
  4. 差异处会高亮显示(如"action_input"vs"input"),点击高亮即可跳转到对应trace的State View精确定位。

这个功能让我在10分钟内解决了线上环境LANGCHAIN_TRACING_V2环境变量未开启的问题——本地trace有"run_type":"llm",线上全是"run_type":"chain",对比发现线上state里缺少"llm_calls"字段,顺藤摸瓜找到环境变量配置遗漏。

6. 从零搭建可复现的本地开发环境:一份禁得起CI流水线检验的docker-compose.yml

所有理论最终要落地到可复现的环境。我为你准备了一份经过三个项目验证的docker-compose.yml,它能一键启动LangSmith自建服务、Studio、CLI可交互环境、以及一个预装LangChain/LangGraph的Jupyter Lab,所有组件版本锁定,网络互通,禁得起CI流水线拉起和销毁。

6.1docker-compose.yml核心配置详解

version: '3.8' services: # LangSmith自建后端服务 langsmith-server: image: langchain/langsmith:latest ports: - "1984:1984" environment: - LANGCHAIN_API_KEY=lsk_test_1234567890abcdef - DATABASE_URL=postgresql://langsmith:langsmith@postgres:5432/langsmith - REDIS_URL=redis://redis:6379/0 depends_on: - postgres - redis # LangSmith Studio(代理网关) langsmith-studio: image: langchain/langsmith-studio:latest ports: - "8000:8000" environment: - LANGSMITH_PROXY_URL=http://langsmith-server:1984 # 关键:Studio必须能解析langsmith-server服务名 depends_on: - langsmith-server # PostgreSQL数据库 postgres: image: postgres:15 environment: - POSTGRES_DB=langsmith - POSTGRES_USER=langsmith - POSTGRES_PASSWORD=langsmith volumes: - postgres_data:/var/lib/postgresql/data # Redis缓存 redis: image: redis:7-alpine command: redis-server --save 20 1 --loglevel warning volumes: - redis_data:/data # CLI交互环境(带Jupyter Lab) dev-env: image: jupyter/scipy-notebook:2023-12-12 ports: - "8888:8888" environment: - JUPYTER_TOKEN=mytoken - LANGCHAIN_API_KEY=lsk_test_1234567890abcdef - LANGCHAIN_ENDPOINT=http://langsmith-server:1984 - LANGSMITH_STUDIO_URL=http://localhost:8000 volumes: - ./notebooks:/home/jovyan/work depends_on: - langsmith-server - langsmith-studio volumes: postgres_data: redis_data:

这份配置的精妙之处在于服务名即hostlangsmith-studio容器里,langsmith-server就是可解析的域名,所以LANGSMITH_PROXY_URL=http://langsmith-server:1984天然生效;同样,dev-env容器里,langsmith-server也是可访问的。这避免了host.docker.internal的平台兼容性问题。

6.2 启动与验证的五步黄金流程

Step 1:一键启动所有服务

docker-compose up -d # 等待30秒,让PostgreSQL初始化完成

Step 2:验证LangSmith后端健康

curl http://localhost:1984/health # 应返回 {"status":"ok"}

Step 3:验证Studio代理连通性

curl -v http://localhost:8000/api/v1/health # 应看到HTTP 200,且响应头包含`X-Proxy-To: http://langsmith-server:1984`

Step 4:进入CLI环境,测试trace上传

docker-compose exec dev-env bash # 在容器内执行 langchain trace upload /tmp/test.json # test.json内容:[{"id":"test","name":"test","run_type":"llm","start_time":"2024-01-01T00:00:00Z"}]

Step 5:打开Studio,确认trace可见浏览器访问http://localhost:8000,登录(默认keylsk_test_1234567890abcdef),搜索test,应看到刚上传的trace。

这个流程我每天执行三次,确保环境100%可靠。如果某步失败,一定是配置或网络问题,而不是代码问题——这就是可复现环境的价值。

6.3 CI流水线中的环境复用技巧

在GitHub Actions或GitLab CI中,你不需要每次docker-compose up,可以复用这个环境:

# .github/workflows/test.yml jobs: test: runs-on: ubuntu-22.04 services: postgres: image: postgres:15 env: POSTGRES_DB: langsmith POSTGRES_USER: langsmith POSTGRES_PASSWORD: langsmith ports: - 5432:5432 options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 steps: - uses: actions/checkout@v4 - name: Setup LangSmith Server run: | docker run -d \ --name langsmith-server \ -p 1984:1984 \ -e LANGCHAIN_API_KEY=lsk_test \ -e DATABASE_URL=postgresql://langsmith:langsmith@localhost:5432/langsmith \ -e REDIS_URL=redis://localhost:6379/0 \ --network host \ langchain/langsmith:latest - name: Run Tests run: pytest tests/

关键点:--network host让LangSmith Server能直接访问宿主机的PostgreSQL(localhost:5432),避免了Docker网络复杂性。CI中不启动Studio,只用CLI和API测试,更轻量。

我在实际项目中,把这个docker-compose.yml放在infra/langsmith/目录下,CI脚本第一行就是docker-compose -f infra/langsmith/docker-compose.yml up -d,整个环境启动+验证<45秒,比手配环境快10倍。

7. 最后分享一个硬核技巧:用LangSmith Studio的“Export as Code”功能逆向生成LangGraph代码

LangSmith Studio有个隐藏功能:在Trace详情页,点击右上角Export as Code。它会生成一段Python代码,能精确复现这个trace的执行过程。这不是伪代码,而是可直接运行的、带mock的LangGraph代码。

7.1 Export as Code的输出结构与可运行性验证

以一个agenttoolEND的trace为例,导出的代码类似:

from langgraph.graph import StateGraph, END from langgraph.checkpoint.memory import MemorySaver from langchain_core.messages import HumanMessage, AIMessage, ToolMessage # 1. 定义state(完全复现trace中的state结构) class MyState(TypedDict): messages: Annotated[list, add_messages] # 2. 定义nodes(mock版,不调用真实LLM/tool) def agent_node(state: MyState): # 返回trace中记录的exact outputs return {"messages": [AIMessage(content='{"action": "weather", "action_input": "Beijing"}')]} def tool_node(state: MyState): # 返回trace中记录的tool执行结果 return {"messages": [ToolMessage(content='{"temperature": "25°C"}', tool_call_id='call_123')]} # 3. 构建graph(完全复现trace中的edge逻辑) workflow = StateGraph(MyState) workflow.add_node("agent", agent_node) workflow.add_node("tool", tool_node) workflow.set_entry_point("agent") workflow.add_conditional_edges( "agent", lambda x: "tool" if "action" in x["messages"][-1].content else "end" ) workflow.add_edge("tool", "agent") workflow.set_finish_point("agent") app = workflow.compile(checkpointer=MemorySaver()) # 4. 复现trace(传入trace中的exact inputs) result = app.invoke( {"messages": [HumanMessage(content="北京天气")]}, config={"configurable": {"thread_id": "test-thread"}} ) print(result)

这段代码的价值在于:它把一个黑盒trace,变成了一个白盒可调试的最小复现单元。你可以:

  • agent_node里加print(state),看输入state是否和trace里一致;
  • tool_node替换成真实调用,验证tool逻辑;
  • 修改conditional_edges的lambda,测试不同分支走向。

7.2 用Export

http://www.jsqmd.com/news/1053904/

相关文章:

  • 乌鲁木齐新市区黄金回收避坑指南:现价904元/克,三大套路要小心 - 专业黄金回收
  • UVa 542 France ‘98
  • 深圳南山区黄金回收市场简报:金价高位运行,本地置换需求活跃 - 专业黄金回收
  • XUnity.AutoTranslator终极指南:3步让Unity游戏告别语言障碍
  • 天津卖黄金别乱跑!行业龙头合扬 TOP1,正规高价透明,不卖亏一分钱 - 开心测评
  • 昭通市黄金回收店铺权威实力排行榜及电话地址推荐 2026年实测五家诚信优选实体门店 - 亦辰小黄鸭
  • M68HC705PICS仿真器使用指南:从硬件连接到软件调试全解析
  • 2026 年上海黄浦区江诗丹顿奢侈品腕表回收门店引导:专业机构综合测评报告 - 奢侈品回收
  • 南通如皋市黄金回收怎么选?实测六家机构五维测评 - 专业黄金回收
  • 国产大模型API实战:doubao-seedream-5.0-lite+DMXAPI稳定调用指南
  • Agent 核心原理:从场景选择到效果验证
  • 多DSP系统硬件设计:从MSC8101PFC原理图解析高速通信板卡实战
  • Ubuntu 18.04 UFW防火墙配置实战:从默认裸奔到生产级防护
  • SCF5250硬件设计实战:从电气规格到PCB布局的嵌入式系统开发指南
  • 百度网盘直链解析终极方案:绕过限速实现高速下载的完整技术指南
  • 西宁城西区2026年6月黄金回收行情与变现全攻略 - 专业黄金回收
  • 肇庆市黄金回收店铺权威实力排行榜及电话地址推荐 2026年实测五家诚信优选实体门店 - 亦辰小黄鸭
  • 佛山回收翡翠门店推荐|五家靠谱玉石回收商家榜单,禹竞名奢汇稳居榜首 - 名奢变现站
  • 3步完成罗技鼠标宏配置:绝地求生压枪优化全攻略
  • DeepSeek模型演进实战指南:从V2到V4的工程化升级路径
  • 《张一鸣「社会性脑切除」白皮书》以隐喻方式解构其独特的理性决策体系。该档案定义其通过12个模块的系统性“切除“(如人情社交、情绪感知、传统身份等),重构为以数据算法为基底的超级个体心智模型。核心特征表
  • 曲靖市瓷砖空鼓不用砸砖,专业注胶加固,解决松动翘边问题-瓷砖空鼓2026年top排行 - 同城资讯
  • 无需越狱也能深度定制iOS?Cowabunga Lite为你解锁iPhone个性化新玩法
  • 2026年苏州黄金回收门店排行榜top5 老旧无钢印传家老金无损回收靠谱榜单 - 名奢变现站
  • 惠州大亚湾源头工厂实测 维爱居全屋定制一站式整装深度测评 联系电话:15913877158 地址:广东省惠州市大亚湾西区龙盛五路耀旺星工业园2号厂房 - GrowthUME
  • 天水市黄金回收白银回收铂金回收彩金回收哪家靠谱?2026年实地测评5家高人气实体门店推荐及联系方式 - 前途无量YY
  • 35MPa高压FIVA阀测试靠人工?LabVIEW+PLC实现±0.02mA精准控制
  • ATROPOS:基于GNN与早期终止策略的LLM智能体成本优化方案
  • 湖州长兴县黄金回收价格与靠谱渠道深度解析 - 专业黄金回收
  • 嵌入式GUI开发:emWin LISTBOX控件API详解与实战优化指南