实现

消息、模型、工具和记忆如何协作

平台适配器只负责收发与归一化,Assistant Runtime 拥有决策边界,模型和工具在明确权限内执行,SQLite 保存可恢复的状态。

架构

核心模块与所有权边界

目录职责
cmd/webui/进程入口、环境装配、SQLite 和运行时依赖注入。
model/assistant/消息事件、通道、回复决策、Agent、媒体、记忆与任务。
model/llm/统一请求、Provider adapter、模型目录、token 预算和重试。
model/storage/Schema、配置、消息、事件、记忆和任务持久化。
webui/Gin API、鉴权、配置、事件、更新和 SSE。
frontend/Vue 3 管理控制台。

调用链

一条消息如何决定回复或忽略

  1. 接收与入队

    平台 adapter 将文本、@、引用、图片、文件和发送者转换为统一 MessageEvent,先写进 SQLite 入站队列再处理;进程崩溃或重启后消息仍在库里,处理失败按退避重试。

  2. 断线补拉

    重连后向平台拉取断线期间的历史并按 seq 检查缺口;每个会话只有最新几条本来就会直接触发的消息进入回复流程,其余只补进历史。

  3. 确定性门禁

    检查群是否可用、机器人/群启用、禁言、模型配额、群等级、响应抑制和机器人互聊抑制,每一步都记下拦截原因。

  4. 触发判断

    私聊直接处理;群聊检查显式 @、引用、称呼、链接和插件命令。同一人在生成期间追加的补充或纠正会合并进正在生成的回复。

  5. 主动接话评分

    未直接触发的群消息由接话模型判断「是不是在跟机器人说话」和 0–1 的闲聊分,再按闲聊档位和冷却放行;出错、超时(60 秒)或解析失败一律沉默。

  6. 上下文组装

    稳定的系统提示与历史在前、缓存断点之后才是记忆、工具证据等每轮变化的内容,并按 token 预算裁剪。

  7. 模型与 Agent 循环

    Agent 每步只执行一个工具,受步数、单工具超时和收尾预留时间约束;超限时强制收尾,校验换行、证据和链接后才返回。

  8. 发送前审核

    模型沉默、一次审核模型调用(私聊收尾、群里叫停、空转、账号安全、主动回复质量),以及发送时的打断、幂等和暂停检查。

  9. 发送与记录

    分条回到来源通道,只有第一条带引用和 @;群发送按文字/媒体两条通道退避。结果代码、原因、投递阶段、耗时与 token 全部持久化。

每一步的流程图、判断条件和结果代码见链路一页。

记忆

超长历史不直接塞进每次请求

01

近期上下文

保留当前会话最近消息,优先满足引用、追问和连续对话。

02

压缩摘要

历史达到阈值后提炼主题、结论和未完成事项,减少重复 token。

03

长期事实

异步提取稳定事实、偏好和关系信息,带来源、置信度和更新时间。

04

按需检索

按时间、关键词、用户、群和平台检索;跨群与跨通道分别受独立开关控制。

检索先使用结构化过滤缩小范围,再做文本相关性与时间衰减排序,最后只向模型提供命中的证据片段。摘要重新加载配置时不会重新计算,只有输入历史变化或摘要版本升级才失效。

多模态

原图、OCR 与历史描述各司其职

平台媒体引用→下载与校验→原图缓存→视觉模型 / OCR→回答与描述缓存
  • 普通图片转换成 Provider 支持的输入,不在媒体层无条件缩小原图。
  • 文本密集截图同时使用高细节视觉输入和 OCR 证据。
  • 历史图片描述按内容 SHA-256 和算法版本缓存。
  • 图片数量和视觉 token 受预算约束,避免 base64 历史无限增长。
  • 视频只抽取有限数量上下文帧,完成后清理临时文件。

数据

SQLite 主库与可管理的媒体缓存

数据默认位置备份要求
配置、凭据、会话、消息、记忆、任务data/diana.db必须备份,并保持主库与 WAL/SHM 一致。
入站媒体data/media可按容量淘汰;历史识图需要时一并备份。
运行日志logs/diana.log定期轮转,不公开平台事件和调试上下文。
安装与更新备份.installer/backups、数据目录下的 .diana-updates保留最近可用版本和恢复证据。