提供源码部署与 pip/uv tool 安装两种方式:源码部署是推荐的首选方式,功能完整且经过充分测试;pip/uv tool 安装适合快速体验,但部分功能支持尚不完善。
Release 下载提示:如果目的是部署 QQ Bot,不需要在 GitHub Release 的 Assets 中挑客户端安装包;按本文源码部署或 pip/uv tool 安装即可。Release 中的
Undefined-Console-*和Undefined-Chat-*是可选客户端,选择说明见 README — Release 下载速查。作为 Python 库嵌入:若你不需要启动 QQ Bot CLI,而是要在自己的应用或测试中复用 Undefined 组件(配置、
AIClient、Skills、认知记忆等),请参阅 Python 库 API 参考 与 配置详解 — 库嵌入配置。CLI 入口(Undefined/Undefined-webui)行为不受库嵌入 API 影响。Python 版本要求:
3.11~3.13(包含)。若使用
uv,通常不需要你手动限制系统 Python 版本;uv会根据项目约束自动选择/下载兼容解释器。
由于项目中使用了 NagaAgent 作为子模块,请使用以下命令克隆项目:
git clone --recursive https://github.com/69gg/Undefined.git
cd Undefined如果已经克隆了项目但没有初始化子模块:
git submodule update --init --recursive推荐使用 uv 进行现代化的 Python 依赖管理(速度极快):
# 安装 uv (如果尚未安装)
pip install uv
# 可选:预装一个兼容解释器(推荐 3.12)
# uv python install 3.12
# 同步依赖
# uv 会根据 pyproject.toml 自动处理 3.11~3.13 的解释器选择
uv sync同时需要安装 Playwright 浏览器内核(用于网页浏览功能):
uv run playwright install网页截图和 Markdown 渲染依赖 Playwright 浏览器内核。源码部署时请执行:
uv run playwright installrender.render_latex 使用 Python 依赖中的 matplotlib.mathtext 在本地渲染常见数学公式,不需要额外安装系统 TeX,也不访问外部网络。复杂 TeX 环境和自定义宏可能不受支持,此时工具会立即返回明确错误。
render.render_html / render.render_markdown 的 layout=long 与普通渲染复用同一套 Playwright 运行时,无需新增系统依赖。渲染 BrowserContext 强制离线并终止全部网络请求;请将所需样式、脚本和图片内联,图片可使用 data: / blob: 资源。
如果 Playwright 自带 Chromium 未安装,渲染器会尝试复用系统已安装的 Chrome/Chromium。需要指定其他路径时,设置 [render].browser_executable_path;与 Playwright 自带版本相比,系统浏览器的版本兼容性不受 Playwright 保证,因此生产环境仍优先执行 uv run playwright install。
以下依赖按启用的功能决定是否需要,缺少时只影响对应能力:
- Docker:Code Delivery Agent 需要
docker可执行文件与可用守护进程(镜像由[code_delivery].docker_image指定,默认ubuntu:24.04,首次运行会拉取)。不使用该 Agent 时可设[code_delivery].enabled = false。 - FFmpeg:必须能从
PATH找到。Bilibili DASH 音视频合并、messages.send_voice与微信侧语音转 SILK 都依赖它;缺失时相关操作会明确报错。 - MCP 服务器的运行时:仅在
config/mcp.json中配置本地子进程 MCP 服务器时需要——command为npx等 Node 命令时需要 Node.js;为uvx时需要uv(uvx是uv tool run的别名,随uv一同安装,见上文安装依赖)。
除 Python 运行环境外,下列服务由部署方自行搭建;后面的 pip/uv tool 部署方式同样适用。本节只说明必要性与配置位置,不重复各上游仓库的安装步骤——请按官方部署说明完成部署后,再在 config.toml 中填写地址与凭据。
| 服务 | 必要性 | 配置位置 | 官方部署说明 |
|---|---|---|---|
| OneBot V11 协议端(NapCat / Lagrange.Core) | 必需:Undefined 自身不实现 QQ 协议,QQ 消息的收发完全由协议端决定 | [onebot],见配置说明 |
NapCatQQ、Lagrange.Core、OneBot V11 标准 |
| SearXNG 搜索服务 | 可选:只影响 web_agent 的内置 web_search 工具 |
[search].searxng_url,见配置说明 |
SearXNG(自托管) |
| Firecrawl 搜索服务 | 可选,且默认关闭(firecrawl_search_enabled = false):可用官方 keyless,或官方 + 自己的 API Key,或指向自部署实例 |
[search.firecrawl],见配置说明 |
Firecrawl 自托管说明 |
| lxmusic2api 音乐服务 | 可选:为 music.* 工具集提供数据与音频解析能力,不随本项目发布 |
[lxmusic2api],见配置说明 |
lxmusic2api |
各项不部署时的具体影响:
- 不部署 OneBot 协议端:Bot 无法登录,收发不了任何 QQ 消息;严格模式缺少
onebot.ws_url会直接报错退出。 - 不部署 SearXNG:
web_search调用时提示未启用;grok_search、firecrawl_search、crawl_webpage不受影响,联网检索能力不中断。 - 不启用 Firecrawl:仅
firecrawl_search工具不可用。 - 不部署 lxmusic2api(或
[lxmusic2api].api_key留空):全部music.*工具从模型工具列表隐藏,其余功能不受影响。
补充说明:
- 上表只列“需要自己起一个服务”的项。模型端点(
[models.*])不在此列:它既可以是自部署的 OpenAI 兼容服务,也可以是远端 API,按需选择即可。 - 想省掉手工搭建:上述服务(NapCat 必需,SearXNG / Firecrawl / lxmusic2api 按需)都可用
uv run deploy up一键容器化部署,镜像与 pin 版本由本项目管理,见容器化一键部署。 - OneBot 协议端除自身部署外,还要按文件发送模式确认文件系统可见性,见下文 NapCat / Lagrange.Core 部署要求。
- 若使用
config/mcp.json中基于npx的 MCP 服务器,宿主机还需具备 Node.js 运行时。 - Code Delivery Agent 需要宿主机提供 Docker,发送原生语音与 B 站视频合并需要 FFmpeg,详见上文其它宿主环境依赖。
复制示例配置文件 config.toml.example 为 config.toml 并填写你的配置信息。
cp config.toml.example config.toml- 局部扩展主提示词(推荐):使用
[prompt.file_includes]把本地文件放入 P0/P1/P2/P3/summary 固定插槽,不需要修改受 Git 跟踪的主提示词。 - 完整覆盖提示词/预置文案:需要替换整份资源时再修改仓库根目录的
res/(例如res/prompts/)。 - 自定义图片资源:修改
img/下的对应文件(例如img/xlwy.jpg)。 - 优先级:若你希望“运行目录覆盖优先”:在启动目录放置
./res/...,会优先于默认资源生效(便于一套安装,多套运行配置)。
主 Prompt 局部扩展示例:
mkdir -p config/prompts
# 创建并编辑 config/prompts/identity.local.xml[prompt.file_includes]
p0 = "config/prompts/identity.local.xml"
p1 = ""
p2 = ""
p3 = ""
summary = ""源码仓库已忽略并从构建产物中排除 config/prompts/*.local.*。每次 AI 请求都会检查文件修改时间,未变化时复用缓存、变化时重新读取;配置路径修改后按现有配置热更新间隔生效。文件缺失或读取失败时会记录警告并跳过该插槽,不会阻止请求。完整配置与插槽位置见配置说明。
Git 与构建排除只防止私有文件被提交或打包;插入后的内容仍会作为 system Prompt 发送给模型供应商,不要在其中保存 API Key 等凭据。
启动方式(二选一):
# 1) 直接启动机器人(无 WebUI)
uv run Undefined
# 2) 启动 WebUI(在浏览器里编辑配置,并在 WebUI 内启停机器人)
uv run Undefined-webui重要:两种方式 二选一即可,不要同时运行。若你选择
Undefined-webui,请在 WebUI 中管理机器人进程的启停。WebUI 功能详见 WebUI 使用指南。
SIGINT(Ctrl+C)与 SIGTERM 都会触发同一套优雅停机流程:停止 OneBot 连接、关闭 Runtime API 与微信服务、停止史官 / memes worker、断开连接、关闭 AI 客户端与检索运行时、停止配置热重载并释放渲染资源。容器、systemd、supervisor 等默认以 SIGTERM 停止进程,无需额外配置;请避免使用 SIGKILL(docker kill -s KILL),否则会跳过全部落盘清理。
若希望 WebUI 启动后自动拉起机器人进程,可在 config.toml 中设置:
[webui]
autostart_bot = true这样运行 uv run Undefined-webui 时会自动启动 bot,无需手动操作。默认为 false。
- 资源读取:运行时会优先从运行目录加载同名
res/.../img/...(便于覆盖),若不存在再使用安装包自带资源;并提供仓库结构兜底查找,因此从任意目录启动也能正常加载提示词与资源文案。 - 并发写入:运行时会为 JSON/日志类文件使用”锁文件 + 原子替换”写入策略,Windows/Linux/macOS 行为一致(会生成
*.lock文件)。
推荐把 Undefined-webui 当作默认入口:
- 运行
uv run Undefined-webui - 在浏览器中打开管理控制台
- 若
config.toml缺失,WebUI 会自动生成模板 - 在控制台中补齐配置、保存并校验
- 直接点击启动 Bot
- 若需要远程管理,再使用桌面端或 Android App 连接到这个 Management API
这样可以避免"先手写配置、再反复命令行重启"的冷启动成本,尤其适合首次部署与远程运维。
注意:pip/uv tool 安装方式的功能支持尚不如源码部署完善,也未经过充分测试。如遇问题,建议优先切换到源码部署。
适合只想“安装后直接跑”的场景,Undefined/Undefined-webui 命令会作为可执行入口安装到你的环境中。
# 方式 1:pip
pip install -U Undefined-bot
python -m playwright install
# 方式 2:uv tool(建议使用该方式进行隔离安装)
# 安装uv(若未安装)
pip install uv
# 可选:显式指定兼容解释器(不指定时 uv 也会自动选择)
# uv python install 3.12
uv tool install Undefined-bot
uv tool run --from Undefined-bot playwright install渲染依赖提醒:同源码部署要求一致,你需要在宿主机上预先安装 Playwright 浏览器内核。请参考上文 3. 安装渲染运行时。未配置前,HTML 与 Markdown 图片渲染可能会失败;LaTeX 常见公式使用本地 mathtext,不依赖浏览器。
安装完成后,在任意目录准备 config.toml 并启动(库嵌入场景也可用 Config.from_mapping() 代替配置文件,见 python-api.md):
# 启动方式(二选一)
#
# 1) 直接启动机器人(无 WebUI)
Undefined
#
# 2) 启动 WebUI(在浏览器里编辑配置,并在 WebUI 内启停机器人)
Undefined-webui重要提示:
Undefined与Undefined-webui二选一即可,不要同时运行两个进程;否则会出现“重复登录/重复收发消息”等问题。
- 选择
Undefined:直接在终端运行机器人,修改config.toml后重启生效(或依赖热重载能力)。- 选择
Undefined-webui:启动后访问 WebUI(默认http://127.0.0.1:8787,密码默认changeme;首次启动必须修改默认密码,默认密码不可登录;可在config.toml的[webui]中修改),在 WebUI 中在线编辑/校验配置,并通过 WebUI 启动/停止机器人进程。- 若希望
Undefined-webui启动后自动拉起机器人进程,可在config.toml的[webui]中设置autostart_bot = true(默认false)。
Undefined-webui会在检测到当前目录缺少config.toml时,自动从config.toml.example生成一份,便于直接在 WebUI 中修改。 提示:资源文件已随包发布,支持在非项目根目录启动;如需自定义内容,请参考上方源码部署的自定义指南。
如果你希望保留完整安装/运行日志,可直接重定向到文件:
# pip 安装日志
python -m pip install -U Undefined-bot 2>&1 | tee install.log
# 运行日志(CLI)
Undefined 2>&1 | tee undefined.log
# 运行日志(WebUI)
Undefined-webui 2>&1 | tee undefined-webui.logwheel 会自带 res/** 与 img/**。为了便于自定义,程序读取资源文件时采用“可覆盖”策略:
- 优先加载运行目录下的同名文件(例如
./res/prompts/...) - 若不存在,再使用安装包自带的资源文件
只需要局部补充主 Prompt 时,优先使用上文的 [prompt.file_includes]:它会在每次请求检查运行目录中的本地文件并在修改后重新读取,也不会复制整份默认 Prompt。
确实需要完整覆盖资源时,无需改动 site-packages,直接在运行目录放置覆盖文件即可,例如:
mkdir -p res/prompts
# 然后把你想改的提示词放到对应路径(文件名与目录层级保持一致)完整资源覆盖在进程内会走资源缓存,修改后应重启 Bot。若希望直接修改“默认提示词/默认文案”(而不是每个运行目录做覆盖),推荐使用上面的“源码部署”,在仓库里修改 res/ 后运行;不建议直接修改已安装环境的 site-packages/res(升级会被覆盖)。
如果你不知道安装包内默认提示词文件在哪,可以用下面方式打印路径(用于复制一份出来改):
python -c "from Undefined.utils.resources import resolve_resource_path; print(resolve_resource_path('res/prompts/undefined.xml'))"资源加载自检(确保 wheel 资源可用):
python -c "from Undefined.utils.resources import read_text_resource; print(len(read_text_resource('res/prompts/undefined.xml')))"除上面的手工部署外,仓库还提供一条命令完成「本体 + NapCat + 按需自托管服务」的容器化部署:
git clone --recursive https://github.com/69gg/Undefined.git
cd Undefined
uv run deploy up # 交互式向导;默认只部署本体 + NapCat脚本会:生成 deploy/ 下的 compose 与各服务配置 → 按最小差异修改 config.toml(改前备份)→ 校验并启动容器 → 输出各服务入口与凭据(含带 token 的 NapCat WebUI 链接)。
需要 Linux + Docker Engine(含 docker compose v2 插件)+ git。完整说明(两种部署模式、可选服务、端口与凭据、Docker 访问方式、升级与排查)见 容器化一键部署。
Bot 本地文件支持三种发送方式,默认 local,保持旧部署的发送行为。是否需要共享文件系统取决于模式:
| 模式 | 共享文件系统 | 协议端要求 | Runtime 文件监听 |
|---|---|---|---|
local(默认) |
必须按发送路径可见 | 能读取 Bot 给出的路径/file:// URI |
不需要 |
url |
不需要 | 对相应消息/文件接口支持 HTTP URL,且能访问 Runtime | 需要 |
stream |
不需要 | 支持 NapCat upload_file_stream 扩展 |
不需要 |
[onebot]
file_send_mode = "local"
file_send_host = "127.0.0.1" # 仅 URL 模式使用,不包含协议、端口或路径local 适用于同一宿主机、同一容器,或共享 volume 且内部路径一致的不同容器。协议端会在自己的文件系统中读取 URI;路径未挂载仍会报 ENOENT。
url 模式复用 [api] Runtime HTTP 服务,无需额外端口。file_send_host 填写协议端实际可达的 IPv4、IPv6 或域名;IPv6 会正确生成带方括号的 URL。端口取实际监听值,修改 api.port 而尚未重启时仍使用旧端口。默认 127.0.0.1 仅适用于协议端与 Bot 共用网络空间的情况,独立容器中的回环地址指向容器自身;需要同时保证 [api].host 的绑定允许协议端访问。Runtime 关闭或未就绪时准备阶段报错,不会自动启动服务。
URL 使用单文件独立令牌,有效期 16 分钟,支持 HEAD、Range 和重复读取。下载读取的是 Bot 保存的独立副本,业务删除源文件或切换模式不会影响有效链接。到期拒绝新请求,正在读取的请求可以完成,然后清理副本。不要在反向代理访问日志中记录文件 URL 查询串。
stream 通过已有 OneBot WebSocket 按 64 KiB 分块上传,每块单独等待确认,最后独立请求完成并校验路径、大小和 SHA-256,再发 QQ 消息。一个 Bot 的 Stream 文件投递串行,多文件顺序准备,文本消息不受上传锁影响。文件准备、发送和明确失败后的回退共用 8 分钟预算,排队等待不计时;协议端文件显式保留 16 分钟。未完成 Stream 失败时仅尝试重置该 Stream,已完成文件依靠保留期回收,不调用清空临时目录的接口。不支持零字节文件,不自动重试上传或跨重启续传。
旧配置缺少新增字段且未通过环境变量指定模式时继续使用 local。 需要跨文件系统发送时,可显式设置 onebot.file_send_mode = "url" 或 "stream"。选择 Stream 后,协议端明确不支持扩展时会提示切换配置,不会静默回退。NapCat 扩展不能视为所有 OneBot 实现的共同能力;使用 Lagrange.Core 等实现时应按其实际能力选 local,或核对所用消息与普通文件上传接口的 URL 支持后选择 url。
实现参考固定版本的 NapCat 上传示例 与 UploadFileStream。Bot 新传输层使用分块 IO,但该上游在合并磁盘分块时仍构造完整内存缓冲区,现有附件登记也可能读取完整文件;不承诺整个链路固定内存占用。
以下功能的本地来源统一经过该传输层,保留原始附件 UID、展示文件名与历史语义:
/stats统计图表render.render_markdown/render.render_latex渲染图片- 定时任务发送图片 / 音频
code_delivery_agent代码交付压缩包messages.send_text_file/messages.send_url_file- Bilibili 视频下载发送
同时覆盖语音、视频缩略图和嵌套合并转发中的媒体,支持 CQ 字符串及消息段数组。已有 HTTP/HTTPS URL、Base64 或协议端资源标识原样通过。两项配置支持按投递快照热更新,见 配置说明。