Files

106 lines
8.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 后端 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`)的分层:
1. 在 `api/<domain>.py` 定义 router、prefix、tags 和 Swagger summary;
2. 使用 `SessionDep`、`CurrentUser`、`Trans` 等依赖注入;
3. 资源型接口配置 `@require_permissions`,确认 `keyExpression` 指向真实资源;
4. 需要审计的操作配置 `@system_log`,新代码优先让权限装饰器位于审计装饰器外层,只记录已授权操作;
5. handler 只做参数解析、权限上下文提取和分支,业务规则下沉到 CRUD/service;
6. 返回领域对象、DTO 或既有分页 dict;正常 JSON 由 `ResponseMiddleware` 包装,不要手工包一层 `code/data/msg`;
7. 用户可见异常通过 `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` 的分层:
1. `get_<entity>_base_query` 构造工作空间过滤;
2. `build_<entity>_query` 追加搜索、作用域、join、count 和分页;
3. `execute_<entity>_query` 转换为 DTO/result;
4. `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`:
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 消息;筛选的作用域、命中和组合规则见 `docs/agents/knowledge-enhancement.md`。
5. 未绑定数据源时,先由模型选择数据源;服务随后校验数据源访问权和连接可用性。
6. 模型生成 SQL 后,服务解析 SQL、对照允许的表元数据校验引用表,并按需应用行权限或助手动态 SQL 变换。
7. 服务执行最终 SQL,规范化大数字和带限定名的列结果,并持久化查询结果。
8. 模型基于实际使用的表结构生成图表配置;服务校验并持久化配置。非会话式流式调用还可请求渲染图片。
9. 分析和预测是基于既有图表记录的独立后续执行。
10. 猜测问题与已配置的推荐问题分开生成。
`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`。