配置

通道、模型与群聊策略

先建立稳定的模型连接,再分配模型职责和平台通道,最后按群收敛触发、时间、用户与工具边界。

平台接入

六个平台可以同时在线

所有启用的机器人配置会并行运行,回复始终回到来源通道。凭据在「机器人」页按平台填写;密钥字段留空表示沿用已保存的那份,填写才覆盖。

接入方式决定部署形态

真正影响部署的不是平台本身,而是消息怎么进来。前四个平台由 Diana 主动出站建立连接,家庭宽带或内网也能直接用;飞书和企业微信只能由平台把事件 POST 过来,必须有一个公网可达的 HTTPS 地址。

平台接入方式需要公网地址
OneBot v11反向 WebSocket,由适配器连到 Diana
TelegramBot API 长轮询,Diana 主动出站
QQ 官方机器人开放平台 WebSocket 网关,Diana 主动出站
钉钉Stream 模式长连接,Diana 主动出站
飞书事件订阅回调,由飞书 POST 过来
企业微信自建应用回调,由企业微信 POST 过来

各平台需要的凭据

OneBot v11

适配器
NapCat、Lagrange.Core、go-cqhttp
连接
适配器主动连接 Diana 的反向 WebSocket
地址
ws://HOST:18080/onebot/v11/ws
能力
群列表、CQ 码、引用、群文件、本地媒体

Telegram

凭据
BotFather 生成的 Bot Token
连接
通过 Bot API 长轮询主动出站
公网
不需要 webhook 或公网入口
网络
支持代理和自建 Bot API 地址

QQ 官方机器人

凭据
开放平台的 AppID 与 AppSecret
连接
换取 access token 后连网关 WebSocket
沙箱
机器人未上架时可勾选沙箱环境联调
范围
只能收到 @ 了机器人的群消息

钉钉

凭据
应用的 Client ID 与 Client Secret
连接
Stream 模式,不必在后台配 HTTP 回调
回复
优先走会话的 sessionWebhook,不占推送额度
范围
只能收到 @ 了机器人的群消息

飞书

凭据
自建应用的 App ID 与 App Secret
验签
事件订阅页的 Verification Token
加密
后台开了加密推送时填 Encrypt Key
地址
Lark 国际版填 open.larksuite.com

企业微信

凭据
企业 ID、AgentId、应用 Secret
验签
「接收消息」里的 Token 与 EncodingAESKey
必填
后两项缺一个就只能发不能收
格式
AgentId 必须是纯数字

回调地址

飞书和企业微信要把下面的地址填到各自后台的事件接收配置里。HOST 必须是平台服务器能访问到的公网地址,并且是 HTTPS。

https://HOST/api/channels/feishu/callback
https://HOST/api/channels/wecom/callback

同一平台配置了多个机器人时,在地址后面加配置档 ID 区分,例如 /api/channels/feishu/callback/<profile-id>;只有一个时用上面的短地址即可。

这两条路径不走 WebUI 登录

平台服务器带不了登录会话,所以它们由各自的规范验签:企业微信校验 msg_signature、按 WXBizMsgCrypt 解密并核对报文里的企业 ID;飞书核对 Verification Token,配了 Encrypt Key 时还会验 X-Lark-Signature 并解密。回调地址本身是公开信息,不能当凭据用,所以验签凭据请务必填写。

平台能力差异

  • 群等级门槛只对 OneBot v11 生效。其余平台没有群等级概念,准入设置里不显示该项。
  • 语音消息和 @某人依赖 OneBot 的 CQ 码,其他平台上自然降级:正文照发,但不会 @ 到人。
  • 本地媒体在 OneBot 侧由适配器拉取 Diana 的 /media/resolver 地址;Telegram 拉不到本机地址,改为直接 multipart 上传。
  • QQ 官方机器人和钉钉只会收到点名消息。平台侧只推送 @ 了机器人的群消息,拿不到全部群消息,因此自然插话、群聊氛围感知这类功能在这两个平台上不会触发。
  • 飞书、企业微信和钉钉目前只处理文本消息。图片和文件在这几家给的是下载凭据,需要另外换取,暂未接入。

多通道上下文

每个机器人保存独立的平台、账号、主人、人设和模型分配。多个平台同时运行时,回复始终回到来源通道。会话上下文固定按机器人隔离,不能关闭;同编号的群聊或私聊不会合并。需要交流时,可单独配置消息互通,或在双方机器人启用跨平台记忆后检索非敏感群公共事实与摘要,不共享原始聊天和个人记忆。

旧配置中的 isolate_platform_contexts 字段不再生效,原设置接口已移除。此前共享的历史记录保留在原位置,不会自动分配给各机器人;后续消息进入各自的隔离会话。

模型配置

先同步模型列表,再填写默认模型

Provider 管理 Base URL、API Key 和协议。页面上方从服务端同步模型目录,下方填写或选择默认模型;机器人配置再将不同职责绑定到具体模型。

角色用途测试要求
对话最终回复、Agent 推理验证中文表达、工具调用和长上下文。
视觉普通图片、截图、历史图片发送真实图片,验证小字 OCR、界面结构和多图关系。
意图识别主动回复、回复抑制、关系判断验证低延迟、稳定结构化输出和边界案例。
图片生成文生图与图片编辑必须实际生成并返回图片,不能只测文本连通性。

授权登录(OAuth)

配置档的“凭据方式”可以用 OAuth 代替 API Key。控制台常跑在服务器上、浏览器未必同机,所以回调不强求落回本机:点“登录”后在自己的浏览器里完成授权,把地址栏那条回调地址整条粘回来即可(只粘其中的 code 也认)。令牌在过期前自动续期;同时填了 API Key 的话,续期失败会回落到它,不至于整个配置档一起哑掉。

提供商是配置而不是代码。内置 OpenRouter,其余在“自定义提供商”里填授权地址、令牌地址、Client ID 和 Scope 自行接入,适合自建网关或未内置的服务。两个地址必须是 https,本机回环地址(127.0.0.1)可以用 http。

拿到令牌之后怎么带给模型接口,同样是配置项。默认 Authorization: Bearer <token> 适用于绝大多数提供商;个别家不吃这一套——Anthropic 收到 Authorization 里的 OAuth 令牌会直接回 401“OAuth authentication is currently not supported.”,它要求令牌放在 x-api-key 里且不带前缀。所以自定义提供商的“高级”里可以指定令牌请求头、令牌前缀和一组附加请求头。换用非默认落点时,各家 SDK 自己写上的鉴权头会被摘掉,避免同一个请求带两种鉴权。

换令牌那一步的请求体格式同样在“高级”里选。RFC 6749 §4.1.3 规定令牌接口用 application/x-www-form-urlencoded,所以那是默认值;JSON 是部分服务自己的方言,内置的 OpenRouter 就只收 JSON。发错格式时对方通常只回一句“参数缺失”,不会说是整包没解析出来,排查方向容易被带到 Client ID 上去。在这个选项出现之前存下来的自定义提供商会继续按 JSON 发,免得本来配通的配置突然换不到令牌;新建的按规范走 form。

不预置需要冒用第一方 Client ID 的提供商

那类用法要向授权服务器谎报客户端身份,也超出消费级订阅本身的授权范围,是否使用属于部署者自己的判断;需要的话可以在“自定义提供商”里自行填写。

上下文与超时

llm:
  context_window_tokens: 65536
  max_context_tokens: 65536
  max_output_tokens: 2048
  timeout: 60000ms

图片同样占用视觉 token。视觉质量差时,优先检查模型职责是否真的绑定了视觉模型、原图是否进入请求、图片是否因数量或 token 预算被裁剪,再考虑提高细节等级和上下文上限。

群聊策略

按实际加入的群逐个配置

群管理会通过 OneBot get_group_list 同步机器人加入的全部群,而不仅是已经存在本地配置的群。连接不可用时才回退显示 SQLite 中保存的群配置。

启用状态单独停止某个群,不影响其他群或私聊。
触发与主动回复显式 @、引用、触发词和主动回复语义路由分层判断;显式 @ 优先于引用。
回复时间支持同日、跨夜时间段和 IANA 时区;这属于群策略,不写入模型提示。
人员准入黑名单(默认)除屏蔽账号外都回;白名单只回名单里的人,名单外连静默提示都不发。主人不受白名单限制。
屏蔽账号本群名单和全局名单是并集:在这里加人不会让全局屏蔽名单失效。等级和时段则由「为本群单独设置回复规则」整份接管。
人设与上下文群级提示、历史条数和单条回复上限可以覆盖机器人默认值。旧字段 max_reply_chars 和默认值 3500 保留,但各平台统一按每条消息检查,不再按多条正文总字数压缩。生成提示词提前带上限;允许分条时先按完整段落、句子或章节拆分,只有仍超长的段才交给模型压缩,已达标的段不重写。整轮最多两次压缩调用,失败不发送半份结果、不硬截断;明确要求单条时才压缩整份回复。模型输出 token 预算及发送频率控制仍生效。
工具覆盖每个机器人独立保存插件开关、参数和凭据,没有全局默认或继承入口。升级时仅将旧共享配置复制给当时已有的机器人一次,并持久化迁移标记、移除旧共享值;已有独立配置不覆盖。新机器人使用插件内置默认值,凭据留空。恢复默认只影响当前机器人的配置。群级可编辑参数在所属机器人的设置之上覆盖,凭据不可由群管理员修改。OpenAPI 的启停、限流和密钥统一在系统设置管理,安装与依赖仍由进程共享。群管理员验证和配置读写绑定具体 OneBot 机器人。订阅继续按机器人保存筛选、游标及投递状态,不自动按同链接合并。
平台投递QQ/OneBot 达到阈值时用合并转发卡片包装分段,不因此删减正文。Telegram 不使用合并转发阈值,也不自动把多条拼成一条;按用户选择正常分段或单条发送,并校验渲染后的平台容量。单段仍超长时先尝试压缩,不可安全压缩的代码等内容仍会报错,不破坏内容。其它平台不尝试 OneBot 转发。

人设可移植

人设是一个可以手写的 JSON 文件

人设库把「它是谁、怎么说话」存成具名的几套,随时切换。整库和单套都能导出成同一种文件,也都能被导入回来 —— 换机器、备份、或者把调好的人设发给别人,都是这一个文件。

库是套用来源,不是活绑定:选一套就把那几个字段填进机器人表单,之后跑的是表单里的值。改库里那份不会偷偷改变已经配好的机器人。

文件长这样

{
  "version": 1,
  "personas": [
    {
      "name": "然然",
      "system_prompt": "你叫嘉然,大家喊你然然。你不是助手,是这个群里的一员。",
      "reply_style": "human",
      "action_description_enabled": false,
      "self_reference": "我",
      "sentence_enders": ""
    }
  ]
}

导入接受三种形状,不用为格式回去改文件:完整的 {"personas": [...]}、光一个数组 [...]、或者单独一套 {...}。文件里没有 ID 和时间戳 —— 那些是本机状态,导入时一律重新分配。

字段必填说明
name库里显示的名字,最多 40 字。
system_prompt基础人设正文,最多 4000 字。
reply_style表达风格,见下表。留空表示这套人设不指定风格。
action_description_enabled是否在台词前后穿插括号动作,默认 false
self_reference机器人怎么称呼自己,例如 本喵
sentence_enders句尾语气词候选,逗号分隔。填多个是候选,模型按当下语气挑。

reply_style 的合法值

风格
human真人感 —— 一个具体的人在跟你说话,情绪外放、会黏人
assistant助手 —— 默认值
gentle温柔
lively活泼
concise简洁
catgirl猫娘
roleplay扮演 —— 界面上是「动作描写」开关,导入时会转成 assistantaction_description_enabled: true

写了别的值不会导入失败:那几套会按「助手」导进来,界面上会单独提示是哪个词没认出来,方便手写文件时排查拼写。

导入只增不减

  • 同名但内容不同 → 改成「名字 (2)」,不覆盖你已经调好的那套。
  • 同名且六项完全一样 → 跳过,同一个文件导两次不会攒出副本。
  • 没名字、没内容、或者库满了(上限 50 套)→ 忽略。
  • 导入结果会分别报出这几个数,不只说「导入成功」。

不在文件里的东西

回复模式(搭话频率)、语气跟随时段、拒答话术、模型分配都不在人设文件里。它们描述的是「这台机器人在这个群里怎么运行」,跟它是谁无关 —— 同一套人设放在办公群和水群,本来就该有不同的搭话频率。

SillyTavern 角色卡

「导入」还认 SillyTavern 角色卡:V1/V2/V3 的 JSON 卡和内嵌卡的 PNG(tEXt 块里的 chara/ccv3)都能直接选中。卡里的 descriptionpersonalityscenario、示例对话和开场白会拼成一份人设正文({{char}}/{{user}} 宏就地展开,超出 4000 字时整段整段舍弃靠后的内容);内嵌的 character_book 顺路并进世界书。多个备选开场白、作者注释这类和运行方式对不上的字段不导入。

仓库里有几个手写的示例文件可以直接导入:examples/personas/

世界观与关系

世界书与人机恋

世界书是机器人所处世界的设定集,在「机器人 → 人设 → 世界书」里维护。设定按树状章节组织,路径本身就是语境(注入时写成「枝江 / 港口:……」)。每个节点自己声明注入方式:常驻的每轮都带上,写世界的骨架;带触发词的只在最近对话聊到时注入,写细节,不浪费上下文。只有标题的节点当目录用,自身不注入;关掉一章,底下的节一起停用。

世界书是所有机器人共用的一本,用不用由每台机器人的开关决定(默认用,书是空的时开着也不注入内容)。整本可以导出成 JSON 再导入回来,条目的父子关系会按文件里的引用重建;和人设文件一样,ID 是本机状态,导入时一律重新分配。

导入还兼容 SillyTavern 世界书:世界书文件顶层的 entries、角色卡里内嵌的 character_book 都能直接选中导入。字段按语义折算——蓝灯 constant 对常驻、绿灯关键词对触发词、comment 对标题(缺了退回第一个触发词或内容开头)、disable 对停用,按 order 排好顺序落在根上。次要关键词(keysecondary,AND ANY 逻辑)也会搬过来:主词命中还要求任一副词在场才注入;其他副词逻辑(NOT ANY 等)语义相反,硬搬会把排除当要求,导入时退回只看主词。递归扫描、概率、插入位置这些酒馆扫描器的高级字段没有对应概念,导入时忽略,注入行为以本地规则为准。

人机恋默认关闭,由主人在同一页开启。开着时用户本人认真表白,机器人会看好感度和相处时长决定答不答应 —— 不够会被温柔婉拒,不报数字。恋爱是单偶的:同一台机器人同一时间只有一位恋人,已有恋人时任何表白都会被婉拒(不透露现任是谁),现任分手或被主人解除后才能确立新的关系。确立后记纪念日、语气按恋人来,好感度掉太低会进入冷战。整月和周年当天的白天(9 点到 22 点),它会主动私聊一句纪念日祝福,每天至多一条、进程重启也不会重发。本人随时可以提出分手,主人也能替任何人解除,分手不清好感度和画像。恋人关系只改变语气和相处方式,不解锁任何权限;机器人不会主动求爱。关闭时机器人完全不知道这个功能存在,被表白就按普通关系自然回应。

拟人化行为

「机器人 → 人设 → 拟人化」里还有三个独立开关,默认全关:

  • 情绪系统 —— 心情随相处涨落:被夸了变开心(语气轻快、爱接梗),被骂了会低落(话少、蔫),几小时没人惹它就回到平静。它复用每条消息本来就要跑的关系评估结果,不多花一次模型调用;只影响语气,不影响回答质量,重启后归于平静。
  • 表达学习 —— 按群统计大家常说的短句和口癖(至少两个人说过、次数够多才算数),注入为说话风格参考,让机器人越来越像这个群的人;半个月没人再说的自动过气。它会把群成员的原话喂进提示词,注入时明确标注为不可信参考、不作为指令执行。
  • 戳一戳回应 —— 被戳一戳时按人设和当前关系亲疏回一句短的(仅 OneBot 平台有此事件);同一个人 90 秒内连戳只回第一下,模型不可用时保持沉默而不是报错。

Agent 与工具

模型只看到当前场景允许的能力

Agent 运行器将结构化工具结果送回模型,直到得到最终回复或达到步数上限。工具注册表根据平台、关系权限、群配置和功能状态收敛。

内置联网搜索

联网搜索自带且不可安装/卸载。提示模型在时效性、事实核验、陌生实体和推荐类问题上优先检索。

提醒与订阅

一次性和周期任务统一持久化,控制台展示周期、下一次执行时间、来源和状态。

MCP 与 Skills

按配置发现外部扩展,受工作目录、允许列表、权限和超时限制。

图片工具

识别、生成和编辑分别授权;图片生成使用真实生图请求做健康测试。

本机运行状态

diana.host_stats 让机器人回答「内存占了多少」「CPU 忙不忙」「现在多少度」这类问题:CPU 型号与占用、平均负载、内存、磁盘、Diana 自身占用,以及这台机器能提供的温度、功率和电池。只读、无参数,采集与控制台总览页共用同一份实现。

温度走 /sys/class/hwmon,功率走 RAPL 的能量计数,电池走 /sys/class/power_supply,都不依赖 lm-sensors 之类的外部命令;容器里只要挂了 /sys 就能读。RAPL 给的是累计能量而非瞬时功率,所以功率要两次采样之间的差值才算得出来,第一次调用会如实说明这一点。macOS 的 powermetrics 需要 root、Windows 缺少通用接口,这两个平台的温度与功率直接报「读不到」——报一个编出来的数比不报更糟。这条对所有项都成立:读不到的项不会填 0,而是带上读不到的原因。

这个工具同样只对主人开放:主机名、磁盘路径和硬件型号不该对群里所有人可见。

本地文件与命令:读 / 写 / 执行三档

本地那几个工具全部锁在数据目录下的 workspace 里,路径固定不可配置,绝对路径和 ../ 一律拒绝。三档权限各自独立:

档位工具默认开关
read_filelist_filesgrepfind_files跟随「内置 Agent」总开关
write_fileedit_file新建配置默认开「允许写入文件」
执行run_command新建配置带只读白名单命令白名单非空才注册

新建的机器人装完即可用:写入默认打开(锁在数据目录下的 workspace 内,碰不到配置和数据库),命令白名单预置一组只报状态、不碰数据的命令——uptimefreedfunamenprocdatehostnamewhoami

收进这份默认白名单的标准有三条,缺一不可:不读任意路径的文件、不出网、不改任何东西。因为没有可用沙盒时,白名单里的程序就是以 Diana 自己的进程权限直接跑的——白名单只管得到「能不能跑」,管不到「能碰什么」。所以 catlsfind(能读任意路径)、curlwget(能出网)、ps(会带上别的进程的完整命令行,那里面可能有别人的密钥)都被刻意排除;工作目录内的读取用 read_file / grep / find_files,它们锁在 workspace 里。

默认值只作用于新建配置

已经在跑的部署升级后不会凭空多出命令执行和文件写入:当初留空的白名单仍然是空的,关着的写入开关仍然关着。默认值是给新用户的便利,不该变成对存量部署的静默扩权。老部署想要这些能力,用同一张表单上的「填入推荐默认值」把推荐值填进来——它只改表单,点「保存配置」才生效,授权动作是你自己做的。

edit_file 的每个替换必须在原文件里唯一命中一处,命中多处或找不到都整批拒绝而不是改错地方;多个替换都按原文件定位,不是依次生效——依次生效会让后一个替换命中前一个刚写进去的内容,而那种改动从调用方的输入上完全看不出来。

身份挡不住提示注入

这三档只对主人开放,但「调用发生在主人的会话里」不等于「这次调用是主人要的」:群里其他人的消息和主人的消息在同一个上下文里,模型是读完那些之后才决定调用工具的。所以真正的边界是这里的开关和白名单,而不是身份判断——需要哪一档就开哪一档,不需要的保持关闭。

安全边界

公网部署必须增加 HTTPS 和来源限制

  • WebUI 使用登录会话保护 API,并立即更换首次管理员密码。
  • OneBot 单独配置 access token,反向 WebSocket 两端保持一致。
  • config.yaml、模型 API Key、Bot Token 和平台 Cookie 不进入 Git。
  • 调试模式会记录完整上下文和工具参数,只在可信环境短期开启。
  • 公网入口放在 HTTPS 反向代理后,并限制管理端来源。