236 lines
11 KiB
Markdown
236 lines
11 KiB
Markdown
# DobotAI 平台
|
||
|
||
DobotAI 是 WeKnora 的企业外部渠道集成层,负责钉钉协议、身份与会话映射、消息编排、流式卡片、媒体收发、覆盖判定和人工支持通知。它只通过 WeKnora 官方 REST/SSE API 调用知识问答与 Agent Chat:不导入 WeKnora 私有包、不修改 WeKnora 源码,也不访问 WeKnora 数据库。
|
||
|
||
## 当前能力
|
||
|
||
- 通过官方 `POST /api/v1/sessions` 与 `POST /api/v1/agent-chat/:session_id` 调用 WeKnora;
|
||
- 严格解析 SSE 的 `answer`、`references`、`tool_call`、`tool_result`、`error` 与终止事件;`error + done=false` 被视为可恢复的工具错误,不会提前结束钉钉卡片;
|
||
- 解析普通引用及智能推理工具结果中的检索证据,供覆盖判定与后端审计使用;
|
||
- 按渠道、会话和用户维护长期 WeKnora Session,并保证回调幂等;
|
||
- 钉钉 Stream 机器人支持文本、richText 以及多图片输入;图片下载经过钉钉官方接口、大小与文件签名校验后,才以 WeKnora 通用多模态请求发送;
|
||
- 钉钉 AI 流式卡片与最终消息回退;通道侧保留原始回答,不修改 WeKnora 持久化消息;
|
||
- 默认快速问答,支持 `/think <问题>` 单次推理、`/think on` 持续推理、`/think off` 或 `/rag` 关闭推理;快速问答与智能推理共用同一 WeKnora Session;
|
||
- 用户级推理轮次、空闲到期、提示开关和首次使用指引;
|
||
- 成功回答的覆盖判定、持久化 Support Case、FAQ Outbox 与钉钉人工支持群通知;
|
||
- 对已覆盖答案点踩时创建 `feedback_down` 人工处理提醒;对已先因未覆盖创建 Case 的同一问题保持“一题一个 Case”幂等;
|
||
- 可选的钉钉问题表异步写入;写入失败不会改变问答成功状态;
|
||
- 可选的回答图片外发:仅将 WeKnora `resource://` 图片通过鉴权下载、内容哈希转存到私有 OSS 后,以受控 HTTPS 地址提供给钉钉。
|
||
|
||
## 架构边界
|
||
|
||
```text
|
||
钉钉 / 内部调用方
|
||
↓
|
||
DobotAI
|
||
├─ 钉钉 Stream、richText、图片、AI 卡片、反馈与通知
|
||
├─ 独立 PostgreSQL:渠道身份、消息、会话映射、Turn、覆盖与支持流程
|
||
└─ WeKnora 官方 REST / SSE API
|
||
↓
|
||
WeKnora:检索、Agent、知识与引用
|
||
```
|
||
|
||
责任边界:
|
||
|
||
- **DobotAI**:钉钉协议、媒体收发、会话映射、命令路由、卡片、覆盖判定、人工支持、渠道审计。
|
||
- **WeKnora**:通用 Agent Chat、检索、知识存储、引用与模型调用。
|
||
- **DobotAI PostgreSQL**:只保存渠道与业务编排数据,不保存 WeKnora 知识正文。
|
||
- **Redis**:仅用于队列、重试、幂等租约和短期状态。
|
||
|
||
## 目录结构
|
||
|
||
```text
|
||
.
|
||
├── cmd/
|
||
│ ├── dobotai/ 主程序入口、运行时装配与后台 Worker
|
||
│ └── directory-import/ 钉钉通讯录导入命令
|
||
├── internal/
|
||
│ ├── channels/dingtalk/ 钉钉 Stream、卡片、媒体、反馈与群通知
|
||
│ ├── qa/ 问答主流程、WeKnora 调用和检索信号记录
|
||
│ ├── weknora/ SSE、工具结果和引用解析
|
||
│ ├── coverage/ 覆盖判定、Support Case 和人工提醒
|
||
│ ├── reasoningmode/ /think 推理模式
|
||
│ ├── settings/ /setting 与首位管理员绑定
|
||
│ ├── outboundimage/ resource:// 图片私有 OSS 外发
|
||
│ ├── questiontable/ 问题表工作流
|
||
│ ├── faqtable/ FAQ 表工作流
|
||
│ ├── directory/ 钉钉通讯录查询与导入
|
||
│ ├── audit/ 审计查询
|
||
│ ├── httpapi/ /healthz、/version、/v1/qa 与审计 API
|
||
│ ├── core/ 核心领域类型
|
||
│ ├── session/ 会话键和会话标题
|
||
│ ├── agentbinding/ 渠道到 WeKnora Agent 的绑定
|
||
│ ├── feedback/ 点赞/点踩领域逻辑
|
||
│ ├── secretstore/ 本地密钥引用存储
|
||
│ ├── dingtalkconfig/ 钉钉凭据校验
|
||
│ ├── runtime/ 运行时管理
|
||
│ └── store/postgres/ PostgreSQL 持久化实现
|
||
├── db/migrations/ SQL 迁移及其契约测试
|
||
├── deploy/dobotai-dingtalk/ 容器 Compose、安装/配置/启动/绑定脚本和部署手册
|
||
├── docs/ 架构说明与 API 边界文档
|
||
├── scripts/ 本地部署与部署资产契约测试
|
||
├── Dockerfile DobotAI 容器镜像构建
|
||
├── .env.example 无真实凭据的配置示例
|
||
└── README.md 项目功能、边界和开发说明
|
||
```
|
||
|
||
目录职责规则:`cmd/`只装配进程,`internal/`承载业务模块,`internal/store/postgres/`只实现数据库持久化,`db/migrations/`只放Schema变更,`deploy/`只放容器运行资产。历史计划、备份、镜像归档和真实环境文件均不进入Git。
|
||
|
||
## 部署方式
|
||
|
||
| 方式 | 适用场景 | 数据库 | 入口 |
|
||
| --- | --- | --- | --- |
|
||
| 源码/原生二进制 | 本地开发、快速调试 | 手工配置阿里云RDS连接 | `go run ./cmd/dobotai` |
|
||
| Docker | 测试、预发布、生产候选 | 既有阿里云RDS;Docker不运行数据库 | `sudo bash ./install-docker.sh` |
|
||
|
||
### 源码部署
|
||
|
||
```bash
|
||
go run ./cmd/dobotai
|
||
curl --noproxy '*' -fsS http://127.0.0.1:8090/healthz
|
||
```
|
||
|
||
源码方式不自动安装Docker、不创建目录、不检查RDS表,也不适合作为长期渠道消费者。
|
||
|
||
### Docker + 阿里云RDS部署
|
||
|
||
克隆仓库后在根目录执行:
|
||
|
||
```bash
|
||
sudo bash ./install-docker.sh
|
||
sudo dobotai-dingtalk-configure
|
||
```
|
||
|
||
第一条命令自动安装Docker/Compose(如缺失)、构建应用镜像、准备目录和配置模板;第二条命令安全录入RDS、WeKnora与钉钉配置,然后检查RDS表:空库初始化`000001`至`000021`,完整表不写入,异常/半成品表拒绝启动。Docker只运行`dobotai-dingtalk`,不创建`dobotai-postgres`、本地数据卷或本地数据库。
|
||
|
||
完整安装、RDS检查、升级和回滚见 [Docker部署手册](deploy/dobotai-dingtalk/README.md)。
|
||
|
||
## 钉钉 Stream
|
||
|
||
使用官方 `dingtalk-stream-sdk-go`,不暴露公网回调入口。
|
||
|
||
- 群聊仅在机器人被 `@` 时处理;
|
||
- 私聊按用户保持长期会话;群聊默认按群共享会话;
|
||
- 回调 `sessionWebhook` 严格限制为 `https`、`*.dingtalk.com`、443端口且不允许重定向;
|
||
- 启用 Stream 必须同时设置以下三项;三者均为空时渠道禁用,部分配置会失败关闭:
|
||
|
||
```text
|
||
DINGTALK_CLIENT_ID
|
||
DINGTALK_CLIENT_SECRET
|
||
DOBOTAI_TENANT_KEY
|
||
```
|
||
|
||
## 推理模式命令
|
||
|
||
```text
|
||
/think <问题> 仅当前问题使用智能推理
|
||
/think on 开启持续智能推理
|
||
/think off 或 /rag 关闭持续智能推理
|
||
/setting rounds <1-50> 设置持续推理自动关闭轮数
|
||
/setting hint <on|off> 设置剩余轮次提示
|
||
/help、/帮助、/h 查看当前模式和帮助
|
||
```
|
||
|
||
持续推理默认最多10轮,成功回答才消耗轮次;10分钟无交互后逻辑到期,下一次问题自动回到快速问答。状态按 `tenant + channel + external_actor_id` 隔离。
|
||
|
||
## 首位管理员终端绑定
|
||
|
||
首位管理员不通过网页生成验证码。先确保钉钉 Stream 机器人已经正常运行,登录部署服务器后执行:
|
||
|
||
```bash
|
||
dobotai bootstrap-admin
|
||
```
|
||
|
||
若二进制未加入 `PATH`,使用其实际绝对路径执行。该命令只读取 `DATABASE_URL` 和 `DOBOTAI_TENANT_KEY`,不会启动 WeKnora、钉钉消费者或问答服务。
|
||
|
||
命令会在终端使用加密随机数生成一个有效期10分钟的六码绑定码,并保持等待。候选管理员必须私聊机器人发送:
|
||
|
||
```text
|
||
/setting <六码绑定码>
|
||
```
|
||
|
||
验证码正确后,终端自动将该钉钉用户绑定为 `super_admin` 并显示成功。已有有效管理员时命令会拒绝执行,防止通过该入口追加或替换管理员。DobotAI 不提供网页管理面;钉钉凭据和运行配置由部署环境文件管理。
|
||
|
||
## 覆盖与人工支持
|
||
|
||
- 有结构化检索引用的回答标记为已覆盖;
|
||
- 没有引用但已执行检索的回答标记为未覆盖;
|
||
- 没有引用且未执行检索的文本标记为 `covered_non_knowledge_response`,不创建 Support Case;
|
||
- 纯图片视觉识别单独记录为 `covered_visual_recognition`,不计入“未覆盖”;
|
||
- 无权威知识时,产品统一回复:`当前暂无已发布的权威知识,暂不建议操作。`;
|
||
- 人工通知只带当前问题和同一用户此前最多5个问题,不包含回答、引用或置信度;
|
||
- 未覆盖与点踩共用幂等 Support Case,避免对同一 Turn 重复通知。
|
||
|
||
## 配置
|
||
|
||
复制 `.env.example` 为仅本机可读的运行时环境文件,并在 Git 外注入真实值。不得提交 API Key、数据库密码、钉钉凭据、OSS AccessKey、预签名 URL 或真实用户/群组标识。
|
||
|
||
关键配置:
|
||
|
||
```text
|
||
DOBOTAI_LISTEN_ADDR
|
||
DOBOTAI_INGRESS_TOKEN
|
||
DOBOTAI_AGENT_BINDINGS
|
||
DOBOTAI_QUICK_AGENT_ID
|
||
DOBOTAI_REASONING_AGENT_ID
|
||
WEKNORA_BASE_URL
|
||
WEKNORA_API_KEY
|
||
DATABASE_URL
|
||
```
|
||
|
||
可选能力必须整组配置或整组留空:
|
||
|
||
- 钉钉 Stream;
|
||
- 钉钉 AI 卡片;
|
||
- 未覆盖问题 FAQ 表;
|
||
- 人工支持群通知;
|
||
- 问题表异步写入;
|
||
- 回答图片私有 OSS 外发。
|
||
|
||
任何部分配置均应在启动时失败关闭,而不是以不完整权限运行。
|
||
|
||
## 数据库迁移
|
||
|
||
DobotAI 使用独立 PostgreSQL,禁止指向 WeKnora 数据库。生产部署前必须按版本顺序执行并演练 `db/migrations/` 中的迁移;当前发布范围包含:
|
||
|
||
```text
|
||
000001_core ... 000018_coverage_visual_recognition_reason
|
||
000019_reasoning_mode_state
|
||
000020_feedback_support_trigger
|
||
000021_coverage_non_knowledge_response_reason
|
||
```
|
||
|
||
迁移前应执行逻辑备份并验证恢复;迁移、二进制部署和钉钉渠道切换是独立步骤,不能把健康检查代替真实渠道验收。
|
||
|
||
## 本地运行
|
||
|
||
```bash
|
||
go run ./cmd/dobotai
|
||
```
|
||
|
||
健康检查:
|
||
|
||
```bash
|
||
curl http://127.0.0.1:8090/healthz
|
||
```
|
||
|
||
运行版本:
|
||
|
||
```bash
|
||
curl http://127.0.0.1:8090/version
|
||
```
|
||
|
||
部署脚本应将 `version`、`commit_sha` 和 `build_time` 写入二进制,并仅在 `/version` 返回预期提交时接受部署。候选源码必须干净,避免运行版本掩盖未提交改动。
|
||
|
||
## 安全要求
|
||
|
||
- 不修改 WeKnora 源码、Schema 或私有包;
|
||
- 不直接连接 WeKnora 数据库;
|
||
- 不将凭据、Token、预签名 URL 或知识正文写入日志;
|
||
- 不接受任意外部图片 URL 作为可信媒体;
|
||
- 对钉钉图片、WeKnora `resource://` 图片和 OSS 返回体均执行来源、大小、类型和签名校验;
|
||
- 外发 OSS Bucket 保持私有;
|
||
- 生产、测试的钉钉应用、数据库、OSS Bucket 和凭据必须相互隔离;
|
||
- 生产上线必须使用已验收的同一构建产物,禁止在生产重新编译。
|
||
|
||
更多设计与边界见 `docs/architecture.md`。 |