当前位置: 首页 > news >正文

OpenClaw05_回声机制

OpenClaw05_回声机制

针对中文版本openClaw进行源码阅读,当前项目针对【回声机制防重】进行解读

文章目录

  • OpenClaw05_回声机制
  • 1-参考地址
  • 2-知识整理
  • 3-动手实操
    • 1-回声机制防重
    • 2-回声机制防重-理解
    • 场景:防止机器人重复发送相同消息
    • 代码示例演示
    • 控制台输出
    • 核心机制图解
    • 关键设计亮点
    • 实际应用场景


1-参考地址

  • github版本OpenClawCN
  • gitee版本OpenClawCN
  • mac进行openclaw卸载参考
  • openClaw源码拆解系列

2-知识整理

  • 1)OpenClaw源码-回声机制防重-源码
  • 2)OpenClaw源码-回声机制防重-理解

3-动手实操

1-回声机制防重

造这些词的人真的都是些神人,本来写一个会话防重大家都能理解,又造一个新词[回声EchoTracker]

export type EchoTracker = { // 记录文本并添加到去重集合,用于回声检测 // text: 要记录的文本内容,可为空字符串或 undefined // opts: 包含附加配置的选项对象 rememberText: ( text: string | undefined, opts: { // 可选的合并后消息体内容 combinedBody?: string; // 可选的与合并消息体关联的会话键 combinedBodySessionKey?: string; // 是否记录详细的调试日志 logVerboseMessage?: boolean; }, ) => void; // 判断给定的键是否存在于最近发送的记录中 has: (key: string) => boolean; // 从最近发送的记录中移除指定键 forget: (key: string) => void; // 根据提供的参数构建唯一标识符 buildCombinedKey: (params: { sessionKey: string; combinedBody: string }) => string; }; // 工厂函数:创建并初始化一个回声追踪器实例 // params: 配置参数对象 export function createEchoTracker(params: { // 最大允许的条目数量,默认为 100 maxItems?: number; // 可选的日志输出回调函数,用于详细信息的记录 logVerbose?: (msg: string) => void; }): EchoTracker { // 使用 Set 数据结构存储最近发送的文本键值,自动去重且保持顺序插入 const recentlySent = new Set<string>(); // 计算实际有效的最大容量,确保至少为 1 const maxItems = Math.max(1, params.maxItems ?? 100); // 内部辅助函数:构建唯一的组合键字符串 // p: 包含会话键和合并后的消息内容的参数对象 const buildCombinedKey = (p: { sessionKey: string; combinedBody: string }) => // 拼接为格式:combined:会话键:合并后的内容 `combined:${p.sessionKey}:${p.combinedBody}`; // 内部辅助函数:修剪集合大小,移除旧数据以符合容量限制 const trim = () => { // 当集合中的元素数量超过最大限制时,循环移除元素 while (recentlySent.size > maxItems) { // 获取迭代器中第一个元素的值(即最早添加的元素) const firstKey = recentlySent.values().next().value as string | undefined; // 如果没有找到键,则中断循环 if (!firstKey) break; // 从集合中删除该键 recentlySent.delete(firstKey); } }; // 实现 rememberText 方法的具体逻辑 const rememberText: EchoTracker["rememberText"] = (text, opts) => { // 如果文本为空,直接跳过记录 if (!text) return; // 将基础文本添加到记录集合中 recentlySent.add(text); // 如果同时提供了合并后的消息体和对应的会话键,则额外添加组合键 if (opts.combinedBody && opts.combinedBodySessionKey) { recentlySent.add( // 调用内部函数构建组合键并加入集合 buildCombinedKey({ sessionKey: opts.combinedBodySessionKey, combinedBody: opts.combinedBody, }), ); } // 如果开启了详细日志模式,则输出当前添加到检测集的信息 if (opts.logVerboseMessage) { params.logVerbose?.( // 输出日志:已添加到回声检测集(当前大小)+ 文本前 50 个字符 `Added to echo detection set (size now: ${recentlySent.size}): ${text.substring(0, 50)}...`, ); } // 执行修剪逻辑,确保内存占用受控 trim(); }; // 返回实现的 EchoTracker 接口对象 return { // 注册记忆文本的方法 rememberText, // 检查键存在性的方法 has: (key) => recentlySent.has(key), // 移除指定键的方法 forget: (key) => { recentlySent.delete(key); }, // 暴露构建组合键的能力 buildCombinedKey, }; }

2-回声机制防重-理解

场景:防止机器人重复发送相同消息

假设你开发了一个 AI 客服机器人,用户问"今天天气怎么样",机器人回复了答案。如果用户快速点击了两次发送按钮,或者网络抖动导致重试,机器人可能会重复发送完全相同的回复,造成糟糕的用户体验。

EchoTracker就是用来**检测并防止这种"回声"(重复发送)**的工具。


代码示例演示

import{createEchoTracker}from'./echoTracker';// 1. 创建追踪器:最多记 50 条,带调试日志consttracker=createEchoTracker({maxItems:50,logVerbose:(msg)=>console.log(`[EchoTracker]${msg}`)});// ========== 模拟机器人发送消息 ==========// 场景:机器人要发送一条回复constreplyText="今天北京晴天,气温15-22度,适合外出!";constsessionId="user_123_session";// 当前会话ID// 2. 发送前检查:这条消息最近发过吗?if(tracker.has(replyText)){console.log("⚠️ 检测到重复内容,跳过发送");}else{// 3. 记录这条消息(表示"我要发了")tracker.rememberText(replyText,{combinedBody:replyText,// 完整消息内容combinedBodySessionKey:sessionId,// 关联到具体会话logVerboseMessage:true// 记录详细日志});// 4. 实际发送消息...sendToUser(replyText);console.log("✅ 消息已发送并记录");}// ========== 模拟重复触发 ==========// 5. 假设用户快速双击,再次触发相同逻辑if(tracker.has(replyText)){console.log("⚠️ 检测到重复内容,跳过发送");// ← 这次会走进这里!}else{tracker.rememberText(replyText,{...});sendToUser(replyText);}// ========== 其他功能演示 ==========// 6. 使用组合键检测(用于更复杂的场景)constcomplexKey=tracker.buildCombinedKey({sessionKey:"user_123",combinedBody:"订单查询: #8848"});console.log(complexKey);// "combined:user_123:订单查询: #8848"// 7. 手动遗忘某条记录(比如用户要求"重新发送"时)tracker.forget(replyText);// 移除记录,允许再次发送

控制台输出

[EchoTracker] Added to echo detection set (size now: 1): 今天北京晴天,气温15-22度,适合外出!... ✅ 消息已发送并记录 ⚠️ 检测到重复内容,跳过发送 combined:user_123:订单查询: #8848

核心机制图解

用户点击发送 ──┐ │ ▼ ┌───────────────┐ │ 检查 has() │◄──────── 查 Set 中是否存在 │ 是否重复? │ └───────┬───────┘ │ ┌───────┴───────┐ ▼ ▼ 是(重复) 否(新消息) │ │ ▼ ▼ 跳过发送 rememberText() ──► 加入 Set 调用 trim() 维护容量 可选:输出调试日志

关键设计亮点

特性说明
自动去重Set数据结构天然去重,同一文本只存一份
LRU 淘汰超过maxItems时,自动删除最早的记录(不是随机删)
双键记录同时记录原始文本 +combined:会话ID:内容组合键,支持多维度查重
调试友好logVerbose回调让开发者能看到追踪器内部状态
手动干预forget()允许业务逻辑主动清除记录(如用户要求重发)

实际应用场景

  1. IM 机器人— 防止网络重试导致的重复消息
  2. Webhook 处理器— 避免重复处理相同的推送事件
  3. 消息队列消费— 幂等性保障,防止重复消费
  4. 表单提交防重— 快速双击提交按钮的保护

这个工具本质上是一个带容量控制的短期记忆缓存,专门用来回答"我最近有没有处理过这个?"这个问题。


http://www.jsqmd.com/news/503484/

相关文章:

  • Qwen3-VL-8B GPU利用率提升:从45%→89%的vLLM参数调优全过程
  • 告别磁盘爆满!用LVM动态扩展Docker存储空间的完整指南(/dev/sdb1案例)
  • SiameseUIE GPU加速部署教程:显存优化+Web服务自启,生产环境稳定运行指南
  • 如何手动下载并安装特定版本的transformers库(以v4.49.0-Gemma-3为例)
  • 拥抱未来:Kotlin Multiplatform 与鸿蒙应用开发深度解析与实践指南
  • WIFI国家码修改背后的秘密:高通平台Regulatory_BDF工具深度解析
  • 3个步骤教你用HomeKit集成实现智能家居控制
  • xManager实战指南:构建无广告音乐流媒体应用管理器的完整方案
  • charting_library_master.zip V31 下载
  • 单片机中断实战:用STM32 HAL库实现UART中断接收数据(附避坑指南)
  • 清华大学Timer模型实战:从数据清洗到预测的完整时间序列分析流程
  • Vue+ElementUI表单校验优化:精准清除校验提示的实战技巧
  • 广州高考复读学校避坑指南 - 妙妙水侠
  • 广州高考复读学校哪家正规?5大核心维度+10所正规院校深度解析 - 妙妙水侠
  • 可视化开发与网站构建:零基础建站者的响应式设计指南
  • NVMe SSD扇区大小与DMASM兼容性问题:read error in os_file_read_by_offset解析
  • P1546 [USACO3.1] 最短网络 Agri-Net
  • 微信版“小龙虾” QClaw 上线,Agent 正在从能力竞争走向入口竞争
  • 性能基准测试案例:系统容量规划的科学实践
  • Keil5开发环境模拟调用丹青识画系统API:嵌入式AI应用前瞻性实验
  • AI大模型训推一体机原生大模型解决方案:AI大模型训推一体机、应用场景与客户价值、典型案例
  • PX4飞控+NOKOV动捕系统实战:从零搭建无人机室内定位(附VRPN配置详解)
  • 2026年河北水利闸门启闭机标杆厂家最新推荐:机闸一体闸门、钢制闸门、平面闸门、拱形闸门、平板闸门、渠道闸门、河道闸门、新河县铄洋水利机械厂,水利工程设备新标杆 - 海棠依旧大
  • AI 辅助开发实战:基于思科毕业设计的网络配置自动化方案
  • python 通过操作鼠标定位来操作Windows软件模拟人工操作
  • 如何从零开始打造你的Stack-Chan?解锁JavaScript驱动机器人的创意无限指南
  • ESP32 OTA更新实战:PlatformIO+Arduino框架下的5分钟快速配置指南
  • 深入解析虚幻引擎多线程渲染的数据同步机制
  • 基于粒子群算法的配电网重构算法优化研究:降低有功网损,采用前推回代法及IEEE33节点标准模型...
  • 2026年3月优质的东莞线盘厂家选择指南:塑料线盘、电缆盘、周转线盘、高速线盘、胶盘、高速盘、高速线盘、一体式线盘、定制线盘OEM厂家 - 海棠依旧大