之前一直有人在问:DeepSeek 这么强,能不能接进 QQ 机器人,让它像真人一样聊天?网上资料大多只教怎么调用 API,真正能做到“拟人化”和“概率回复”的完整教程很少。这篇文章就把整个流程拆开讲透,从一个空目录开始,到最终跑起一个会概率回复、会假装思考、会带一点人性化语气的 QQ 机器人。
文章面向有一定 Python 基础、但不熟悉 NoneBot2 和 OneBot 协议的开发者。学完之后,你能独立完成 DeepSeek API 接入、群聊/私聊消息监听、概率回复逻辑设计、上下文记忆管理,以及后续的部署和排错。
1. 背景与核心概念
1.1 这个项目到底能做什么
先想象一个场景:你在自己的 QQ 群里挂一个机器人账号,群聊里有人发了一句“今天的代码怎么又跑不起来了”,别的群友可能在等你的回复,而机器人会根据设定好的概率“考虑”要不要接话。如果接话,它会用 DeepSeek 生成一个口语化、简短、像真人口吻的回复,而不是冷冰冰地输出一段 Markdown 文档。
这是很多“聊天机器人群”里常见的效果,核心诉求有三点:
- 接入大模型:让回复内容更有智能感,而不是关键词匹配。
- 拟人化:语气自然、简短、有情绪起伏,不像客服。
- 概率回复:不是每条消息都回,而是按一定概率回复,模拟真人“潜水”和“偶尔冒泡”的状态。
本文实现的机器人就是围绕这三点展开。
1.2 关键词拆解:DeepSeek、拟人化聊天、概率回复
DeepSeek是一家国内 AI 公司提供的大模型服务,它的 API 兼容 OpenAI 的调用格式,所以你可以直接用openai这个 Python SDK 访问,不需要额外封装复杂的签名逻辑。官方目前常见模型标识包括deepseek-chat和deepseek-reasoner,前者适合日常对话,后者适合需要展示思考链路的推理场景。因为版本更新较快,具体模型标识以 DeepSeek 开放平台文档为准。
拟人化聊天并不是让模型“变成真人去骗人”,而是在限定角色和语气的前提下,让回复更接近日常聊天。比如“嗯嗯”“笑死”“确实”这类词,放在正式问答里不合适,但放在拟人化聊天里就很自然。
概率回复是机器人行为层面的设计。群聊中不是每一条消息都值得回复,也不是每一条消息模型都有必要处理。设定一个概率阈值(比如 35%),让机器人像真人一样“偶尔发言”,既能降低 API 成本,也能减少群聊刷屏带来的反感。
1.3 整体方案与效果预览
本文采用的技术路径是:
- 使用NoneBot2作为机器人框架。
- 使用OneBot V11协议与 QQ 协议端通信。
- 使用DeepSeek 官方 API生成对话内容。
- 在插件层实现概率回复、冷却时间、会话上下文、随机延时等逻辑。
最终目录结构大概是:
qq-deepseek-bot/ ├── .env ├── bot.py ├── pyproject.toml ├── requirements.txt └── plugins/ └── qq_chat.py我们先把最小可用版本跑通,再做进阶优化。
2. 方案设计与原理讲解
2.1 一条 QQ 消息如何走到大模型
要理解整个项目,先看一条消息的流转链路:
- 群友在 QQ 群发消息。
- QQ 协议端(负责连接 QQ 账号的应用)收到这条消息,并通过 OneBot 协议推送给 NoneBot2。
- NoneBot2 根据事件类型和插件注册规则,把消息交给对应的插件处理。
- 插件判断是否应该回复,如果触发概率条件,就调用 DeepSeek API。
- 模型生成回复文本。
- 插件通过协议端把回复消息发送到群聊。
这里的“QQ 协议端”在日常开发中通常指 go-cqhttp、NapCat、Lagrange.OneBot 这类开源实现。它们负责处理 QQ 登录、事件上报、消息发送等底层脏活,让上层框架可以专注于业务逻辑。
需要特别注意:QQ 机器人接入方式更新非常快,不同协议端的登录方式、配置方式差异也很大。本文不会把某个协议端的细节写成永久固定的步骤,而是给出通用接入思路。你在实际部署时,以你选择的协议端官方文档为准。
2.2 技术选型说明
为什么不直接用 go-cqhttp 写个回调脚本?因为后期维护成本高。NoneBot2 有成熟的插件机制、事件分发、会话状态管理,社区资料也丰富,更适合做“持续迭代”的机器人项目。
为什么不直接在 QQ 协议端里配置 AI 功能?因为协议端只负责消息收发,不负责业务逻辑。把业务逻辑独立到 NoneBot2 插件层,以后想换模型、改概率、加功能,都不需要动协议端配置。
2.3 概率回复的设计思路
概率回复听起来简单,就是一句random.random() < 0.35。但实际工程里要考虑几个问题:
- 被 @ 时必须回:有人在群里明确 @ 机器人,如果不回,体验很差。
- 私聊概率和群聊概率要分开:私聊通常更期待回复,群聊则要克制。
- 冷却时间:如果刚好连续两次随机到了回复,可能造成“刷屏”观感,所以要记录每个会话的最后回复时间。
- 空消息不处理:只有纯图片、表情、回复等没有文本内容的消息,直接忽略。
本文代码会把这些规则整合成should_reply()函数。
2.4 拟人化聊天的关键点
拟人化不能只靠一句 system prompt 解决。实际效果取决于三个层面:
- 角色设定:告诉模型“你是一个性格温和的中文网友”,而不是“你是一个智能助手”。
- 回复长度控制:真人聊天很少写几百字长文,设置
max_tokens=300,同时在 prompt 中强调“不要长篇大论”,基本能保证简短口语化。 - 回复节奏:真人打字需要时间。代码里根据回复长度生成 1 到 6 秒的随机延时,观感会自然很多。
这三点会在后面代码中逐一体现。
3. 环境准备与账号配置
3.1 运行环境清单
在开始之前,先确认本机环境:
- 操作系统:Windows 10/11、macOS、Linux 均可。
- Python 版本:3.10 或更高版本。
- QQ 协议端:任选一个还在持续维护的 OneBot V11 实现。
- DeepSeek 开放平台账号,并且已经创建 API Key。
版本说明:本文代码用到了 Python 3.10 的X | Y类型联合语法,如果你只有 Python 3.9,可以改成Union[X, Y]。
3.2 申请 DeepSeek API Key
登录 DeepSeek 开放平台,找到“API Keys”页面,创建一个新的 Key。创建后立刻复制保存,因为很多平台只在创建时展示一次。
调用地址和模型名如下:
- 基础地址:
https://api.deepseek.com - 对话模型:
deepseek-chat
如果你的代码要跑在服务器上,注意不要把 Key 提交到 Git 仓库。后面我们会统一放进.env文件。
3.3 初始化项目结构
创建一个项目目录:
mkdir qq-deepseek-bot cd qq-deepseek-bot然后创建以下文件结构:
qq-deepseek-bot/ ├── .env ├── bot.py ├── pyproject.toml ├── requirements.txt └── plugins/ └── __init__.py └── qq_chat.pyplugins/__init__.py可以是一个空文件,作用是让 Python 把plugins识别成包。
3.4 安装依赖
编写requirements.txt:
nonebot2>=2.3.0 nonebot-adapter-onebot>=2.4.0 openai>=1.40.0 python-dotenv>=1.0.0然后执行安装:
pip install -r requirements.txt如果你的本机同时存在多个 Python 版本,建议使用python3 -m venv .venv创建虚拟环境,避免依赖冲突。
3.5 启动并配置 QQ 协议端
这里以 OneBot V11 协议端为例。下载并启动你选择的 QQ 协议端程序后,一般需要配置以下内容:
- 反向 WebSocket 或正向 WebSocket 地址。
- 监听端口,例如
9001。 - 上报格式选择 OneBot V11。
如果你的协议端支持反向 WebSocket,可以让 NoneBot2 监听一个端口,协议端主动连接上来。这种方式最稳定,也是本文默认使用的连接方式。
协议端启动后,先不要急着跑机器人,我们要先保证 NoneBot2 这边能正常接收事件。
4. 核心代码实现
4.1 编写 .env 配置文件
.env文件保存机器人配置和 DeepSeek 配置,便于统一管理:
# NoneBot 配置 HOST=127.0.0.1 PORT=8080 SUPERUSERS=[] # DeepSeek 配置 DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxx DEEPSEEK_BASE_URL=https://api.deepseek.com DEEPSEEK_MODEL=deepseek-chat # 概率回复配置 REPLY_PROBABILITY_GROUP=0.35 REPLY_PROBABILITY_PRIVATE=0.75 REPLY_COOLDOWN_SECONDS=20 # 上下文与生成配置 MAX_HISTORY_LENGTH=12 MAX_TOKENS=300 BOT_PERSONALITY=你是一个性格温和、说话口语化的中文网友,聊天时语气自然,偶尔带一点幽默,不要长篇大论,不要输出Markdown语法。关键参数说明:
HOST/PORT:NoneBot2 服务监听地址。127.0.0.1表示只允许本机连接,如果你把协议端部署在另一台服务器,需要改成0.0.0.0并做好防火墙限制。REPLY_PROBABILITY_GROUP:群聊普通消息回复概率,0.35 表示约三分之一概率回复。REPLY_PROBABILITY_PRIVATE:私聊回复概率,可以设置高一些。REPLY_COOLDOWN_SECONDS:同一个群或同一个好友的回复冷却时间。BOT_PERSONALITY:拟人化角色设定,会作为 system prompt 传给模型。
注意:.env只是配置文件,默认情况下会被公开在代码仓库里吗?不一定,但建议把.gitignore加上.env,避免 Key 泄露。
4.2 编写 bot.py 入口文件
bot.py是 NoneBot2 的启动入口:
# 文件路径:bot.py import nonebot from nonebot.adapters.onebot.v11 import Adapter nonebot.init() driver = nonebot.get_driver() driver.register_adapter(Adapter) nonebot.load_builtin_plugins() nonebot.load_from_toml("pyproject.toml") if __name__ == "__main__": nonebot.run()nonebot.init()负责初始化框架配置,load_from_toml("pyproject.toml")会读取项目中的插件列表并加载。
4.3 编写 pyproject.toml 插件声明
在pyproject.toml里声明 NoneBot2 使用的适配器和插件:
[project] name = "qq-deepseek-bot" version = "0.1.0" description = "DeepSeek 拟人化聊天 QQ 机器人" requires-python = ">=3.10" [tool.nonebot] driver = "~fastapi+~httpx+~websockets" adapters = [ { name = "OneBot V11", module_name = "nonebot.adapters.onebot.v11" } ] plugins = ["plugins.qq_chat"]注意:plugins列表里的模块名要和你实际的插件文件路径对应。
4.4 编写 DeepSeek 客户端封装
先封装一个统一调用 DeepSeek 的模块。这里不需要单独建文件,直接在插件里封装函数即可,但为了后续复用,我更推荐拆成utils/deepseek_client.py。不过为了减少初始复杂度,本文直接写在插件里。
4.5 实现概率回复核心插件
这是整个教程最重要的部分。创建plugins/qq_chat.py:
# 文件路径:plugins/qq_chat.py import asyncio import os import random import time from collections import defaultdict, deque from typing import Deque, Dict, Union from dotenv import load_dotenv from nonebot import on_message from nonebot.adapters.onebot.v11 import ( Bot, GroupMessageEvent, Message, PrivateMessageEvent, ) from nonebot.log import logger from openai import AsyncOpenAI # ===== 读取配置 ===== load_dotenv() API_KEY = os.getenv("DEEPSEEK_API_KEY", "").strip() BASE_URL = os.getenv("DEEPSEEK_BASE_URL", "https://api.deepseek.com").strip() MODEL = os.getenv("DEEPSEEK_MODEL", "deepseek-chat").strip() REPLY_PROBABILITY_GROUP = float(os.getenv("REPLY_PROBABILITY_GROUP", "0.35")) REPLY_PROBABILITY_PRIVATE = float(os.getenv("REPLY_PROBABILITY_PRIVATE", "0.75")) REPLY_COOLDOWN_SECONDS = float(os.getenv("REPLY_COOLDOWN_SECONDS", "20")) MAX_HISTORY_LENGTH = int(os.getenv("MAX_HISTORY_LENGTH", "12")) MAX_TOKENS = int(os.getenv("MAX_TOKENS", "300")) PERSONALITY = os.getenv( "BOT_PERSONALITY", "你是一个性格温和、说话口语化的中文网友,聊天时语气自然,偶尔带一点幽默,不要长篇大论,不要输出Markdown语法。", ) if not API_KEY: logger.warning("未在 .env 中配置 DEEPSEEK_API_KEY,机器人将无法调用 DeepSeek") # ===== 初始化 OpenAI 客户端 ===== client = AsyncOpenAI(api_key=API_KEY or "sk-dummy", base_url=BASE_URL) # ===== 全局状态 ===== matcher = on_message(priority=10, block=False) # 记录每个会话最后一次回复时间 last_reply_time: Dict[str, float] = {} # 记录每个会话的最近聊天记录 session_history: Dict[str, Deque[dict]] = defaultdict( lambda: deque(maxlen=MAX_HISTORY_LENGTH) ) def should_reply(event: Union[GroupMessageEvent, PrivateMessageEvent]) -> bool: """判断当前消息是否应该回复。""" if isinstance(event, GroupMessageEvent): # 被 @ 时一定回复 if getattr(event, "to_me", False): return True # 群聊普通消息按概率回复 return random.random() < REPLY_PROBABILITY_GROUP # 私聊按概率回复 return random.random() < REPLY_PROBABILITY_PRIVATE def get_session_id(event: Union[GroupMessageEvent, PrivateMessageEvent]) -> str: """生成会话 ID,群聊按群 ID,私聊按用户 ID。""" if isinstance(event, GroupMessageEvent): return f"group_{event.group_id}" return f"private_{event.user_id}" def build_messages(session_id: str, user_content: str) -> list: """构建发送给 DeepSeek 的消息列表。""" history = session_history[session_id] messages = [{"role": "system", "content": PERSONALITY}] messages.extend(list(history)) messages.append({"role": "user", "content": user_content}) return messages async def ask_deepseek(messages: list) -> str: """调用 DeepSeek 对话接口,返回回复文本。""" resp = await client.chat.completions.create( model=MODEL, messages=messages, max_tokens=MAX_TOKENS, temperature=1.0, presence_penalty=0.2, frequency_penalty=0.3, stream=False, ) return resp.choices[0].message.content.strip() @matcher.handle() async def handle_chat( bot: Bot, event: Union[GroupMessageEvent, PrivateMessageEvent], ): # 只处理群聊和私聊 if event.message_type not in ("group", "private"): return # 概率回复判断 if not should_reply(event): return session_id = get_session_id(event) # 冷却时间判断 now = time.time() if now - last_reply_time.get(session_id, 0) < REPLY_COOLDOWN_SECONDS: return last_reply_time[session_id] = now # 提取纯文本内容 user_text = event.get_plaintext().strip() if not user_text: return # 构建消息并调用 DeepSeek messages = build_messages(session_id, user_text) try: reply = await ask_deepseek(messages) except Exception as exc: logger.opt(exception=exc).error("调用 DeepSeek 失败") return if not reply: return # 保存到当前会话上下文 session_history[session_id].append({"role": "user", "content": user_text}) session_history[session_id].append({"role": "assistant", "content": reply}) # 模拟真人打字延时 delay = min(6.0, 0.8 + len(reply) / 30 + random.uniform(0.3, 1.5)) await asyncio.sleep(delay) # 发送消息 await bot.send(event, Message(reply))代码拆开来看:
should_reply()实现了概率回复核心规则。get_session_id()区分不同群和不同好友的会话上下文。build_messages()把 system prompt 和聊天历史拼装成 API 需要的数据结构。ask_deepseek()使用AsyncOpenAI异步调用 DeepSeek,速度更快,也不会阻塞机器人其他事件。handle_chat()是事件处理入口,负责过滤消息、调用模型、保存上下文、模拟延时、发送回复。
4.6 运行机器人
确认协议端已经启动后,在项目根目录执行:
python bot.py启动后控制台一般会输出当前监听地址和插件加载信息。此时去 QQ 群里发一条消息,如果概率命中,机器人会回复;如果明确 @ 机器人,则一定回复。
首次运行最常见的现象是“机器人收不到群消息”,这种情况大概率是 QQ 协议端没有正确连接到 NoneBot2,或者.env中的HOST/PORT与协议端配置不一致。
5. 进阶优化:让聊天更像真人
5.1 人格设定与 System Prompt
拟人化的核心不是代码,而是 prompt。上面代码中的BOT_PERSONALITY是模板,实际使用时建议根据你的群氛围调整。例如:
BOT_PERSONALITY=你是一个喜欢打游戏、偶尔熬夜、说话带点逗比气质的大学生,线上聊天喜欢用短句和语气词,偶尔吐槽但不会骂人,不要输出Markdown语法,不要长篇大论。每次调用模型时,第一轮都会把这条 system prompt 发给模型。上下文历史越久,模型越容易保持人设,但 token 消耗也会增加,所以这里设置了MAX_HISTORY_LENGTH,超出的历史会自动丢弃。
5.2 随机延时与打字效果
代码里使用了:
delay = min(6.0, 0.8 + len(reply) / 30 + random.uniform(0.3, 1.5))这个表达式的作用是:回复越短,等待时间越短;回复越长,等待时间越长。同时加入随机数,让节奏不那么固定。
如果你希望更逼真,可以把“分句发送”也做进去:把回复按句子拆开,每发送一句等待一小段随机时间,效果更像真人打字。但要注意拆分逻辑,不要把一个完整的代码片段拆得乱七八糟。
5.3 群聊上下文与成本控制
默认情况下,每个群和每个好友都有独立的上下文,互不干扰。session_history字典的 key 是group_{group_id}和private_{user_id}。
大模型按 token 计费,随着聊天记录增长,每次请求携带的上下文会变长。deque(maxlen=MAX_HISTORY_LENGTH)会限制最多保存 12 条历史消息,超过后自动丢弃最早的消息,这是很常用的内存管理方式。
还有一些成本控制技巧:
- 把
max_tokens控制在 100 到 300 之间。 - 限制普通群聊的回复概率,比如从 0.35 降到 0.2。
- 如果群里讨论太密集,可以适当提高
REPLY_COOLDOWN_SECONDS。
5.4 多角色与多群配置
如果你的机器人同时服务多个群,但希望不同群有不同人设,可以把BOT_PERSONALITY从全局配置改成按群 ID 配置。例如:
PERSONALITY_MAP = { "group_123456": "你是程序员交流群的活跃成员,喜欢聊技术和硬件。", "group_888888": "你是游戏群的搞笑担当,经常发梗图。", }然后在build_messages()里改为:
personality = PERSONALITY_MAP.get(session_id, PERSONALITY)这样同一个机器人可以适配不同群聊氛围。
6. 常见问题与排查思路
6.1 高频报错汇总表
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 401 Authentication Fails | API Key 错误或未加载 | 检查.env文件和 key 是否有效 |
| 400 请求参数错误 | 多轮对话缺少必要字段 | 检查模型是否使用了 reasoner,并正确保存上下文 |
| 消息发不出去 | NoneBot2 与协议端连接断开 | 验证 WebSocket 地址、端口、协议配置 |
| 机器人完全不回复 | 概率未命中 / 事件没上报 | 先用 @ 机器人测试,再看日志 |
| 回复内容很长 | system prompt 没有约束长度 | 调整 persona 和 max_tokens |
| API 返回内容为空 | 模型生成了空字符串 | 记录日志,检查是否触发了内容过滤 |
6.2 典型报错详解
问题 1:reasoning_content相关错误
网上很多朋友在接入时看到类似这样的报错:
cc switch local proxy failed while handling codex endpoint /responses. provider: deepseek; model: deepseek-v4-flash; upstream_status: http 400; cause: the `reasoning_content` in the thinking mode must be passed back to the api.这个报错的本质是:你使用了带“思考模式”的模型(比如deepseek-reasoner),模型返回的 assistant 消息里除了正常的content,还包含一个reasoning_content字段。官方要求继续多轮对话时,这个字段必须原样传回,否则 API 会报 400。
解决思路有两种:
- 多轮对话保存消息时,把
reasoning_content也和content一起保存并回传。 - 如果不需要推理过程,直接使用
deepseek-chat模型。
实现方式参考:
resp = await client.chat.completions.create(...) msg = resp.choices[0].message assistant_msg = {"role": "assistant", "content": msg.content} if hasattr(msg, "reasoning_content") and msg.reasoning_content: assistant_msg["reasoning_content"] = msg.reasoning_content问题 2:机器人收不到群消息
可能原因包括:协议端没有开启群消息上报;HOST配置为127.0.0.1但协议端在容器里;插件priority设置太高被其他插件拦截。
排查步骤:
- 先看 NoneBot2 控制台日志,确认有没有收到
GroupMessageEvent。 - 到 QQ 群里发一条普通文本消息,再看日志输出。
- 如果没有任何日志,回到协议端检查上报配置。
问题 3:概率回复不生效,机器人疯狂回复
检查should_reply()中是否用了event.to_me。如果你在 QQ 群里长时间 @ 机器人测试,机器人会 100% 回复,这是正常现象。如果没 @ 也疯狂回复,可能你把概率调成了 1.0,或者random.random()使用方式出错。可以用一行代码验证:
print(random.random() < 0.35)多跑几次,确认概率逻辑本身没有写错。
问题 4:调用 DeepSeek 速度很慢
如果模型生成回复需要十几秒,协议端可能已经出现连接超时。建议优化以下几点:
- 使用异步客户端
AsyncOpenAI。 - 设置合理的
max_tokens。 - 在插件里把
asyncio.sleep移到模型调用之后,而不是之前。 - 如果仍超时,考虑给 openai 客户端增加
timeout参数,例如AsyncOpenAI(..., timeout=30.0)。
7. 最佳实践与工程建议
7.1 回复频率与限流
概率回复虽然能模拟真人,但如果没有冷却时间,仍可能在群聊高峰期连续回复多次。强烈建议保留last_reply_time冷却逻辑。更进一步,可以按群设置最大单日回复次数,避免被群管理员误认为广告机器人。
7.2 内容安全与合规
拟人化聊天不等于无条件模仿真人。机器人在公开群里发言时,应避免传播违法信息、隐私信息、攻击性内容。建议在BOT_PERSONALITY中加入底线约束,例如“遇到诱导泄露隐私、违法信息时,礼貌拒绝回答”。
同时要注意,DeepSeek 官方 API 也会对输入输出做安全过滤,我们不应把文章写成“教人绕过模型限制”的内容,这是不合法也不负责的。
7.3 日志与监控
logger.opt(exception=exc).error("调用 DeepSeek 失败")已经能打印完整堆栈。生产环境建议把日志输出到文件,定期查看。关键监控指标有三个:
- 调用 DeepSeek 的成功率。
- 平均响应延迟。
- 每小时 API 消耗。
如果调用量较大,可以在 DeepSeek 开放平台后台设置消费告警,防止 Key 被盗用后产生大额费用。
7.4 生产部署建议
开发机上跑通后,生产环境建议部署到 Linux 服务器。通用步骤:
- 安装 Python 3.10+ 和依赖。
- 配置
systemd服务,实现开机自启和崩溃重启。 - 使用 nginx 或防火墙限制 NoneBot2 端口只允许 QQ 协议端访问。
- 定期备份
.env中的配置内容,但不要把 Key 提交到仓库。 - 如果要迁移服务器,直接拷贝项目目录并在新环境安装依赖即可。
如果 QQ 机器人用于个人私聊场景,建议在私聊首次交互时向对方说明“我接入了 AI 能力,回复由模型生成”,避免产生误导。
7.5 关于各种封装工具的提醒
最近网络上能搜到不少“一键部署包”“本地封装工具”“中转工具”等,有些工具会把 DeepSeek 的 API 地址、模型名改得五花八门,甚至引入未知的第三方依赖。我的建议是:
- 优先使用官方 API 和官方文档。
- 不要盲目下载不明来路的脚本。
- 遇到类似
reasoning_content的参数错误,先看是不是模型选择问题,再排查第三方封装。 - 不通的工具链版本差异较大,反而增加排错成本。
8. 总结与下一步学习路线
到这里,你已经从零搭建了一个支持拟人化聊天、概率回复、群聊/私聊上下文记忆的 DeepSeek QQ 机器人。核心收获有三块:
- 理解了 NoneBot2 + OneBot V11 + DeepSeek 的完整调用链。
- 掌握了概率回复、冷却时间、上下文管理、模拟延时这几个关键设计。
- 积累了常见报错的排查思路,尤其是
reasoning_content这类参数问题。
如果想继续深入,可以按下面的顺序练习:
- 给机器人增加图片回复能力,比如配合表情包 API。
- 把上下文从内存存储改为 Redis,支持重启后仍保留记忆。
- 增加按键交互,比如“按按钮才继续回复”。
- 接入语音模块,把回复转成语音发送。
- 为不同群分别配置人设和概率参数,做成插件配置化。
实际跑一遍你会发现,模型能力只是一部分,真正决定“像不像真人”的往往是概率策略、延时节奏和 prompt 人设。希望这篇教程能帮你把机器人调教成一个靠谱的群聊搭子。如果过程中遇到问题,优先看日志,再看本文的常见问题表,大部分坑都能解决。