QA机器人搭建

停更提示:该文章尚未完成,项目因故搁置,择期重启,谢谢!

本文使用 NoneBot2 搭建了一个 QQ 机器人,并为其加入 QA 功能。

准备工作

  1. 下载go-cqhttp

    go-cqhttp releases

  2. 创建新 Python 环境

    1
    conda create --name nb python=3.8

    之后输入y确认创建新环境。执行完毕后如下:

    conda create

    之后切换至创建好的环境:

    1
    conda activate nb
  3. 安装nb脚手架

    1
    pip install nb-cli

    安装nb脚手架

安装NoneBot机器人

配置 go-cqhttp 以登录 QQ

直接打开下载好的go-cqhttp_windows_amd64.exe,和之前一样直接打开会有提示;若通过命令行则没有。

直接打开提示

直接打开也挺好,点击几次确定(截图没截到)后会自动生成go-cqhttp.bat,通过命令行打开的话还没有,内容如下:

1
2
%Created by go-cqhttp. DO NOT EDIT ME!%
start cmd /K "go-cqhttp.exe"

点击生成的go-cqhttp.bat后会打开go-cqhttp.exe,非常方便。第一次打开选择反向WebSocket(输入3)后回车。

首次打开go-cqhttp

关闭当前命令行窗口。修改config.ymlaccount内的uinpassword(约第 4、5 行);修改servers.ws-reverse.universal(约第 98 行)为ws://127.0.0.1:8765/onebot/v11/ws,端口号不得冲突。点击go-cqhttp.bat打开go-cqhttp,之后按提示登录。

登录成功

出现上图即视为登录成功,黄字警告暂时不管,将该命令行窗口最小化。

新建 NoneBot2 项目

在准备工作(2)(3)的基础上,使用nb-cli新建NoneBot项目。在准备工作(3)的命令行窗口中输入:

1
nb create

脚手架nb-cli中自带适配器nonebot-adapter-onebot
之后让你填写项目名。此处以“chatbot”为例。之后会要求选择存储 Bot 的路径,此处我选择第一项,所以直接敲击enter键。若要选择第二项,使用选中选项后敲击enter键。

nbc2

之后选择添加echo方便后续调试。注意这里英文提示发生了改变:使用移动,使用space选中选项,使用enter键确认选项。相比上一步,你需要额外使用空格键来选中选项;不过,这里也可以使用鼠标左键选中。

nbc3

选平台(适配器adapter)没想到 V12 已经出了但我还是选择了 V11 怕文档不全社区不活跃不利于后续添加聊天功能。

nb5

之后会自动安装,等待安装结束即可:

nb6

nb7

配置 NoneBot2 项目以启动 Bot

正如上一步所配置的,NoneBot2 在chatbot目录中。所以我们进入chatbot目录对 NoneBot2 项目进行进一步配置。

1
cd ./chatbot

修改其中的env.dev中的PORT,使之与go-cqhttpconfig.ymlservers.ws-reverse.universal(约第 98 行)ws://127.0.0.1:{{PORT}}/onebot/v11/ws处的内容对应:

1
2
3
4
HOST=127.0.0.1
PORT=8654 # 修改这一项
LOG_LEVEL=DEBUG
FASTAPI_RELOAD=true

执行以下命令运行 nonebot2:

1
nb run

8

运行成功后go-cqhttp.exe的警告也会消失:

9

此时,你若向机器人输入/echo 123就能收到机器人的 echo:

QQ聊天测试

则机器人成功搭建。

添加 QA 功能

停更提示:该文章尚未完成,项目因故搁置,择期重启,谢谢!

通过如下步骤添加 QA 功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from nonebot import on_message                        # 导入必要的包

def get_answer(msg):
return QA_model.predict(msg)

def should_answer(msg):
return should_answer_model.predict(msg)

async def message_checker(event: Event) -> bool: # 创建匹配规则
return event.is_tome() or should_answer(event.get_plaintext())

matcher = on_message(rule=message_checker) # 1.1 定义事件响应器并注册匹配规则

# @matcher.handle()
# async def _(bot: Bot, event: GroupMessageEvent):
# await matcher.send("群聊消息事件响应成功!")


# @matcher.handle()
# async def _(bot: Bot, event: PrivateMessageEvent):
# answer_text = get_answer(event.get_plaintext())
# await matcher.send(answer_text)

@matcher.handle() # 使用`matcher`响应器的`handle`装饰器装饰函数
async def handle_func(msg: str = EventPlainText()): # `EventPlainText`用于获取当前事件的消息纯文本部分
answer_text = get_answer(msg) # 在`handle_func`中编写逻辑
await matcher.finish(answer_text)

避坑指南

  • 新建 NoneBot2 项目时无法选中适配器

    nb5

    请严格按照提示操作,不要忘记按空格键选中

  • 端口号被占用

    • 更换端口。
      go-cqhttpconfig.ymlservers.ws-reverse.universal(约第 98 行)ws://127.0.0.1:{{PORT}}/onebot/v11/ws和 NoneBotenv.dev 内的两处端口号,换成一个不被占用的。更换后记得重启 NoneBot。
    • 终结占用端口的程序。可以使用任务管理器与资源监视器来实现,也可以按如下步骤实现。
      1. 查看系统当前所有的端口使用情况

        1
        netstat -ano |findstr "端口号"
        1
        2
        3
        C:\Users\admin>netstat -ano | findstr "8080"
        TCP 0.0.0.0:8080 0.0.0.0:0 LISTENING 10180
        TCP 192.168.1.104:1887 1**.1**.2**.2**:8080 ESTABLISHED 9696

        这里,输出的内容即为:

        协议 本地地址 外部地址 状态 PID
        TCP 0.0.0.0:8080 0.0.0.0:0 LISTENING 10180
        TCP 192.168.1.104:1887 1**.1**.2**.2**:8080 ESTABLISHED 9696
      2. 根据PID查找占用的进程:

        1
        tasklist |findstr "进程id号"
        1
        2
        C:\Users\admin>tasklist |findstr "10180"
        ApplicationWebServer.exe 10180 Services 0 15,284 K

        同理,输出的意思是:

        映像名称 PID 会话名 会话# 内存使用
        ApplicationWebServer.exe 10180 Services 0 15,284 K
      3. 最后,根据进程的名称杀掉进程:

        1
        taskkill /f /t /im "进程id或者进程名称"

        执行完毕后仍可通过netstat -ano |findstr "端口号"查看端口号是否被占用。

有用的资源

停更提示:该文章尚未完成,项目因故搁置,择期重启,谢谢!