内容核验:2026-10-15,参照当日 Langfuse 官方 v4 文档。本文以概念和设计示意为主,不是完整可运行项目;示例金额、分数、通过率和耗时均非实测数据。AgentScope/MCP 节点名称是业务埋点示例,需要显式配置语义映射。版本和部署条件以文末官方资料为准。
在 LLM 应用里,Prompt 已经不只是代码中的一段字符串,而是一个需要版本、发布、回滚、评估和持续优化的工程资产。Langfuse Prompt Management 正是围绕这个问题设计的。
本文基于 Langfuse 2026 年当前官方文档整理。Langfuse 迭代较快,具体页面入口、字段名和版本要求请以官方最新文档为准。
1. 为什么 Prompt 不应该永远写死在代码里
传统写法:
java
String prompt = "你是一个专业银行业务助手......";
问题:
text
改一个字也要改代码
需要重新构建发布
无法方便查看历史版本
无法快速回滚
Prompt 效果难和 Trace 关联
产品/业务人员很难参与
因此 Langfuse 的思路是:
把 Prompt 从代码发布周期中解耦出来。
2. Prompt Object
一个 Prompt 不只是文本。
可以理解为:
text
Prompt
├── name
├── type
├── prompt content
├── variables
├── config
├── version
└── labels
其中最重要的是:
text
Version
Label
3. Text Prompt 与 Chat Prompt
Langfuse 支持两类常见 Prompt。
Text Prompt
text
你是一名 {{role}},请回答:{{question}}
Chat Prompt
json
[
{"role": "system", "content": "你是一名 {{role}}"},
{"role": "user", "content": "{{question}}"}
]
Chat Prompt 更适合现代对话模型的消息结构。
4. Variables:动态变量
Langfuse 使用:
text
{{variable}}
表示变量。
例如:
text
你是一名 {{role}}。
当前用户问题:{{question}}
运行时:
text
role = 银行业务助手
question = 查询账户余额
编译后才得到最终 Prompt。
这样可以让 Prompt 模板和动态业务数据分离。
5. Version:每次修改都有版本
Langfuse 每次更新 Prompt 会创建新 Version。
例如:
text
V1
V2
V3
V4
Version 代表不可变历史。
它解决:
text
谁改了 Prompt?
当前是哪一版?
之前是什么内容?
哪一次修改导致质量下降?
6. Label:代码不要绑死版本号
Version 是历史编号,Label 是指针。
典型 Label:
text
production
latest
staging
官方当前语义中:
latest自动指向最新创建版本production通常表示生产使用版本- 也可以创建自己的环境、租户或实验 Label
例如:
text
V7 ← latest
V6 ← production
V5
V4
生产代码读取:
text
production
而不是:
text
version = 6
这样发布 Prompt 时不需要改业务代码。
7. Prompt 发布流程
推荐流程:
#mermaid-svg-WjeAhl6qSu4sjmz8{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-WjeAhl6qSu4sjmz8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-WjeAhl6qSu4sjmz8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-WjeAhl6qSu4sjmz8 .error-icon{fill:#552222;}#mermaid-svg-WjeAhl6qSu4sjmz8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-WjeAhl6qSu4sjmz8 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-WjeAhl6qSu4sjmz8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-WjeAhl6qSu4sjmz8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-WjeAhl6qSu4sjmz8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-WjeAhl6qSu4sjmz8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-WjeAhl6qSu4sjmz8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-WjeAhl6qSu4sjmz8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-WjeAhl6qSu4sjmz8 .marker.cross{stroke:#333333;}#mermaid-svg-WjeAhl6qSu4sjmz8 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-WjeAhl6qSu4sjmz8 p{margin:0;}#mermaid-svg-WjeAhl6qSu4sjmz8 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-WjeAhl6qSu4sjmz8 .cluster-label text{fill:#333;}#mermaid-svg-WjeAhl6qSu4sjmz8 .cluster-label span{color:#333;}#mermaid-svg-WjeAhl6qSu4sjmz8 .cluster-label span p{background-color:transparent;}#mermaid-svg-WjeAhl6qSu4sjmz8 .label text,#mermaid-svg-WjeAhl6qSu4sjmz8 span{fill:#333;color:#333;}#mermaid-svg-WjeAhl6qSu4sjmz8 .node rect,#mermaid-svg-WjeAhl6qSu4sjmz8 .node circle,#mermaid-svg-WjeAhl6qSu4sjmz8 .node ellipse,#mermaid-svg-WjeAhl6qSu4sjmz8 .node polygon,#mermaid-svg-WjeAhl6qSu4sjmz8 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WjeAhl6qSu4sjmz8 .rough-node .label text,#mermaid-svg-WjeAhl6qSu4sjmz8 .node .label text,#mermaid-svg-WjeAhl6qSu4sjmz8 .image-shape .label,#mermaid-svg-WjeAhl6qSu4sjmz8 .icon-shape .label{text-anchor:middle;}#mermaid-svg-WjeAhl6qSu4sjmz8 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-WjeAhl6qSu4sjmz8 .rough-node .label,#mermaid-svg-WjeAhl6qSu4sjmz8 .node .label,#mermaid-svg-WjeAhl6qSu4sjmz8 .image-shape .label,#mermaid-svg-WjeAhl6qSu4sjmz8 .icon-shape .label{text-align:center;}#mermaid-svg-WjeAhl6qSu4sjmz8 .node.clickable{cursor:pointer;}#mermaid-svg-WjeAhl6qSu4sjmz8 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-WjeAhl6qSu4sjmz8 .arrowheadPath{fill:#333333;}#mermaid-svg-WjeAhl6qSu4sjmz8 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-WjeAhl6qSu4sjmz8 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-WjeAhl6qSu4sjmz8 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WjeAhl6qSu4sjmz8 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-WjeAhl6qSu4sjmz8 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WjeAhl6qSu4sjmz8 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-WjeAhl6qSu4sjmz8 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-WjeAhl6qSu4sjmz8 .cluster text{fill:#333;}#mermaid-svg-WjeAhl6qSu4sjmz8 .cluster span{color:#333;}#mermaid-svg-WjeAhl6qSu4sjmz8 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-WjeAhl6qSu4sjmz8 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-WjeAhl6qSu4sjmz8 rect.text{fill:none;stroke-width:0;}#mermaid-svg-WjeAhl6qSu4sjmz8 .icon-shape,#mermaid-svg-WjeAhl6qSu4sjmz8 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WjeAhl6qSu4sjmz8 .icon-shape p,#mermaid-svg-WjeAhl6qSu4sjmz8 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-WjeAhl6qSu4sjmz8 .icon-shape .label rect,#mermaid-svg-WjeAhl6qSu4sjmz8 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WjeAhl6qSu4sjmz8 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-WjeAhl6qSu4sjmz8 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-WjeAhl6qSu4sjmz8 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否
是
创建新 Prompt Version
latest
Playground / Experiment 验证
效果达标?
设置 production Label
生产应用自动读取
这和软件发布非常像:
text
开发版本
测试
发布
监控
回滚
8. 回滚为什么很简单
如果:
text
V8 ← production
上线后发现异常,只需要把 production 指回:
text
V7 ← production
代码仍然读取:
text
production
不需要重新改代码发布。
但这不等于所有运行中的应用瞬时切换。SDK 存在本地缓存和过期后的后台刷新,回滚的可见时间取决于缓存 TTL、刷新结果和应用实例。紧急切换需要按所用 SDK 的缓存控制方式刷新或重新获取,并核对实际 Generation 关联的 Prompt Version。
9. Prompt Diff
Prompt Version Diff 用于比较版本差异。
例如:
text
V6:
当用户需要业务数据时,可以调用工具。
V7:
当用户需要真实业务数据时,必须优先调用 MCP Tool。
如果 Tool 调用率发生变化,可以结合 Diff 快速分析具体 Prompt 改动。
10. Prompt 缓存
很多人担心:
"每次模型调用前都去 Langfuse 拉 Prompt,会不会把 Langfuse 变成业务强依赖?"
Langfuse SDK 的 Prompt 获取有客户端缓存机制,官方目标就是避免 Prompt 管理给应用增加额外延迟和可用性风险。
因此推荐使用官方 SDK 的 Prompt 获取与缓存能力,而不是每次自行同步 HTTP 拉取。
缓存只能降低依赖,不能保证第一次获取必定成功。建议应用启动时预取 Prompt、提供经过审核的 fallback,并监控拉取和后台刷新失败。
11. Prompt 与 Trace 关联
这是 Prompt Management 很关键的一步。
如果 Trace 只记录:
text
模型回答错误
但不知道使用了哪个 Prompt Version,就很难复盘。
关联后:
text
Trace
└── Generation
└── Prompt: account-agent V7
就可以按版本统计:
text
Latency
Token
Cost
Score
调用次数
12. Prompt 与 Experiment 结合
例如要比较:
text
Prompt V7
Prompt V8
可以对同一个 Dataset 跑 Experiment:
text
Dataset
├── V7 Experiment
└── V8 Experiment
比较:
text
Tool 正确率
回答正确率
Cost
Latency
这就把 Prompt 优化从:
text
"我觉得 V8 好像更好"
变成:
text
"V8 在 100 条回归数据上 Score 提升 8%"
13. Agent Prompt 推荐怎么拆
复杂 Agent 不建议一个超大 Prompt 管所有事情。
可以按职责拆分:
text
account-agent-system
intent-router
mcp-tool-policy
answer-format
但也不要过度拆分到无法追踪依赖。
更重要的是建立:
text
命名规范
Version 规范
Label 规范
Owner
上线流程
14. Prompt 中不要放什么
不要把这些直接固化在 Prompt:
text
Secret
密码
API Key
敏感用户信息
容易变化的业务数据
动态信息应该通过变量、工具、RAG 或受控上下文注入。
15. 一个 AgentScope + MCP 示例
Prompt:
text
account-agent-system
模板:
text
你是一个银行业务智能助手。
当前用户问题:{{question}}
当用户询问真实账户、余额、流水等业务数据时,
必须调用对应 MCP Tool 获取真实结果,禁止自行编造。
版本:
text
V1:初始版本
V2:增加"禁止编造"
V3:强化 Tool 选择策略
然后使用 Dataset 进行回归,就可以比较每版 Tool 正确率。
16. 总结
Prompt Management 的核心不是"把 Prompt 放到网页上",而是建立:
text
Prompt
↓
Version
↓
Label
↓
Test / Experiment
↓
Production
↓
Trace / Score
↓
持续优化
只有当 Prompt 与 Trace、Score 和 Experiment 连起来时,Prompt 才真正从一段文本升级为工程资产。