1. 项目概述为什么调试和测试 LLM 应用不能靠“肉眼盯屏”我上周帮一个教育科技团队复盘他们刚上线的 AI 闪卡生成器用户反馈里有一条特别扎眼“生成的卡片里混进了‘巴黎是法国首都’这种题还重复出现了三次。”我打开后台日志一看不是模型崩了也不是 API 调用失败——而是整整 12% 的输出里有语法错误、概念错位、甚至完全无关的常识题。更麻烦的是开发同学说“我们每天手动抽样看 50 条已经尽力了。”这句话暴露了一个行业普遍存在的认知盲区LLM 应用不是传统软件它的“bug”不报错、不崩溃它安静地胡说八道而且每次胡说的方式还不一样。这就是 LangSmith 存在的根本理由。它不是又一个“AI 开发平台”而是一套专为非确定性系统设计的质量控制流水线。你不会用 Excel 表格去监控一个数据库的事务一致性同理你也不能靠翻聊天记录来验证一个 LLM 应用是否稳定可靠。LangSmith 把“调试”这件事从“人盯屏幕找异常”升级成了“用数据定义什么是正常”。它解决的不是“模型能不能跑”而是“模型在什么条件下会跑偏”“偏到什么程度算不可接受”“偏了之后怎么快速定位是 prompt 问题、chain 结构问题还是模型本身的问题”。关键词里虽然写着“None”但实际贯穿全文的核心词是可追溯性、可量化性、可归因性。LangSmith 的价值不在于它多炫酷而在于它把原本模糊的“感觉不对劲”转化成了清晰的指标——比如“当输入含代码片段时coherence 评分下降 37%”或者“在使用 torch.no_grad 相关 prompt 时has_code 判定准确率仅 61%”。这些数字背后是你可以立刻动手改 prompt、换模型、加校验逻辑的具体依据。它适合三类人正在把第一个 LangChain 链路从 Jupyter Notebook 搬进生产环境的工程师需要向产品/运营同事证明“AI 功能已达标”的技术负责人以及所有被“这个模型今天好像不太灵”这类模糊反馈折磨过的 AI 产品经理。这不是锦上添花的工具而是 LLM 应用从玩具走向产品的必经门槛。2. 核心思路拆解LangSmith 如何重构 LLM 开发工作流2.1 传统 ML 工作流 vs. LLM 应用工作流本质差异决定工具选型很多人一上来就问“LangSmith 和 MLflow 有什么区别”这个问题本身就藏着陷阱。MLflow 解决的是确定性模型的生命周期管理你训练一个 ResNet-50它在相同输入下永远输出相同的 softmax 向量所以你可以用准确率、F1 值、混淆矩阵这些硬指标闭环验证。但 LLM 不同——它没有“训练完成”这回事它的“能力”高度依赖 prompt 的措辞、上下文长度、甚至温度参数temperature的微小变化。我实测过同一个 GPT-4 请求把“请用简洁语言解释”改成“请用不超过 20 字解释”输出长度方差能从 ±3 字扩大到 ±15 字。这意味着没有“测试集准确率”这个概念你无法像评估分类模型那样给 1000 个样本打标签然后算准确率。LLM 的输出是开放域文本人工标注成本极高。错误模式高度碎片化不是“全对”或“全错”而是“80% 的卡片格式正确但其中 15% 的答案包含事实性错误5% 的问题与输入主题无关”。这种混合错误必须分层诊断。问题根源难以定位当一张卡片出错是原始文档解析错了是检索到的上下文不相关是 prompt 指令模糊还是模型本身幻觉传统调试器的断点在这里完全失效。LangSmith 的设计哲学正是直面这些差异。它不试图把 LLM 当成黑盒模型去评测而是把它当成一个由 prompt、chain、外部 API、后处理逻辑共同构成的动态系统来观测。它的核心不是“测结果”而是“录过程”——通过 tracing追踪机制把每一次 LLM 调用的完整上下文、中间步骤、耗时、token 消耗、甚至调用链路上每个组件的输入输出全部结构化记录下来。这就像给整个 AI 流水线装上了工业级传感器网络任何异常都能回溯到具体哪一毫秒、哪个组件、哪一行 prompt 出了问题。2.2 LangSmith 的四大支柱为什么是这四个模块而不是其他组合LangSmith 的功能模块不是随意堆砌的而是针对 LLM 开发痛点形成的闭环。我把它拆解为四个相互咬合的支柱缺一不可第一支柱Tracing追踪——建立可观测性的基础设施这是 LangSmith 的地基。它默认开启无需额外编码只要配置好环境变量LANGCHAIN_TRACING_V2true所有通过 LangChain 调用的 LLM、检索器、工具函数都会自动被记录。关键在于它记录的不是最终结果而是全链路快照比如一个闪卡生成链路它会记录DocumentLoader 从 PDF 中提取的原始文本片段含页码Retriever 返回的 top-3 相关段落含相似度分数PromptTemplate 渲染后的完整提示词含所有变量值LLM 的原始响应含 token 数、耗时、模型名称OutputParser 处理后的结构化卡片数据JSON 格式这种粒度让“为什么这张卡片错了”有了明确答案。我遇到过一次案例卡片答案总是比预期长 30%追踪发现是 Retriever 返回了一段冗长的参考文献说明而 prompt 没有明确指令“忽略参考文献”。没有 tracing这个问题会归因为“模型太啰嗦”实际根源在数据预处理环节。第二支柱Datasets数据集——构建可复现的测试基准LLM 开发最怕“这次好了下次又坏”。Datasets 模块就是解决这个问题的。它强制你把测试用例从零散的 notebook 单元格里抽离出来变成结构化的、版本可控的资产。LangSmith 支持三种数据集类型选择逻辑很清晰Key-Valuekv数据集适用于需要多输入或多输出的复杂链路。比如闪卡生成器你的输入可能是{document: XGBoost原理.pdf, topic: 梯度提升}输出是{question: ..., answer: ..., difficulty: 中}。kv 格式天然匹配这种结构。LLM 数据集纯文本输入输出适合简单 prompt 测试。比如只测试“总结这段文字”这个单一能力。Chat 数据集用于对话场景记录完整的 message historysystem/user/assistant 交替序列。重点在于Dataset 不是静态的测试集而是可执行的测试协议。你上传一个 CSV它就自动变成一个可被run_on_dataset函数批量执行的测试套件。这直接解决了“手动测试效率低”的问题——我见过团队把 200 个典型用户提问存成 dataset每次迭代后 5 分钟内就能跑完全量回归测试而不是花半天时间人工抽查。第三支柱Evaluators评估器——将主观判断转化为客观指标这是 LangSmith 最具革命性的部分。传统做法是让 QA 同事读卡片打分“好不好”。LangSmith 把这个过程自动化、标准化。它的评估器分两类内置评估器Built-in Criteria如conciseness、coherence、helpfulness。它们本质是预设好的 prompt 解析规则。比如conciseness评估器会向另一个 LLM 提问“请用 1-5 分评价以下回答的简洁性1 分表示极其冗长5 分表示极度精炼”然后解析返回的数字。这听起来像“用 AI 测 AI”但实测非常稳定——因为评估 LLM 只需做单维度判断比生成复杂内容简单得多。自定义评估器Custom Criteria这才是真功夫所在。你可以用自然语言描述任何业务规则比如{has_code: 问题中是否明确要求解释 Python 代码语法}。LangSmith 会把这个描述包装成 prompt让评估 LLM 去判断。关键技巧在于评估 prompt 本身也需要调优。我最初写的{is_vague: 问题是否模糊}效果很差后来改成{is_vague: 问题是否缺少必要上下文如编程语言、库名、错误信息导致无法给出具体答案}准确率从 52% 提升到 89%。这本质上是在做“评估器的 prompt engineering”。第四支柱Monitoring Visualization监控与可视化——从被动响应到主动预警很多团队把 LangSmith 当成测试工具忽略了它的生产监控价值。Web UI 的过滤能力极强你可以设置告警规则比如“当coherence评分 3.5 的请求占比连续 5 分钟超过 10%”系统会自动标红并推送通知。更实用的是语义搜索当用户投诉“生成的 PyTorch 卡片全是错的”你不用翻日志直接在 UI 搜索框输入“PyTorch error”系统会基于 embedding 匹配所有含类似语义的 trace几秒钟定位到问题高发的 prompt 模板。这比 grep 日志快一个数量级。这四个支柱形成闭环Tracing 提供数据源 → Datasets 定义测试场景 → Evaluators 给出质量度量 → Monitoring 发现异常模式 → 异常 trace 反哺到 Datasets 做针对性回归测试。它不是一个功能列表而是一个有机的工作流操作系统。3. 实操细节解析从零搭建闪卡生成器的完整质量保障体系3.1 环境初始化为什么.env文件的顺序和变量名如此关键很多新手卡在第一步环境变量配置。表面看只是复制粘贴但背后有三个易踩的坑我用血泪经验总结坑一LANGCHAIN_TRACING_V2必须在LANGCHAIN_API_KEY之后设置LangChain SDK 的初始化逻辑是先读取LANGCHAIN_API_KEY建立连接再根据LANGCHAIN_TRACING_V2决定是否启用 tracing。如果你把TRACING_V2true写在.env文件最前面而API_KEY因网络延迟稍晚加载SDK 可能以“无 key”状态启动 tracing导致所有 trace 数据丢失。正确姿势是# .env 文件严格按此顺序 LANGCHAIN_API_KEYlsk_abc123... OPENAI_API_KEYsk-xyz789... LANGCHAIN_TRACING_V2true LANGCHAIN_ENDPOINThttps://api.smith.langchain.com LANGCHAIN_PROJECTflashcards-prod提示LANGCHAIN_PROJECT这个变量必须在tracing启用后设置否则新 trace 会默认进入default项目导致数据分散。我建议在 Python 代码里显式设置而非依赖.env。坑二LANGCHAIN_ENDPOINT的 URL 末尾不能带斜杠官方文档没明说但实测https://api.smith.langchain.com/带斜杠会导致 SDK 认证失败报错401 Unauthorized。必须写成https://api.smith.langchain.com不带斜杠。这是 HTTP 客户端库的路径拼接 bug属于隐藏雷区。坑三虚拟环境隔离不足引发的依赖冲突LangSmith SDK 依赖较新版本的langchain-core和pydantic。如果你的全局 Python 环境里装了旧版 LangChain比如 0.1.xpip install langsmith可能因依赖约束失败。我的标准操作是# 创建干净的虚拟环境 python -m venv ./langsmith-env source ./langsmith-env/bin/activate # Linux/Mac # ./langsmith-env/Scripts/activate # Windows # 先升级 pip再安装 pip install --upgrade pip pip install langsmith python-dotenv openai注意openai包必须显式安装因为 LangSmith 的某些评估器会调用 OpenAI API 进行评估但它不作为直接依赖声明。漏装会导致运行时报ModuleNotFoundError。3.2 Dataset 构建实战CSV 格式里的魔鬼细节上传 CSV 看似简单但字段命名和数据清洗直接决定评估效果。以我们闪卡生成器的 CSV 为例原始文件pytorch_flashcards.csv结构如下frontbacksource_pagetorch.no_grad 的作用是什么阻止计算图构建节省内存...p23如何创建一个 PyTorch 张量使用 torch.tensor() 或 torch.zeros()...p45这里有两个关键点第一input_keys和output_keys必须与 CSV 列名完全一致且区分大小写如果 CSV 里列名是Front首字母大写而你写input_keys[front]LangSmith 会静默忽略该列导致 dataset 为空。我建议在上传前用 pandas 验证import pandas as pd df pd.read_csv(data/pytorch_code_syntax_flashcards.csv) print(CSV columns:, df.columns.tolist()) # 输出 [front, back, source_page]第二source_page这类元数据字段要善用它能极大提升问题定位效率在 LangSmith UI 中当你点击某条 trace 查看详情时source_page会作为 metadata 显示在右侧栏。当发现某张卡片答案错误你可以直接看到它来自 PDF 的第 23 页立刻去检查原文是否表述不清或存在歧义。这比在几百页文档里大海捞针高效得多。第三CSV 数据必须经过严格清洗我遇到过最坑的案例CSV 中back字段包含未转义的双引号导致upload_csv解析失败报错pandas.errors.ParserError: Error tokenizing data。解决方案是用 Excel 或 VS Code 打开 CSV确保所有字段用双引号包裹且内部双引号用两个双引号转义He said Hello。更稳妥的做法是用 Python 生成 CSVimport csv with open(cleaned.csv, w, newline, encodingutf-8) as f: writer csv.DictWriter(f, fieldnames[front, back]) writer.writeheader() for card in cards: # 自动处理特殊字符 writer.writerow({front: card[front].replace(, ), back: card[back].replace(, )})3.3 自定义评估器编写如何写出高准确率的自然语言判定规则内置评估器方便但业务场景往往需要定制。以has_code评估器为例最初的版本RunEvalConfig.Criteria({has_code: Does this question involve code syntax?})实测在 100 个样本上准确率仅 68%。问题出在“code syntax”这个表述太宽泛。LLM 评估器会把“Python 中的 for 循环怎么写”正确和“机器学习中的损失函数有哪些”错误但含“循环”一词都判为True。优化过程如下Step 1明确业务边界我们定义“代码语法题”的核心特征是问题中必须出现具体的编程语言名、库名、关键字或符号并要求解释其用法。排除所有泛泛而谈的“原理”“概念”“作用”类问题。Step 2构造正负样本准备 5 个典型正例应判 True和 5 个典型负例应判 False例如正例PyTorch 中 torch.no_grad() 的作用是什么负例深度学习中反向传播的原理是什么Step 3迭代优化 prompt 描述最终稳定的版本RunEvalConfig.Criteria({ has_code: ( 判断问题是否明确要求解释特定编程语言或库的代码语法细节。 必须同时满足1) 提及具体语言/库名如 Python, PyTorch, NumPy 2) 包含代码相关关键词如 语法, 写法, 如何实现, 作用, 用法 3) 问题对象是代码元素如函数、操作符、关键字、语法结构。 若任一条件不满足返回 False。只返回 True 或 False不要解释。 ) })关键改进点用分号分隔三个硬性条件避免 LLM 自由发挥列举具体语言/库名缩小语义范围强制只返回布尔值避免评估 LLM 生成冗长解释影响解析“不要解释”指令显著提升解析稳定性。Step 4验证与阈值设定运行评估后在 UI 中查看每条判定的 reasoning悬停可见。如果 reasoning 里出现“我认为...”“可能...”等模糊表述说明 prompt 还不够强硬需继续收紧。最终我们设定当has_code评分为False但coherence评分 4.0 时触发人工复核——这代表问题本身质量高但不符合代码题定位可能是 prompt 设计偏差。3.4 生产环境监控配置如何设置真正有用的告警规则LangSmith UI 的监控面板强大但默认视图容易让人迷失。我推荐聚焦三个核心仪表盘仪表盘一Trace 健康度概览Dashboard Projects Your Project重点关注两个指标Error Rate错误率不是 HTTP 错误而是llm组件抛出的OutputParserException或自定义校验失败。设置阈值 5% 持续 10 分钟告警。Latency P9595 分位延迟闪卡生成要求实时性P95 3000ms 视为性能退化。注意延迟突增往往伴随 token 消耗激增需关联查看。仪表盘二评估指标趋势Dashboard Datasets Your Dataset对每个关键评估器如has_code,coherence设置趋势图。重要技巧不要只看平均分。我添加了“低于阈值的 trace 数量”折线图。当coherence 3.0的 trace 数从每天 5 个突然涨到 50 个即使平均分只降了 0.2也意味着出现了新的错误模式必须立即介入。仪表盘三语义异常检测Dashboard Traces Search这是最强大的功能。在搜索框输入torch.no_grad AND coherence 3.0→ 定位特定关键词下的质量问题error OR fail OR not work→ 捕获用户反馈中的负面语义latency 5000 AND token_usage 1000→ 发现低效的长上下文请求注意语义搜索依赖 embedding 模型首次使用需等待几分钟索引建立。建议在项目初期就开启让数据充分积累。4. 实操全流程演示从创建项目到部署监控的完整 walkthrough4.1 第一步创建专属项目与初始化客户端5 分钟搞定别跳过这一步很多团队直接用default项目导致 trace 数据混杂后期无法分离 A/B 测试或不同版本。以下是生产环境推荐的初始化脚本init_langsmith.pyimport os import uuid from dotenv import load_dotenv, find_dotenv from langsmith import Client # 1. 加载环境变量必须在最前 load_dotenv(find_dotenv()) # 2. 验证必要变量 required_vars [LANGCHAIN_API_KEY, OPENAI_API_KEY] for var in required_vars: if not os.getenv(var): raise ValueError(fMissing required environment variable: {var}) # 3. 设置 LangChain 运行时配置 os.environ[LANGCHAIN_TRACING_V2] true os.environ[LANGCHAIN_ENDPOINT] https://api.smith.langchain.com # 4. 创建唯一项目名避免命名冲突 project_name fflashcards-prod-{uuid.uuid4().hex[:8]} os.environ[LANGCHAIN_PROJECT] project_name # 5. 初始化客户端并创建项目 client Client() try: project client.create_project( project_nameproject_name, descriptionProduction flashcard generator with full monitoring, # 启用自动归档避免 trace 积压 metadata{environment: production, version: v1.2.0} ) print(f✅ Project created: {project_name}) print(f View at: https://smith.langchain.com/projects/{project.id}) except Exception as e: print(f❌ Failed to create project: {e}) # 如果项目已存在直接使用 project client.read_project(project_nameproject_name)运行后你会得到一个带时间戳和随机后缀的项目名如flashcards-prod-a1b2c3d4并在控制台看到访问链接。关键经验项目名里加入版本号v1.2.0和环境标识prod后续在 UI 中筛选时一目了然。4.2 第二步构建闪卡生成链路并注入 tracing核心代码我们的链路设计遵循最小可行原则DocumentLoader → Retriever → Prompt → LLM → OutputParser。以下是带完整 tracing 注释的代码flashcard_chain.pyfrom langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import JsonOutputParser from langchain_openai import ChatOpenAI from langchain_community.document_loaders import PyPDFLoader from langchain_community.vectorstores import FAISS from langchain_openai import OpenAIEmbeddings from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.chains import RetrievalQA # 1. 文档加载与切分模拟真实流程 loader PyPDFLoader(docs/xgboost_tutorial.pdf) docs loader.load() text_splitter RecursiveCharacterTextSplitter(chunk_size500, chunk_overlap50) splits text_splitter.split_documents(docs) # 2. 向量存储Retriever embeddings OpenAIEmbeddings() vectorstore FAISS.from_documents(splits, embeddings) retriever vectorstore.as_retriever(search_kwargs{k: 3}) # 3. 定义 Prompt关键明确指令格式约束 prompt_template 你是一个专业的 AI 教育助手负责为机器学习工程师生成高质量的闪卡。 请严格按以下规则生成一张闪卡 - FRONT问题必须是一个具体、可答的代码语法问题明确提及编程语言如 Python或库如 XGBoost。 - BACK答案必须是精确、简洁的技术解释不超过 50 字禁止使用“可能”“通常”等模糊词汇。 - FORMAT只输出 JSON严格遵循{{front: 问题文本, back: 答案文本}} 当前上下文 {context} 用户请求 {input} prompt ChatPromptTemplate.from_template(prompt_template) # 4. 初始化 LLM启用 tracing llm ChatOpenAI( modelgpt-3.5-turbo, temperature0.3, # 降低随机性提升一致性 max_tokens256 # 防止过长输出 ) # 5. 构建链路LangChain 自动注入 tracing chain ( {context: retriever, input: lambda x: x} | prompt | llm | JsonOutputParser() ) # 6. 执行并查看 tracing 效果 if __name__ __main__: result chain.invoke(生成一张关于 XGBoost 中 early_stopping_rounds 参数的闪卡) print(✅ Generated card:, result) # 此时完整 trace 已自动记录到 LangSmith包含 # - retriever 返回的 3 个 context 片段 # - 渲染后的完整 prompt含 context 和 input # - LLM 的原始响应含 token 数、耗时 # - JsonOutputParser 的解析结果实操心得temperature0.3是经过大量测试的平衡点。设为 0 会导致模型过于死板无法处理边缘 case设为 0.7 以上则一致性骤降。这个参数必须和你的评估指标一起调优。4.3 第三步运行全量评估并解读结果手把手分析假设我们已创建好名为xgboost_syntax的 dataset包含 50 个典型 prompt。现在运行综合评估from langchain.smith import run_on_dataset from langchain.smith import RunEvalConfig # 定义多维度评估 eval_config RunEvalConfig( evaluators[ # 内置评估器 RunEvalConfig.Criteria(conciseness), RunEvalConfig.Criteria(coherence), RunEvalConfig.Criteria(helpfulness), # 自定义评估器 RunEvalConfig.Criteria({ has_code: ( 问题是否明确要求解释 XGBoost 或 Python 的代码语法细节 必须提及 XGBoost、Python、scikit-learn 或具体函数名如 early_stopping_rounds 且问题焦点是代码用法而非数学原理。只返回 True 或 False。 ) }), RunEvalConfig.Criteria({ no_facts: ( 答案中是否包含未经上下文支持的事实性陈述如 XGBoost 由微软开发 若答案所有内容均能在提供的 context 中找到依据返回 False否则返回 True。 ) }) ] ) # 执行评估指定项目名便于追踪 results run_on_dataset( clientclient, dataset_namexgboost_syntax, llm_or_chain_factorychain, # 注意传入的是 chain不是 llm evaluationeval_config, project_nameeval-xgboost-v1.2.0, # 关联版本号 )评估完成后在 LangSmith UI 的Datasets xgboost_syntax Runs页面你会看到一个表格。重点看这几列Column解读我的经验StatusSuccess或ErrorError行点开看 stack trace90% 是JsonOutputParser解析失败根源是 prompt 指令不够强硬Conciseness1-5 分若平均分 3.5检查 prompt 是否有冗余描述如“请详细解释”Coherence1-5 分若某条 trace 分数低点开看reasoning常发现 LLM 在答案里编造了上下文不存在的细节has_codeTrue/False若 False 率 20%说明 prompt 的“代码题”引导不足需强化关键词no_factsTrue/False若 True 率高说明 retriever 返回的 context 不够精准或 prompt 缺少“仅基于 context 回答”指令关键技巧点击任意一列标题可排序。比如点击Coherence降序立刻看到最不连贯的 5 个输出集中分析共性问题。4.4 第四步建立生产监控看板UI 操作指南登录smith.langchain.com按以下路径配置进入项目仪表盘Projects →flashcards-prod-a1b2c3d4添加核心指标卡片点击右上角 Add Widget选择Trace Count设置 Filterstatus successTime RangeLast 24 hours添加第二个卡片Average LatencyFilterstatus successAggregationP95设置关键告警点击左上角Alerts→Create AlertNameHigh Coherence FailureConditioncoherence 3.0的 trace 数量 10inLast 15 minutesNotification勾选 Email并填入运维邮箱保存为共享看板点击右上角Save DashboardNameFlashcards Production HealthShare勾选Share with team实操心得告警阈值必须基于历史数据设定。我建议先运行 3 天 baseline观察coherence 3.0的自然发生率通常 2%再将告警阈值设为 5 倍即 10%。避免“狼来了”效应。5. 常见问题与排查技巧实录那些文档里不会写的坑5.1 问题一run_on_dataset执行后 UI 显示 0 条 trace但控制台无报错现象代码运行成功results对象有数据但 LangSmith UI 的 dataset 页面显示No runs found。根本原因LANGCHAIN_PROJECT环境变量未在run_on_dataset执行时生效。LangSmith SDK 会读取当前进程的环境变量如果在run_on_dataset调用前未正确设置trace 会进入default项目。排查步骤在调用run_on_dataset前添加调试打印print(Current LANGCHAIN_PROJECT:, os.getenv(LANGCHAIN_PROJECT)) print(Current LANGCHAIN_TRACING_V2:, os.getenv(LANGCHAIN_TRACING_V2))检查输出是否为你期望的项目名。如果不是说明变量未加载。终极解决方案在run_on_dataset调用时显式传入project_name参数results run_on_dataset( clientclient, dataset_namemy_dataset, llm_or_chain_factorychain, project_nameflashcards-prod-a1b2c3d4 # 强制指定不依赖环境变量 )5.2 问题二自定义评估器返回None或格式错误导致评估中断现象在 UI 的评估结果里某条 trace 的has_code列显示None且该 trace 的evaluation标签页为空。原因分析评估 LLM通常是 gpt-3.5-turbo在解析你的自然语言指令时失败返回了非布尔值如I think its True或{result: True}。LangSmith 默认只接受纯True/False字符串。解决方法在自定义评估器 prompt 末尾强制添加解析指令RunEvalConfig.Criteria({ has_code: ( 你的任务是严格判断问题是否符合代码语法题定义... 【重要】最后只输出一个单词True 或 False。不要任何标点、空格、解释。 ) })进阶技巧添加重试逻辑。LangSmith 支持max_retries参数RunEvalConfig.Criteria( {has_code: ...}, max_retries2 # 失败时自动重试 2 次 )5.3 问题三Tracing 数据量过大项目被限速或产生高额费用现象项目运行几天后trace 数量达 10 万UI 响应变慢且收到 LangSmith 的用量提醒邮件。真相LangSmith 按 trace 数量和存储时长计费。高频调用如每秒 10 次会产生海量 trace。成本优化方案采样率控制在生产环境不记录所有 trace而是按比例采样。在.env中添加LANGCHAIN_SAMPLING_RATE0.1 # 只记录 10% 的 trace自动清理设置 trace 保留策略。在 UI 的Settings Project Settings中开启Auto-delete traces after 30 days。分级 tracing对关键路径如付费用户生成卡片启用 full tracing对普通用户启用 minimal tracing只记录 LLM 输入输出不记录 retriever 等中间步骤。通过langsmithSDK 的traceable装饰器实现from langsmith import traceable traceable(run_typellm, nameflashcard_generation) # 全量 tracing def generate_card(input_text): return chain.invoke(input_text) traceable(run_typellm, namefree_user_card, tags[free]) # 标记为免费用户 def generate_free_card(input_text): return chain.invoke(input_text)然后在 UI 的Traces页面用tags ! free过滤掉免费用户 trace。5.4 问题四CSV 上传后dataset 页面显示0 examples但文件确认无误排查清单按优先级排序检查文件编码必须是UTF-8。用 VS Code 打开 CSV右下角看编码如果不是 UTF-8点击转换并保存。检查 BOM 头Windows Excel 生成的 CSV 常含 BOMByte Order MarkLangSmith 无法识别。用 Python 去除with open