Grok模型接入QQ机器人:从OneBot协议到OpenAI兼容接口的完整实践

发布时间:2026/9/8 11:35:33
Grok模型接入QQ机器人:从OneBot协议到OpenAI兼容接口的完整实践 之前在做群机器人时一直想找一个上下文能力强、回答质量高的模型来驱动 QQ 机器人。试过好几个方案要么上下文太短多聊几句就“失忆”要么回答太模板化放在群聊里显得有些生硬。后来把 Grok 模型接入 QQ 机器人后对话体验提升了不少支持长上下文、可调教空间大而且调用方式走的是标准的 OpenAI 兼容接口接入成本并不高。这篇文章就把整个接入过程完整拆解一遍从环境准备、OneBot 协议连接、Python 代码实现到系统提示词调教、常见报错排查、生产环境注意事项全部覆盖。想给自己 QQ 群加一个 AI 助手的新手或者想快速验证 Grok 模型在 IM 场景下效果的同学都可以照着操作。1. 背景与核心概念1.1 Grok 模型是什么Grok 是 xAI 推出的对话式大模型设计上强调逻辑推理、代码生成和长文本理解。和普通聊天机器人不同Grok 在多轮对话中的上下文保持能力比较强适合用来做需要“记住前文”的 QQ 机器人。本文标题里提到的 Grok 4.3你可以把它当成一个具体的模型版本示例。实际上模型版本更新很快不同时间点开放的模型名称、上下文长度、价格策略都不一样。本文的核心思路是通用的只要你的账号能调用某个 Grok 模型并且拿到 API Key就可以通过下面的方式接入 QQ 机器人。1.2 QQ 机器人的几种实现方式QQ 机器人的实现方案大致分为两类第一类是官方机器人接口。优点是合规、稳定但需要通过官方平台申请审核流程较长支持的能力也受平台约束。第二类是基于 OneBot 协议的非官方实现例如 NapCat、Lagrange、go-cqhttp 等。这类方案部署灵活可以自建协议端适合学习、测试和内部工具。本文演示的就是这种方案。这里需要说清楚非官方协议端存在账号风控风险建议使用小号进行学习和测试不要在生产环境直接使用主账号更不要用于违反平台规则的活动。1.3 整体接入链路Grok 接入 QQ 机器人的完整数据链路如下QQ 群/私聊消息 ↓ OneBot 协议端NapCat 等 ↓ WebSocket 推送消息事件 ↓ Python 机器人程序接收 ↓ 调用 Grok APIOpenAI 兼容接口 ↓ 返回回复内容 ↓ 通过 WebSocket 发送到 QQ简单来说我们并不需要直接和 QQ 底层协议打交道只要让 Python 程序连接 OneBot 协议端的 WebSocket 服务订阅消息事件再把收到的消息交给 Grok API 处理最后把回复发回群聊即可。2. 环境准备与版本说明2.1 运行环境本文示例使用 Python 3 编写建议使用 Python 3.9 或更高版本。操作系统不限Windows、Linux、macOS 都可以。如果你的服务器在国内注意确保运行环境能够正常访问 Grok API 的域名否则会出现超时报错。版本需要根据你的项目实际情况调整本文示例以常见环境为例重点演示配置思路。2.2 安装依赖需要安装的 Python 库有websockets连接 OneBot 协议端的 WebSocket 服务。httpx调用 Grok API支持异步请求。python-dotenv读取.env环境变量文件管理密钥。安装命令pip install websockets httpx python-dotenv也可以把依赖写入requirements.txtwebsockets12.0 httpx0.27.0 python-dotenv1.0.0然后执行pip install -r requirements.txt2.3 准备 OneBot 协议端本文以 NapCat 为例。NapCat 是目前社区使用较多的 OneBot 协议实现安装后可以在本地开启 WebSocket 服务。安装完成并登录 QQ 账号后需要做以下配置在 NapCat 管理界面中找到网络配置。开启 WebSocket 服务器记下监听端口默认通常是3001。确认可以访问类似ws://127.0.0.1:3001的地址。不同版本的 NapCat 配置入口名称可能略有差异但核心思路一致只要协议端能提供一个 WebSocket 地址供我们连接即可。2.4 准备 Grok API Key登录 Grok 模型对应的开放平台在控制台中创建 API Key。创建后请立即复制保存因为密钥通常只会完整显示一次。如果你还没有开通需要先完成实名认证和余额充值。具体开通流程以平台页面为准。获得 API Key 后建议写入项目根目录的.env文件而不是直接写在代码里XAI_API_KEY你的-api-key XAI_BASE_URLhttps://api.x.ai/v1 XAI_MODELgrok-4.3 ONEBOT_WS_URLws://127.0.0.1:3001注意XAI_MODEL这个值一定要以你账号真实可用的模型名称为准。如果控制台显示的模型名称不是grok-4.3请改成实际名称否则调用时会报模型不存在。3. 核心原理拆解3.1 OneBot 协议的消息推送OneBot 协议规定了机器人端和协议端之间的通信格式。协议端收到 QQ 消息后会通过 WebSocket 推送一个 JSON 事件对象。一个典型的群消息事件如下{ post_type: message, message_type: group, group_id: 123456789, user_id: 987654321, raw_message: 你好, message: [ { type: text, data: { text: 你好 } } ] }我们需要关注几个字段post_type事件类型message表示消息事件。message_type消息类型group表示群聊private表示私聊。group_id群号。user_id发送者 QQ 号。raw_message原始消息文本。3.2 发送消息的动作要向 QQ 发送消息机器人端需要向协议端发送一个“动作”请求。动作名通常是send_group_msg或send_private_msg。例如{ action: send_group_msg, params: { group_id: 123456789, message: Hello from Grok }, echo: reply }echo字段用于判断响应对应哪一次请求示例中可以简单处理。3.3 OpenAI 兼容接口的调用方式Grok API 走的是 OpenAI 兼容格式核心接口是POST {XAI_BASE_URL}/chat/completions请求体格式{ model: grok-4.3, messages: [ { role: system, content: 你是一个友好的QQ机器人助手 }, { role: user, content: 你好 } ], temperature: 0.7, max_tokens: 2048 }其中messages数组就是对话上下文system系统提示词用来设定人设和行为规范。user用户消息。assistant模型之前的回复。多轮对话的本质就是把历史消息全部放进messages数组一起发送给模型。上下文越长模型越能“记住”之前聊过什么但消耗的 token 也越多。3.4 上下文管理策略每个 QQ 用户可以建立独立的上下文会话。简单做法是用group_id user_id作为会话 Key。每个会话维护一个消息队列。设置最大轮数超过上限就丢弃最早的记录。这样做既能保证多轮对话效果又不会让请求体无限膨胀。4. 完整实战案例下面进入完整代码实现。项目结构如下grok_qq_bot/ ├── .env # 环境变量配置文件 ├── requirements.txt # Python 依赖 ├── config.py # 配置读取 ├── grok_api.py # Grok API 调用封装 └── bot.py # QQ 机器人主程序4.1 编写配置文件文件路径config.pyimport os from dotenv import load_dotenv load_dotenv() # Grok API 配置 XAI_API_KEY os.getenv(XAI_API_KEY, ) XAI_BASE_URL os.getenv(XAI_BASE_URL, https://api.x.ai/v1) XAI_MODEL os.getenv(XAI_MODEL, grok-4.3) # OneBot WebSocket 地址 ONEBOT_WS_URL os.getenv(ONEBOT_WS_URL, ws://127.0.0.1:3001) # 对话参数 DEFAULT_TEMPERATURE 0.7 DEFAULT_MAX_TOKENS 2048 # 上下文保留轮数每轮包含 user 和 assistant 两条消息 MAX_CONTEXT_TURNS 20 # 系统提示词 SYSTEM_PROMPT ( 你是一个友善、幽默、乐于助人的QQ机器人助手。 请使用简体中文回复回答要清晰、简洁、准确。 如果遇到无法确认的问题请直接说明你不确定不要编造信息。 当用户提到违法、暴力、色情等敏感内容时请礼貌拒绝回答。 )这里把系统提示词单独放在配置里方便后续调教不需要改动代码逻辑。4.2 编写 Grok API 调用模块文件路径grok_api.pyimport httpx import config async def chat_with_grok( messages, temperatureNone, max_tokensNone, ): 调用 Grok 的 Chat Completions 接口。 messages 是 OpenAI 兼容格式的消息列表。 if temperature is None: temperature config.DEFAULT_TEMPERATURE if max_tokens is None: max_tokens config.DEFAULT_MAX_TOKENS url f{config.XAI_BASE_URL}/chat/completions headers { Authorization: fBearer {config.XAI_API_KEY}, Content-Type: application/json, } payload { model: config.XAI_MODEL, messages: messages, temperature: temperature, max_tokens: max_tokens, } async with httpx.AsyncClient(timeout90) as client: resp await client.post(url, jsonpayload, headersheaders) resp.raise_for_status() data resp.json() return data[choices][0][message][content]这里使用httpx.AsyncClient发起异步请求避免在 WebSocket 事件循环中同步阻塞。timeout90表示最长等待 90 秒防止模型推理较慢时提前超时。4.3 编写 QQ 机器人主程序文件路径bot.pyimport asyncio import json import re from collections import defaultdict, deque import websockets import config from grok_api import chat_with_grok # 过滤消息中的 CQ 码例如图片、At 等 CQ_CODE_PATTERN re.compile(r\[CQ:\w[^\]]*\]) # 会话上下文存储 # key: group_群号_QQ号 或 private_QQ号 # value: deque保存最近若干轮消息 sessions defaultdict( lambda: deque(maxlenconfig.MAX_CONTEXT_TURNS * 2) ) def get_session_key(event): 根据事件生成会话 Key。 if event.get(group_id): return fgroup_{event[group_id]}_{event[user_id]} if event.get(user_id): return fprivate_{event[user_id]} return None def build_messages(session_key, user_message): 构造发送给模型的完整消息列表。 messages [{role: system, content: config.SYSTEM_PROMPT}] for item in sessions[session_key]: messages.append(item) messages.append({role: user, content: user_message}) return messages async def send_message(ws, event, reply): 向 QQ 发送回复消息。 if event.get(group_id): action send_group_msg params {group_id: event[group_id], message: reply} else: action send_private_msg params {user_id: event[user_id], message: reply} await ws.send( json.dumps( { action: action, params: params, echo: reply, } ) ) async def handle_event(ws, event): 处理一条来自 OneBot 协议端的事件。 if event.get(post_type) ! message: return raw_message event.get(raw_message, ) or event.get(message, ) plain_text CQ_CODE_PATTERN.sub(, raw_message).strip() if not plain_text: return session_key get_session_key(event) if not session_key: return group_id event.get(group_id) # 群聊中使用指令前缀触发避免机器人回复过多消息导致刷屏 if group_id and not plain_text.startswith(/grok): return if group_id: plain_text plain_text.replace(/grok, , 1).strip() if not plain_text: await send_message(ws, event, 请直接对我说你想聊的内容) return messages build_messages(session_key, plain_text) try: reply await chat_with_grok(messages) except Exception as exc: print(f[Grok调用异常] {exc}) await send_message(ws, event, 我暂时开小差了请稍后再试。) return # 调用成功后再写入上下文避免失败消息污染历史 sessions[session_key].append( {role: user, content: plain_text} ) sessions[session_key].append( {role: assistant, content: reply} ) await send_message(ws, event, reply) async def main(): print(f正在连接 OneBot WebSocket: {config.ONEBOT_WS_URL}) async with websockets.connect(config.ONEBOT_WS_URL) as ws: print(连接成功等待消息...) async for raw in ws: try: event json.loads(raw) await handle_event(ws, event) except Exception as exc: print(f[消息处理异常] {exc}) if __name__ __main__: asyncio.run(main())这段代码实现了几个关键功能第一过滤 CQ 码。QQ 群消息里可能包含[CQ:image,filexxx]、[CQ:at,qqxxx]这样的代码块直接发给模型会导致理解混乱所以需要用正则去掉。第二群聊指令前缀。群聊里如果机器人响应所有消息会非常吵。示例中只有以/grok开头的消息才会被机器人处理私聊则全部响应。第三上下文独立存储。每个用户在自己的会话中聊天互不干扰。第四调用失败不影响历史记录。只有模型成功返回后才把当前对话写入上下文队列避免把异常情况带入下一轮。4.4 运行与验证启动机器人前先确认 NapCat 已经运行并且 WebSocket 地址正确。然后执行python bot.py看到如下输出表示连接成功正在连接 OneBot WebSocket: ws://127.0.0.1:3001 连接成功等待消息...此时在 QQ 群聊中发送/grok 用一句话介绍量子计算机器人应该会调用 Grok API然后把回复发送到群里。私聊中直接发送任何消息即可触发。4.5 结果说明如果一切正常你会看到模型返回的内容完整出现在 QQ 消息中。由于代码没有做长消息分段处理当回复超过 QQ 单条消息长度限制时可能会被截断或发送失败。这个问题可以在生产环境中处理超过一定长度就按固定字符数分段发送或者用“继续”机制让模型分多次输出。后续章节会给出建议。5. 丰富调教内容与方法接入只是第一步真正让机器人好用的是“调教”。调教主要体现在系统提示词、生成参数和上下文策略三个方面。5.1 系统提示词设计系统提示词决定机器人的“人设”。同一个模型提示词不同表现可能完全不同。下面是一个“群聊百科助手”风格的提示词示例你是一个群聊百科助手名叫小格。 你的特点 1. 回答简洁单次回复一般不超过100字。 2. 遇到技术问题给出可以操作的具体建议。 3. 面对无意义刷屏时温和地提醒用户换一个话题。 4. 不知道的内容直接说不知道不要编造。 5. 不参与争吵不输出攻击性言论。如果希望机器人偏向代码辅助可以把提示词换成你是群里的代码助手擅长 Python、Java、SQL 等语言。 当用户提出编程问题时优先给出可运行的代码示例并解释关键点。 如果用户没有提供完整背景先询问必要信息再回答。建议把提示词放到.env文件旁边的单独配置文件里或者使用配置中心管理。这样调整人设时不需要重新部署代码。5.2 生成参数调节OpenAI 兼容接口支持多个生成参数其中比较重要的是temperature控制随机性。值越低回复越稳定越高越有创造性。建议工具类机器人使用0.3到0.5闲聊机器人使用0.7到0.9。max_tokens限制最大输出长度。群聊场景建议 500 到 1024避免回复过长刷屏。top_p核采样参数一般保持默认不需要频繁调整。在示例代码中这些参数已经在config.py里配置你可以按需修改。5.3 上下文长度控制超长上下文是 Grok 的优势但也要注意成本。每轮对话都携带全部历史消息token 消耗会随着对话进行快速增长。建议策略限制每个会话的最大轮数示例中MAX_CONTEXT_TURNS 20。定期清理长时间不活跃的会话节省内存。对敏感信息进行脱敏后再送入模型。如果只做单轮问答机器人可以不保留上下文每次只发送当前消息。5.4 敏感内容过滤作为 QQ 群机器人调教时一定要加入安全约束。在系统提示词中明确要求模型拒绝回答违法、暴力、色情等敏感内容是最基础的一层防护。如果对安全要求较高还可以在代码层增加关键词过滤拦截明确违规的输入和输出。例如BLOCK_WORDS [xxx关键词1, xxx关键词2] def check_block_words(text): for word in BLOCK_WORDS: if word in text: return True return False在调用 API 之前检查用户消息在发送回复之前检查模型输出命中关键词就不回复或回复固定提示语。需要注意的是关键词过滤只是辅助手段不能完全替代模型自身的安全对齐。6. 常见问题与排查思路实际运行过程中可能会遇到各种报错。下面整理了一份常见问题对照表。问题现象常见原因解决思路连接不上 OneBot WebSocket地址或端口写错或者协议端没有开启 WebSocket 服务检查ONEBOT_WS_URL确认 NapCat 已运行连接后收不到任何消息协议端配置了 Access Token客户端未携带在 WebSocket 连接 URL 中加上 token或关闭鉴权报错401API Key 错误或已过期重新生成 API Key检查.env配置报错404提示模型不存在XAI_MODEL名称不对登录开放平台控制台确认当前可用的模型名称请求超时网络不稳定或模型推理时间过长增大timeout增加重试机制群聊中 bot 回复所有消息太吵没有设置触发前缀只在/grok指令下响应或只响应 at 消息回复内容被 QQ 截断单条回复过长按 200 到 400 字符分段发送Windows 控制台输出乱码编码问题设置PYTHONIOENCODINGutf-8模型上下文“记不住”上下文轮数太少或会话 Key 设计不合理增大MAX_CONTEXT_TURNS统一会话 Key 规则这里单独说明一下 WebSocket 鉴权问题。部分 OneBot 协议端允许设置 Access Token如果设置了连接时需要添加请求头或 URL 参数。具体格式取决于协议端版本建议查阅对应文档通常是通过Authorization: Bearer {token}或 URL 查询参数传入。7. 最佳实践与工程建议7.1 密钥安全管理绝对不要把 API Key 硬编码在代码里也不要提交到 Git 仓库。推荐使用.env文件配合.gitignore或者使用服务器的环境变量。.gitignore至少包含.env __pycache__/ *.pyc venv/7.2 错误重试与限流Grok API 在高峰期可能返回 429请求过多或 5xx服务端错误。生产环境建议实现简单的重试逻辑例如失败后等待 1 秒、3 秒、5 秒重试三次。同时要注意单用户调用频率。QQ 群聊中如果多个用户同时触发可能出现并发请求。建议使用线程安全的队列或信号量控制最大并发数。7.3 日志记录记录完整的运行日志对排查问题非常重要。至少记录以下信息收到消息的时间、群号、用户 ID、消息内容摘要。调用 Grok API 的耗时和返回状态。发送消息失败的异常堆栈。可以使用 Python 标准库logging实现避免把所有输出都打印到控制台。7.4 长消息分段发送QQ 单条消息长度有限。当模型回复较长时建议先判断长度超过阈值就分段发送。分段示例def split_message(text, limit200): return [text[i:ilimit] for i in range(0, len(text), limit)]分段时要注意不要在代码块中间断开否则会影响阅读体验。7.5 账号安全与合规再次提醒非官方协议端存在账号风控风险务必使用小号测试。正式场景中如果确实需要在 QQ 生态做机器人优先了解官方机器人开放能力。同时机器人输出内容必须遵守法律法规和平台规定。不要诱导模型生成违规内容不要将机器人用于刷量、骚扰、诈骗等任何违法用途。7.6 生产环境架构建议本文示例是一个最小可运行版本便于理解原理。如果要做成正式服务建议使用成熟框架如 NoneBot2它提供了插件管理、权限控制、会话管理能力。将 Grok API 调用抽成独立服务方便扩展和复用。使用消息队列削峰避免高并发时直接压垮协议端。增加监控告警例如调用失败率超过阈值时通知维护人员。8. 总结与下一步到这里整个 Grok 模型接入 QQ 机器人的流程就完整跑通了。我们一起实现了从 OneBot 协议端接收消息、过滤 CQ 码、调用 Grok 接口、维护多轮上下文、发送回复到 QQ 的全链路代码并且分析了系统提示词、生成参数、上下文长度控制等调教方法。对于常见的连接失败、鉴权错误、模型名称错误等问题也整理了排查方向。这套代码虽然简单但是一个非常好的学习样板。理解了它你再去看 NoneBot2 等成熟框架的源码会发现思路是相通的无非是协议适配、消息处理、模型调用、上下文管理这几个模块。下一步你可以尝试做这几件事第一把项目里的系统提示词改成自己真正需要的场景比如编程助手、学习辅导、群聊百科。第二尝试接入更多模型平台因为示例里用的是 OpenAI 兼容接口很多模型服务都可以用同样的代码接入。第三完善重试、限流、日志、分段发送等生产级能力把这个最小示例打磨成一个稳定的服务。动手实践是掌握这项技术最好的方式。建议先跑通最小示例再逐步加功能。如果过程中遇到问题欢迎对照本文的常见问题章节逐一排查。