Fix SSE route dependency and align architecture docs
This commit is contained in:
@@ -24,7 +24,13 @@
|
||||
|
||||
### 2.1 `DocumentProcessor` 责任过载
|
||||
|
||||
`backend/app/services/document_processor.py` 当前同时承担:
|
||||
现状判断:
|
||||
|
||||
- `backend/app/services/document_processor.py` 已经不再是当前主要编排点
|
||||
- 上传、查询和问答的核心组织逻辑已经明显下沉到 `backend/app/application/*` 以及 `backend/app/shared/bootstrap.py`
|
||||
- `DocumentProcessor` 当前更接近一个兼容旧调用路径的 legacy façade
|
||||
|
||||
其历史上曾集中承载过以下职责:
|
||||
|
||||
- 文档解析
|
||||
- 摘要生成
|
||||
@@ -33,22 +39,34 @@
|
||||
- Milvus 入库
|
||||
- 检索入口
|
||||
|
||||
这使上传处理链路、检索链路与基础设施初始化逻辑耦合在一个大类中。流程编排与具体实现没有边界,后续无论替换 parser、embedding、vector store 还是增加文档状态管理,都会直接影响同一个类。
|
||||
当前真正还需要收口的问题不是“继续拆这个大类”,而是把文档元数据、解析、分块、向量化和索引写入的稳定边界进一步收束到 application service 与端口接口中,避免后续重构继续围绕旧实现形态做判断。
|
||||
|
||||
### 2.2 检索逻辑缺少稳定边界
|
||||
|
||||
`backend/app/services/rag/retriever.py` 当前同时管理:
|
||||
现状判断:
|
||||
|
||||
- `backend/app/services/rag/retriever.py` 已经明显退化为兼容层
|
||||
- 真正承担检索编排的是 `KnowledgeRetrievalService` 和 `shared/bootstrap` 中的 wiring
|
||||
- `Retriever` 应被视为业务侧端口,而不是当前主编排单元
|
||||
|
||||
其历史上曾集中承载过以下职责:
|
||||
|
||||
- embedder 初始化
|
||||
- Milvus 连接与 collection lifecycle
|
||||
- 检索执行
|
||||
- 结果映射
|
||||
|
||||
这意味着“检索能力”不是一个稳定的业务能力接口,而是一个直接依赖具体 embedding 和 Milvus 实现的复合服务。后续如果从 `BGE-M3 + hybrid search` 切到 `1536 dense-only` 或替换向量索引实现,会直接影响检索服务本身。
|
||||
所以这里的重点不是把旧 retriever 当成未来架构核心,而是确认检索能力的稳定边界已经迁移到 application 层,并继续清理仍然残留的 provider-specific 细节。
|
||||
|
||||
### 2.3 `QAAgent` 责任过载
|
||||
|
||||
`backend/app/services/agent/qa_agent.py` 当前同时承担:
|
||||
现状判断:
|
||||
|
||||
- `backend/app/services/agent/qa_agent.py` 已经不是当前主要问答编排点
|
||||
- 当前实际的问答编排已经主要落到 `AgentConversationService`
|
||||
- `QAAgent` 当前更接近向后兼容的 legacy façade
|
||||
|
||||
其历史上曾集中承载过以下职责:
|
||||
|
||||
- 检索调用
|
||||
- 上下文构建
|
||||
@@ -57,7 +75,7 @@
|
||||
- SSE 流式问答流程
|
||||
- 会话 workflow 编排
|
||||
|
||||
这导致 Agent workflow 与检索底座、LLM provider、上下文构造逻辑紧耦合。后续切换 LLM provider、替换 session store、复用 retrieval 能力时,影响面会扩散到整个 Agent 实现。
|
||||
剩余风险不在于“它还很大”,而在于仍有少量 API 入口和 session 读写没有完全收口到 application service,导致目标边界和现状之间还存在断点。
|
||||
|
||||
### 2.4 API 层直接编排具体服务
|
||||
|
||||
@@ -73,6 +91,10 @@
|
||||
- 路由层知道过多内部实现细节
|
||||
- 后续如果内部模块调整,路由层也要跟着改
|
||||
|
||||
现状里这条判断需要修正:大部分主流程已经通过 `backend/app/shared/bootstrap.py` 统一装配,并由 application service 承担编排;真正还没有完全收口的是 `backend/app/api/routes/agent.py` 中的 session/history/feedback 这类接口,它们仍直接访问 `ConversationStore`。
|
||||
|
||||
因此,当前问题不是“路由层仍然是主编排中心”,而是“少数会话管理接口还没有通过 application service 统一封装”,这会持续打破 API 只做 transport concerns 的边界。
|
||||
|
||||
### 2.5 文档元数据与对象存储组织方式耦合
|
||||
|
||||
当前文档列表与下载逻辑高度依赖 MinIO 对象命名方式和对象遍历结果。对象存储目前承担了部分“业务真相”的角色,但对象存储只适合作为文件二进制载体,不适合作为完整文档元数据和状态管理的唯一来源。
|
||||
@@ -84,7 +106,9 @@
|
||||
- `knowledge` 通过 `DocumentProcessor.search()` 访问检索
|
||||
- `agent` 通过 `Retriever` 访问检索
|
||||
|
||||
这会导致同一检索能力未来演进成两条链路,难以统一检索策略、元数据模型和可替换边界。
|
||||
这条问题描述需要更新。现在检索主链路已经被 `KnowledgeRetrievalService` 统一收束,`knowledge` 与 `agent` 的共享底座比过去清晰得多。
|
||||
|
||||
当前仍未完全收口的是 Agent 的 session 相关能力:公开 API 里还存在 `/agent/session/{id}`、`/agent/session/{id}/history`、`/agent/sessions`、`/agent/feedback` 等接口直接读写 `ConversationStore`,这意味着“问答编排统一了,但会话管理还没有统一入口”。
|
||||
|
||||
## 3. Architecture Goals
|
||||
|
||||
@@ -132,7 +156,8 @@
|
||||
系统必须形成稳定的单向依赖关系:
|
||||
|
||||
- `api -> application -> domain`
|
||||
- `application -> infrastructure` 通过端口/实现绑定
|
||||
- `application -> domain ports`
|
||||
- `composition root -> application + infrastructure bindings`
|
||||
- `infrastructure -> external systems`
|
||||
|
||||
不允许出现基础设施实现反向驱动业务编排,也不允许 domain 依赖 Web 或第三方 SDK。
|
||||
@@ -238,12 +263,20 @@ backend/app/
|
||||
- 通用异常
|
||||
- 通用工具
|
||||
- 公共基础设施无关组件
|
||||
- composition root 与依赖装配
|
||||
- 运行时共享的 wiring 辅助入口
|
||||
|
||||
非职责:
|
||||
|
||||
- 不承载业务编排
|
||||
- 不变成新的 `services` 大杂烩目录
|
||||
|
||||
说明:
|
||||
|
||||
- `shared` 不是业务层,但它是本项目当前明确的装配层。
|
||||
- `backend/app/shared/bootstrap.py` 是现阶段的 composition root,负责把端口实现、基础设施适配器和 application service 连接起来。
|
||||
- 后续如果新增 wiring 入口,应继续保持在同一类装配边界内,不要把依赖装配拆回各个路由或 service 构造函数中。
|
||||
|
||||
## 5. Module Responsibilities
|
||||
|
||||
### 5.1 `api`
|
||||
@@ -269,6 +302,11 @@ backend/app/
|
||||
- `KnowledgeRetrievalService`
|
||||
- `AgentConversationService`
|
||||
|
||||
说明:
|
||||
|
||||
- 这 4 类是当前已经明确成型的核心用例服务,但不是 application 的全部上限。
|
||||
- 现有 Agent session 管理接口所需的会话查询、历史读取、删除和反馈归档能力,后续应补入 application 层的明确用例服务或子服务,而不是继续让 API 直连 `ConversationStore`。
|
||||
|
||||
### 5.3 `domain`
|
||||
|
||||
`domain` 层定义系统内部真正稳定的概念,例如:
|
||||
@@ -467,6 +505,21 @@ backend/app/
|
||||
- 当前 `QAAgent` 的 workflow 编排职责在目标态应迁移到这里,或被其吸收后只保留 façade 角色。
|
||||
- SSE 与普通问答必须共用这一层,不允许复制业务编排逻辑。
|
||||
|
||||
### 7.5 `AgentSessionService`
|
||||
|
||||
职责:
|
||||
|
||||
- 读取会话详情
|
||||
- 读取会话历史
|
||||
- 列出会话
|
||||
- 删除会话
|
||||
- 记录会话反馈
|
||||
|
||||
说明:
|
||||
|
||||
- 这类能力目前仍散落在 `backend/app/api/routes/agent.py`,并直接依赖 `ConversationStore`。
|
||||
- 目标态应把它们收口到 application 层,保证 API 只处理 transport concerns,而不是继续承担 session 级业务访问。
|
||||
|
||||
## 8. Core Workflows
|
||||
|
||||
### 8.1 文档上传入库链路
|
||||
@@ -519,27 +572,63 @@ backend/app/
|
||||
- 业务编排链必须完全复用
|
||||
- 检索能力必须来自同一 `KnowledgeRetrievalService`
|
||||
|
||||
### 8.4 Agent Session 管理链路
|
||||
|
||||
目标流程如下:
|
||||
|
||||
1. `api/agent/session/*` 或 `api/agent/sessions` 接收会话管理请求
|
||||
2. `AgentSessionService` 读取、列出、删除或归档反馈
|
||||
3. `ConversationStore` 负责持久化与会话生命周期细节
|
||||
4. API 输出 session 详情、历史、列表或反馈结果
|
||||
|
||||
约束:
|
||||
|
||||
- 会话详情、历史、列表和反馈接口不属于问答编排本身,应由独立的 session application service 处理。
|
||||
- 这部分能力不应继续直接暴露 `ConversationStore` 给路由层。
|
||||
|
||||
## 9. Dependency Rules
|
||||
|
||||
系统内部依赖方向固定如下:
|
||||
|
||||
```text
|
||||
api -> application -> domain
|
||||
application -> infrastructure (through ports)
|
||||
application -> domain ports
|
||||
composition root -> application + infrastructure bindings
|
||||
infrastructure -> external systems
|
||||
```
|
||||
|
||||
具体规则如下:
|
||||
|
||||
- `api` 可以依赖 `application` 和 API 自己的 request/response models
|
||||
- `application` 可以依赖 `domain` 和端口绑定后的 infrastructure 实现
|
||||
- `application` 只能依赖 `domain`、端口接口,以及通过 composition root 注入进来的实现实例
|
||||
- `domain` 不能依赖 `api` 或 `infrastructure`
|
||||
- `infrastructure` 可以依赖 `domain` 定义的端口和数据模型,但不能反向驱动 application 逻辑
|
||||
|
||||
说明:
|
||||
|
||||
- 端口绑定发生在 `shared/bootstrap.py` 这类 composition root,而不是 application 层内部。
|
||||
- application 只能接收已装配好的依赖实例,不能反向“依赖某个 infrastructure 实现类”作为其设计前提。
|
||||
|
||||
## 10. Migration Mapping From Current Code
|
||||
|
||||
当前关键代码到目标模块的映射如下。
|
||||
|
||||
### 10.0 旧 facade 存续策略
|
||||
|
||||
当前仓库里仍保留若干旧 facade / 兼容入口,包括但不限于:
|
||||
|
||||
- `backend/app/services/document_processor.py`
|
||||
- `backend/app/services/rag/retriever.py`
|
||||
- `backend/app/services/agent/qa_agent.py`
|
||||
|
||||
这些类的定位是“兼容现有调用方的过渡入口”,不是目标态的主要编排层。它们在迁移完成前应继续保留,直到对应的调用方、测试和 API 入口都迁移到 application service 或新的适配层为止。
|
||||
|
||||
约束:
|
||||
|
||||
- 不允许因为目标架构已经定义,就在没有替换调用方的情况下直接删除这些 facade。
|
||||
- 任何清理旧 `services` 的动作,都必须先确认是否还存在非 HTTP 的内部调用、测试依赖或临时适配依赖。
|
||||
- 这些 facade 可以逐步瘦身,但在迁移窗口内应优先保持行为兼容,而不是追求“文件级清零”。
|
||||
|
||||
### 10.1 文档处理
|
||||
|
||||
当前:
|
||||
@@ -551,6 +640,7 @@ infrastructure -> external systems
|
||||
- 其流程编排职责迁移到 `application/documents/DocumentCommandService`
|
||||
- 解析、分块、向量、入库分别通过端口接入
|
||||
- 检索入口从该类中剥离,不再由 ingest orchestration 承担 search 职责
|
||||
- 迁移期间该类作为兼容 facade 保留,直到所有直接调用点收口完成
|
||||
|
||||
### 10.2 检索
|
||||
|
||||
@@ -563,6 +653,7 @@ infrastructure -> external systems
|
||||
- `domain/retrieval` 中定义 `Retriever` 端口和统一检索结果模型
|
||||
- `infrastructure/vectorstore` 中承载具体检索实现
|
||||
- `application/knowledge/KnowledgeRetrievalService` 作为统一检索用例入口
|
||||
- 迁移期间该类作为兼容 facade 保留,避免影响现有检索调用方
|
||||
|
||||
### 10.3 Agent Workflow
|
||||
|
||||
@@ -576,6 +667,7 @@ infrastructure -> external systems
|
||||
- 具体 LLM 调用走 `AnswerGenerator`
|
||||
- 具体 session 读写走 `ConversationStore`
|
||||
- 检索统一走 `KnowledgeRetrievalService`
|
||||
- 迁移期间该类作为兼容 facade 保留,避免影响现有问答和测试调用点
|
||||
|
||||
### 10.4 存储
|
||||
|
||||
|
||||
Reference in New Issue
Block a user