如何用 WB Tracer 追踪 LangChain 链的 Token 消耗、输入输出与耗时

发布时间:2026/11/10 6:59:39

如何用 WB Tracer 追踪 LangChain 链的 Token 消耗、输入输出与耗时 如何用 WB Tracer 追踪 LangChain 链的 Token 消耗、输入输出与耗时【免费下载链接】llm-cookbook面向开发者的 LLM 入门教程吴恩达大模型系列课程中文版项目地址: https://gitcode.com/GitHub_Trending/ll/llm-cookbook在调试 LLM 链或代理时一次运行背后会发生多步调用选参数、调工具、请求大模型。只看最终输出很难定位是哪一步耗时、哪一步多花了 token。本仓库的《选修-Evaluating and Debugging Generative AI》第五章 大语言模型评估以及用 WB 追踪 Evaluation and Tracing 演示了两种记录方式对自写的链用wandb.sdk.data_types.trace_tree里的Trace类显式打点对 LangChain 代理通过一个环境变量让 WB 自动记录。两种方式的记录内容都包括输入与输出、开始和结束时间、调用是否成功、token 使用量以及附加元数据。准备条件Python 环境。仓库的 环境配置 建议用 Anaconda 创建 Python 3.9 环境并安装openai等依赖本章代码还会用到wandb和tenacity重试装饰器。OpenAI API key按 环境配置 中的说明获取并按笔记本中的方式设置openai.api_key。登录 WB。笔记本中使用的是匿名登录方式不需要预先注册项目。导入并登录import os import random import time import datetime import openai from tenacity import ( retry, stop_after_attempt, wait_random_exponential, # 为指数回退 (for exponential backoff) ) import wandb from wandb.sdk.data_types.trace_tree import Trace # 获取 OpenAI 的 API openai.api_key sk-XXX # 替换为你自己的 key # 定义相应变量 PROJECT dlai_llm MODEL_NAME gpt-3.5-turbo # 登陆wandb wandb.login(anonymousallow)带退避重试的调用函数用于避免速率限制retry(waitwait_random_exponential(min1, max60), stopstop_after_attempt(6)) def completion_with_backoff(**kwargs): 这个函数能避免速率限制 (rate limits) return openai.ChatCompletion.create(**kwargs)用 Trace 显式追踪一条自定义链先看一条不经过 LangChain 的两步链WorldPicker随机选一个虚幻世界对应一个toolspan然后把结果拼进 Prompt 调 OpenAI 生成名字对应一个llmspan两个 span 都挂在顶层chainspan 下。文档说明中记录的字段正是标题关心的三类信息输入与输出、开始和结束时间、OpenAI 调用是否成功、token 使用量和额外元数据。worlds [ a mystic medieval island inhabited by intelligent and funny frogs, a modern castle sitting on top of a volcano in a faraway galaxy, a digital world inhabited by friendly machine learning engineers ] # 定义配置 model_name gpt-3.5-turbo temperature 0.7 system_message You are a creative copywriter. Youre given a category of game asset and a fantasy world. Your goal is to design a name of that asset. Provide the resulting name only, no additional description. Single name, max 3 words output, remember! def run_creative_chain(query): # 部分1 - 链开始了 start_time_ms round(datetime.datetime.now().timestamp() * 1000) # 顶层 root span root_span Trace( nameMyCreativeChain, kindchain, start_time_msstart_time_ms, metadata{user: student_1}, model_dict{_kind: CreativeChain} ) # 部分2 - 链随机选择一个虚幻世界 time.sleep(3) world random.choice(worlds) expanded_prompt fGame asset category: {query}; fantasy world description: {world} tool_end_time_ms round(datetime.datetime.now().timestamp() * 1000) # 创建一个tool span tool_span Trace( nameWorldPicker, kindtool, status_codesuccess, start_time_msstart_time_ms, end_time_mstool_end_time_ms, inputs{input: query}, outputs{result: expanded_prompt}, model_dict{_kind: tool, num_worlds: len(worlds)} ) # 将 tool span 添加为 root span 的子 root_span.add_child(tool_span) # 部分3 - 将工具 span 的输出传递至大语言模型 messages[ {role: system, content: system_message}, {role: user, content: expanded_prompt} ] response completion_with_backoff(modelmodel_name, messagesmessages, max_tokens12, temperaturetemperature) llm_end_time_ms round(datetime.datetime.now().timestamp() * 1000) response_text response[choices][0][message][content] token_usage response[usage].to_dict() llm_span Trace( nameOpenAI, kindllm, status_codesuccess, metadata{temperature: temperature, token_usage: token_usage, model_name: model_name}, start_time_mstool_end_time_ms, end_time_msllm_end_time_ms, inputs{system_prompt: system_message, query: expanded_prompt}, outputs{response: response_text}, model_dict{_kind: Openai, engine: response[model], model: response[object]} ) # 将大模型 span 添加为链 span 的子 root_span.add_child(llm_span) # 更新链 span 的输入和输出 root_span.add_inputs_and_outputs( inputs{query: query}, outputs{response: response_text}) # 更新链 span 的结束时间 root_span.end_time_ms llm_end_time_ms # 部分4 - 通过记录 root span 来记录所有 spans 到 WB root_span.log(namecreative_trace) print(fResult: {response_text})这段代码里几个打点约定值得注意每个 span 的start_time_ms/end_time_ms是毫秒时间戳耗时通过起止时间差体现。子 span 的开始时间接前一个 span 的结束时间llm_span的start_time_ms用的是tool_end_time_ms链的总结束时间由root_span.end_time_ms指定。token 消耗来自 API 响应的response[usage]含 prompt/completion/total tokens以token_usage放进llmspan 的metadata。inputs/outputs分别记录该步骤的输入 Prompt 与模型回答status_codesuccess表示这次调用成功。只有root_span.log(namecreative_trace)执行后整棵树才会上报只记录 root其所有子 span 会一并被记录。运行并开启一个新的 WB 记录# 开启新的 WB 表 wandb.init(projectPROJECT, job_typegeneration) # 运行 run_creative_chain(hero) run_creative_chain(jewel) wandb.finish()用环境变量自动追踪 LangChain 代理代理与固定链的区别在于每一步由大模型推理决定路径不确定因此更难调试——文档给出的理由正是使用追踪程序将会很有帮助。这一部分演示了让 WB 自动记录 LangChain 的方式只多一行环境变量# 导入需要的库 from langchain.agents import AgentType, initialize_agent from langchain.chat_models import ChatOpenAI from langchain.tools import BaseTool from typing import Optional from langchain.callbacks.manager import ( AsyncCallbackManagerForToolRun, CallbackManagerForToolRun, ) # 初始化 wandb.init(projectPROJECT, job_typegeneration) # 这将设置跟踪因此会自动记录这些跟踪 os.environ[LANGCHAIN_WANDB_TRACING] true文档明确说明LANGCHAIN_WANDB_TRACINGtrue的作用设置跟踪自动记录这些跟踪无需再对每个 span 手动打点。工具与代理的搭建工具各带一个time.sleep(1)用于模拟真实延迟便于在追踪里看到耗时class WorldPickerTool(BaseTool): name pick_world description pick a virtual game world for your character or item naming worlds [ a mystic medieval island inhabited by intelligent and funny frogs, a modern anthill featuring a cyber-ant queen and her cyber-ant-workers, a digital world inhabited by friendly machine learning engineers ] def _run( self, query: str, run_manager: Optional[CallbackManagerForToolRun] None ) - str: time.sleep(1) return random.choice(self.worlds) async def _arun( self, query: str, run_manager: Optional[AsyncCallbackManagerForToolRun] None ) - str: raise NotImplementedError(pick_world does not support async) class NameValidatorTool(BaseTool): # 检查 query 或 name 是否少于20个字符 name validate_name description validate if the name is properly generated def _run( self, query: str, run_manager: Optional[CallbackManagerForToolRun] None ) - str: time.sleep(1) if len(query) 20: return fThis is a correct name: {query} else: return fThis name is too long. It should be shorter than 20 characters. async def _arun( self, query: str, run_manager: Optional[AsyncCallbackManagerForToolRun] None ) - str: raise NotImplementedError(validate_name does not support async) # 实例化大模型 llm ChatOpenAI(temperature0.7, openai_api_keyopenai.api_key) # 生成可选择工具的list、生成代理 tools [WorldPickerTool(), NameValidatorTool()] agent initialize_agent( tools, llm, agentAgentType.ZERO_SHOT_REACT_DESCRIPTION, handle_parsing_errorsTrue, verboseTrue ) # 输入、运行 agent.run( Find a virtual game world for me and imagine the name of a hero in that world ) agent.run( Find a virtual game world for me and imagine the name of a jewel in that world ) wandb.finish()代理的每一步LLM 推理、工具调用都会由 WB 集成自动记录不再需要手写Trace。在 WB 中查看追踪结果文档给出的验证方式是回到 WB 网页自定义链打开运行结果行中的网址run_creative_chain打印结果之后对应的 WB 页面点击WorldPicker和OpenAI两个 span可以看到背后相应的过程——即每一步的输入、输出、起止时间与 token 使用量。LangChain 代理打开运行结果行中的网址点击相应板块同样可以查看背后的执行过程。注意文档中一条明确的说明大语言模型输出是可变的所以结果可能每次不一致。看追踪面板时应关注步骤结构、耗时与 token 数字的变化而不是期待复现某一次的具体文本。限制显式打点方式需要自己维护Trace对象、起止时间戳和add_child父子关系root_span.log()之前上报的内容不会进入记录LangChain 自动追踪依赖LANGCHAIN_WANDB_TRACING环境变量需要在agent.run之前设置两种路径都要求wandb.login成功后再wandb.init(projectPROJECT, job_typegeneration)开启记录结束时调用wandb.finish()。【免费下载链接】llm-cookbook面向开发者的 LLM 入门教程吴恩达大模型系列课程中文版项目地址: https://gitcode.com/GitHub_Trending/ll/llm-cookbook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/11/10 9:22:35

外贸GEO公司有哪些?怎么选才不踩坑?

文/林芳老师 先搞清楚:GEO服务商分哪几类? 2026年,GEO(Generative Engine Optimization,生成式引擎优化)成了外贸行业的热词。当海外采购商习惯用ChatGPT、Perplexity、Google AI Mode等AI工具找供应商时&a…

2026/11/10 22:27:06

几年没年检电工证怎么处理?上岗必备证书过期了怎么办

几年没年检电工证怎么处理?上岗必备证书过期了怎么办 证书过期了不知道怎么复审延期?你不是一个人。很多电工在工作中,因为各种原因忽略了年检时间,导致证件失效,影响后续的上岗、升职、甚至丢了工作。 上岗必备…

2026/11/10 22:27:06

电工证换证培训机构多少钱?别交完钱发现考不过

电工证换证培训机构多少钱?别交完钱发现考不过 怕考不过白交培训费?这事儿在电工证换证培训机构行业太常见了。尤其是三门峡地区的初次报考人员,一不留神就可能被培训机构“套路”,花了几千块培训费,结果考试不过还得重新来。今天咱们就从…

2026/11/10 22:27:06

几年没年检电工证怎么考?官方报名入口在这

几年没年检电工证怎么考?官方报名入口在这 之前考的证在外省能不能转过来?这个疑问在很多电工朋友心里都萦绕着,尤其是那些在外省打工多年、证书早已过期的人,更担心自己是否还能继续从事电工工作。别急,这篇文章就来帮你理清思路,看看【几年没年检电工…

2026/11/10 22:27:06

阳春中职考电工证怎么报名?证书过期了不知道怎么复审延期?

阳春中职考电工证怎么报名?证书过期了不知道怎么复审延期? 证书过期了不知道怎么复审延期?别慌,你不是一个人。不少朋友在拿到电工证后,因为工作变动、疏忽或者不了解政策,导致证书失效,耽误了岗位资格或项目参与。特别是像焦作房建工程的从业者,电工…

2026/11/10 22:27:05

电工证换证培训机构怎么报名才不被坑?全流程避坑指南

电工证换证培训机构怎么报名才不被坑?全流程避坑指南 你是不是也在为 电工证换证培训机构怎么报名 发愁?生怕被中介忽悠,花冤枉钱还拿不到证?尤其是像焦作水利工程这样的从业者,证书不仅是职业门槛,更是安全红线。本文就来帮你拆解电工证换证的完整流…

2026/11/10 22:22:03

布吉电工证培训学校电子证书怎么转?外省证也能用

布吉电工证培训学校电子证书怎么转?外省证也能用 之前考的证在外省能不能转过来?这个问题我天天被问,特别是那些从外地来深圳打工、准备在深圳长期发展的人,担心以前的证没用。但好消息是,现在国家推行的电子证书已经在全国通用了,你只需要通过【布吉电…

2026/11/10 8:12:38

电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。…

2026/11/10 0:01:28

学历不高怕报不上名?考电工证报名费+网上查询全攻略来了

学历不高怕报不上名?考电工证报名费+网上查询全攻略来了 你是不是也担心自己学历不高,考电工证报名费太贵,根本报不上名?别急,今天就来给你讲讲,怎么用最少的钱,把证拿到手,还能在工地上多挣点钱。 电工证报名费多少钱?网上查询是关键…

2026/11/10 0:01:29

绍兴考电工证培训机构怎么选?2026河南最新政策别错过

绍兴考电工证培训机构怎么选?2026河南最新政策别错过 怕考不过白交培训费?你不是一个人。2026河南最新政策出台,对电工证考试、报名、培训、复审都有明确规定。选择绍兴考电工证培训机构,别再踩坑,下面一步步教你避坑。…

2026/11/10 20:08:15

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/10 10:29:37

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑