前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
返回 AI 情报前线
All News · 全部资讯9915
  • Meta 新开放权重模型支持苹果芯片本地运行
  • 英伟达推出百万上下文开放多模态 Agent 模型
  • 用Claude Code做手机声波联机游戏
  • Google OAuth 支持刷新令牌密钥绑定
  • 将低频流程移入 Claude Code 按需技能
  • Copilot 多模型编排需累计计算调用费用
  • Gemini CLI 消费者登录退役带来的迁移提醒
  • 编码智能体自动放行配置可能成为攻击入口
  • 用事件钩子识别编码智能体何时等待操作
  • 并行编程 Agent 背后的 Git 工作树机制
  • Copilot 部分模型将于11月16日退役
  • NoteBank 用片段回放补强长上下文记忆
  • Meta 推出8160亿参数开放权重多模态模型
  • 两台 M5 Ultra Mac 可运行 Muse 开放模型
  • SageMaker 支持部署 Muse Spark Open
  • 谷歌 ADK 配方库贯通 Agent 开发部署
  • 为多轮 Agent 建立持续评估流水线
  • ctxtrim 压缩日志,节省编程上下文
  • 技能触发不准,先改好 description
  • AI 生成页面上线前,补验 GA4 事件链路
  • 让客服机器人把处理结果反馈到检索排序
  • Muse Spark Open 发布,主打编程与 Agent
  • FLUX 3 Klein 开放权重,8GB 显存可运行
  • Gemini 4 Argon 整合机器人控制与仿真
  • 英伟达开放多模态模型,面向企业智能体
  • Vercel 扩展后端与 Agent 部署能力
  • 英伟达发布面向智能体的多模态开放模型
  • 英伟达扩充智能体模型,覆盖云端与本地
  • 日合并超三万次,Anthropic 重构版本控制
  • CLiF 将智能体运行记录转为训练评测资产
  • GitHub 代码扫描智能体修复正式可用
  • Webhook 驱动 Agent 的可靠性要点
  • 用 TypeScript 为 Agent 补齐应用连接器
  • 177 项科研技能补齐智能体领域知识
  • 发现 AI 擅自决策:简单审查胜过复杂流水线
  • WhatsApp 智能体上线后的工程难题
  • Netflix 为编程智能体接入 IDE 代码分析引擎
  • PentAGI 用多智能体执行渗透测试
  • MCP 排错日志里的凭据泄露隐患
  • Jev新版加入图像输入与26.2万上下文
  • 微软用知识编译降低智能体延迟与耗量
  • Grok语音模型升级,接口与价格保持不变
  • 把 ClickUp 项目记录变成 Agent 可查询记忆
  • Matrix-Game 4.0 开源单卡实时生成游戏
  • Agent 接入外部服务前先检查失败恢复能力
  • 多模型网关踩坑:推理预算吃光了回答
  • Step 5 Preview 开放权重,可部署百万上下文
  • AI 工具写操作防重:执行前先抢占
  • 给 n8n 的模型输出加一道契约检查
  • 自托管 AI 工具漏洞公告可能漏过扫描
  • 本地运行 Gemma 4:推测解码与草稿模型
  • 已加载 51 / 9915
8.0
热点
AI SCORE
技术实践2026-10-16 01:15

让客服机器人把处理结果反馈到检索排序

dev.to · AI#检索增强#反馈闭环#Agent
Editor brief · 编辑速览

机器人反复给出错误建议,可能是因为后续处理结果没有关联到回答依据。文章建议记录每次调用使用的知识条目 ID,将用户或人工处理结果回写为评分,并让检索排序使用这些评分。

文章思维导图
Knowledge map
拖拽缩放
Full translation

完整中文译文

你的客服 bot 告诉客户,清除应用缓存就能解决同步错误。但这招没用。客户再次回复,团队里的一位同事找到了真正的解决办法:重新授权集成,然后关闭了工单。到了下周二,另一位客户报告了同样的错误,bot 又一次建议清除缓存,语气还是那么笃定。

简单来说:每次调用结束时,还没人知道它给出的建议是否有效,因此等反馈到来时,已经找不到可以关联的对象了。你需要为每次调用保留记录,记下生成答案时所依据的已存储笔记的 ID。等用户、工单系统或接手处理的同事给出结果判定后,把它作为评分回传给这些笔记,并让 bot 从会在排序时考虑评分的记忆中召回内容。这样到了下一次,无效的建议和有效的建议就不再处于同等地位。整个过程不会删除任何内容:失败的建议仍会保留,只是附上了它对应的结果。

为什么 bot 无法从自己的调用中学习

典型的自定义 bot,就是在模型调用外面包上一层检索:一个 system prompt、一次对帮助文章或已存储笔记的搜索,再加上用户的问题。上周那个答案最终有没有用,并不在这些输入里,而是在客户的回复和客服工单系统里。

团队通常会依次尝试三种修复方法。

修改 system prompt。加上一句「遇到同步错误时,不要建议清除缓存」。prompt 确实适合承载策略,但它的扩展能力和任何人工维护的文档一样:每出现一次糟糕的回答,就加上一条规则;没人清理,重要规则还得和过时规则争夺模型的注意力。

把答案和纠正内容存进记忆。这样,纠正内容就能在调用结束后保留下来,但清除缓存的建议也同样留了下来,而相似度搜索是按内容与问题的接近程度排序的。两条笔记都匹配,都会被召回,然后由模型在上下文里挑选一条。错误笔记即使已经失败了十次,它与问题的相似度也和一次都没失败时一样。

把结果关联到笔记上。当某次调用的结果确定后,就把它记录到影响了答案的那些笔记上。这样,失败的笔记带着失败记录,有效的笔记带着成功记录,考虑结果的召回机制就能区分二者。只有这种修复方法,才打通了从实际结果到下一次召回内容的反馈路径。

每次调用需要保留什么

答案是在调用过程中生成的,结果判定却是在调用结束后才到来,有时甚至要过几天,而且来自另一个进程。因此,每次调用都必须留下记录,让后来的判定能找到对应的对象:

调用记录:bot 为每次调用保留的信息,使之后到来的结果判定能够找到评价对象。记录包括问题、答案,以及生成答案时所依据的已存储笔记的 ID,并用一个结果判定也会携带的键来关联。

这些 ID 对应的是每条笔记,而不是整段对话。失败的是某一条建议,不是整场交流。如果模型能够指出自己依赖了哪些召回笔记,就保留这些笔记的 ID;否则,就保留 prompt 中所有笔记的 ID,并接受它们的评分会一起变化。

这个键必须是结果判定会携带的标识:比如工单 ID、讨论串 ID,或者你的反馈按钮已经在发送的 session ID。如果一个键对应多个答案,下面的代码会保留最新的那个。

把调用记录放在你自己的数据库里,与 bot 用于召回的笔记分开存储。如果写进同一个记忆库,每条记录下来的答案都会成为下一次召回的候选,错误答案也包括在内。

结果判定从哪里来

明确的评分很少见。其他处理结果往往已经记录在某个地方,把这些来源接入反馈流程,比一直等着用户点「踩」更有效。

其中两类情况需要谨慎处理。如果转交人工的原因本就超出了 bot 的职责范围,比如退款或客户情绪激动,那么转交这件事并不能说明建议是否有效。而最常见的情况——用户没有再回复——也不能算作结果判定。

第三类情况最关键。评分可以降低无效建议的排名,但只有笔记才能提供真正有效的建议,因此,人工找到的解决办法需要写进 bot 用于召回的记忆库。

评分会改变什么,又不会改变什么

评分无法改变已经给出的答案。它改变的是下一次召回返回内容的顺序。

保留失败的笔记,不要删除它。清除缓存在处理另一种错误时可能是正确的办法;而且,一旦删除笔记,就无法再回答「为什么 bot 在十月份让客户清除缓存」这个问题。

评分调整的是排名,而不是真伪。如果帮助文章本身有误,就去修正文章。这套反馈循环不依赖某个特定产品:让 bot 检查一份无效建议清单,也能近似实现;你自己维护的存储可以增加一个结果字段;托管的记忆层则可以代为维护这些记录。关键在于,要有一条从结果回到召回的路径。

一个最小代码实现

这里使用的是 mnemoverse 0.4.0,也就是 Mnemoverse(作者所在公司)的 Python SDK,并按照 Python SDK 页面上的说明完成配置。模型调用只是占位示例,调用记录存放在 SQLite 中。

import json
import sqlite3

from mnemoverse import MnemoClient

memory = MnemoClient()  # reads MNEMOVERSE_API_KEY
DOMAIN = "bot:support"
db = sqlite3.connect("calls.db")
db.execute("CREATE TABLE IF NOT EXISTS calls "
           "(call_id TEXT PRIMARY KEY, question TEXT, answer TEXT, used TEXT, concepts TEXT)")

def answer(call_id: str, question: str) -> str:
    recalled = memory.read(question, domain=DOMAIN, top_k=5)
    reply, relied_on = bot.reply(question, recalled.items)  # your model call
    used = [str(item.atom_id) for item in relied_on]
    db.execute("INSERT OR REPLACE INTO calls VALUES (?, ?, ?, ?, ?)",  # latest answer per key
               (call_id, question, reply, json.dumps(used), json.dumps(recalled.query_concepts)))
    db.commit()
    return reply

def on_verdict(call_id: str, outcome: float, fix: str | None = None) -> None:
    row = db.execute("SELECT question, used, concepts FROM calls WHERE call_id = ?",
                     (call_id,)).fetchone()
    if row is None:
        return  # no call record: the verdict has nowhere to land
    question, used, concepts = row[0], json.loads(row[1]), json.loads(row[2])
    if used:
        result = memory.feedback(atom_ids=used, outcome=outcome,  # -1.0 to +1.0
                                 query_concepts=concepts, domain=DOMAIN)
        print("updated:", result.updated_count)
    if fix:  # what actually worked, from the person who solved it
        note = memory.write(f"Problem: {question}\nWhat worked: {fix}", domain=DOMAIN)
        if not note.stored:
            print("Not stored:", note.reason)

on_verdict("ticket-1042", -1.0, fix="Re-authorise the integration under Settings, Connections.")
on_verdict("ticket-1043", 1.0)  # the customer confirmed it worked

feedback 使用的 domain 与 read 相同;SDK 页面指出,如果不提供这个参数,SDK 会发送 "general"。如果写入内容与同一 domain 中最接近的记忆过于相似,就不会存储,因此代码会检查 stored。

API 文档用一句话说明了它的作用:「评分会重新排列下一次返回的内容。」概览则说明了什么会保留:「feedback 改变的是下一次 read 的顺序,而不是已存储的文本。」运行在 MCP client 上的 bot 则通过 memory_feedback 工具进行评分。

用对照验证效果

先存入两组分别涉及不同问题的笔记,再通过 answer() 分别回答这两个问题,并检查两条调用记录没有共用任何 ID。打印每次调用所依赖笔记的 valence,也就是 API 参考文档中的 "Outcome polarity [-1, +1]",然后停止进程。

在一个新进程中,只对第一次调用提交负面判定。updated_count,也就是参考文档中的 "Number of atoms updated",应该等于该次调用记录的 ID 数量。如果为零,先检查 ID 和 domain。

再次读取这两个问题,并打印同一批笔记的 valence。需要观察的是:与第 1 步相比,第一次调用所用笔记的值是否向 -1 移动。

对照组:第二次调用没有收到任何判定,因此,它的笔记就是第 3 步的比较对象。如果第二次调用的笔记发生了变化,而第一次调用的没有,就检查结果判定关联到了哪个键。如果两组笔记的变化一致,那么第 3 步就无法证明判定产生了效果。

这个库的介绍页面也展示了同样的循环如何用于 coding agents,只不过那里的结果判定来自构建或测试运行,同时还更详细地讨论了结果记忆的局限。你的 bot 所给答案的结果判定,如今最终落在了哪里?

如果还想采取进一步措施,可以考虑屏蔽此人和/或举报滥用行为。

Original source

本文由 AI 翻译整理自 dev.to · AI,原文版权归原作者所有。

阅读英文原文
上一篇
AI 生成页面上线前,补验 GA4 事件链路
下一篇
Muse Spark Open 发布,主打编程与 Agent