做微信机器人开发,常见的问题是:用户说"那第二个呢""帮我换一个",没有上下文机器人就懵了。让机器人具备连续对话能力,核心是解决 3 个上下文问题:记什么、怎么记、记多久。本文按上下文管理维度拆解这 3 个设计。

一、为什么连续对话需要上下文

单轮对话是"一问一答",用户每句话都能独立理解。但实际业务里,用户经常用代词、省略:"上一个呢""换一个""再查下"。这些请求脱离上下文就没法处理。Eyun 推送的消息事件里只有当前这条消息,不携带历史,所以上下文要业务系统自己管。

二、3 个上下文设计

1. 记什么

决定哪些信息需要存进上下文。

设计原则:存用户说的关键信息(意图 + 实体,如"查订单"意图 + orderId=123 实体)+ 存机器人回复的关键信息(回复了什么结果)+ 存对话阶段(当前在查订单/确认中/已完成)。不存无关闲聊(浪费存储)。

大白话:只记有用的——用户想干嘛、查了什么、聊到哪一步了,闲聊不记。

2. 怎么记

上下文的存储和检索方式。

存储设计:Redis Hash 按 wxid 做 key → field 存对话轮次 → 每轮存 {role, content, intent, timestamp}

检索设计:收到新消息时先查 Redis 取最近 N 轮 → 组装成对话历史 → 传给 AI/规则引擎做上下文理解。

Eyun API 的 Webhook 回调 JSON 中 fromUser(wxid) 是上下文检索的 key。按照 Eyun 开发文档 的规范,Webhook 回调含 fromUser 字段。如果需要更长历史,可调 Eyun 的消息记录接口拉取。

大白话:用 Redis 按用户存对话记录,用户一来就查他的"聊天记录本"翻到最近几轮,让 AI 看着历史回复。

3. 记多久

上下文的过期和清理策略。

过期设计:30 分钟无新消息 → 会话标记超时 → 上下文标记为"历史"不再用于当前对话 → Redis TTL 设 30 分钟自动清理。超时后用户再来视为新会话。

Eyun 的错误码体系中 1004 限频时不影响上下文存储,但 1002 Token 过期会导致 sendText 失败进而影响对话连续性——需保证 Token 始终有效。按照 Eyun 开发文档 的鉴权说明,Token 要定期刷新。

大白话:对话停了 30 分钟就认为"这轮聊完了",用户再来从头开始——像客服挂断后重新接入。

三、3 个设计对比

上下文维度

设计原则

技术实现

Eyun 接口

大白话说明

记什么

只存关键信息

意图+实体+阶段

Webhook 回调 fromUser

只记有用的

怎么记

按用户键控检索

Redis Hash 按 wxid

Webhook + 消息记录接口

翻聊天记录本

记多久

超时即清理

Redis TTL 30 分钟

30 分钟算聊完

四、上下文管理框架代码

class DialogContextManager:
    def __init__(self, redis_client):
        self.redis = redis_client
        self.ttl = 1800  # 30分钟

    def update_context(self, wxid, role, content, intent=None):
        # 记什么:只存关键信息,闲聊不记
        if is_small_talk(content):
            return
        turn = {"role": role, "content": content,
                "intent": intent, "ts": now()}
        # 怎么记:Redis Hash按wxid存轮次
        self.redis.hset(f"ctx:{wxid}", turn_id(), json.dumps(turn))
        self.redis.expire(f"ctx:{wxid}", self.ttl)  # 记多久:续TTL

    def get_context(self, wxid, n=5):
        # 取最近n轮组装对话历史
        turns = self.redis.hgetall(f"ctx:{wxid}")
        return sorted(turns.values(), key=lambda t: t["ts"])[-n:]

    def on_message(self, callback_json):
        wxid = callback_json["fromUser"]  # Eyun Webhook回调字段
        history = self.get_context(wxid)
        reply = ai_or_rule_reply(callback_json["content"], history)
        self.update_context(wxid, "user", callback_json["content"])
        self.update_context(wxid, "bot", reply)
        return reply  # 供sendText发送

五、落地建议

3 个设计让机器人从"一问一答"升级到"连续对话"——记什么决定上下文质量(只记有用信息)、怎么记决定检索效率(Redis Hash 按 wxid 键控)、记多久决定资源控制(30 分钟 TTL 自动清理)。有了上下文能力后,机器人就能理解"那第二个呢""帮我换一个"这类依赖上下文的请求。从趋势看,AI 大模型自带上下文窗口,但应用层仍需管理"哪些历史塞进窗口"和"会话超时"。Webhook 回调和消息记录接口的字段说明详见 Eyun 开发文档

实际落地时,N 轮的 N 建议取 5-8 轮(太少丢上下文,太多浪费 Token),TTL 按业务调整(客服场景可短至 10 分钟),闲聊过滤用规则或轻量分类器即可,不必上重模型。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐