news 2026/10/8 12:50:15

华为云Flexus+DeepSeek征文|DeepSeek-R1 Agent 可观测性实战:用 Langfuse + OpenTelemetry 打通 Dify 全链路追踪与评测,把 endpoint

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
华为云Flexus+DeepSeek征文|DeepSeek-R1 Agent 可观测性实战:用 Langfuse + OpenTelemetry 打通 Dify 全链路追踪与评测,把 endpoint

1. 从“部署成功”到“运行正常”:Dify 上 DeepSeek-R1 Agent 的可观测性缺口

你大概率经历过这个场景:用华为云 Flexus X 实例一键拉起 Dify,接上 MaaS 平台的 DeepSeek-R1 商用推理服务,搭出一个企业知识库问答 Agent,压测通过、体验顺滑、正式上线。第一周风平浪静,第二周开始出问题——用户投诉“有时候回答特别慢”,但你不知道慢在哪一步:是 R1 思考太久?知识库检索太慢?还是工具调用卡住了?某个深夜 Agent 连续输出几十次错误答案,你第二天早上才发现,却根本不知道那批请求是哪个版本、哪条 Prompt、调用了哪些工具。

这些问题的共同根源是:大模型应用是概率系统,不能用“部署成功”来定义“运行正常”。传统监控只能告诉你“进程活着、接口 200”,却无法回答“这次回答的质量如何、推理链路是否健康”。LLMOps 之所以成为 AI 工程领域最热的方向之一,就是因为可观测性是 Agent 从 demo 走向生产的分水岭。

本文要解决的就是这件事:在 Dify 上跑 DeepSeek-R1 Agent,用 Langfuse 采集 trace、用 OpenTelemetry 统一埋点,覆盖工具调用、检索与评测环节,并给出可复制的模型 endpoint 与环境变量配置片段。适合已经用 Dify 搭过 Agent、但被“黑盒”问题困扰的开发者。整套方案的核心检索词是 Dify DeepSeek-R1 Agent 全链路追踪,读完你能自己搭出一套可回放、可评测、可告警的观测体系。

2. 前置准备:TaoToken 接入 DeepSeek-R1 与 Langfuse 自托管选型

在动手配 OTel 之前,先把模型入口和观测后端这两件事定下来。模型侧我用的是 TaoToken 提供的统一 API 入口,它兼容 OpenAI 协议,Dify 里配模型时直接填 Base URL 和 Key 就能用,省去在多个平台之间来回切换的麻烦。官网地址是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 端点是 https://taotoken.net/api (注意这个不加 UTM 参数)。

观测后端选 Langfuse,理由是它是开源 + 自托管路线里最成熟的选择:Traces、Scores、Datasets、Prompts 管理全部开源,Docker 一条命令就能跑起来,数据完全留在企业内部。对金融、政企这类数据敏感场景,这是刚需。整个体系跑在 Flexus X 实例上,架构是 Dify 负责 Agent 编排,DeepSeek-R1 走 MaaS 推理服务,Langfuse 以 Docker Compose 方式自托管,Nginx 做统一入口且 Langfuse 仅内网可达。

资源规划上给三档参考。内部试用、日会话小于 500,4C8G 够用,Dify 和 Langfuse 同机,Langfuse 限制 1G 内存。团队使用、日会话 500 到 5000,建议 8C16G,Langfuse 独立容器限 2G,采样率 0.5。生产对外服务、日会话超过 5000,16C32G 或上 CCE 高可用,Langfuse 单独实例,采样率 0.1。两个容易踩的容量坑:Langfuse 的 Postgres 会随 Trace 增长迅速膨胀,务必配好 retention 定期清理;思维链 reasoning_content 动辄几千 token,入库前必须截断,否则一周就能吃掉几个 G 存储。

Langfuse 的四个核心概念先建立起来,后面所有操作都围绕它们。Trace 是一次完整会话或一次 Agent 运行的顶层容器,对应 Dify 里的一次对话。Observation 是 Trace 内部的子单元,分三类:span 是工作流节点和工具调用,generation 是一次 LLM 调用,event 是日志或异常标记点。Score 是挂在 Trace 或 Observation 上的质量分,来源可以是人工、规则或 LLM-as-judge。Dataset 是一组“输入-期望输出”样本,用于回归测试和模型对比。映射到 Dify Agent:一条 Trace 等于一次用户问答,span 是知识检索和工具调用,generation 是每次调用 DeepSeek,Score 是我们对这次回答打的质量分。

3. 可复制配置:Dify 模型 endpoint 与 Langfuse/OTel 环境变量片段

这一节是全文最需要你动手的部分,配置片段可以直接复制。先配 Dify 的模型供应商,在 Dify 的“设置 → 模型供应商 → OpenAI-API-compatible”里新增一个模型,关键字段如下:

{ "model": "deepseek-r1", "model_type": "llm", "credentials": { "api_base": "https://taotoken.net/api", "api_key": "sk-你的TaoToken密钥", "mode": "chat", "context_size": "65536", "max_tokens_to_sample": "8192" }, "model_properties": { "mode": "chat", "context_size": 65536 } }

这里 Base URL 填 https://taotoken.net/api ,Key 从 TaoToken 控制台的 API Keys 页面拿,Model ID 填 deepseek-r1。三件套(Base URL + Key + Model ID)缺一不可,Dify 里配错任何一个都会在调用时报 401 或 model not found。

接着配 Dify 的 OpenTelemetry 导出。编辑 Dify 的 docker-compose.yaml,在 api 与 worker 服务中加入以下环境变量:

services: api: environment: ENABLE_OTEL: "true" OTEL_EXPORTER_OTLP_ENDPOINT: "http://langfuse:4318" OTEL_EXPORTER_OTLP_PROTOCOL: "http/protobuf" OTEL_SERVICE_NAME: "dify-api" OTEL_TRACES_SAMPLER: "parentbased_traceidratio" OTEL_TRACES_SAMPLER_ARG: "1.0" worker: environment: ENABLE_OTEL: "true" OTEL_EXPORTER_OTLP_ENDPOINT: "http://langfuse:4318" OTEL_EXPORTER_OTLP_PROTOCOL: "http/protobuf" OTEL_SERVICE_NAME: "dify-worker"

4318 是 Langfuse 的 OTLP HTTP 接收端口。如果 Dify 与 Langfuse 不在同一 Compose 网络,把 langfuse 换成实际地址。采样率生产环境建议从 0.1 起步,观测稳定后再逐步调高。注意 api 和 worker 的 OTEL_SERVICE_NAME 要区分开,否则链路会被拆成两条。

再配 Langfuse 自托管。官方提供 docker-compose 部署方式,核心服务包括 web、worker、postgres、redis、minio:

git clone https://github.com/langfuse/langfuse-docker.git cd langfuse-docker cp .env.example .env # 编辑 .env:设置 SALT、ENCRYPTION_KEY、NEXTAUTH_SECRET docker compose up -d

启动后访问 http://:3000 ,创建账号和 Project,在 Settings → API Keys 里拿到 Public Key、Secret Key 和 OTLP Endpoint。这三个凭据后面写评测脚本和配 Dify 导出都要用。

最后是 R1 思维链的提取配置。Dify 的 Agent 节点里,DeepSeek-R1 的 reasoning_content 会出现在节点输出的 llm_result 中。在 Agent 节点的“结束”分支接一个代码节点,把思维链写入会话变量:

def main(reasoning_content: str, answer: str) -> dict: truncated = reasoning_content[:2000] return { "reasoning_trace": truncated, "answer": answer, "trace_event": { "type": "llm_reasoning", "model": "deepseek-r1", "reasoning_tokens": len(reasoning_content) } }

截断到 2000 字符是为了避免观测数据膨胀。配合 Langfuse 的事件标记功能,你能在 Trace 时间轴上直观看到模型在哪个节点开始思考、思考了多久、输出了多少思考 token。

4. 验证请求:从一次 Agent 问答到评测分数的完整链路

配置完成后,跑一次 Agent 问答来验证链路是否打通。在 Dify 里发起一个测试对话,比如“帮我查一下上个月华北区的销售额汇总”,然后到 Langfuse 的 Projects 页面刷新。判断链路完整的标准有四条:有根 Trace,一条用户会话对应一个根 Trace 而不是散落的碎片 span;有 LLM 调用,能看到 DeepSeek 的每次请求,含 model、input、output、tokens;有工作流节点,知识检索和工具调用按顺序排列;有时间轴,每个 span 都有耗时,能一眼看出慢在哪。

如果看不到 Trace,优先检查三件事:Dify 与 Langfuse 网络是否互通,在 Dify 容器里执行 curl langfuse:4318 看能否连通;ENABLE_OTEL 是否生效,重启后查看 Dify 日志有无 OTel 相关报错;协议是否匹配,http/protobuf 和 http/json 不能混用。

链路打通后,用 Trace 回放定位一次“回答质量劣化”。打开那条 Trace,你会看到这样的结构:

Trace: "帮我查一下上个月华北区的销售额汇总" ├─ span: 意图路由 (12ms) → 分类: 数据查询 ├─ span: 工具调用 (340ms) → search_sales("华北区", "上月") │ └─ event: 检索命中 0 条 可疑点 ├─ generation: DeepSeek-R1 (8.2s) ← 思考 6123 tokens, 回答 214 tokens │ └─ reasoning_content: "检索结果为空,但用户明确要求汇总, │ 我基于历史知识补充了一个估计值......" └─ span: 输出 (18ms) → 回答: "上月华北区销售额约 X 万元"

问题瞬间水落石出:不是模型变笨了,而是工具调用传参错了(“华北区”没匹配上库里的“华北区域”),R1 在检索为空的情况下基于先验知识硬答,还给了个看似确定的数字。修复方向有两个:修正工具的参数归一化,把“华北区”映射到“华北区域”;在 Agent Prompt 里加硬约束,检索结果为空时必须明确告知用户,禁止推测具体数字。

接下来验证评测闭环。在 Langfuse 中创建 Dataset,把生产环境的高质量会话和线上发现的问题样本沉淀进去,一个像样的黄金集至少 50 到 100 条。然后用 LLM-as-judge 打分,裁判 Prompt 示例:

你是一个严谨的评测员。请根据以下维度对回答打分(每项 0-10): 1. 忠实度: 回答是否完全基于给定知识, 未引入外部幻觉 2. 完整性: 是否覆盖了用户问题的所有关键方面 3. 可操作性: 是否给出了可直接执行的建议或结论 4. 安全性: 是否存在泄露、误导或不当内容 【问题】{question} 【参考知识】{context} 【待评回答】{answer} 请输出 JSON: {"faithfulness": 8, "completeness": 7, "actionability": 9, "safety": 10, "reason": "..."}

用脚本把评分写回对应 Trace:

from langfuse import Langfuse langfuse = Langfuse( public_key="pk-...", secret_key="sk-...", host="http://<flexus-ip>:3000" ) langfuse.score( trace_id="trace_id_xxx", name="faithfulness", value=8.0, comment="回答忠实于知识库, 但漏了同比数据" )

实测下来,我们对“运维工单助手”做了三轮迭代,用 80 条黄金集评测,忠实度与完整性的平均分变化如下:

迭代变更内容忠实度完整性结论
基线R1 直答,无检索校验6.87.1幻觉率偏高
v2增加知识库 RAG + 引用来源8.57.9忠实度 +1.7
v3v2 + 检索为空禁答硬约束9.18.2双指标达标

这张表就是给产品经理、给评审看的最硬证据:“R1 比 V3 强”不再是一句感觉,而是一组可以持续跟踪的数字。

5. 常见报错排查:401、local proxy failed、reading choices、OAuth 对照

配置过程中最容易撞上的几类报错,这里逐一对照。

401 Unauthorized。出现在 Dify 调用模型时,说明 TaoToken 的 Key 配错了或者没生效。检查三件套:Base URL 是不是 https://taotoken.net/api ,Key 有没有多余空格,Model ID 是不是 deepseek-r1。如果 Key 是从控制台复制的,注意别把前后引号也带进去。

local proxy failed。出现在 Dify 容器内访问 Langfuse 时,通常是网络不通。在 Dify 的 api 容器里执行 curl -v http://langfuse:4318 ,如果解析不到主机名,说明两个服务不在同一 Compose 网络,把 OTEL_EXPORTER_OTLP_ENDPOINT 改成 Langfuse 的实际 IP 或域名。如果连接被拒绝,检查 Langfuse 的 4318 端口有没有映射出来。

reading choices 相关报错。出现在解析模型响应时,多半是 Dify 的模型配置里 mode 填错了。DeepSeek-R1 走 chat 模式,如果填成 completion,返回结构对不上就会报这个。另外 context_size 和 max_tokens_to_sample 要按模型实际能力填,填太大可能被服务端拒绝。

OAuth 报错。出现在 Langfuse 登录或 API 调用时,通常是 NEXTAUTH_SECRET 没配或者配得太短。在 .env 里设置一个足够长的随机字符串,重启 Langfuse 容器。如果是 API 调用报 OAuth,检查 Public Key 和 Secret Key 有没有搞反,Public Key 用于客户端上报,Secret Key 用于服务端 API。

Trace 只有一半。Dify 的 API 与 Worker 都导出了,但 Langfuse 里只看到 API 的 span。检查两边的 OTEL_SERVICE_NAME 是否一致,不一致会导致链路被拆成两条;确认异步任务(Agent 执行在 Worker 侧)的导出配置已生效。

数据量爆炸。全量采样加完整思维链入库,一周就把 Postgres 撑爆。生产环境采样率先设 0.1,思维链截断到 2000 字符,定期归档旧 Trace。

思维链字段丢失。R1 的 reasoning_content 在 Dify 某些版本不会自动进入 OTel 的 generation output。用代码节点显式提取并写入 metadata 或事件,别依赖隐式传递。

评测分数不稳定。LLM-as-judge 同一问题评两次分不一样。固定温度等于 0,一次评测跑 3 次取中位数,维度拆细,不要一个笼统的质量分,拆成忠实度、完整性等,模型在细粒度维度上更稳定。

时区与 ID 对不上。Dify 的会话 ID 与 Langfuse Trace ID 映射困难。在 Dify 的 HTTP 请求节点把会话 ID 写入 Trace 的 metadata,比如 session_id,Langfuse 里按 metadata 检索,打通业务侧与观测侧。

6. 语义一致 CTA:把观测闭环接回你的 Dify 工作流

整套体系跑通后,你会发现可观测性带来的最大变化不是“多了一个看板”,而是 Agent 的迭代方式变了。以前改 Prompt 靠感觉,现在改之前先跑一遍黄金集,分数下降就回滚,分数上升才发布。以前用户投诉“答得慢”,你只能猜,现在打开 Trace 一眼看出是 R1 思考 token 失控还是工具调用卡住。

如果你还没配好模型入口,先去 TaoToken 控制台拿 API Key,接入文档在 https://taotoken.net/doc ,里面有 Dify、Cline、Claude Code 等客户端的完整配置示例。想先验证 DeepSeek-R1 的对话效果,可以直接用模型对话页面试几轮,确认 Base URL 和 Key 没问题再往 Dify 里配。如果你打算长期跑编码类或 Agent 类任务,Coding Plan 的额度模型比按次计费更划算,适合把观测体系当成日常开发流程的一部分。

最后留一个实用技巧:Langfuse 的 Prompts 管理支持多版本 Prompt 的 A/B 对比,把评测分数和 Prompt 版本关联起来,你就能回答“这次改动到底值不值”这个问题。观测的终点不是看板,而是让每一次改动都有数据支撑。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/8 12:49:48

AI 智能体的开发框架:用 TaoToken 统一 Key 打通多工具调用链

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

作者头像 李华
网站建设 2026/10/8 12:49:00

使用Cursor进行编码初体验:把Base URL改到TaoToken的完整配置与验证

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

作者头像 李华
网站建设 2026/10/8 12:49:00

Netty 4.2 内存模型重构剖析:从 PooledByteBufAllocator 到 O...

Netty 4.2 内存模型重构剖析&#xff1a;从 PooledByteBufAllocator 到 Off-Heap 直接内存的演进逻辑上周有个重构需求&#xff0c;团队想把核心网关从 Netty 4.1 升级到 4.2&#xff0c;但在压测阶段发现 OutOfDirectMemoryError 的频发率不降反升。排查后发现&#xff0c;4.2…

作者头像 李华
网站建设 2026/10/8 12:45:56

小龙虾 OpenClaw Win11 部署常见问题:TaoToken 统一 Key 通道排障清单

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

作者头像 李华
网站建设 2026/10/8 12:45:17

Java 实现 Excel 批量导入 MySQL 的工程实践与性能优化

简介&#xff1a;这份资源面向Java后端初学者与需要处理数据迁移的开发者&#xff0c;提供了一套完整的Excel与MySQL双向数据同步示例。项目基于Apache POI解析xls/xlsx文件&#xff0c;通过JDBC连接MySQL&#xff0c;实现Excel数据导入数据库&#xff0c;并在检测到重复数据时…

作者头像 李华