首页 / 资讯中心 / 文章详情

LangSmith实战:LLM应用监控从接入到落地的全流程指南

LangSmith实战:LLM应用监控从接入到落地的全流程指南 ★ FEATURED ARTICLE
做LLM应用开发最让人头疼的往往不是模型选型也不是提示词写不好而是应用上线之后你根本不知道它在线上干了什么。用户说了一句奇怪的话模型回了一个奇怪的答案中间到底发生了什么传统日志里只有输入和输出完全是一团黑盒。LangSmith就是这个场景下我最常用的工具它专门用来做LLM应用的追踪、调试、评估和监控。这篇文章我就从实际使用的角度把LangSmith监控从接入到落地讲透适合正在做AI应用开发、尤其是基于LangChain做项目的朋友参考。我第一次接触LangSmith是在一个聊天机器人项目上线第二周用户反馈说回答越来越慢了可服务器指标一切正常。后来才发现是某个工具调用环节反复重试每次重试都触发一次完整的大模型请求延迟凭空多出七八秒。这个结论如果只靠传统日志不知道要排查多久而有了LangSmith的链路追踪问题在十分钟内就定位了。所以我一直认为LLM应用做监控不是可选项而是工程化的刚需。1. 为什么LLM应用离不开专门的监控工具1.1 传统日志审计解决不了的问题做过后端开发的人都熟悉传统的日志排查思路打点、收集、聚合、看错误率。但LLM应用跟传统Web服务有个本质区别它的核心计算单元是模型调用而这个调用本身存在不确定性。同样的输入今天和明天的输出可能完全不同甚至同一个模型版本温度参数调高一点结果天差地别。这种不确定性带来了一系列监控困境。第一个困境是链路不可见。一次用户请求可能经历了检索、提示词组装、模型调用、工具执行、结果解析、二次模型调用等多个环节。传统日志只能记录每个环节的输入输出但环节之间的时序关系、依赖关系、嵌套关系很难串联起来。你看到日志里有三次模型调用却不知道第一次为什么触发第二次第二次的上下文从哪来。第二个困境是评估难。传统后端的成功失败有清晰的判断标准状态码就是状态码。但LLM应用里的成功是什么模型返回了内容不代表答案正确回答流畅不代表没有幻觉。你很难用一个布尔值来判定一次模型调用是否成功更别提监控它的质量趋势了。第三个困境是成本可见性差。LLM应用的成本跟调用量、输入token数、输出token数强相关一段超长的上下文可能让单次调用成本翻几倍。没有专门的监控手段你根本算不清某个功能一个月烧了多少钱也不知道哪个用户或哪个场景在消耗大头。这三个困境恰恰就是LangSmith这类LLM可观测性工具出现的原因。1.2 LangSmith的定位与价值LangSmith是LangChain生态里的可观测性与评估平台它的核心能力可以概括为四件事追踪、调试、评估、监控。追踪指的是把一次完整的LLM应用请求拆解成一颗树每个节点都是一个执行步骤比如一次模型调用、一次检索、一次工具执行。每个步骤的输入、输出、耗时、消耗的token数、使用的模型名全部被记录下来。调试指的是你可以直接在网页上查看任意一次请求的完整链路逐步查看每一步的输入输出甚至可以直接修改参数重新运行某一步来验证假设。评估指的是你可以把一批真实请求沉淀为数据集然后对新版本模型、提示词做批量回归测试用分数、对比的方式量化质量变化。监控指的是在项目仪表盘上实时看到延迟、错误率、token消耗的趋势用图表和数据来掌握整个应用的健康度。用一句话概括如果说LangChain是帮助你构建LLM应用的工具链那LangSmith就是给这条工具链配上的仪表盘和黑匣子。1.3 适用场景与使用成本评估我个人的经验是LangSmith几乎适用于所有LLM应用场景。单人开发的原型项目可以用它来快速调试提示词和链路小团队协作可以用它的项目和成员权限来组织工作上了生产线的应用可以用它做线上监控和数据回流。成本方面LangSmith有免费层和付费层。免费层对于开发调试和中小流量项目基本够用付费层主要增加的是调用量配额、数据保留时长和高级功能。如果你的数据合规要求非常严格不允许任何数据出内网LangSmith也提供了自托管方案可以部署在私有环境里数据完全本地化。2. 基础接入把第一个Trace跑起来2.1 环境准备与密钥获取接入LangSmith的第一步是注册账号并创建一个项目。注册完成后进入设置页面获取API Key这个Key就是一串以ls_开头的字符串相当于你访问LangSmith服务的凭证。项目概念可以这样理解一个项目对应一个应用或一个服务。你可以在同一个账号下创建多个项目分别对应线上环境、测试环境或者不同的子应用。这样在查看监控数据时各个项目的指标是隔离的不会互相干扰。获取到API Key后需要在你的应用环境里配置两个关键环境变量export LANGCHAIN_TRACING_V2true export LANGCHAIN_API_KEYls_你的密钥 export LANGCHAIN_PROJECTmy-llm-app第一个变量LANGCHAIN_TRACING_V2是总开关告诉SDK开启追踪第二个变量是身份凭证第三个变量指定数据归属哪个项目。这三个变量配置完成后你的应用只要是通过LangChain构建的基本就能自动开始上报追踪数据了不需要在代码里做任何额外改动。注意环境变量中的LANGCHAIN_PROJECT如果没设置默认会用default项目多个应用的数据会混在一起后期排查会非常痛苦。我建议从第一天就养成显式设置项目名的习惯。2.2 安装SDK并验证链路如果你的项目不是基于LangChain或者你想更细粒度地控制追踪行为就需要直接安装并调用LangSmith的Python SDK。pip install langsmith安装完成后用一段最简单的代码来验证链路是否打通from langsmith import Client client Client() print(项目列表:, client.list_projects())如果能够正常返回项目列表说明你的API Key配置正确SDK和环境是通的。接下来创建一个最基础的追踪from langsmith import traceable traceable(run_typechain) def generate_answer(question: str) - str: result f这是对问题的模拟回答{question} return result traceable(run_typellm) def call_model(prompt: str) - str: return f模型输出: {prompt} traceable(run_typechain) def main_flow(question: str) - str: prompt f用户问题{question} model_result call_model(prompt) return generate_answer(model_result) main_flow(LangSmith怎么接入) main_flow(今天天气怎么样)运行这段代码后登录LangSmith网页端打开你的项目就能看到刚刚生成的两条追踪记录。点开任意一条能看到main_flow下嵌套着call_model和generate_answer两个子步骤每个子步骤的运行时长都单独记录。第一次跑通这个链路时那种代码运行过程被完整可视化的感觉真的很颠覆直觉。你写的每一层函数调用在网页上都变成了一棵可展开的树每一步的输入输出、耗时、成本全部清清楚楚。2.3 不写代码也能接入与LangChain的自动集成如果你使用的是LangChain的链式API或LangGraphLangSmith的接入甚至不需要写任何追踪代码。只要环境变量配置好了LangChain的Runnable对象、Agent的执行过程、工具调用、检索器的运行细节都会自动上报。这种自动上报的原理是LangChain在底层设计时就集成了回调系统。每次Runnable执行时都会触发一系列回调事件包括开始、结束、错误、token流式输出等。LangSmith SDK实现了一套回调处理器把这些事件捕获并组装成Span树。这也就是为什么你在LangSmith上看到的链路结构跟你代码里的嵌套调用关系几乎完全一致。如果你用了with_config方法来配置运行参数还可以做到更精细的控制from langchain_core.runnables import RunnableConfig config RunnableConfig( metadata{user_id: 12345, env: production}, tags[customer-service] ) result chain.invoke({question: 退款流程是什么}, configconfig)这段配置会让本次运行时附带元数据和标签后续在LangSmith筛选时就能按这些字段过滤查找。3. 核心概念拆解Trace、Run与Span3.1 一次请求的一生理解LangSmith的数据模型是玩转监控的关键。它最核心的概念有三个Trace、Run和Span。Trace表示一次完整的请求链路从用户发起请求到最终返回响应是一次业务闭环。你可以把它想象成你在电商平台下了一个订单从下单到收货的全程物流信息都被记录下来这就是一条Trace。Run是Trace中的一个节点代表一次具体的执行步骤比如一次大模型调用、一次向量检索、一次工具调用。Run之间可以嵌套形成父子关系。回到物流的类比一条Trace是你整个订单的物流轨迹而Run则是轨迹上的每一个节点包裹到达转运中心、包裹派送中、包裹签收。Span这个概念更多是习惯性的叫法它和Run在LangSmith中本质上是同一类东西。早期LangSmith叫RunOpenTelemetry生态里叫Span。如果你的团队有OpenTelemetry背景完全可以把它当作Span来理解。这种Trace-Run的树状结构带来一个非常大的好处你可以只看任意一个子步骤的细节而不影响对整个请求的理解。比如用户问了一个问题链路的顶层显示耗时8秒展开后看到大部分时间花在call_model上retrieve_documents只用了200毫秒判断依据一目了然。3.2 手动追踪的两种姿势除了装饰器这种自动追踪方式LangSmith还提供了更底层的RunTree API适合需要精确控制追踪结构的场景。from langsmith.run_trees import RunTree parent RunTree( namemy_chain, run_typechain, inputs{question: 什么是LangSmith} ) child_llm parent.create_child( namechat_model_call, run_typellm, inputs{prompt: 请回答什么是LangSmith} ) child_llm.end(outputs{response: LangSmith是一个可观测性平台}, usage{total_tokens: 36}) parent.end(outputs{answer: 完成}) parent.post()这里run_type参数很关键它有四种取值llm、chain、tool、retriever。你上报的Run类型不同LangSmith网页端展示的图标、可用的统计维度、可附加的元数据字段都会不同。比如llm类型的Run可以记录usage信息来计算token成本和延迟指标而tool类型的Run则更适合记录工具的原始输入输出。手动追踪的好处是灵活但代价也是明显的就是需要你手动管理父子关系和生命周期代码量会多不少。我个人的建议是能用装饰器就尽量用装饰器只有当链路结构非常规或者需要动态决定子步骤数量时才用RunTree手动构建。3.3 元数据与标签的工程价值很多初学者忽略metadata和tags认为这只是锦上添花。实际上元数据和标签是监控数据能被真正用起来的关键。元数据本质上是一组键值对适合记录结构化信息比如用户ID、会话ID、实验版本号、部署环境。标签则是一些短字符串适合做粗粒度的分类标记比如high-value、needs-review、error-type-timeout。有了这些字段LangSmith的筛选器才能发挥作用。比如线上突然有一批请求报错你想知道这批请求是不是来自同一个渠道就可以用元数据channelandroid来过滤。又比如你在做提示词A/B测试给两个版本分别打了prompt-v1和prompt-v2的标签就能在仪表盘里对比两条链路的质量指标。一个实用的习惯上线前先在代码里统一好元数据的键名规范避免出现user_id和UserId这种大小写不一致的字段。混乱的字段命名会让后续查询变成灾难。3.4 采样与成本控制全量追踪最直观但不是所有场景都需要全量。如果你的应用流量很大每个请求都上报完整的链路数据不仅会增加网络开销还会快速消耗配额。这时候就需要采样。采样最朴素的做法就是按比例随机采样。比如你只想保留10%的请求轨迹可以在请求入口处做一次随机数判断import random import os os.environ[LANGCHAIN_TRACING_V2] true os.environ[LANGCHAIN_TRACING_SAMPLE_RATE] 0.1LangSmith SDK支持通过LANGCHAIN_TRACING_SAMPLE_RATE环境变量来设置采样率值范围从0到10意味着完全不上报1意味着全量上报。这个变量的优先级高于代码内的追踪开关如果设置了0.5则只有约一半的请求会被记录。需要注意的是采样率设置后你在LangSmith上看到的延迟、错误率等指标只是样本数据的统计结果不是全量真实值。在解读数据时要清楚这一点尤其是做容量规划和成本预估时要把采样率当成系数折算回去。当然采样策略也可以做得更聪明。比如对所有错误请求无条件全量追踪对成功请求只采样10%。这种条件采样逻辑需要自己在代码里判断处理但效果远比一刀切的随机采样好我后面会细说。4. 监控面板实操从延迟到成本4.1 项目仪表盘读法数据上报之后真正的工作才开始。打开LangSmith项目页面你会看到一系列图表和指标这些不是摆设而是线上应用健康状况的直接反映。仪表盘最值得关注的是延迟指标。LangSmith默认会展示P50、P90、P95分位延迟如果你只盯着平均延迟就会被少数极慢请求拉高数值误导。P95延迟的意义在于告诉你95%的请求在多少毫秒内完成这个值对用户体验的参考价值远高于平均值。接着说token消耗和成本。在项目概览里能看到输入token数、输出token数和总成本估算。这个成本估算基于模型单价表计算虽然和账单数字有出入但作为趋势参考完全够用。我见过不止一个团队上线了某个功能却不知道它每天烧掉多少费用直到月底对账单时才傻眼。监控面板上的成本曲线能帮你尽早发现这种问题。错误率指标同样重要。LangSmith会把运行异常标记为错误状态并聚合出错误率曲线。如果错误率突然从0.5%跳升到10%多半是上游模型API出问题、检索服务挂了或者你的代码在处理某种特殊输入时出现了异常。这时候可以直接点进错误率最高的时间段查看对应的Trace失败原因。4.2 用监控定位一次线上事故理论讲多了容易抽象我用一次真实发生的事故来演示完整的排查流程。某个周末我的一个对话机器人项目收到用户反馈说回答越来越慢了。服务器CPU、内存、网络指标都正常传统监控完全无异常。这时我打开LangSmith先看项目仪表盘的延迟曲线发现P95延迟从平时的2秒飙升到9秒持续时间大约四十多分钟。然后我按时间范围筛选出那个时间段的Trace按延迟降序排列点开最慢的一条看链路树。链路显示顶层耗时9.2秒展开后看到retrieve_documents耗时0.3秒call_model耗时0.4秒而tool_execute这一步耗时高达8.2秒。关键原因找到了是工具调用环节出了问题。点进tool_execute的详情看到这个工具在循环调用某个外部API由于该API内部限流每次都等待超时重试机制又反复触发。整个请求在网络等待上浪费了绝大部分时间。没有链路追踪这个排查可能要花几个小时有了LangSmith从发现问题到定位根因只花了不到十分钟。这个案例很好地说明了一条完整的链路树对排障效率的提升是革命性的。4.3 评测与数据回流监控不只是看数字还可以把线上数据变成改进模型能力的素材。LangSmith允许你在Trace上打人工评分。打开任意一条Trace你可以打分并写下评语标记这个回答是优秀、一般还是不可接受。这些人工反馈会沉淀到项目的数据集成为后续评估模型的基准。更进一步你可以把这些真实Trace整理成数据集用于回归测试。比如把线上收集的1000条真实用户问题保存为数据集每次修改提示词或更换模型版本时都用这批问题批量跑一遍自动比对新旧版本回答的质量。这里要说明一下数据集和监控是两个关联但不同的模块。监控关注的是运行状态和健康度数据集关注的是质量基准和回归验证。LangSmith把两者打通了好处是你在监控中看到的糟糕回答可以一键存入数据集然后触发一次针对这个问题的修复验证流程。这种从问题发现到解决验证的闭环才是LLM应用迭代的正确姿势。5. 生产环境必须知道的坑5.1 追踪数据丢失的常见原因接入LangSmith后遇到的第一类问题是明明代码跑完了网页上却看不到Trace。我排查过几回整理了最常见的三个原因。第一个原因是环境变量没生效。很多人把环境变量写在.env文件里但代码读取的却是系统环境变量导致SDK根本没拿到配置。验证方法是在代码启动处打印一下os.environ.get(LANGCHAIN_TRACING_V2)确认值真的是true而不是True或1。第二个原因是异步代码没有等待上报完成。LangSmith的异步追踪在底层是异步发送数据的如果你的主线程结束得太快上报请求还没来得及发出去进程就退出了数据就丢了。在FastAPI这类异步框架里特别常见正确做法是确保请求处理函数的生命周期覆盖追踪上报或者在进程退出前做个短暂的等待。第三个原因是采样率设成了0或者误配置。我之前调试过一次怎么跑都不出数据最后发现是某个公共配置文件里把LANGCHAIN_TRACING_SAMPLE_RATE设成了0被自己坑了。5.2 异步与多线程追踪错乱这个问题比较隐蔽但一旦遇到会让数据完全不可信。Python的异步和多线程环境下上下文变量是不可跨任务传递的。LangSmith内部用上下文变量来维护当前活跃的Run如果异步任务或新线程没有正确继承上下文新的子Run就会被挂到错误的父Run下面或者干脆变成根Run导致链路断裂和串线。典型的症状是并发量稍微上来后有些Trace的子步骤跑到别的Trace底下去了数据组织完全乱套。解决办法是尽量让追踪装饰器包裹完整的异步函数而不是在异步函数内部去手动创建子Run。traceable装饰器本身对异步函数有良好的上下文传播支持只要结构合理就不会出问题。另外如果你用了asyncio.gather并行执行多个子任务尽量在装饰器层面做并行让每个并行的子任务都成为一个独立的子Run而不是在同一个Run内部手动切换。5.3 敏感数据脱敏与隐私控制LLM应用处理的数据往往包含用户对话内容甚至可能有手机号、地址、身份信息。默认情况下LangSmith会把模型的输入输出传送到云端进行展示这在很多场景下是有合规风险的。好消息是LangSmith提供了多种数据控制手段你可以在环境变量级别关闭输入输出记录export LANGCHAIN_TRACING_REDACT_INPUTStrue export LANGCHAIN_TRACING_REDACT_OUTPUTStrue设置后网页端只显示字段的哈希摘要信息不显示原始内容。如果你只想脱敏部分字段也可以在traceable装饰器中传入自定义的redact参数或者在上报前对数据做预处理。我个人的建议是对于线上生产环境的数据如果业务允许优先做脱敏处理即使业务需要查看完整对话内容也应该按角色权限来限制访问。毕竟监控是为了服务开发和排障不是为了把用户隐私暴露给团队里所有人。5.4 权限与团队协作当一个项目有多个人共同维护时权限管理的重要性就凸显出来了。LangSmith允许你邀请团队成员并分配不同角色比如只读成员、项目成员、项目管理员等。很多团队刚上手时不重视这个所有人都用同一个管理员账号这样不仅操作记录混乱而且有人不小心改动了项目设置其他人也不知道。一个比较稳妥的做法是团队里每个成员都有独立账号根据职责分配角色项目的访问权限按环境分开开发环境大家都能看生产环境只有少数核心人员有查看和操作权限。另外API Key的保管也建议分环境管理。开发环境的Key和生产环境的Key分开生成定期轮换这样即使某个Key泄露了影响范围也可以控制在单个环境内。5.5 数据保留与成本优化到了项目中期你可能会发现LangSmith的调用量配额消耗得很快。除了调整采样率还有一些实用的优化手段。第一合理设置数据保留时间。LangSmith有数据保留策略超过保留期的数据自动清理。对大多数项目来说30天到90天的保留期足够了更长的时间段基本用不上只会白占配额。第二低价值请求不追踪。比如健康检查接口、批量内部任务、测试脚本的请求这些数据噪声大、价值低。可以在代码层面做一个过滤对这类请求直接关闭追踪。第三对部分链路只记录摘要。不一定每条Trace都要完整记录每一步的输入输出。你可以在子环节的选择上做取舍比如只保留顶层输入、顶层输出和关键模型调用的详细信息中间的检索过程只保存统计摘要。这些细节优化加起来往往能让同样配额下承载的项目数量翻倍而且不会明显损失监控价值。6. 监控数据如何反哺应用优化6.1 从Trace中发现提示词问题线上真实的Trace是提示词优化的金矿。你在调试环境精心设计的提示词可能在真实用户输入下表现完全不同。有一次我在一个文档问答项目里发现用户一个问题带了两三个问句模型只回答了最后一句。从Trace里看到我的提示词构建逻辑在拼接用户问题时出现了问题第二个问句被截断了。这种问题在单测和调试环境根本不会暴露只有在真实流量下才有可能遇到。所以我的习惯是每周抽时间把线上Trace翻一遍重点看那些模型回答比较长、步数比较多、耗时比较高的请求往往能发现提示词设计和用户真实输入之间的差距。6.2 用评估数据做版本回归改提示词或换模型之前先建好评估集这是我从踩坑中学到的教训。早期我改提示词比较随意改完看几个测试用例觉得没问题就上线了结果线上效果有时反而不如旧版本。后来我养成了一个习惯任何一次模型配置变更都在LangSmith里选一批有代表性的历史Trace作为数据集先跑一轮批量评估对比旧版本和新版本在同样问题上的表现。评估维度包括回答完整性、格式规范性、关键信息准确度等也可以引用大模型作为裁判来自动评分。这套流程跑下来我的提示词迭代成功率明显提升基本不会再出现改完上线才发现变差了的尴尬情况。6.3 把监控指标接入告警监控的最终形态是告警。不能让研发天天登录网页看仪表盘要让异常主动来找人。LangSmith本身提供了一些告警能力你可以基于错误率、延迟等指标配置通知规则。我建议从三个告警开始配置错误率突增告警、P95延迟超阈值告警、成本日环比突增告警。这三个指标分别对应可用性、体验和成本覆盖了LLM应用最重要的三个关注维度。在配置告警阈值时要参考历史基线。如果你的项目平时错误率就是0.2%那阈值设成1%就比较合理如果平时错误率就是2%就不能照搬别人的1%。一切基于自己项目的统计数据这样才能减少误报和漏报。等你的监控数据积累到一定量级可以反过来用LangSmith的数据集做模型微调数据的筛选——把线上高质量回答作为正样本把不理想回答标注为负样本这是一条非常值得投入的数据闭环路径。个人折腾下来最大的体会是LangSmith这类工具越早接入越值钱。不要等项目上线出问题了再回头补监控那时候你已经错过了调试阶段大量有价值的过程数据。从第一个Hello World级别的连接开始就打开追踪让监控成为开发习惯的一部分长期下来积累的数据资产远远超出你的预期。最后分享一个小细节记得偶尔回看一个月前、两个月前的Trace快照你会明显看到自己的提示词、链路设计是怎么一步步演进到今天的这种成长的记录感也是坚持写监控日志的额外奖励。
阅读完成 · 觉得有帮助?
咨询建站