bug: prompt cache key collides version numbers with numeric labels, returning the wrong prompt

在自托管或 Langfuse Cloud 环境中,使用 Redis 存储并开启了默认的 Prompt 缓存( LANGFUSE_CACHE_PROMPT_ENABLED 默认值为 true )。用户通过 /api/public/v2/prompts/{name}?version=N 或 ?label

bug: prompt cache key collides version numbers with numeric labels, returning the wrong prompt

bug: prompt cache key collides version numbers with numeric labels, returning the wrong prompt

快速结论:当 Langfuse 的 Prompt 同时存在版本号 N 和值为 “N” 的自定义标签时,Redis 缓存键会因未区分类型而碰撞,导致按版本查询和按标签查询互相返回错误的 Prompt 版本。优先排查 getCacheKeyparams.version ?? params.label 的合并逻辑。

问题场景

在自托管或 Langfuse Cloud 环境中,使用 Redis 存储并开启了默认的 Prompt 缓存(LANGFUSE_CACHE_PROMPT_ENABLED 默认值为 true)。用户通过 /api/public/v2/prompts/{name}?version=N?label=N 获取 Prompt 时触发。该问题会影响生产环境中按版本或标签固定 Prompt 的使用。

报错原文

The server side prompt cache builds its Redis key without distinguishing a version lookup from a label lookup, so a version number and a numeric label with the same text share one cache entry and return each other's content.
In packages/shared/src/server/services/PromptService/index.ts, getCacheKey returns:
  `${prefix}:${params.version ?? params.label}`
where prefix is `prompt:{projectId}:{epoch}:{promptName}`. version is a number and label is a user provided string. Labels are allowed to be purely numeric.
So a request for version 3 and a request for label "3" produce the identical key `prompt:{projectId}:{epoch}:{name}:3` and share one cached value. Whichever request populates the key first wins, and the other request gets a cache hit with the wrong prompt version.

原因分析

根本原因是 getCacheKey 函数(位于 packages/shared/src/server/services/PromptService/index.ts,约第 198 行)将 params.version ?? params.label 直接拼接为缓存键后缀,而没有对查找类型(version 或 label)进行区分。由于 Langfuse 允许标签值为纯数字(正则 /^[a-z0-9_\-\.]+$/),当版本号 N 与标签值 “N” 相同时,两者共享同一个 Redis 键,导致首次请求确定缓存内容后,后续请求返回错误的 Prompt 版本。

环境排查

  • 确认是否启用了 Prompt 缓存:检查环境变量 LANGFUSE_CACHE_PROMPT_ENABLED,未设置或设为 true 即受影响。
  • 确认是否使用 Redis 作为缓存后端(v3 部署标准配置)。
  • 确认项目中是否存在同一 Prompt 名称下,某个版本号 N 同时存在于其他版本的自定义标签中(例如:版本 3 存在,同时其他版本有标签 “3”)。
  • 检查 packages/shared/src/server/services/PromptService/index.tsgetCacheKey 函数的实现。

解决步骤

  1. 修改缓存键生成逻辑:在 getCacheKey 函数中,将 version 和 label 分别添加类型前缀,例如 version:${params.version}label:${params.label},以避免命名空间碰撞。这是官方确认的修复方案,可优先尝试。
  2. 无需迁移旧缓存:由于 PR #12363 引入了 epoch 失效机制,旧的缓存键会在 TTL 到期后自然过期,不需要手动刷新或迁移。
  3. 添加回归测试:建议新增测试用例,验证 version=Nlabel="N" 返回不同的缓存键和不同的 Prompt 内容。

验证方法

在修复后,重复复现步骤:创建同名 Prompt,版本 3 内容为 A,版本 7 添加标签 “3” 且内容为 B。先请求 ?version=3 应返回 A,再请求 ?label=3 应返回 B(而不是缓存中的 A)。对称验证先请求标签,再请求版本,两者返回均正确即表示修复生效。

参考来源

langfuse/langfuse #14788

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

celebrityanime
celebrityanime
文章: 13204

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注