把AI助理装进微信:文件传输助手变身私人DeepSeek完整教程

前面九篇都在讲"机器人怎么服务别人",这篇反过来讲一个服务自己的用法:把你手机里的「文件传输助手」变成一个 AI 助手入口。

用起来是这样:你在文件传输助手里发一句「帮我把这段话改得正式一点」,几秒后回复就出现在同一个对话框里。不用装 App、不用切软件——微信是你已经 24 小时在用的界面,AI 就长在这个界面里。

技术上有个有意思的反转:前面所有客服机器人都在过滤"自己发的消息"(避免机器人自己跟自己对话),而这一篇的核心恰恰是只处理自己发的消息。位置换一下,同一个回调体系就变成了私人助理。

微信侧基于托管 API 形态(HTTP 主动调用 + Webhook 回调),代码以 WTAPI 的接口为例;模型侧以 OpenAI 兼容的 /chat/completions 为例(DeepSeek 同构,改 base_url 与模型名即可),字段以各自官方文档为准。


在这里插入图片描述

一、思路反转:从"过滤本号消息"到"只处理本号消息"

普通客服机器人的过滤规则是:

if from_user == to_user:     # 自己发的消息,跳过
    continue

因为机器人要回复的是别人。但私人助理场景正好相反——你要的就是自己发出的消息:

场景触发条件回复目标
客服机器人别人发来(FromUserName ≠ 本号)发给那个客户
私人 AI 助理本号发出,且目标是文件传输助手发到文件传输助手

判断"本号发出"的依据在回调报文里有两个字段:消息体的 Data.FromUserName 与信封层的 Wxid(机器人自己的号)。先别急着写逻辑,第一步是确认字段值——不同环境的值可能有差异,用打印器看一眼最稳。


二、第一步:确认字段(5 分钟)

前面讲过回调的"裸打印器",这次派上正经用场:用手机在文件传输助手发一条消息,看打印出来的字段长什么样。

# probe.py —— 只打印,确认本号消息的字段特征
from flask import Flask, request

app = Flask(__name__)

@app.route("/callback", methods=["POST"])
def callback():
    msg = request.get_json(silent=True) or {}
    if msg.get("TypeName") == "AddMsg":
        d = msg.get("Data", {})
        print("Wxid       :", msg.get("Wxid"))                    # 本号 wxid
        print("FromUserName:", d.get("FromUserName", {}).get("string"))
        print("ToUserName :", d.get("ToUserName", {}).get("string"))
        print("MsgType    :", d.get("MsgType"))
        print("Content    :", d.get("Content", {}).get("string"))
    return "", 200

✅ 你要确认三件事:

  1. 在文件传输助手发消息时,FromUserName 是否等于 Wxid(也就是"本号发出");
  2. ToUserName 的值是不是 filehelper;
  3. MsgType 是否为 1(文本)。

印花确认之后,判定条件就写成这两个字段的组合。如果字段值与你预期不符,以打印结果为准调整——这是唯一可靠的依据。


三、私人助理最小实现

# my_ai.py —— 文件传输助手 = 私人 AI 助手
import json
import queue
import threading
import time
import requests
from flask import Flask, request

API_BASE = "https://wx.chuapi.com"
APP_ID   = "YOUR_APPID"
WX_HEADERS = {
    "X-finder-TOKEN": "YOUR_TOKEN",
    "Authorization": "Bearer YOUR_JWT",   # 部分环境需要
    "Content-Type": "application/json",
}

# 模型侧(OpenAI 兼容;换成 DeepSeek 只需改这两个值)
LLM_URL   = "https://api.openai.com/v1/chat/completions"
LLM_KEY   = "sk-你的Key"
LLM_MODEL = "gpt-4o-mini"                 # DeepSeek 填 deepseek-chat

SYSTEM_PROMPT = (
    "你是我的私人助理。回答简洁准确、说中文、不使用 Markdown 语法。"
    "需要列举时用「1. 2. 3.」这种纯文本编号。"
    "不确定的事直接说不确定,不要编造。"
)

# ---------- 单一会话上下文(文件传输助手只有我一个人)----------
SESSION = []
MAX_MESSAGES = 10                          # 保留最近 5 轮

def get_history():
    return SESSION[-MAX_MESSAGES:]

def push_history(role, content):
    global SESSION
    SESSION = (SESSION + [{"role": role, "content": content}])[-MAX_MESSAGES:]

# ---------- 发送:过长内容分段 ----------
def post_text(to_wxid, content):
    """官方发消息接口 postText,参数仅 appId/toWxid/content"""
    requests.post(f"{API_BASE}/finder/v2/api/message/postText",
        headers=WX_HEADERS,
        data=json.dumps({"appId": APP_ID, "toWxid": to_wxid, "content": content}),
        timeout=10)

def send_long(content, chunk=800):
    """示例分段长度;微信文本长度限制以客户端实际表现为准"""
    for i in range(0, len(content), chunk):
        post_text("filehelper", content[i:i + chunk])
        time.sleep(1.0)                    # 分段之间留间隔,避免触发频控

# ---------- 模型调用 ----------
def call_llm(messages):
    try:
        r = requests.post(LLM_URL,
            headers={"Authorization": f"Bearer {LLM_KEY}",
                     "Content-Type": "application/json"},
            json={"model": LLM_MODEL, "messages": messages,
                  "temperature": 0.5, "max_tokens": 800},
            timeout=(5, 30))
        d = r.json()
        return d["choices"][0]["message"]["content"], d.get("usage", {})
    except Exception as e:
        print("[LLM异常]", e)
        return None, {}

# ---------- 指令系统 ----------
ENABLED = {"on": True}                     # /off 可临时关掉,夜里不打扰

def handle_command(text):
    """返回直接可回的文本,或 None 表示不是指令"""
    if not text.startswith("/"):
        return None
    cmd = text[1:].strip().lower()
    if cmd == "off":
        ENABLED["on"] = False
        return "已关闭自动回复,发 /on 重新开启"
    if cmd == "on":
        ENABLED["on"] = True
        return "已开启自动回复"
    if cmd == "clear":
        global SESSION
        SESSION = []
        return "上下文已清空"
    return None

# ---------- 事件处理 ----------
def handle_self_message(my_wxid, to_user, text):
    text = text.strip()
    direct = handle_command(text)
    if direct is not None:
        post_text("filehelper", direct)
        return
    if not ENABLED["on"]:
        return
    msgs = [{"role": "system", "content": SYSTEM_PROMPT}] + \
           get_history() + [{"role": "user", "content": text}]
    reply, usage = call_llm(msgs)
    if not reply:
        post_text("filehelper", "调用失败,稍后再试")
        return
    send_long(reply)
    push_history("user", text)
    push_history("assistant", reply)
    print(f"[用量] {usage}")

# ---------- 回调接入 ----------
app = Flask(__name__)
_seen, task_queue = set(), queue.Queue()

def consumer():
    while True:
        msg = task_queue.get()
        d = msg.get("Data", {})
        if d.get("MsgType") != 1:
            continue
        from_user = d.get("FromUserName", {}).get("string", "")
        to_user   = d.get("ToUserName", {}).get("string", "")
        # 核心反转:只处理「本号发出」且目标为文件传输助手的消息
        if from_user != msg.get("Wxid") or to_user != "filehelper":
            continue
        handle_self_message(msg.get("Wxid"), to_user,
                            d.get("Content", {}).get("string", ""))

@app.route("/callback", methods=["POST"])
def callback():
    msg = request.get_json(silent=True) or {}
    if msg.get("TypeName") == "AddMsg":
        d = msg.get("Data", {})
        key = f"{msg.get('Appid')}:{d.get('NewMsgId')}"    # 官方去重键
        if key not in _seen:
            _seen.add(key)
            task_queue.put(msg)
    return "", 200                                          # 3 秒内必须返回

if __name__ == "__main__":
    threading.Thread(target=consumer, daemon=True).start()
    app.run(host="0.0.0.0", port=8080)

✅ 验证四步:

  1. 文件传输助手发「你好」→ 收到 AI 回复(基础通路 OK);
  2. 连问两句相关的(「给我三个方案名」→「第二个再解释一下」)→ 第二次能接上(上下文 OK);
  3. 发 /clear → 回「上下文已清空」,再问「第二个是什么」→ AI 表示不知道(清空生效);
  4. 发 /off 后再发普通问题 → 无回复(开关生效)。

四、几个真正好用的用法

跑通之后,这个通道的价值取决于你怎么用它。几个实测顺手的姿势:

用法输入示例为什么省事
文案打磨粘贴一段草稿 + 「改得正式一点,200 字内」微信里改文案不用切软件
长文摘要粘贴一篇长文 + 「提炼三条要点」手机上读长文效率翻倍
临时翻译「翻译成英文:…… 」不用开翻译 App
起名/起标题「给这个活动起 5 个标题」发散需求,AI 批量给
待办拆解「把这个目标拆成可执行步骤:……」把想法直接变清单

两个工程小技巧:

  • 前缀命名空间:所有指令以 / 开头(/on /off /clear),普通对话不带前缀。这样你自己回看记录时,一眼能分清"哪些是我问 AI 的、哪些是 AI 答的";
  • 上下文定期清空:不同话题之间习惯性发一次 /clear。否则上一条任务的内容会混进新问题的上下文,答案会被带偏——这是私人助理最常犯的体验问题。

五、为什么这个场景特别适合先拿它练手

对刚入门的人来说,这是风险最低、收益最快的一个练手项目:

维度说明
影响面只和自己对话,不对外发送,不存在骚扰他人或营销违规
技术点覆盖回调接入、去重、异步、多轮上下文、模型调用、指令系统——核心骨架全练到了
成本个人提问量小,token 消耗可控(每一次调用都会打印 usage)
复用这套代码把"客服回复"那一行换掉,就是一个客服机器人的雏形

先拿自己练手,确认整条链路稳定,再接真实业务——这是最省事的上线路径。

合规声明:本文场景为个人自用效率工具,仅与本账号的文件传输助手交互,不涉及对外发送。请勿将本方案改造成对外群发、营销骚扰或批量触达工具;个人微信自动化操作需遵守微信平台规则,涉及他人内容时注意个人信息保护。模型接口与微信接口的能力、参数与限制以各自官方文档实时内容为准。


Logo

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

更多推荐