上周老板甩给我一个需求:"做个微信机器人,能自动回消息那种。" 我第一反应是,这不就是接个AI模型的事吗?大模型这么火,调几个API不就完了。

结果闷头研究了一周才发现,我一开始就想错了方向。机器人能不能"智能",AI模型只是一方面,更关键的是底层的API能力够不够全。AI再聪明,接不到消息、发不出回复、维持不了上下文,那也就是个嘴皮子利索的摆设。

我把机器人需要的能力拆成四层,挨个对照 Eyun开发文档 看每层API能不能撑住。下面把这四层和我踩过的坑一起记下来,给同样在做机器人的朋友省点事。

第一层:消息接收——Webhook回调实时推送用户消息

机器人要回消息,先得能收到消息。这一层靠的是 Webhook 回调机制。

机制不复杂:在平台后台配一个回调URL,微信那边有新消息进来,平台就POST一段JSON到你这个URL。消息类型靠 msgType 字段区分,1是文本、3是图片、34是语音,每种类型对应字段不一样。

我第一版踩的坑:回调接口里直接跑业务逻辑,查数据库、调AI,一个请求三四秒,平台等不及判定超时,重推了三次,客户收到三条一样的回复被截图吐槽。后来改成收到消息先入队列,立刻返回 code=1000,业务处理全丢异步任务,才稳住。

还有个细节别忽略:平台是"至少推送一次",不是"只推一次"。每条消息有唯一的 msgId,必须用这个做幂等去重,不然网络波动一重推,你就重复处理。

第二层:消息处理——按msgType解析转成AI能消化的格式

消息收进来是原始JSON,AI处理不了,得先解析。

文本消息最简单,直接拿 content 字段丢给AI。图片麻烦点,回调里只有 fileId 和 aesKey,要调 downloadFile 接口把图片下载下来,再做OCR或者图像识别。语音更麻烦,微信用的是silk格式,得转成MP3再丢给语音识别模型。

我踩的坑:一开始以为所有消息都能直接处理,结果图片消息来了,回调里没图,只有个 fileId。折腾半天才搞明白要二次下载。建议对照文档先把每种 msgType 的回调字段和后续处理流程列清楚,别边写边猜。

这一层的核心就一句话:把微信的消息格式,翻译成AI能消化的输入。翻译不好,AI再强也白搭。

第三层:回复发送——sendText/sendImage支持多种回复形式

AI生成回复后,得发回给用户。这一层用的是发送接口。

最常用的是 sendText,发文本;要发商品图就调 sendImage;发操作教程用 sendVideo;电商场景发商品卡片还能调 sendApplets。请求体都是JSON,带上 wId(实例ID)、wcId(接收方wxid)、content 就能发。

我踩的坑有两个:

  • 回复秒发,被风控了。一秒回一条太像机器人,加了3-6秒随机延迟才稳。

  • 图片URL用了内网地址,接口返回成功但对方收不到图。平台服务器访问不到内网,换公网CDN才行。

这一层的要点是:回复形式要匹配场景。客服问价回文本就行,问商品详情就配张图,别啥都回一坨字。

第四层:会话管理——msgId唯一标识+消息记录维持多轮上下文

单轮问答简单,难的是多轮对话。用户说"那它多少钱",你得知道"它"指的是上一轮聊的那个商品。

这一层不靠单一接口,靠的是消息记录的持久化。每条消息有唯一 msgId,回调进来时把 fromUser、content、msgId、时间戳一起落库,AI处理时拉最近N条作为上下文。wcId 在这里反过来用——从哪个wxid来的消息,上下文就拉那个wxid的。

我踩的坑:上下文拉太长,token爆了。AI模型有上下文窗口限制,拉了20条历史丢进去,单条回复就要等五六秒。后来改成只拉最近5条,且只保留关键字段,延迟降到两秒内。

四层能力支撑表

层次

机器人需要的能力

Eyun API提供什么

关键字段/接口

消息接收

实时拿到用户消息

Webhook回调推送

msgType、msgId、fromUser

消息处理

按类型解析消息体

msgType区分+downloadFile下载资源

fileId、aesKey

回复发送

多种形式回复用户

sendText/sendImage/sendVideo/sendApplets

wId、wcId、content

会话管理

维持多轮对话上下文

msgId唯一标识+消息记录同步

fromUser、时间戳

这张表是我做完项目倒推出来的,四层缺一不可。少了接收层机器人是聋子,少了处理层是傻子,少了发送层是哑巴,少了会话层是金鱼——聊一句忘一句。

机器人核心处理流程代码

下面这段是四层串起来的核心流程,Python写的,能看清每层怎么衔接:

import redis, requests, time, random
from flask import Flask, request, jsonify

app = Flask(__name__)
r = redis.Redis(decode_responses=True)
BASE_URL = "https://api.eyunz.com"      # 以文档实际地址为准
HEADERS = {"Authorization": "Bearer eyk_your_auth", "Content-Type": "application/json"}
W_ID = "你的实例ID"                       # 一个 wId 对应一个登录的微信

def ai_reply(wxid, text):
    """调AI模型生成回复,这里省略AI调用细节"""
    history = r.lrange(f"ctx:{wxid}", 0, 4)   # 拉最近5条上下文
    # ... 把 history + text 丢给大模型 ...
    return "这是AI生成的回复"

@app.route("/webhook", methods=["POST"])
def webhook():
    data = request.json
    msg_id = data.get("msgId")
    # 第一层:接收+幂等去重
    if msg_id and not r.set(f"msg:{msg_id}", "1", nx=True, ex=600):
        return jsonify({"code": "1000"})
    from_user = data.get("fromUser")
    msg_type = data.get("messageType")
    # 第二层:按类型解析,这里只处理文本
    if msg_type != 1:
        return jsonify({"code": "1000"})
    text = data.get("content", "")
    # 第四层:落库上下文(第三层回复在AI里调)
    r.rpush(f"ctx:{from_user}", text)
    r.ltrim(f"ctx:{from_user}", -5, -1)       # 只留最近5条
    # 第三层:AI生成回复并发送
    reply = ai_reply(from_user, text)
    time.sleep(random.uniform(3, 6))          # 模拟人工节奏,防风控
    requests.post(f"{BASE_URL}/sendText",
        json={"wId": W_ID, "wcId": from_user, "content": reply},
        headers=HEADERS, timeout=10)
    r.rpush(f"ctx:{from_user}", reply)        # 回复也进上下文
    return jsonify({"code": "1000"})

四层在代码里都能对上:setnx做接收层幂等、messageType判断走处理层、sendText是发送层、Redis列表存上下文是会话层。异步处理我没写进去,实际项目里 ai_reply 和 sendText 要丢进Celery队列,webhook入口秒回,不然高并发扛不住。

写在最后

做完这个机器人我最大的感触是:AI是大脑,API是手脚。大脑再聪明,手脚不灵光也干不成事。Eyun 这套API把接收、处理、发送、会话四层都覆盖了,机器人该有的能力基本齐活,剩下的就是业务逻辑怎么接。

想看每个接口具体参数和回调字段定义的,直接翻 Eyun开发文档,比我这篇全多了。做机器人这事儿想清楚四层架构再动手,比闷头写代码省心得多。

Logo

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

更多推荐