diff --git a/deploy/dobotai-dingtalk/README.md b/deploy/dobotai-dingtalk/README.md index a54f2bc..deaf9d9 100644 --- a/deploy/dobotai-dingtalk/README.md +++ b/deploy/dobotai-dingtalk/README.md @@ -1,29 +1,153 @@ -# DobotAI 容器化运行(测试环境) +# DobotAI DingTalk 容器部署手册 -容器和Compose服务固定名为 `dobotai-dingtalk`。容器使用宿主网络,以兼容测试环境已有的 `127.0.0.1` PostgreSQL、WeKnora和健康检查地址;它不暴露新端口,不更改数据库容器或WeKnora容器。 +> 适用范围:DobotAI 测试环境的容器化运行。容器和 Compose 服务名固定为 `dobotai-dingtalk`。 +> 本文不授权生产部署;生产必须使用已验收的同一镜像、独立备份和独立变更审批。 -## 日常操作 +## 1. 定位 -完成一次安装后,日常仅需要两条命令: +DobotAI 是钉钉渠道的对话编排与交付层,不是知识库或文档解析平台。 + +它负责: + +- 接收钉钉 Stream 消息、富文本和图片; +- 将请求路由到 WeKnora Agent,并维护渠道会话; +- 通过钉钉 AI 卡片或 Markdown 流式交付回答; +- 处理 `/think`、`/setting` 等渠道命令; +- 保存 Turn、会话映射、覆盖判定、Support Case、反馈和审计数据; +- 对“真实检索过但没有引用”的回答创建未覆盖提醒; +- 将 `resource://` 图片按私有 OSS 规则安全外发。 + +它不负责: + +- WeKnora 文档、Chunk、向量、图谱、解析或模型运行; +- WeKnora Agent 的知识检索策略; +- 直接暴露 PostgreSQL、WeKnora 或对象存储到公网; +- 替代钉钉应用、机器人或群权限配置。 + +## 2. 架构 + +```text +钉钉用户 / 群 + │ DingTalk Stream + ▼ +┌──────────────────────────────────────┐ +│ dobotai-dingtalk 容器 │ +│ - 消息解析、会话编排、卡片流式交付 │ +│ - /think、/setting、首位管理员绑定 │ +│ - 覆盖判定、Support Case、审计 │ +└───────┬──────────────────┬───────────┘ + │ │ + │ HTTP Agent Chat │ PostgreSQL + ▼ ▼ + WeKnora 服务 DobotAI 独立数据库 + - Agent/检索 - Turn / 会话 / 覆盖判定 + - 文档/Chunk - Support Case / 反馈 / 设置 + - 模型与解析 +``` + +### 2.1 容器边界 + +| 资源 | 归属 | 是否由本容器创建/删除 | +| --- | --- | --- | +| `dobotai-dingtalk` | DobotAI应用进程 | 是,容器可重建 | +| DobotAI PostgreSQL | 独立数据服务 | 否,保留现有数据卷 | +| WeKnora | 独立知识服务 | 否 | +| `/var/lib/dobotai-test/secrets` | 宿主机密钥目录 | 仅挂载读写,不迁移、不输出 | +| `/etc/dobotai-test/dobotai.env` | 受保护运行配置 | Docker读取,脚本原子更新 | + +测试环境的 PostgreSQL、WeKnora 已通过宿主机回环地址提供服务,因此 Compose 使用 `network_mode: host`。这不是新开公网端口:DobotAI仍按 `DOBOTAI_LISTEN_ADDR` 监听,默认是 `127.0.0.1:8090`。 + +### 2.2 容器安全属性 + +Compose 固定启用: + +```text +容器名:dobotai-dingtalk +网络:host(仅兼容现有测试宿主机回环依赖) +运行身份:与原 dobotai-test 服务用户相同的 UID:GID +根文件系统:只读 +临时写入:仅 /tmp tmpfs +额外权限:no-new-privileges +重启策略:unless-stopped +``` + +对应的关键 Compose 配置如下;不要为避免端口冲突额外添加 `ports:` 映射: + +```yaml +services: + dobotai-dingtalk: + container_name: dobotai-dingtalk + network_mode: host + read_only: true + restart: unless-stopped +``` + +## 3. 安装前检查 + +安装操作人员需要具备测试服务器的 `sudo` 和 Docker 权限。开始前确认: + +```text +1. 已构建或导入经审查的 DobotAI 镜像; +2. 现有 /etc/dobotai-test/dobotai.env 存在且权限为 0600; +3. 现有密钥目录 /var/lib/dobotai-test/secrets 存在; +4. DobotAI PostgreSQL 与 WeKnora 已健康; +5. 已记录当前原生服务二进制SHA和运行状态; +6. 如本版本包含 SQL 迁移,已先完成逻辑备份与迁移演练。 +``` + +不要执行: + +```text +docker compose down -v +docker volume rm / prune +删除 PostgreSQL / WeKnora 数据卷 +将密钥、数据库连接串或 API Key 写入命令行、日志或 Git +``` + +## 4. 构建和导入镜像 + +在已审查且工作树干净的源码目录构建。示例中的值均为占位符: + +```bash +docker build \ + --build-arg VERSION=test- \ + --build-arg COMMIT_SHA=<完整提交SHA> \ + --build-arg BUILD_TIME= \ + -t dobotai-dingtalk:test- . +``` + +跨主机传输时先保存镜像归档并记录 SHA-256;测试服务器导入后必须复核归档哈希和镜像标签。生产不得在目标机重新编译,应使用已测试的同一镜像归档或不可变镜像摘要。 + +## 5. 安装容器资产(不切换服务) + +将本目录、候选镜像和已核验的归档放到测试服务器的受控发布目录。确认镜像已经 `docker load` 后执行: + +```bash +sudo DOBOTAI_IMAGE=dobotai-dingtalk:test- \ + bash ./install-test.sh +``` + +该脚本会: + +```text +1. 检查候选镜像、现有 env 与密钥目录; +2. 备份原生 DobotAI 二进制和 systemd Unit,并写入 SHA-256; +3. 安装 Compose、配置器、启动器和绑定脚本; +4. 生成权限 0600 的 /opt/dobotai-test/container/runtime.env; +5. 保持原生 dobotai-test.service 继续运行。 +``` + +它不会读取或打印环境变量值、不会修改数据库、不会启动容器。 + +## 6. 配置并启动 + +日常只需要执行: ```bash sudo dobotai-dingtalk-configure -sudo dobotai-dingtalk-bind-admin ``` -第一条命令以隐藏输入方式更新 `/etc/dobotai-test/dobotai.env` 中的必填配置;不会将秘密传入命令行、终端输出或Git。环境文件写入成功后,它会受控停止原生 `dobotai-test.service`、启动 `dobotai-dingtalk`,并以 `/healthz` 验证。容器健康检查失败时自动停止容器并恢复原生服务。 - -第二条命令在已运行的容器内执行 `dobotai bootstrap-admin`。终端显示六码后,候选管理员私聊钉钉机器人: - -```text -/setting <六码> -``` - -绑定成功后终端自动退出。该命令不会启动第二个钉钉 Stream 消费者。 - -## 配置项说明与示例 - -`sudo dobotai-dingtalk-configure` 会在每个输入项前显示相同的说明和示例。现有值永不显示;提示“已配置”时直接回车即可保留原值。秘密项以隐藏输入读取,以下示例均为脱敏占位符。 +该命令交互更新 `/etc/dobotai-test/dobotai.env`。每项都会显示用途和脱敏格式示例;已配置的值永不回显,直接回车表示保留。 | 环境变量 | 用途 | 格式示例 | | --- | --- | --- | @@ -36,6 +160,121 @@ sudo dobotai-dingtalk-bind-admin | `DINGTALK_CLIENT_ID` | 钉钉应用Client ID/AppKey | `dingxxxxxxxx` | | `DINGTALK_CLIENT_SECRET` | 钉钉应用Client Secret/AppSecret | `<你的钉钉 AppSecret>` | -## 安装前置条件 +保存成功后,配置器自动调用启动器: -安装脚本只接受已构建、已审查的本地镜像,并在切换前备份原生二进制与Systemd Unit。它不读取或打印环境文件中的值,也不停止旧服务。生产环境必须独立审查、备份和验证,不复用测试镜像以外的未验证构建。 +```text +停止原生 dobotai-test.service +→ 启动 dobotai-dingtalk +→ 检查 http://127.0.0.1:8090/healthz +→ 健康成功后禁用原生服务 +``` + +首次容器启动失败会恢复原生服务;容器版本升级失败会恢复上一容器镜像。 + +## 7. 首位管理员绑定 + +仅当该租户不存在有效管理员时执行: + +```bash +sudo dobotai-dingtalk-bind-admin +``` + +终端会显示一个10分钟有效的随机六码。候选管理员必须私聊钉钉机器人发送: + +```text +/setting <六码绑定码> +``` + +验证成功后,终端自动写入 `super_admin/active` 并退出。已有有效管理员时命令拒绝执行,防止借由该入口追加管理员或意外提权。 + +## 8. 覆盖判定与未覆盖提醒 + +覆盖判定基于真实的 `knowledge_searched` 工具事件和结构化引用,不按关键词猜测。 + +| 场景 | 覆盖结果 | 是否创建 Support Case | +| --- | --- | --- | +| 有引用 | `covered_has_references` | 否 | +| 实际检索过但无引用 | `uncovered_no_references` | 是 | +| 明确无权威知识/无答案 | `uncovered_explicit_no_answer` | 是 | +| 图片未检索、纯视觉识别 | `covered_visual_recognition` | 否 | +| 文本未检索、闲聊或普通非知识响应 | `covered_non_knowledge_response` | 否 | + +因此“在吗”“你好”“谢谢”等未触发知识检索的文本不会产生未覆盖提醒;真正检索过但没有权威引用的问题仍会进入人工支持流程。 + +## 9. 数据库迁移门禁 + +DobotAI进程只连接数据库,**不会自动发现或执行 SQL 迁移**。包含新迁移的版本必须在容器替换前由发布流程显式完成: + +```text +1. 对 DobotAI PostgreSQL 做逻辑备份; +2. 使用 pg_restore --list 验证备份非空; +3. 在事务中执行已审查的 .up.sql; +4. 向 dobotai_schema_migrations 写入对应 version/name/applied_at; +5. 查询约束、列或索引确认生效; +6. 再替换容器镜像并进行健康与业务验收。 +``` + +`000021_coverage_non_knowledge_response_reason` 是一个示例:它只扩展 `coverage_decisions.reason_code` 的 CHECK 约束,不回写历史Turn、覆盖判定或Support Case。 + +## 10. 日常检查 + +```bash +# 健康检查 +curl --noproxy '*' -fsS http://127.0.0.1:8090/healthz + +# 运行版本 +curl --noproxy '*' -fsS http://127.0.0.1:8090/version + +# 容器状态与重启次数 +sudo docker inspect -f '{{.Config.Image}}|{{.State.Running}}|{{.RestartCount}}' dobotai-dingtalk + +# 最近日志(不要复制含敏感内容的原始上下文) +sudo docker logs --since 10m dobotai-dingtalk +``` + +验收至少应同时满足: + +```text +容器 running,重启次数为0; +/healthz 返回 ok; +/version 的 commit_sha 与发布记录一致; +钉钉 Stream 仅启动一个消费者; +旧 dobotai-test.service 为 inactive + disabled; +目标业务路径已由真实钉钉消息验证。 +``` + +## 11. 升级与回滚 + +### 升级 + +```text +构建/导入经审查的新镜像 +→ 备份DobotAI PostgreSQL +→ 应用并记录必要迁移 +→ 将 runtime.env 中的 DOBOTAI_IMAGE 更新为新标签 +→ 执行 sudo dobotai-dingtalk-start +→ 健康、版本、日志、钉钉真实消息验收 +``` + +注意拼写:数据库和应用名称是 `DobotAI`;上述流程中的镜像名为 `dobotai-dingtalk`。 + +### 自动回滚 + +启动器会保存替换前的容器镜像: + +```text +首次容器化失败:停止候选容器,恢复原生服务; +后续容器升级失败:停止候选容器,恢复上一容器镜像。 +``` + +数据库迁移不能仅靠容器回滚撤销。只有经过审查且已验证的 `.down.sql` 才可用于数据库回滚;任何数据恢复都必须先确认备份可用。 + +## 12. 明确非目标 + +```text +不容器化或重建 WeKnora; +不容器化或删除 DobotAI PostgreSQL; +不重新启用已删除的网页管理面; +不在生产环境复用测试凭据、测试镜像或未验收的迁移; +不把密钥、Token、连接串、钉钉凭据写入 Git、命令行或日志。 +``` \ No newline at end of file