这次我们来看一个很典型的应用型改造:把 DeepSeek 接入 QQ 机器人,做成一个会“看情况回复”的拟人化聊天机器人。和常见那种每条消息都必回、一问一答的机器人不同,这里的重点是“概率回复”——让机器人根据设定概率决定要不要回复,在群聊里更接近真人的聊天节奏,不会显得像刷屏机器。
这个项目本身没有复杂的前端界面,核心就三件事:让 QQ 机器人能收到消息、把消息转发给 DeepSeek API 获取回复、按概率决定是否回复。如果你已经跑过 QQ 机器人,或者调过 DeepSeek API,那剩下的工作量很小。如果都没接触过,这篇文章也可以当成一条完整的入门链路,从环境准备到代码编写全部走一遍。
下面先从核心能力开始看,再按“部署协议端 -> 开发机器人服务 -> 接入 DeepSeek API -> 概率回复逻辑 -> 测试与排错”的顺序展开。本文所有代码以通用示例为主,实际路径、端口、模型名需要按你自己使用的框架和 API 文档调整。
1. 核心能力速览
| 能力项 | 说明 |
|---|---|
| 项目用途 | 将 DeepSeek 大模型接入 QQ 机器人,实现拟人化聊天与概率回复 |
| 核心玩法 | 群聊 / 私聊场景下,按概率决定是否回复,可结合多轮上下文 |
| 模型接入方式 | 调用 DeepSeek API(也可替换为本地模型或兼容 OpenAI 接口的服务) |
| 机器人协议端 | 可选 NapCat、Lagrange、go-cqhttp 等 OneBot 实现,按官方文档配置 |
| 开发语言 | Python,使用异步 WebSocket / HTTP 与协议端通信 |
| 是否支持批量任务 | 支持,可对多个群、多个关键字、多个回复策略做集中管理 |
| 是否支持 API 接口 | 机器人服务本身可暴露 HTTP 接口,便于外部调用或测试 |
| 显存要求 | API 模式下本地几乎不消耗显存;若改用本地模型,显存需按模型版本单独评估 |
| 启动方式 | 先启动协议端,再启动 Python 机器人服务 |
| 适合场景 | QQ 群聊陪伴、自动答疑、引流测试、智能客服、个人助理 |
| 注意事项 | QQ 账号风控风险较高,建议使用小号并在合规前提下测试 |
从材料看,这类接入的核心热度集中在“Deepseek + QQ 机器人 + 概率回复”。简单说,就是把 DeepSeek 的对话能力包装成一个更接近真人行为的 QQ 机器人,而不是单纯执行指令。
2. 适用场景与使用边界
2.1 适合谁
- 想给 QQ 群加一个“会聊天”的机器人,而不是只回关键词的傻瓜机器人。
- 想测试 DeepSeek API 在真实社交场景里的回复质量。
- 需要批量管理多个群的自动回复,例如社群运营、粉丝群答疑。
- 对概率回复、上下文记忆、系统提示词这些拟人化策略感兴趣的技术爱好者。
2.2 不适合什么场景
- 不适合需要 100% 精确响应的客服系统,概率回复会导致消息漏回。
- 不适合高频轰炸式营销,容易触发 QQ 风控,也会让群成员反感。
- 不适合没有授权就采集、存储他人聊天记录的场景。
- 如果是企业级生产环境,不建议直接使用个人 QQ 账号做载体,优先评估官方机器人或企业微信方案。
2.3 使用边界与合规提醒
接入 QQ 机器人存在账号风控风险,特别是新号、频繁加群、快速回复、大量私聊的情况。建议:
- 使用专门的小号测试,不要用主号。
- 控制回复频率,结合概率回复和冷却时间,避免短时间连续回复。
- 不要存储或转发敏感聊天内容。
- 如果机器人会生成图片、语音或涉及人脸声音,必须确认授权。
- 严禁将机器人用于诈骗、骚扰、刷屏、引流外链等违规行为。
从合规角度看,DeepSeek API 是正规模型服务,但聊天机器人生成的内容仍然需要人工抽检,不能完全依赖模型自纠错。
3. 环境准备与前置条件
在写代码之前,先把环境理清楚。下面是一份通用检查清单,按你自己的系统调整。
| 检查项 | 要求说明 |
|---|---|
| 操作系统 | Windows 10/11,或 Linux(Ubuntu/Debian 等)均可 |
| Python | 推荐 3.9 及以上,建议用 3.10 或 3.11 |
| QQ 账号 | 建议小号,且能正常登录手机/PC QQ |
| 机器人协议端 | NapCat、Lagrange、go-cqhttp 任选其一,按官方文档获取 |
| DeepSeek API Key | 在 DeepSeek 开放平台注册并创建,确认账户有余额 |
| 网络环境 | 能访问 DeepSeek API 地址,能访问 QQ 协议端本地端口 |
| 磁盘空间 | 纯 API 模式几百 MB 足够;本地模型模式需要预留模型文件空间 |
| 端口规划 | 协议端 WebSocket 端口(例如 3001)、机器人服务端口(例如 8080)避免冲突 |
这里没有固定写死某个框架版本,因为 QQ 协议端更新比较频繁,不同时期推荐项目会变化。更稳妥的做法是:先选择一个活跃维护的 OneBot 实现,然后看它的文档确认 WebSocket 地址和事件格式。
4. 整体接入架构
从整体上看,一条消息从 QQ 群到 DeepSeek 返回,会经过下面几个环节:
- QQ 客户端登录账号,通过协议端(OneBot 实现)暴露本地 WebSocket 服务。
- 机器人服务连接这个 WebSocket,订阅
message事件。 - 收到消息后,先做过滤:是否来自机器人自己、是否在黑名单、是否以命令前缀开头、是否满足概率条件。
- 如果满足回复条件,将消息组装成对话上下文,调用 DeepSeek API。
- 拿到模型回复后,通过协议端发送到对应群或私聊。
概率回复的“概率”放在第 3 步,也就是在调用 API 之前判断。这样能减少无效 API 请求,也能控制机器人的活跃度。判断逻辑很简单:
import random def should_reply(probability: float) -> bool: return random.random() < probability如果概率设置为 0.3,平均每 10 条满足过滤条件的消息中约有 3 条会触发回复。为了拟人化,还可以加冷却时间和连续回复限制。
5. 部署机器人协议端
QQ 机器人协议端的部署方式因项目而异,这里给出通用步骤,具体以你选择的项目文档为准。
- 下载对应系统的协议端压缩包。
- 解压后启动程序,生成配置文件。
- 配置 QQ 账号登录信息和 WebSocket 服务端口。
- 登录成功后,协议端会输出类似
WebSocket server started at ws://127.0.0.1:3001的日志。 - 建议开启
事件上报中的消息事件,并按需开启反向 WebSocket或正向 WebSocket。
以常见的正向 WebSocket 为例,机器人服务作为客户端去连接协议端的ws://127.0.0.1:3001。有些协议端默认是反向 WebSocket,即协议端主动连接你的机器人服务,这时你要提供一个 HTTP/WS 服务器地址。
更稳妥的做法是先跑通协议端的 Echo 功能:在配置里开启后,手动发一条消息,看协议端日志是否打印消息内容。这一步能排除“协议端没连上”的问题,再往下写机器人逻辑就容易定位。
6. 安装机器人服务端依赖
建议新建一个虚拟环境,避免污染系统 Python。
python -m venv qqbot-env # Windows qqbot-env\Scripts\activate # Linux / macOS source qqbot-env/bin/activate机器人服务可以使用aiocqhttp,它是 OneBot 的 Python 异步 SDK,基于 NoneBot2 生态的一部分。安装命令:
pip install aiocqhttp另外需要安装 OpenAI SDK 或直接使用httpx调用 DeepSeek API。因为 DeepSeek 接口兼容 OpenAI 格式,可以直接使用openaiPython 包,也可以直接用httpx。这里推荐openai包,更省事:
pip install openai httpx python-dotenv如果你的协议端事件格式不是 OneBot 标准,需要换成对应的 SDK。判断标准很简单:协议端文档里写的是“OneBot 协议”,就可以用aiocqhttp;如果写的是“WebSocket 原始事件”,则需要自己解析 JSON。
7. 编写概率回复核心逻辑
7.1 项目目录结构
建议按下面结构组织代码,后续加功能不会乱:
qqbot/ ├── config.py ├── deepseek_client.py ├── bot.py ├── .env ├── requirements.txt └── logs/7.2 配置文件
使用.env存放 API Key 和概率参数,不要把密钥写死在代码里。
# .env DEEPSEEK_API_KEY=sk-your-key DEEPSEEK_BASE_URL=https://api.deepseek.com DEEPSEEK_MODEL=deepseek-chat REPLY_PROBABILITY=0.3 BOT_NAME=小深 MAX_CONTEXT_LENGTH=6 REPLY_CD_SECONDS=30其中REPLY_PROBABILITY表示每条满足条件的消息触发回复的概率;REPLY_CD_SECONDS表示冷却时间,避免机器人连续回复太多条。
7.3 读取配置
# config.py import os from dotenv import load_dotenv load_dotenv() DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY") DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL", "https://api.deepseek.com") DEEPSEEK_MODEL = os.getenv("DEEPSEEK_MODEL", "deepseek-chat") REPLY_PROBABILITY = float(os.getenv("REPLY_PROBABILITY", "0.3")) BOT_NAME = os.getenv("BOT_NAME", "小深") MAX_CONTEXT_LENGTH = int(os.getenv("MAX_CONTEXT_LENGTH", "6")) REPLY_CD_SECONDS = int(os.getenv("REPLY_CD_SECONDS", "30"))7.4 DeepSeek API 客户端
下面使用openai包调用 DeepSeek 接口。注意base_url要替换成 DeepSeek 的地址,模型名按实际 API 文档确认。
# deepseek_client.py from openai import OpenAI class DeepSeekClient: def __init__(self, api_key: str, base_url: str, model: str): self.client = OpenAI(api_key=api_key, base_url=base_url) self.model = model def chat(self, messages: list[dict], max_tokens: int = 1024, temperature: float = 0.8): resp = self.client.chat.completions.create( model=self.model, messages=messages, max_tokens=max_tokens, temperature=temperature, ) return resp.choices[0].message.content.strip()这里没有加流式输出,先跑通主流程。后面需要更快的首字响应时,再改成stream=True。
7.5 主机器人逻辑
使用aiocqhttp连接 OneBot 协议端,监听消息事件,实现过滤、概率判断、上下文组装、回复。
# bot.py import asyncio import random import time from aiocqhttp import CQHttp from aiocqhttp.message import escape from config import ( DEEPSEEK_API_KEY, DEEPSEEK_BASE_URL, DEEPSEEK_MODEL, REPLY_PROBABILITY, BOT_NAME, MAX_CONTEXT_LENGTH, REPLY_CD_SECONDS, ) from deepseek_client import DeepSeekClient bot = CQHttp() deepseek = DeepSeekClient(DEEPSEEK_API_KEY, DEEPSEEK_BASE_URL, DEEPSEEK_MODEL) # 记录每个群的最后回复时间,用于冷却 last_reply_time: dict[str, float] = {} # 按群/用户维度保存简单上下文 contexts: dict[str, list[dict]] = {} def should_reply_this_message(message_text: str) -> bool: # 过滤命令消息,这里是示例,按自己需求扩展 if message_text.startswith(("/", "!", "#")): return False # 概率判断 return random.random() < REPLY_PROBABILITY def build_messages(group_id: str, user_text: str) -> list[dict]: system_prompt = f"你是一个名叫{BOT_NAME}的QQ群聊机器人,请用自然、口语化的中文回复,不要每次都长篇大论。" history = contexts.get(group_id, []) messages = [{"role": "system", "content": system_prompt}] messages.extend(history) messages.append({"role": "user", "content": user_text}) return messages @bot.on_message() async def on_message(event): msg = str(event.message).strip() if not msg: return # 只处理群消息,私聊也可以按需放开 message_type = event.message_type if message_type not in ("group", "private"): return group_id = str(event.group_id) if event.group_id else f"private_{event.user_id}" user_id = str(event.user_id) # 不回复机器人自己 if user_id == str(event.self_id): return # 冷却判断 now = time.time() if now - last_reply_time.get(group_id, 0) < REPLY_CD_SECONDS: return # 过滤与概率判断 if not should_reply_this_message(msg): return messages = build_messages(group_id, msg) try: reply = await asyncio.to_thread( deepseek.chat, messages, ) except Exception as e: print("DeepSeek API error:", e) return # 简单上下文只保留最近几轮 contexts.setdefault(group_id, []).append({"role": "user", "content": msg}) contexts.setdefault(group_id, []).append({"role": "assistant", "content": reply}) contexts[group_id] = contexts[group_id][-MAX_CONTEXT_LENGTH:] last_reply_time[group_id] = now # 发送到群/私聊 if message_type == "group": await bot.send(event, escape(reply)) else: await bot.send(event, escape(reply)) if __name__ == "__main__": # TODO: 修改为实际协议端 WebSocket 地址 bot.run(host="127.0.0.1", port=8080, use_ws=True, ws_host="127.0.0.1", ws_port=3001)这段代码做了几件关键事:
- 按群存储最后回复时间,实现冷却。
- 按群存储对话上下文,但只保留最近几轮,避免 token 膨胀。
- 概率判断放在调用 API 之前,减少无效调用。
- 过滤掉以
/、!、#开头的命令消息。
bot.run的具体参数需要参考aiocqhttp文档。如果你使用的是反向 WebSocket,则不需要ws_port连接,而是提供一个 HTTP 服务给协议端回调。
7.6 概率回复的进阶设计
基础的随机概率在真实群聊里会显得有点“神经质”,可以做成更拟人的策略组合:
- 关键词触发:消息里包含群友昵称、指定词汇时,回复概率提高。
- 被 @ 必回:如果消息包含
CQ:at且指向机器人,就忽略概率直接回复。 - 时间衰减:离上次回复越久,回复概率越高。
- 上下文粘性:机器人自己发过言后,短时间内继续回复概率降低,避免连续刷屏。
- 随机延迟:决定回复后,先随机等 1-5 秒再调用 API,更像真人阅读和打字。
被 @ 必回的判断逻辑可以放在should_reply_this_message前:
if f"[CQ:at,qq={event.self_id}]" in msg: # 被点名,不走概率 reply = await get_reply(...) await send(...) return这样的组合比单纯random.random() < 0.3更像真人,也更适合群聊环境。
8. DeepSeek API 调用配置与测试
在写进机器人之前,先单独验证 DeepSeek API 能不能通。可以用curl或 Python 脚本测试。
8.1 curl 测试
curl https://api.deepseek.com/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-your-key" \ -d '{ "model": "deepseek-chat", "messages": [ {"role": "system", "content": "你是QQ群里的一个幽默群友。"}, {"role": "user", "content": "今天好累,有没有什么提神的方法?"} ], "max_tokens": 256, "temperature": 0.8 }'实际请求地址和鉴权方式以 DeepSeek 开放平台文档为准,以上是通用兼容 OpenAI 格式的示例。
8.2 Python 测试
from openai import OpenAI client = OpenAI( api_key="sk-your-key", base_url="https://api.deepseek.com" ) resp = client.chat.completions.create( model="deepseek-chat", messages=[ {"role": "system", "content": "你是一个说话很自然的群聊机器人。"}, {"role": "user", "content": "晚上吃什么?"} ], max_tokens=200, temperature=0.9, ) print(resp.choices[0].message.content)建议先用这个脚本确认 API Key、网络、模型名都正确,再启动机器人服务。否则机器人一收到消息就报错,排查起来会混在一起。
8.3 系统提示词怎么设计
拟人化效果很大程度取决于 system prompt。不要只写“你是机器人”,要给出具体人设和行为约束。
示例:
你是一个活跃在QQ群里的普通群友,名字叫小深。 你不喜欢每次都说“你好”“有什么可以帮你”这种客服话术。 你回复用口语化中文,偶尔用网络流行语,但不过度。 你说话自然,有自己观点,偶尔可以反问群友。 如果群友在闲聊,你就跟着聊;如果群友在讨论技术,你也能给出简明意见。 每次回复控制在50字以内,除非用户明确要求详细回答。真实群聊中,人设稳定比单次回复质量更重要。后面可以把这个 prompt 放到配置文件里,方便调试。
9. 群聊与私聊场景配置
9.1 群聊
群聊是概率回复的主要场景。默认情况下,每条群消息都可能触发回复,但为了降低风控和刷屏风险,建议:
- 将概率控制在 0.2-0.4 之间。
- 开启冷却时间,例如 30 秒内只回复一次。
- 只回复白名单群,而不是所有群。
- 对 @ 机器人的消息提高优先级。
白名单配置可以在config.py中加入:
ALLOWED_GROUPS = os.getenv("ALLOWED_GROUPS", "").split(",")然后在on_message中判断:
if event.message_type == "group" and ALLOWED_GROUPS: if str(event.group_id) not in ALLOWED_GROUPS: return9.2 私聊
私聊场景一般不建议用概率回复,用户主动找你聊天时,每条都回体验更好。可以按消息类型区分概率策略:
if event.message_type == "private": reply_probability = 1.0 # 私聊必回 else: reply_probability = REPLY_PROBABILITY9.3 多群批量管理
如果机器人要接入十几个群,不要每个群启动一个进程。可以在同一个服务里维护群维度的配置,例如每个群有独立的概率、冷却时间、人设。
group_configs = { "123456": {"probability": 0.2, "cd": 60, "prompt": "技术群,简洁回答"}, "789012": {"probability": 0.5, "cd": 10, "prompt": "闲聊群,活跃一点"}, }这样相当于用一份代码做了批量任务管理,后续调整只需要改配置。
10. 资源占用与性能观察
10.1 API 模式
使用 DeepSeek API 的情况下,本地只有 Python 进程和协议端进程,资源占用很低。正常情况下内存占用通常在几百 MB 以内,CPU 占用可以忽略。显存占用为 0,因为推理发生在云端。
10.2 本地模型模式
如果你不走 API,改成部署本地 DeepSeek 模型,资源占用差异很大。显存需求取决于模型版本:量化版本和完整版本差很多。这块需要以你实际使用的模型为准,不要轻信网上单一说法。可以先用工具监控nvidia-smi和内存占用:
nvidia-smi -l 1观察 GPU 显存和温度,再根据显存占用调整模型量化等级、上下文长度、并发数。
10.3 影响性能的因素
- 并发消息量:群越多、消息越频繁,异步回调越密集。
- API 响应速度:DeepSeek API 的延迟直接影响机器人“打字时间”。
- 上下文长度:每轮都带历史消息,token 越多响应越慢。
- 冷却时间和概率:回复越频繁,API 调用越多,成本和风控风险越高。
- 日志写入:如果每条消息都写磁盘,日志量大时会影响性能。
优化建议:先小范围测试,再逐步扩大。不要一开始就把概率调到 1.0 并接入所有群。
11. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 协议端启动成功但收不到消息 | 账号未登录成功,或事件未开启 | 查看协议端日志,手动发消息测试 | 重新登录账号,开启消息事件上报 |
| 机器人服务连接不上协议端 | WebSocket 地址或端口写错 | 检查协议端日志和机器人启动日志 | 修改ws_host/ws_port,确认端口未被占用 |
| 收到消息但没有任何回复 | 概率不满足、冷却时间未到、消息被过滤 | 在on_message里加临时日志 | 打印概率判断结果,调整配置 |
| DeepSeek API 调用报错 | API Key 错误、模型名错误、网络不通 | 先运行纯 API 测试脚本 | 检查 Key、base_url、模型名 |
| 回复内容不自然,全是客服话术 | system prompt 不够具体 | 查看构造的 messages 日志 | 优化人设 prompt,调整 temperature |
| 机器人回复太频繁 | 概率设置过高或冷却时间太短 | 检查配置 | 调低概率,增加冷却时间 |
消息里出现[CQ:at]乱码 | 发送时未转义 CQ 码 | 发送前使用escape | 参考aiocqhttp.message.escape |
| QQ 账号被风控或冻结 | 频繁登录、快速回复、大量加群 | 检查登录设备和网络环境 | 使用小号,降低回复频率,登录后手动稳定一段时间 |
| 上下文越长回复越慢 | 历史消息太多 | 打印 token 数量 | 限制MAX_CONTEXT_LENGTH或截断历史 |
最有效的定位方式是在机器人服务里加日志。每次收到消息、概率判定、调用 API、返回结果都打印一行。日志格式可以简化为:
[时间] 群:123456 用户:789 消息:你好 概率:0.3 结果:回复这样基本能定位绝大多数问题。
12. 最佳实践与合规提醒
12.1 工程化实践
- 第一次测试先把概率设为 1.0,确认链路通,再改成正常概率。
- 配置和代码分离,不要为了改概率重写代码。
- 给 API 调用加超时和重试,避免偶发网络错误导致丢消息。
from openai import APITimeoutError, APIConnectionError- 记录 API 调用成本和失败次数,方便后续调整概率。
- 不要把 DeepSeek API Key 提交到公开仓库,
.env文件要加入.gitignore。 - 启动服务时指定固定端口,并在系统防火墙里放行,避免端口冲突。
12.2 合规与安全边界
这部分非常重要,务必在发布和使用时都遵守:
- 使用小号,并接受账号可能被风控的事实,不要用主号冒险。
- 机器人只能处理已经授权的账号和群,不要未经同意抓取群成员信息。
- 涉及语音、图片、人脸等生成能力时,只能处理获得明确授权的内容。
- 不要在机器人里植入自动加好友、自动拉群、群发广告等违规功能。
- 对外提供服务时,要给机器人服务加访问鉴权,避免第三方乱调用。
如果你要把这个机器人用于商业场景,建议先确认所用协议端与 QQ 官方政策的兼容性,优先选择官方机器人或企业级 IM 方案。
13. 总结与下一步
这个项目最值得尝试的点在于:它把“大模型对话”和“真实社交场景”结合在了一起,而且概率回复这个机制让机器人看起来不再像一个没有感情的应答机。整个改造链路不长,最难的部分反而不是 DeepSeek API,而是 QQ 协议端的账号稳定性和消息过滤策略。
建议第一次跑的时候,先把概率调到 1.0,在一个测试群里验证通链路;再逐步调低概率,加入冷却、白名单、人设 prompt 这些拟人化细节。最容易踩的坑通常是两个:一是协议端连不上,二是 API Key 或模型名配置错误导致调用 401。这两个问题都可以通过分段测试快速定位。
后续可以继续扩展的方向很多:接入 DeepSeek 的 Reasoner 模型做复杂推理、在机器人里加入知识库检索、用定时任务主动发消息、把回复内容通过语音合成播报、或者把多个大模型配置成可切换的“角色”。只要协议端事件稳定,往上叠加功能的空间很大。
想省事的话,建议先按本文搭一个最小可用版本,然后再按自己的群聊风格调整概率和人设。如果这篇文章对你有帮助,建议收藏备用,后面接入其他模型或改造成本地部署时还能拿来做参考。