V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
461229187
V2EX  ›  程序员

居然只用 20 多行代码就可以实现微信聊天机器人

  •  1
     
  •   461229187 · 289 天前 · 9636 次点击
    这是一个创建于 289 天前的主题,其中的信息可能已经有所发展或是发生改变。

    用了一年多 chatGPT 和白嫖了 vscode 的 copilot ,现在感觉已经离不开了,所以也想把这么好用的东西推荐给自己的家人和朋友。但是由于网络的限制,想让他们体验到聊天机器人的神奇是很困难的。当然现在百度阿里等巨头都已经发布了他们的产品,但需要下载相应的 app ,还要登录等一些列操作,稍微繁琐一点都会让他们失去兴趣。所以我打算开发一个微信聊天机器人,他们只需要加微信好友即可体验到。

    在编写代码前,先要对以下几个东西做一些了解,简单且好用。

    GPT API

    在国内访问 chatGPT 是比较麻烦的,搞不好还容易封号。所以这里我推荐一下国内可用的一个接口,GPT-API-free,看名字就知道这是个免费的,虽然免费,但是有调用频率的限制,60 请求/小时/IP&Key ,可以通过 github 领取。理论上自己用的话免费的就可以,如果想调用 GPT4 ,每天也可以使用 3 次。

    如果你访问频率高,可以购买付费服务,如果 gpt3.5 的话,我预测 30 块用一年应该没什么问题,GPT4 的话就比较贵了。

    wechaty

    Wechaty 是一款用于构建聊天机器人的开源程序,他运行于 node(v16+) 环境,它提供了几乎微信所有操作接口,例如登录、接发消息、好友操作、备注、群组等等,这样我们就可以通过 Wechaty + GPT API 的组合实现微信聊天机器人了。

    对了,你最好再申请个微信号,不然封号就得不偿失了。我已经用了半个多月,没被封号。

    需要注意的是还需要了解一个库配合 wechaty 实现在命令行中扫码登录微信,qrcode-terminal ,他用法非常简单,无需去看文档。

    代码实现

    由于功能很简单,我也懒得去搞部署之类的东西,所以我直接在服务器上写的代码...

    安装依赖

    首先创建一个 node 项目,npm init

    安装依赖:

    npm install wechaty qrcode-terminal axios
    

    代码不多,创建一个 index.js 即可,首先引入即将使用到的方法,并创建聊天机器人示例:

    import axios from 'axios';
    import { ScanStatus, WechatyBuilder, log } from 'wechaty'
    import qrcodeTerminal from 'qrcode-terminal'
    
    const bot = WechatyBuilder.build({
      name: 'codexu-chat-bot', // 名字随意
    })
    
    const sk = '' // 顺便把接口 sk 定义上
    
    bot.start();
    

    如果你将代码放在 git 仓库,建议创建环境变量等方式去获取 sk ,保证安全,不要泄漏。

    扫码登录

    随后先实现扫码登录功能,bot 实例提供了很多事件监听,这里我们监听 scan 事件,它提供了两个参数,二维码和状态,这里我们需要对二维码做一下转换,并通过 qrcodeTerminal 将二维码展示在命令行中。

    function onScan(qrcode, status) {
      if (status === ScanStatus.Waiting || status === ScanStatus.Timeout) {
        const qrcodeImageUrl = [
          'https://wechaty.js.org/qrcode/',
          encodeURIComponent(qrcode),
        ].join('')
        log.info('StarterBot', 'onScan: %s(%s) - %s', ScanStatus[status], status, qrcodeImageUrl)
    
        qrcodeTerminal.generate(qrcode, { small: true })  // show qrcode on console
    
      } else {
        log.info('StarterBot', 'onScan: %s(%s)', ScanStatus[status], status)
      }
    }
    
    bot.on('scan', onScan)
    

    与登录相关的,bot.on 还可以监听到 loginlogout 事件,请自行添加。

    处理聊天信息

    然后就是关键的处理聊天消息,这里我使用 axios 去调用接口,需要在 header 中传入 sk ,并按照接口文档传递模型和消息记录:

    async function onMessage(msg) {
      const text = msg.text()
      let cacheMessagesItem = cacheMessages.find(item => item.name === talker.name);
      const message = {
        role: "user",
        content: text
      }
      const data = {
        model: 'gpt-3.5-turbo-1106',
        messages: [message]
      }
      const result = await axios.post(`https://api.chatanywhere.com.cn/v1/chat/completions`, data, {
        headers: {
          Authorization: `Bearer ${sk}`,
          'Content-Type': 'application/json'
        }
      })
      const resultContent = result.data.choices[0].message.content;
    
      await msg.say(resultContent)
    }
    
    bot.on('message', onMessage)
    

    然后通过 node index.js 运行即可,如果在服务器上推荐使用 pm2 去管理程序,不然报错可能就停止了。

    至此就已经实现了微信聊天机器人的基本功能,快去体验一下吧。

    优化

    通过 20 多行代码就实现了聊天机器人是不是很简单,但是它现在还傻傻的不太好用,我们可以对他进行一些优化。

    机器人人设

    当我把它介绍给亲人朋友时,神奇的是他们都会问这么几个问题:

    • 你是谁?
    • 你认识李旭吗?(我本人)

    但是 chatGPT 只能傻傻的回答他是什么语言大模型之类的,毫无新意,这样的话我们可以为他建立人设。

    image.png

    image.png

    可以看到调用 GPT 接口时,messages 参数是一个数组,它是连续聊天的关键,也就是说你把聊天记录都传进来,这样 GPT 就可以在回答时参考上下文来回答。

    所以我们只需要在每次调用接口时,告诉 GPT 它要去扮演李旭的机器人这个角色,并告诉他我是谁就可以了。

    const message = {
      role: "user",
      content: `本次对话你扮演的是李旭的机器人的角色,是微信的聊天助手,你的微信名是李旭的机器人,李旭是一个非常帅的人并且有才华的人,今年 18 岁。`
    }
    

    同理,如果你想实现连续聊天,把聊天记录传到 messages 中即可,当然调用接口是按照字数收费,并且数据有最大限制,所以我们尽量传 10 条以内的聊天记录也就够了,这里大家自行实现列队功能吧。

    自动添加好友

    当我把机器人名片推给别人时,还需要手动去微信添加好友,这就很麻烦了,尤其是朋友再推给其他人时,还需要让我去同意添加,这样比较麻烦。

    幸运的是 wechaty 还提供了对添加好友的操作。

    bot.on('friendship', async friendship => {
      try {
        switch (friendship.type()) {
          case 2:
            await friendship.accept()
            break
        }
      } catch (e) {
        console.error(e)
      }
    })
    

    这样我们就实现了自动添加好友的功能。

    其他

    我目前可以想到的:

    • 年龄大的人比较爱发语音,并且眼神不好,语音的体验方式更适合,可以借助转录将语音转成文字,再将结果文字转换成语音发送给使用者。
    • GPT4 接口较贵,所以默认使用 GPT3 即可,加入判断,在聊天文字前输入 GPT4 ,再去调用 GPT4 模型,这样可以根据需要使用不同模型。
    • 可以做一些画图的功能或识别图像的功能。

    总结

    当我产生了做这个机器人的想法到实现,我都没有想到居然如此简单,看似复杂的功能,已经被 wechaty 做成了非常简单的操作。

    另外其他人在使用的时候,你是可以看到他们的聊天记录的,我建议你应该告诉使用者你可以看到他们的消息。

    我没跟我妈说能看到他的问题,我看到她在问失眠怎么办?哎...

    第 1 条附言  ·  289 天前
    记录一下,备用机几天没充电了,发现服务器掉了,报错
    Error: 状态同步超过 297.966s 未响应,5s 后尝试重启
    所以这个微信机器人还得长期手机端在线才行...
    45 条回复    2024-02-23 10:32:41 +08:00
    TenProX
        1
    TenProX  
       289 天前 via iPhone
    支持大佬的作品!膜拜!
    sekiseki
        2
    sekiseki  
       289 天前
    wechaty 两年前已经看过了,但是要扫码。还有更方便的。
    winglight2016
        3
    winglight2016  
       289 天前
    感谢大佬无私分享!

    我之前也考虑做个类似的小工具,但是发现 github 上的几个微信库都非常陈旧,包括这个 wechaty ,lz 确定能兼容最新版的微信吗?
    461229187
        4
    461229187  
    OP
       289 天前
    @sekiseki 还有高手?叫什么我去研究一下
    461229187
        5
    461229187  
    OP
       289 天前
    @winglight2016 没深入研究,反正目前我这点功能足够用了,运行正常
    mybro
        6
    mybro  
       289 天前
    敢用 wechaty 的都是勇士😄
    461229187
        7
    461229187  
    OP
       289 天前
    @mybro 所以到底还有什么代替品😂
    heider
        8
    heider  
       289 天前
    这个连续聊天的实现太傻了。。。
    lingeo
        9
    lingeo  
       289 天前
    微信机器人还推荐[wcferry]( https://github.com/lich0821/WeChatFerry.git),目前已经已经支持到 3.9.2.23 ,作者人很好。
    461229187
        11
    461229187  
    OP
       289 天前
    @heider 我问了 GPT_API_free 客服,让我这么搞的,确实有点浪费,还有更好方式嘛?
    461229187
        12
    461229187  
    OP
       289 天前
    @lingeo #9 🎉
    dabai0806
        13
    dabai0806  
       289 天前
    好像都没有提供发送微信语音的接口
    461229187
        14
    461229187  
    OP
       289 天前
    @dabai0806 只能发文本和文件,但是接收是可以语音的
    a86356
        15
    a86356  
       289 天前
    这个不是一个 token 每个月 200 的那个吗? ipad 登录协议
    okura
        16
    okura  
       289 天前 via Android
    这个我之前试过,好像对微信号有要求的
    461229187
        17
    461229187  
    OP
       289 天前
    @okura 我办了个副卡,目前就加了 10 个人左右,暂时没啥问题
    zhusimaji
        18
    zhusimaji  
       289 天前
    很危险,吃枣药丸
    461229187
        19
    461229187  
    OP
       289 天前
    @zhusimaji 手机号花了 10 块,问题不大😂
    opengps
        20
    opengps  
       289 天前
    同意添加好友哪里,你完全可以设置成不需要经过你同意,而不用开发一套功能出来
    461229187
        21
    461229187  
    OP
       289 天前
    @opengps 凑字数,这样也可以更灵活,比如加个校验什么的,可以避免谁都可以加
    Alias4ck
        22
    Alias4ck  
       289 天前
    微信机器人很危险 很容易被封号
    gniviliving
        23
    gniviliving  
       289 天前
    @lingeo #10 这个只支持 windows 版本,而且微信版本也限制在 3.9.2.29 及以下
    chairuosen
        24
    chairuosen  
       289 天前
    好了,知道你叫李旭了
    461229187
        25
    461229187  
    OP
       289 天前   ❤️ 3
    @chairuosen 叫李旭的很多,如果你见到一个很帅的,那就是我了
    rick2c
        26
    rick2c  
       289 天前
    难道只有我觉得很好用么,自己随便接了一个给小作坊做[微信群通知]( https://github.com/c-rick/nestjs-wechaty)方便还免费
    AsherTan
        27
    AsherTan  
       289 天前
    @mybro 咋说?有漏洞吗?
    abersheeran
        28
    abersheeran  
       289 天前
    所以为啥不直接用个人的微信公众号,除了不能在群里直接艾特使用之外,好像也没有少别的功能,而且更稳定,无需扫码登录或者担心微信给你干掉了。
    yufeng0681
        29
    yufeng0681  
       289 天前
    正好在看一本书《我们为什么要睡觉》 ,里面提到 安眠药的本质是镇定脑部某区域, 不能让人进入深度睡眠,人无法进入到恢复模式。最后身体只会越来越差。
    要想解决失眠问题,不能依赖安眠药
    cat9life
        30
    cat9life  
       289 天前
    wechaty 走的是 web 协议吗?不支持网页版微信的可以使用吗
    lingeo
        31
    lingeo  
       289 天前
    @Alias4ck 导致封号的原因是机器人行为,并不是破解了什么。
    spediacn
        32
    spediacn  
       289 天前 via iPhone
    的确,敢用 wechaty 的都是勇士
    hellojay
        33
    hellojay  
       289 天前
    wechaty 的 padlocal 还是可以的,就是要收费每个月 200 。我用了好几年了没什么问题
    rekulas
        34
    rekulas  
       289 天前
    我没记错的话 wechaty 免费版只能用老号登录 web 协议吧? 免费机器人那么多为何要推荐一个收费的
    Alias4ck
        35
    Alias4ck  
       289 天前
    @lingeo 我说的就是这啊,微信生态就这样啊 所以慎用微信机器人我也没说破解吧
    izjing666
        36
    izjing666  
       289 天前
    web 协议是怎么解决一直掉线的问题?
    coderpwh
        37
    coderpwh  
       289 天前
    我是自己写了一个 xposed 的微信机器人,备用机挂着就好
    nunterr
        38
    nunterr  
       289 天前
    挺好的东西,主要是用起来被微信封的概率太高,以至于不敢用😄
    v9JOFrNzq9Q9jyox
        39
    v9JOFrNzq9Q9jyox  
       289 天前
    感谢无私分享!
    HanSonJ
        40
    HanSonJ  
       289 天前
    461229187
        41
    461229187  
    OP
       289 天前
    @nunterr 千万别用大号
    wzdsfl
        42
    wzdsfl  
       289 天前
    作为使用 wechaty 一年+的过来人,我总结经验如下:
    1 、OP 给出的 wechaty 是基于 web 协议的,虽然可以加上 uos 来绕过微信 web 协议的阻拦,但是仍存在 [!较大!] 封号可能,并且存在一些问题:获取不到 wxid ,缺少一些 API (半年警告封号 2 次)
    2 、进阶:使用其他 provider ,如 padLocal 之类,个人如果有限制机器(win),可以用 https://github.com/wechaty/puppet-xp ,可以跑本地微信机器人,原理是利用 Hook 进行消息拦截和内存 call ,一般不会封号(稳定使用 1 年+)
    3 、再进阶:绕过框架,直接使用 dll 进行 hook 。好处是可以自定义框架,存在更高自由度,缺点是不同版本微信存在不同的功能,并且有的会收费。

    目前我在使用 https://github.com/ttttupup/wxhelper/tree/dev-3.9.5.81 进行类 wechaty 封装,并且项目开源免费,有使用需求的朋友可以关注这个项目
    RockShake
        43
    RockShake  
       289 天前
    疫情期间用了这个 API 提醒群成员打卡,收集核酸情况,封了两个人的 Web 微信
    461229187
        44
    461229187  
    OP
       289 天前
    @wzdsfl 感谢大佬指点
    winglight2016
        45
    winglight2016  
       267 天前
    @461229187 #5 我试了一下 wechaty ,先用 docker 版,失败在扫描登录后 regular 代码出错,然后直接下载 wechaty/get-started 仓库运行,很奇怪的是,这次就没有二维码扫了

    lz 能不能介绍一下最基本的运行环境,可以扫描登录成功就行,谢谢🙇🏻
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2844 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 13:00 · PVG 21:00 · LAX 05:00 · JFK 08:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.