mirror of
https://gh-proxy.org/https://github.com/klinsmaya/SQLBot.git
synced 2026-11-08 01:06:59 +08:00
8.1 KiB
8.1 KiB
后端 Agent 说明
领域与代码映射
oid和workspace_id是同一个工作空间 ID 的历史命名。AssistantModel.type实际值域0–4:0普通小助手;1高级应用;4页面嵌入;2、3为遗留兼容值,行为分别等同0、1,当前无创建入口。AssistantModel.domain表示对接目标系统的域名,不是业务领域。DataTraining是「SQL 示例库」概念的持久化命名。Chat.chat_type目前只有chat一个有效值;datasource是为未实现的表字段备注自动生成功能预留的遗留值。ChatRecord.recommended_question同时承载两种内容:开场记录中是数据源配置的推荐问题,普通记录中是模型生成的猜测问题。
代码组织
- 领域代码放在
backend/apps/<domain>/。多数域采用api/、crud/或curd/、models/分层;schemas/仅system和settings有,chat另有task/,ai_model、db、mcp、template、swagger不遵循该布局——新代码跟随所在域的既有形态。 - 项目同时存在
crud和curd拼写;不要为统一命名制造无关重构。 - 新 router 注册到
backend/apps/api.py。 - 应用组装、中间件、MCP 和 MCP 图片静态挂载属于
backend/main.py;init_fastapi_app在此触发 xpack 初始化,前端 dist 静态挂载与/xpack_static提取由 xpack 包内完成(见docs/agents/xpack.md)。 - SQLModel 结构变更必须配套 Alembic 迁移;细节见
docs/agents/migrations.md。 - 用户可见后端消息使用
backend/locales/,不要硬编码新文案。
API 黄金路径
新 endpoint 参考 terminology、data_training 域和 datasource 域内的 recommended_problem 模块(backend/apps/datasource/api/recommended_problem.py)的分层:
- 在
api/<domain>.py定义 router、prefix、tags 和 Swagger summary; - 使用
SessionDep、CurrentUser、Trans等依赖注入; - 资源型接口配置
@require_permissions,确认keyExpression指向真实资源; - 需要审计的操作配置
@system_log,新代码优先让权限装饰器位于审计装饰器外层,只记录已授权操作; - handler 只做参数解析、权限上下文提取和分支,业务规则下沉到 CRUD/service;
- 返回领域对象、DTO 或既有分页 dict;正常 JSON 由
ResponseMiddleware包装,不要手工包一层code/data/msg; - 用户可见异常通过
Trans使用 locale key;HTTPException留在 API 层,不要让 CRUD 依赖 FastAPI 响应细节。
Endpoint 命名沿既有风格:
- 分页:
GET /page/{current_page}/{page_size}; - 新增或更新:
PUT "",按info.id分支; - 删除:
DELETE "",传 ID 列表; - 启用/禁用:
GET /{id}/enable/{enabled}; - 导出:
GET /export; - 导入:
POST /uploadExcel。
只在确实与现有 API 兼容性冲突时发明新形态,并说明原因。
CRUD 与查询
- 查询构建参考
build_<entity>_query的分层:get_<entity>_base_query构造工作空间过滤;build_<entity>_query追加搜索、作用域、join、count 和分页;execute_<entity>_query转换为 DTO/result;page_<entity>返回 API 需要的分页元数据。
- 默认过滤当前
current_user.oid;管理员或助手场景必须显式说明为何可以切换工作空间。 - 使用 SQLAlchemy
select/and_/or_表达查询;不要为用户输入拼接 SQL 字符串。 - 分页先 count,再计算
total_pages,最后构造 offset/limit 子查询。 - 创建/更新前完成重复性、必填和作用域校验;不要先写入再依赖唯一约束报错。
- 事务提交通常发生在 CRUD/service 边界;API handler 不要随意中途 commit。
- embedding、缓存清理或后台任务沿用当前领域的线程任务模式,不在请求路径中阻塞等待长任务。
异步与阻塞
- FastAPI handler 可以是
async def,但不要在事件循环中执行外部 HTTP、pandas 大文件解析、CPU 密集转换或长时间文件 IO。 - 这些操作参考现有
asyncio.to_thread(inner)模式。 - 数据库 session 由依赖注入管理;在线程中需要新 session 时使用对应
session_maker()并确保清理。 - 不要把
asyncio.to_thread当成绕过权限或事务边界的手段。
模型与 DTO
- 表模型继承
SQLModel, table=True;输入/输出 DTO 使用 Pydantic BaseModel 或非 table SQLModel。 - 大 ID 使用
BigInteger;返回给前端时按既有 DTO 规则处理超过 JavaScript 安全整数的情况。 - 时间、启用状态、工作空间归属和高级应用/数据源作用域要显式建模,不依赖调用方隐式状态。
- 新增字段同时考虑迁移、导入/导出、embedding、缓存和 xpack 调用。
安全与事务边界
- 保留认证、工作空间/数据源权限、审计日志和既有错误响应模式;不要在 handler 中绕过它们。
- 生成 SQL、路径、Host 头和上传文件都按不可信输入处理。
- 不要削弱行数限制、权限过滤、元数据查询控制、Host 校验或路径穿越防护。
- 修改连接池、事务和异步执行边界时,先阅读相邻实现和回归测试;不要把阻塞调用移回事件循环。
- 商业实现留在 xpack;本仓库只保留对已发布包的调用和初始化。xpack 是必装硬依赖(启动即 import,无降级),许可证只做功能门控;加载场景见
docs/agents/xpack.md。
Chat 问题流程
主要入口在 backend/apps/chat/api/chat.py:
POST /chat/start与POST /chat/assistant/start在工作空间内创建会话,并可绑定初始数据源或助手上下文。POST /chat/question先解析快速命令。普通问题进入stream_sql;/regenerate直接再生。/analysis和/predict在会话内会直接拒绝(temporary not supported),实际通过POST /record/{chat_record_id}/{action_type}触发。stream_sql构造LLMService,创建ChatRecord,并启动异步执行。- 已绑定数据源时,服务先提取关键词并扩展术语,再筛选适用的术语、SQL 示例和自定义提示词,随后组装 SQL 消息;筛选的作用域、命中和组合规则见
docs/agents/knowledge-enhancement.md。 - 未绑定数据源时,先由模型选择数据源;服务随后校验数据源访问权和连接可用性。
- 模型生成 SQL 后,服务解析 SQL、对照允许的表元数据校验引用表,并按需应用行权限或助手动态 SQL 变换。
- 服务执行最终 SQL,规范化大数字和带限定名的列结果,并持久化查询结果。
- 模型基于实际使用的表结构生成图表配置;服务校验并持久化配置。非会话式流式调用还可请求渲染图片。
- 分析和预测是基于既有图表记录的独立后续执行。
- 猜测问题与已配置的推荐问题分开生成。
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。