From cd1c1e0e388030a5ad7515ae59edf69c42ead26e Mon Sep 17 00:00:00 2001 From: ulleo Date: Thu, 24 Sep 2026 18:17:55 +0800 Subject: [PATCH 1/2] docs: add CLAUDE.md importing AGENTS.md for auto-load --- CLAUDE.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..86154202 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,3 @@ +项目规范统一维护在 AGENTS.md(单一事实来源),本文件仅作 Claude Code 自动加载的导入入口,不要在此另写规则。 + +@AGENTS.md From ad0beea1b7f969ff0c7435e481cd979d98746acd Mon Sep 17 00:00:00 2001 From: ulleo Date: Thu, 24 Sep 2026 18:18:57 +0800 Subject: [PATCH 2/2] docs: enrich domain glossary and rewrite open questions for handoff --- CONTEXT.md | 86 ++++++++++++++++++++++++++-- docs/agents/backend.md | 17 ++++-- docs/agents/domain-open-questions.md | 75 +++++++++++++----------- docs/agents/knowledge-enhancement.md | 41 +++++++++++++ 4 files changed, 174 insertions(+), 45 deletions(-) create mode 100644 docs/agents/knowledge-enhancement.md diff --git a/CONTEXT.md b/CONTEXT.md index 905a2a29..b47b597a 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -14,32 +14,80 @@ _Avoid_: Organization、tenant 工作空间的标识。历史上的 `oid` 和 `workspace_id` 字段表示同一个概念。 _Avoid_: 把 `oid` 理解成独立的组织概念 +**System Admin / 系统管理员**: +内置的系统级管理员账号,拥有全部管理能力,不属于工作空间角色体系。 +_Avoid_: Workspace Admin + +**Workspace Admin / 工作空间管理员**: +工作空间内拥有管理能力的成员角色,由成员权重非零标识。 +_Avoid_: System Admin + **Datasource / 数据源**: 已配置的外部数据源,以及 SQLBot 用于生成查询的表、字段、关系和 embedding 等元数据。 _Avoid_: Database、connection +**Excel Datasource / Excel 数据源**: +上传的 Excel/CSV 物化到内置库后按 PostgreSQL 处理的导入型数据源。 +_Avoid_: 外部连接型数据源、内存数据源 + +**Dynamic Datasource / 动态数据源**: +高级应用每次会话从宿主 API 实时拉取的数据源,不落库。 +_Avoid_: 内置数据源、普通数据源 + +**Table Relation / 表关系**: +人工在关系图上维护的表关联,为多表查询提供 JOIN 上下文。 +_Avoid_: 外键约束(数据库层的约束) + **SQL Example / SQL 示例**: -用于引导 SQL 生成的“问题 + SQL”示例。 +用于引导 SQL 生成的“问题 + SQL”示例,必须归属于一个数据源或一个高级应用。 _Avoid_: Data training、training data **Terminology / 术语**: -业务词或短语的解释,可包含同义词,用于提升问题和表结构理解。 +业务词或短语的解释,由主词和同义词构成,用于提升问题和表结构理解。 _Avoid_: Custom prompt、SQL example **Custom Prompt / 自定义提示词**: -附加在模型任务上的场景指令,可按工作空间、数据源或助手场景生效。 +附加在模型任务上的场景指令,按任务环节(生成 SQL、分析、预测)分类,可按工作空间、数据源或高级应用生效。 _Avoid_: Terminology、SQL example +**Knowledge Scope / 知识作用域**: +术语、SQL 示例和自定义提示词生效的边界:工作空间、数据源或高级应用。高级应用是独立知识域,不继承工作空间级知识。 +_Avoid_: 权限——作用域决定向模型注入哪些知识,权限决定用户能访问哪些数据 + +**Row Permission / 行权限**(xpack): +对表追加的行级过滤条件;同一表命中多条时取 AND,经改写 SQL 执行。 +_Avoid_: Column Permission + +**Column Permission / 列权限**(xpack): +从可见字段中剔除指定列;同一表命中多条时求交,作用于提供给模型的表结构。 +_Avoid_: Row Permission + +**Base Model / 基础模型**: +实际调用供应商 API 时使用的模型标识。 +_Avoid_: 模型名称(仅显示用,与基础模型无强制关系) + +**Default Model / 默认模型**: +系统全局唯一的默认问答模型;工作空间不设各自的默认模型。 +_Avoid_: 工作空间默认模型(该概念不存在) + ### 会话 **Chat / 会话**: 用户在一个工作空间内连续提出数据问题的对话。 _Avoid_: Assistant、dashboard +**Chat Origin / 会话来源**: +会话创建入口的溯源标记:页面、MCP 或小助手。 +_Avoid_: 助手目标域名(Assistant Domain) + **Chat Record / 会话记录**: 一次问题执行的可持久化结果,包含问题、生成 SQL、查询结果、图表配置、错误以及关联的后续记录。 _Avoid_: Chat +**Opening Record / 开场记录**: +助手会话开始时自动创建的占位记录,无提问,承载数据源配置的推荐问题;不是一次真实的问答。 +_Avoid_: 会话中第一条问答记录 + **Analysis / 分析**: 基于既有问题结果的模型生成解读。 _Avoid_: Prediction @@ -75,9 +123,37 @@ _Avoid_: Ordinary assistant、page-embedded assistant _Avoid_: Ordinary assistant、advanced assistant **Assistant Domain / 助手目标域名**: -小助手对接的外部目标系统域名。 +允许承载小助手或嵌入页面的宿主 origin 精确白名单,仅在握手类接口校验。 _Avoid_: Business domain、workspace +**Assistant Certificate / 助手凭据**: +高级应用逐请求透传给宿主数据源 API 的宿主系统凭据。 +_Avoid_: App Secret(验签密钥,不是透传凭据) + +**App Secret / 应用密钥**: +页面嵌入应用与宿主页面共享的密钥,用作宿主自签 JWT 的验签依据。 +_Avoid_: app_id(仅用于反查应用,无认证作用)、Assistant Certificate + +**MCP**: +以独立服务进程暴露问数工具集的集成形态,调用者以真实用户身份接入,数据权限按该用户计算。 +_Avoid_: Ordinary Assistant、Page-embedded Assistant + **Dashboard / 仪表板**: -为重复分析保存的数据视图集合。 +由会话图表快照与文本、Tab 组件组成的画布;图表组件是会话记录的配置快照,数据在查看时实时查询。 _Avoid_: Chat、chat record + +### 商业扩展(xpack) + +以下词条的实现位于商业扩展包 sqlbot-xpack。 + +**License / 许可证**(xpack): +商业授权凭据,以整体有效或失效门控商业功能,无功能级能力项。 +_Avoid_: 社区版/企业版(代码仅区分许可证有效与否) + +**Authentication Source / 认证源**(xpack): +用于外部身份登录的 SSO 身份源,支持 CAS、OIDC、LDAP、OAuth2、SAML2。 +_Avoid_: Platform Integration + +**Platform Integration / 平台集成**(xpack): +企业微信、钉钉、飞书、Larksuite 的组织与用户同步及扫码登录。 +_Avoid_: Authentication Source diff --git a/docs/agents/backend.md b/docs/agents/backend.md index a5062d13..5bb29664 100644 --- a/docs/agents/backend.md +++ b/docs/agents/backend.md @@ -3,12 +3,11 @@ ## 领域与代码映射 - `oid` 和 `workspace_id` 是同一个工作空间 ID 的历史命名。 -- `AssistantModel.type`: - - `0`:普通小助手; - - `1`:高级应用; - - `4`:页面嵌入。 +- `AssistantModel.type` 实际值域 `0`–`4`:`0` 普通小助手;`1` 高级应用;`4` 页面嵌入;`2`、`3` 为遗留兼容值,行为分别等同 `0`、`1`,当前无创建入口。 - `AssistantModel.domain` 表示对接目标系统的域名,不是业务领域。 - `DataTraining` 是「SQL 示例库」概念的持久化命名。 +- `Chat.chat_type` 目前只有 `chat` 一个有效值;`datasource` 是为未实现的表字段备注自动生成功能预留的遗留值。 +- `ChatRecord.recommended_question` 同时承载两种内容:开场记录中是数据源配置的推荐问题,普通记录中是模型生成的猜测问题。 ## 代码组织 @@ -85,7 +84,7 @@ Endpoint 命名沿既有风格: 1. `POST /chat/start` 与 `POST /chat/assistant/start` 在工作空间内创建会话,并可绑定初始数据源或助手上下文。 2. `POST /chat/question` 先解析快速命令。普通问题进入 `stream_sql`;`/regenerate` 直接再生。`/analysis` 和 `/predict` 在会话内会直接拒绝(temporary not supported),实际通过 `POST /record/{chat_record_id}/{action_type}` 触发。 3. `stream_sql` 构造 `LLMService`,创建 `ChatRecord`,并启动异步执行。 -4. 已绑定数据源时,服务先提取关键词并扩展术语,再筛选适用的术语、SQL 示例和自定义提示词,随后组装 SQL 消息。 +4. 已绑定数据源时,服务先提取关键词并扩展术语,再筛选适用的术语、SQL 示例和自定义提示词,随后组装 SQL 消息;筛选的作用域、命中和组合规则见 `docs/agents/knowledge-enhancement.md`。 5. 未绑定数据源时,先由模型选择数据源;服务随后校验数据源访问权和连接可用性。 6. 模型生成 SQL 后,服务解析 SQL、对照允许的表元数据校验引用表,并按需应用行权限或助手动态 SQL 变换。 7. 服务执行最终 SQL,规范化大数字和带限定名的列结果,并持久化查询结果。 @@ -95,4 +94,12 @@ Endpoint 命名沿既有风格: `ChatFinishStep` 允许一次执行在生成 SQL、查询数据或生成图表后停止。不要假设所有调用方都需要完整图表流程。 +### 记录状态与衍生关系 + +- 记录终态二元:`finish=true` 即终态,`error` 非空即失败。生成 SQL、执行、图表任一阶段失败都写同一个 `error` 字段;失败阶段从已填充字段推断(有 SQL 无数据为执行失败,有数据无图表为图表失败),精确失败点看 ChatLog 的 `error` 标记。 +- 分析和预测各生成一条新的完整记录,复制源记录的问题、图表和数据,以 `analysis_record_id` / `predict_record_id` 指回源记录;衍生记录不能再被分析、预测或再生。 +- 再生记录以 `regenerate_record_id` 指向被再生记录,形成链,沿链回溯可取到原始问题。 +- 开场记录(`first_chat=true`)不能被分析、预测或再生;查找"上一条记录"时排除开场记录。 +- 问题快捷入口按位置分两个标签:"猜你想问"是会话级快捷提问入口(开场记录展示数据源配置的推荐问题,输入框区域展示生成的猜测问题);"继续问"是每次成功回答后的追问入口(生成的猜测问题)。 + 验证要求与测试选择标准见 `docs/agents/testing.md`。 diff --git a/docs/agents/domain-open-questions.md b/docs/agents/domain-open-questions.md index 7aa6c65d..a7375d82 100644 --- a/docs/agents/domain-open-questions.md +++ b/docs/agents/domain-open-questions.md @@ -2,63 +2,68 @@ 这份文件是待查证目录,不是每项任务都要逐条询问的问卷。只处理影响当前任务的边界,先检查源码、测试和已有文档;仍无法确定且影响业务决策时再询问使用者。问题确认后,把稳定术语移入根目录 `CONTEXT.md`,行为规则放入对应按需文档,再从本文删除对应问题。 +2026-09-24 全量查证过一轮(主仓库 + sqlbot-xpack 可读源码):各节"已确认"为代码事实,对应词条已入 `CONTEXT.md`;标注【待答】的问题需要产品/设计判断,均附代码现状,回答后按开头流程归档("设计 vs 待修"类问题需二选一:按现状入档+风险注记,或转待修项)。 + ## 工作空间与用户 -- 用户在工作空间中的角色如何定义?`UserWsModel.weight` 的取值和含义是什么? -- 系统管理员、工作空间管理员、普通用户、数据源管理员之间的权限边界是什么? -- 用户是否可以同时属于多个工作空间?切换工作空间对会话、数据源、模型和助手上下文有什么影响? +已确认:成员权重 0=普通成员、1=工作空间管理员(-1 为"无关联记录"哨兵);系统管理员为内置 id=1 的 admin 账号,与成员权重正交;用户可同时属于多个工作空间,当前工作空间是用户表上的单值;数据源可见性=工作空间归属。 -## 数据源与元数据 +【待答】 +- "数据源管理员"这一角色叫法是否存在于产品文案?代码中不存在该角色:数据源管理接口全部要求工作空间管理员,行/列权限面向普通用户配置。 +- 用户-工作空间关联表(sys_user_ws)无 (uid, oid) 唯一约束,理论上可出现重复关联行。接受现状还是待修? -- 数据源的完整生命周期是什么?创建、连接校验、元数据同步、启用/禁用、删除分别如何界定? -- Excel 数据源在领域上是普通数据源的一种,还是有独立生命周期和限制? -- 表关系、表备注、字段备注、embedding 的业务含义和维护责任分别是什么? -- 高级应用动态数据源与普通数据源在领域上的差异是什么? +## 数据源与元数据 -## 知识增强 +已确认:创建时不校验连接(校验是独立步骤,重新勾选表前强制执行);元数据同步无定时任务,仅创建、重新勾选表、单表字段同步三个触发点;数据源级无启用/禁用(仅表/字段级);Excel 为物化进内置库的导入型数据源;表关系人工维护、无自动推断;备注为"同步值 + 用户值"双轨且用户值优先;表级/数据源级两级 embedding;动态数据源每次会话实时拉取宿主 API、不落库。 -- 术语、SQL 示例、自定义提示词的作用域规则是否完全一致? -- 当同一问题命中多个术语、多个 SQL 示例或多个自定义提示词时,选择和组合规则是什么? -- embedding 相似度、关键词匹配和高级应用/数据源绑定之间的优先级是什么? +【待答】 +- 删除数据源时不清理推荐问题(ds_recommended_problem)和行/列权限(ds_permission、ds_rules),成为孤儿数据。接受现状还是待修? +- CoreDatasource.status 全代码只见赋值 "Success";是否存在其他历史取值或预期取值(如连接失败标记)? ## 权限 -- 工作空间权限、数据源权限、行权限、列权限、API 权限如何叠加? -- 权限冲突时使用交集、并集还是显式拒绝优先? -- 页面嵌入、高级应用和 MCP 场景下的用户身份与数据权限如何映射? +已确认:数据源可见性=工作空间归属(硬边界,校验失败拒绝);行权限多条命中 AND、列权限多条命中求交;无 deny 语义;admin(id=1)绕过行/列权限;高级应用不走本地行/列权限、改用宿主表级 rule;行权限经 LLM 改写 SQL 执行;列权限只作用于提供给模型的表结构和数据预览。 -## 助手与集成 +【待答】 +- 行权限的强制执行方式是"LLM 改写 SQL",无确定性的 WHERE 注入或结果集二次过滤兜底。按现状入档+风险注记,还是列待加固项? +- 行/列权限未命中任何规则即不限制(fail-open);white_list_user 字段在权限两个模型中已定义但全代码无读取。同上二选一。 -- `AssistantModel.type` 目前确认 `0` 普通小助手、`1` 高级应用、`4` 页面嵌入;是否还有其他历史值或保留值? -- 普通小助手、高级应用、页面嵌入在目标系统认证、数据源获取和页面能力上的完整差异是什么? -- `app_id`、`app_secret`、`domain` 与目标系统信任关系如何建模? +## 助手与集成 -## Chat 流程与产物 +已确认:type 实际值域 0/1/2/3/4,2≡0、3≡1(遗留兼容值、无创建入口,已记入 backend.md);普通小助手/高级应用/页面嵌入三形态的认证、数据源获取、页面能力差异已查明;domain 是 origin 精确白名单、仅握手类接口校验、运行期 API 不校验;app_id 仅反查、app_secret 作 HMAC 验签。 -- `Chat.chat_type`、`Chat.origin`、`first_chat`、`regenerate_record_id` 等状态字段的完整业务含义是什么? -- 分析记录、预测记录和普通问答记录的生命周期与展示关系是什么? -- 生成失败、执行失败、图表失败时,`ChatRecord` 的最终状态如何界定? -- 猜测问题和推荐问题在产品展示上是否使用相同入口?二者是否需要统一命名? +【待答】 +- /system/assistant/info/{id}、/system/assistant/app/{appId} 在认证白名单内且响应未剔除 app_secret:通过 origin 校验的页面即可获取应用的 app_id 与 app_secret。按现状入档+风险注记,还是列待加固项? +- type=3 除与 type=1 共用动态数据源分支外是否曾有专属语义?(代码无单独分支,历史命名无法追溯。) ## 模型配置 -- 供应商、模型类型、基础模型、模型名称、默认模型、工作空间映射之间的准确关系是什么? -- 系统默认模型和工作空间可用模型的决策顺序是什么? -- 自定义模型在助手和 MCP 场景中的约束是什么? +已确认:模型名称是显示名、基础模型是真实模型标识;默认模型为系统全局唯一标志(首个模型自动成为默认、禁删),无"工作空间默认模型"概念;工作空间映射决定可选范围;选型链为助手自定义模型 → MCP 指定模型 → 系统默认,指定模型校验失败静默回退;embedding 使用固定本地模型,不走供应商/默认模型体系。 + +【待答】 +- 助手/MCP 指定模型会校验其属于当前工作空间的映射,但回退到系统默认模型时不校验默认模型是否映射到该工作空间。设计如此还是缺陷? +- model_type 字段存而不用(前端仅 0=大语言模型有效,运行时引擎实际由 protocol 决定)。遗留预留还是待实现? ## 仪表板 -- 仪表板只能由会话图表创建,还是也可以独立创建和编辑? -- 仪表板组件、会话记录、图表配置之间的归属关系是什么? -- 仪表板查看和编辑权限如何与工作空间、数据源权限叠加? +已确认:可独立创建(含文件夹、文本、Tab 组件),非只能来自会话图表;图表组件是会话图表的整份配置快照(无外键引用),查看时按快照内数据源+SQL 实时重执行,数据源被删则该组件标记失败;仅创建者本人可见可改;无分享无导出。 + +【待答】 +- 仪表板纯私有(无分享/协作)是否为产品定位? +- 删除会话不级联删除其记录(无外键、无清理);删除文件夹不级联删除子节点(孤儿在资源树上不显示)。接受现状还是待修? ## MCP 与嵌入 -- MCP 调用者、工作空间和数据源之间的授权关系是什么? -- 页面嵌入、小助手嵌入、MCP 在产品分类上的边界是什么? +已确认:MCP 为独立服务进程(8001 端口),暴露 7 个工具;调用者以真实用户身份接入,数据源授权=其工作空间全部数据源(无显式授权列表);行/列权限按该用户生效;另有 Open API 形态(API Key 验签映射到真实用户);页面嵌入、小助手嵌入、MCP 的认证边界已查明。 + +【待答】 +- mcp_model_list(仅凭 oid 即返回该工作空间模型列表)与 mcp_assistant(构造内置用户、无调用方鉴权)两个无鉴权入口:产品上有外层防护预期(网关/内网部署)还是待修? +- mcp_question 不校验会话归属:持有有效 token 加 chat_id 即可向他人会话提问(主应用 /chat/question 有权限装饰器而 MCP 路径没有)。设计如此还是待修? +- Open API(API Key)是否作为第四种对外暴露形态在 CONTEXT.md 立词条? ## xpack 商业概念 -- 许可证能力项、版本限制和功能开关如何影响领域对象? -- 认证源、平台集成、审计日志和商业权限的领域边界是什么? -- xpack 侧是否需要独立 `CONTEXT.md` 来维护商业扩展术语? +已确认:许可证仅整体有效/失效门控(无功能级能力项,硬校验为 product 与有效期);有效时才挂载外观、自定义提示词、认证源、平台集成、审计五组路由(到期动态摘除);行/列权限路由不受许可证门控;认证源=SSO 身份源、平台集成=企业 IM 对接、审计=查询侧在 xpack、写入侧在主仓库。词条已入 CONTEXT.md"商业扩展(xpack)"小节。 + +【待答】 +- 许可证数据的 edition、count 字段已定义但代码不消费(可能在 validator 二进制内部检查)。按现状记录,还是属于待实现? diff --git a/docs/agents/knowledge-enhancement.md b/docs/agents/knowledge-enhancement.md new file mode 100644 index 00000000..da1ec7ae --- /dev/null +++ b/docs/agents/knowledge-enhancement.md @@ -0,0 +1,41 @@ +# 知识增强 + +术语、SQL 示例和自定义提示词在问数流程中按作用域注入模型上下文。概念定义见根目录 `CONTEXT.md`;本文记录作用域、命中和组合的行为规则,修改相关知识逻辑前先对照本文确认预期行为。 + +## 作用域规则 + +三类知识的作用域维度不完全一致: + +| 维度 | 术语 | SQL 示例 | 自定义提示词 | +|---|---|---|---| +| 工作空间级(全局) | 支持 | 不支持 | 支持 | +| 数据源级 | 支持多选 | 仅单选 | 支持多选 | +| 高级应用级 | 支持 | 支持 | 支持 | +| 任务环节分类 | 无 | 无 | 生成 SQL / 分析 / 预测 | + +- SQL 示例必须绑定一个数据源或一个高级应用,没有工作空间级示例;两者都为空时不注入任何示例。 +- 数据源场景取并集:工作空间级知识 + 绑定当前数据源的知识。 +- 高级应用场景取替换:只注入绑定该高级应用的知识,工作空间级知识不生效。这是有意设计,不是缺陷。 +- 作用域的工作空间解析:普通小助手按助手所属工作空间;页面嵌入助手按当前用户的工作空间;高级应用按助手所属工作空间并使用应用绑定。 + +## 命中与组合规则 + +- 组合语义是“命中即注入”:命中多少条注入多少条,不做全局排序或择优。 +- 术语:优先用 LLM 提取的关键词匹配(无关键词时用原始问题),按逗号拆分逐词匹配;同义词命中归并到主词条目。 +- SQL 示例:用完整问题做双向包含匹配(问题包含示例问题,或示例问题包含问题)。 +- 自定义提示词:不做问题匹配,作用域内全部注入。 +- 关键词/包含匹配与 embedding 召回是并集关系,不是优先级关系:embedding 只是补充召回渠道,不淘汰关键词命中的结果。 +- `EMBEDDING_ENABLED=false` 时退化为纯关键词/包含匹配。 +- embedding 召回按相似度降序取 top N(默认 5)、相似度阈值默认 0.4,由 `EMBEDDING_*_SIMILARITY` / `EMBEDDING_*_TOP_COUNT` 配置。 +- 注入顺序固定:自定义提示词 → 术语 → SQL 示例,各自独立成段附在 schema 信息之后。 +- 术语另有一个独立用途:提取的关键词经术语同义词扩展后用于表匹配,与术语注入互不影响。 + +## 已知边界 + +- 关键词/包含匹配的命中数量没有上限,极端情况下可能注入大量内容(token 风险);只有 embedding 召回受 top N 限制。 + +## 代码入口 + +- 命中与作用域查询:`backend/apps/terminology/curd/terminology.py`、`backend/apps/data_training/curd/data_training.py`、`sqlbot-xpack/src/sqlbot_xpack/custom_prompt/curd/custom_prompt.py`。 +- 注入编排:`backend/apps/chat/task/llm.py` 的 `filter_terminology_template` / `filter_training_template` / `filter_custom_prompts`。 +- `backend/apps/settings/models/setting_models.py` 的 `term_model` 是无引用的遗留代码,与术语功能无关,不要在其上扩展。