dsh-langfuse
Đã xác minhdsh-langfuse · v0.1.1 · MIT
dsh-langfuse: Langfuse LLM observability for DeepSeek Harness — one OpenTelemetry trace tree per agent session, with feedback scores and subagent lineage.
Cài đặt
dsh plugin add dsh-langfuse Xác nhận layer đã áp bằng dsh --profile default --dump-config — xem hướng dẫn cài plugin.
Mã nguồn
Thẻ
Readme
dsh-langfuse
DeepSeek Harness 的 Langfuse LLM 可观测插件——每个 agent 会话一棵 OpenTelemetry trace 树,附反馈打分与子 agent 血缘。
把每个 agent 会话以 OpenTelemetry trace 树上报到 Langfuse:turn → trace、模型 step → generation、工具调用 → tool span,带 GenAI 语义约定属性、token 用量、首 token 时间与错误状态。
✨ 特性
- 🧵 全链路追踪——每轮 turn、每次 generation、每个工具调用都进 Langfuse,含模型/供应商/用量(含缓存与推理 token)/TTFT
- 🚚 Content-Length 传输——报文单次写入并显式带
Content-Length,绝不发 chunked。部分 Langfuse 部署的前置网关会破坏 chunked 的 POST 体(400 Failed to parse OTel JSON Trace),本传输从根上绕开这类问题 - 👍 反馈打分——
/feedback记录变成挂在最近一轮 turn trace 上的 TEXT score - 🔗 子 agent 血缘——子会话的 turn trace 链接到父会话的 trace(同进程)
- 🎚️ 三种上报模式——
FULL(实时)/FEEDBACK_ONLY(用户记录反馈时才上报)/DISABLED(默认,不出网) - 🔒 可选 input——generation input(system prompt / 工具 / prompt)仅在
includeGenerationInput开启时导出 - 🛡️ 配置失败即报错——非法 URL、缺密钥、非法数值在插件加载时即抛出
🚀 快速开始
dsh plugin --profile web add dsh-langfuse
export LANGFUSE_PUBLIC_KEY=pk-lf-...
export LANGFUSE_SECRET_KEY=sk-lf-...
# 可选:自建实例或非 EU region
export LANGFUSE_HOST=https://langfuse.example.com
dsh web # 重启实例,聊一轮即可在 Langfuse 看到 trace
有 key 即 FULL 实时上报;无 key 则 DISABLED。LANGFUSE_TELEMETRY_MODE=FEEDBACK_ONLY 收敛为反馈门控,LANGFUSE_INCLUDE_GENERATION_INPUT=1 导出 generation input。
自带 patch 会禁用 dsh-base 的 session-telemetry-otel 行(seam 每个 context 只接受一个后端)并挂载本包;dsh --profile web --dump-config 可不启动直接查看组合结果。
显式 cordis.yml 行
- id: session-telemetry-langfuse
name: dsh-langfuse
config:
mode: FULL # FULL | FEEDBACK_ONLY | DISABLED(默认)
exporter:
url: https://cloud.langfuse.com/api/public/otel/v1/traces
auth:
publicKey: !!js process.env.LANGFUSE_PUBLIC_KEY
secretKey: !!js process.env.LANGFUSE_SECRET_KEY
processor: {} # 可选;原样透传给 BatchSpanProcessor
includeGenerationInput: false
⚙️ 配置
| 字段 | 默认 | 含义 |
|---|---|---|
mode |
DISABLED |
FULL 实时导出;FEEDBACK_ONLY 记录反馈时才回放导出;DISABLED 什么都不构造 |
exporter.url |
— | 完整 OTLP traces 端点(…/api/public/otel/v1/traces),非 DISABLED 必填 |
exporter.timeoutMillis |
10000 |
单请求超时 |
auth.publicKey / auth.secretKey |
— | Langfuse 项目密钥对(Basic auth),非 DISABLED 必填 |
processor |
{} |
原样透传给 BatchSpanProcessor;重试(有限退避,6 次)在 exporter 内 |
includeGenerationInput |
false |
导出 langfuse.observation.input(system prompt / 工具 schema / 模型 / 用户 prompt) |
maxAttributeChars |
16384 |
单属性载荷上限,超长截断并打 …[truncated] 标记(canonical log 保留全量) |
shutdownTimeoutMillis |
3000 |
SDK 关停排空的截止时间 |
feedbackScoreName |
user-feedback |
/feedback 推送的 score 名 |
🧭 Langfuse 里的呈现
| dsh 会话事件 | Langfuse 概念 |
|---|---|
turn/start / turn/end |
trace(turn N;错误结束 → ERROR 状态) |
step/start + request/header + assistant/message |
generation(step T.S)——模型/供应商/输出/gen_ai.usage.* |
每步第一个 assistant/chunk |
langfuse.observation.completion_start_time(TTFT) |
tool/call + tool/result |
tool span(入参→input,结果→output,isError→ERROR) |
user/message |
trace input |
feedback/record |
TEXT score,挂在最近一轮 turn trace |
| 子会话 turn | trace 链接到父会话 trace |
agent-error ops 记录 |
异常事件 + ERROR 状态 |
| 其余事件(todo、plan、compaction…) | 开放 turn 上的时间点 span event |
关联属性用本包自有词汇(dsh.turn_idx、dsh.step_idx、dsh.event_seq…),多个遥测后端可共用一个 Langfuse 项目而不冲突。
🏗️ 工作原理
- 遥测 seam 后端:harness 把一切模型可见内容记入 canonical session log;本插件实现
SessionTelemetryBackend(@deepseek-ai/dsh-session-telemetry),天然覆盖全部事件(含没见过的类型),并免费获得 seam 的同意语义与脱敏 waterfall - OTel SDK + 自定义 exporter:
BasicTracerProvider+BatchSpanProcessor造 span,@opentelemetry/otlp-transformer序列化,自定义SpanExporter以Content-Length+ 有限重试投递 - 折叠时间线:
SessionTimeline把平铺记录流按(session.id, turn, step)折成 span 树;边界时间一律取记录自身时间戳——实时捕获与 canonical log 回放产出完全一致的树 - at-most-once 交付(继承自 seam):丢失窗口=崩溃窗口;接收方用
langfuse.session.id+dsh.turn_idx+dsh.event_seq关联
🧪 开发
npm run check # biome + typecheck + vitest(单测 & seam 集成)+ 构建
30 个测试覆盖配置校验、折叠时间线、传输(Content-Length 存在、无 Transfer-Encoding、重试/退避)、score 推送,以及驱动真实 SessionTelemetryCoordinator 的全链路 seam 集成。
⚠️ 限制
- 每个 context 只接受一个后端(自带 patch 已禁用官方 OTLP-logs 行)
- 子 agent 血缘仅同进程尽力而为(跨进程重启后父 trace id 未知)
- 无持久化投递(at-most-once)
- score 推送 fire-and-forget(失败只告警)