AI 机器人“Retry”在公开主题(非私信)中生成重复回复而非重新生成

严重程度

普通 —— 但在繁忙的公共话题中会造成严重干扰:重复点击“重试”会导致该话题被大量重复的机器人帖子淹没,因此对成员而言,看起来像是机器人在“自行发帖/陷入循环”。

平台

  • 服务器:Discourse 核心 main 分支(2026.7.x 系列),在最新的 origin/maindbf5eedac40,2026-07-14)上复现。discourse-ai 已集成在核心中。
  • 客户端:在多种浏览器/设备上复现(桌面版 Chrome、Android Chrome、iOS Safari)—— 由于问题出在服务器端,客户端无关紧要。

描述

实际结果:公共话题中,点击 AI 机器人回复上的重试按钮,会向话题追加一个全新的机器人帖子。原始回复保持不变,因此每次重试都会增加一个新帖子。N 次重试 → N 个额外帖子。

预期结果: 重试应就地重新生成现有的机器人回复(替换其内容),就像在 AI 机器人的私信/直接消息对话中那样。不应创建新帖子。

复现步骤(基于全新的 Discourse)

  1. 启用 Discourse AI + AI 机器人;创建/启用一个 AI **代理(角色)并关联一个机器人用户,开启“允许话题提及”**功能以便其能在公共话题中回答(allow_topic_mentions)。将你的用户组添加到代理的允许组以及 ai_bot_allowed_groups 中。
  2. 在一个公共话题中,在帖子中 @提及 机器人以触发其回复。
  3. 在机器人的回复上,打开帖子管理/扳手菜单,点击重试(重新生成操作 → POST /discourse-ai/ai-bot/post/:post_id/retry)。
  4. 观察: 会追加一个的机器人回复,而不是重新生成现有的回复。重复点击重试 → 每次增加一个额外帖子。
  5. 作为对比,在与机器人的私信中执行相同操作:重试会正确地就地重新生成(无重复)。私信与公共话题之间的这种差异即为关键线索。

在公共话题中 100% 复现。

根本原因(代码指针,当前 origin/main

  • BotController#retry_responseplugins/discourse-ai/app/controllers/discourse_ai/ai_bot/bot_controller.rb)将 Jobs::CreateAiReply 加入队列,并传入 reply_post_id: post.id —— 即“重新生成此现有帖子”。
  • Jobs::CreateAiReply 将其加载为 reply_post 并传递给 Playground#reply_to(..., existing_reply_post: reply_post)
  • Playground#reply_toplugins/discourse-ai/lib/ai_bot/playground.rb)中:
    • stream_reply = post.topic.private_message? if stream_reply.nil? → 对于公共话题结果为 false(约第 518 行)。
    • existing_reply_post 仅在 if stream_reply 分支内被使用(reply_post = existing_reply_post,约第 538 行)。
    • 非流式 else 分支(约第 662 行)无条件执行 PostCreator.create!(...),追加一个新帖子,且从未触及正在重试的帖子。

因此,对于任何非私信话题,retry_response 中“就地重新生成”的意图被静默丢弃,转而创建了重复帖子。(这种不对称性也意味着公共话题的机器人回复是非流式的,这是既有的行为;具体的 bug 在于重试路径上忽略了 existing_reply_post。)

建议的修复方案(仅方向)

无论是否流式,都应尊重 existing_reply_post —— 例如,在非流式分支中,如果存在 existing_reply_post,则对其进行 revise(修订)而不是调用 PostCreator.create!;或者将“复用现有帖子”的决策与 stream_reply 解耦。

安全模式

不适用 —— 服务器端插件行为,与主题/站点 JS 无关。

1 个赞