feat(config): 删死配置 + 同步文档(T5 架构审查整改)
- Issue5: 删除 QdrantStoreConfig / VectorStoreConfig.qdrant / task_queue.redis_url - OV1: 同步 6 处文档(api-design §1/§4.3/§5/§6、rag-layer §9、agent-runtime §3、 design §5.5/§8.4.1、config-design、web-ui §4.1)+ tests/fixtures/rag.yaml - TaskQueue 标注 v1 仅 InMemory,Redis/Valkey 为 v2 预留(Scope 缩减裁定) - Storage Adapter 仅 ChromaAdapter,工厂移除 qdrant 分支 - 历史评审记录保留原样不改写 - 新增 3 用例,同步 2 个 qdrant 依赖用例;全量 189 passed / 100.00%(991 stmts/252 br)
This commit is contained in:
@@ -206,7 +206,7 @@ class PromptRegistry:
|
||||
```
|
||||
会话级: 显式状态机(管理大流程与人工介入)
|
||||
│
|
||||
└── 步骤内部: 任务队列(抽象 `TaskQueue`,默认 InMemory,生产可切 Redis/Valkey,接口详见 docs/api-design.md §5)
|
||||
└── 步骤内部: 任务队列(抽象 `TaskQueue`,v1 仅 InMemoryQueue;Redis/Valkey 为 v2 预留,接口详见 docs/api-design.md §5)
|
||||
└── 任务级状态(pending/running/completed/failed)
|
||||
```
|
||||
|
||||
@@ -288,7 +288,7 @@ events 表:
|
||||
### 3.5 步骤内部任务队列
|
||||
|
||||
```
|
||||
Task Queue(抽象 `TaskQueue`:默认 InMemoryQueue;生产切换 RedisQueue/ValkeyQueue 时行为一致,接口与幂等键见 api-design §5):
|
||||
Task Queue(抽象 `TaskQueue`:v1 仅 InMemoryQueue 实现;RedisQueue/ValkeyQueue 为 v2 预留,接口与幂等键见 api-design §5):
|
||||
task:generate-chapter-3
|
||||
status: pending | running | completed | failed
|
||||
payload: {chapter_id, data_refs, rule_refs, prompt_version}
|
||||
|
||||
+9
-17
@@ -29,13 +29,12 @@ FastAPI Orchestrator(单进程,默认)
|
||||
│
|
||||
├── SessionManager(会话状态机,见 agent-runtime §3)
|
||||
├── Agent 调度(Parser / Impact / Writer / QA)
|
||||
├── TaskQueue 抽象(默认 InMemory,可切 Redis/Valkey)
|
||||
├── TaskQueue 抽象(默认 InMemory;Redis/Valkey 为 v2 预留,见 §5)
|
||||
└── RagService 调用(规则检索)
|
||||
```
|
||||
|
||||
**架构决策**(与用户确认):
|
||||
- **编排形态**:抽象 `TaskQueue` 接口 + 双实现。默认 `InMemoryQueue`(开发/测试/演示零依赖);部署时可切换 `RedisQueue` / `ValkeyQueue`(Redis 协议兼容,`redis-py` 客户端通用)。
|
||||
- **许可说明**:Redis 内部使用合法(RSALv2/SSPLv1 仅限制「提供 Redis 托管服务给第三方」);若需完全开源无限制,使用 Valkey(BSD-3),代码无需改动。
|
||||
- **编排形态**:抽象 `TaskQueue` 接口 + **单一 `InMemoryQueue` 实现**(开发/测试/演示零依赖)。(T5 架构审查整改:Scope 缩减裁定移除 Redis/Valkey 双实现;接口保留供 v2 扩展。)
|
||||
- 所有 API 返回 JSON;长任务(解析/影响调查/生成)采用「异步启动 + 轮询/推送」模式。
|
||||
|
||||
---
|
||||
@@ -196,10 +195,10 @@ WS /api/ws/sessions/{id}
|
||||
Orchestrator 进程内 asyncio 任务池消费队列
|
||||
状态与任务结果共享内存(FastAPI 进程内)
|
||||
|
||||
切换(RedisQueue/ValkeyQueue):
|
||||
(v2 预留)RedisQueue/ValkeyQueue:
|
||||
Orchestrator 投递 → Redis/Valkey Stream
|
||||
worker 进程消费 → 执行 → 状态写回 SQLite / 事件回传
|
||||
需额外部署 worker 容器(见 §6)
|
||||
需额外部署 worker 容器(见 §6)—— v1 不实现(Scope 缩减裁定)
|
||||
```
|
||||
|
||||
---
|
||||
@@ -210,7 +209,7 @@ WS /api/ws/sessions/{id}
|
||||
|
||||
```python
|
||||
class TaskQueue(ABC):
|
||||
"""统一任务队列抽象(内存 / Redis / Valkey 实现)"""
|
||||
"""统一任务队列抽象(v1 仅 InMemory 实现;Redis/Valkey 为 v2 预留,Scope 缩减裁定)"""
|
||||
|
||||
@abstractmethod
|
||||
def enqueue(self, task: TaskSpec) -> TaskHandle: ...
|
||||
@@ -238,14 +237,13 @@ class TaskQueue(ABC):
|
||||
| 实现 | 依赖 | 使用场景 | 说明 |
|
||||
|------|------|---------|------|
|
||||
| `InMemoryQueue` | 无 | 开发 / 测试 / 演示(默认)| asyncio 任务池,进程内状态 |
|
||||
| `RedisQueue` | redis-py | 生产部署 | Redis Streams(RSALv2,内部使用合法)|
|
||||
| `ValkeyQueue` | redis-py(兼容)| 生产部署(零许可风险)| Valkey 兼容 Redis 协议,代码同 RedisQueue |
|
||||
| `RedisQueue` / `ValkeyQueue` | redis-py | **v2 预留**(不实现)| Scope 缩减裁定移除双实现;接口保留供 v2 扩展 |
|
||||
|
||||
### 5.3 幂等去重
|
||||
|
||||
- 任务幂等键:`(session_id, step, chapter_id)`(runtime §7.3)
|
||||
- 重复 enqueue 同一幂等键 → 已完成直接返回缓存结果;进行中则返回原 handle
|
||||
- `InMemoryQueue` 与 `RedisQueue` 行为一致(单测以 MockAdapter 风格覆盖双实现)
|
||||
- v1 仅 `InMemoryQueue` 实现(单测覆盖)
|
||||
|
||||
---
|
||||
|
||||
@@ -266,7 +264,7 @@ docker-compose.yml(最小):
|
||||
command: uvicorn app.main:app --host 0.0.0.0 --port 8000
|
||||
```
|
||||
|
||||
### 6.2 生产(Redis/Valkey 可选)
|
||||
### 6.2 生产(v1 单容器;Redis/Valkey worker 为 v2 预留)
|
||||
|
||||
```
|
||||
docker-compose.yml(扩展):
|
||||
@@ -274,13 +272,7 @@ docker-compose.yml(扩展):
|
||||
api: # FastAPI 编排 + REST/WS
|
||||
...
|
||||
command: uvicorn app.main:app --host 0.0.0.0 --port 8000
|
||||
worker: # 任务消费(仅切换队列时启用)
|
||||
build: .
|
||||
command: python -m app.worker
|
||||
depends_on: [queue]
|
||||
queue: # Redis 或 Valkey 二选一
|
||||
image: valkey/valkey:8 # 零许可风险(或 redis:7,内部使用合法)
|
||||
volumes: ["queue_data:/data"]
|
||||
# worker / queue: v2 预留(Scope 缩减裁定移除 Redis/Valkey 双实现,v1 不启用)
|
||||
```
|
||||
|
||||
### 6.3 目录结构
|
||||
|
||||
+7
-37
@@ -55,9 +55,8 @@ APP_PORT=8000
|
||||
DATA_DIR=/data # 用户数据根目录
|
||||
CONFIG_DIR=/config # YAML 配置目录
|
||||
|
||||
# ── 队列(可选,默认 InMemory)───────────────────
|
||||
QUEUE_BACKEND=memory # memory | redis | valkey
|
||||
REDIS_URL=redis://queue:6379/0 # 切换队列时使用
|
||||
# ── 队列(v1 仅 InMemory;Redis/Valkey 为 v2 预留,Scope 缩减裁定)──
|
||||
QUEUE_BACKEND=memory # v1 仅 memory
|
||||
```
|
||||
|
||||
| 变量 | 必填 | 默认 | 说明 |
|
||||
@@ -98,8 +97,7 @@ paths:
|
||||
shared_root: /data/shared
|
||||
|
||||
task_queue:
|
||||
backend: memory # memory | redis | valkey(对应 QUEUE_BACKEND)
|
||||
redis_url: ${REDIS_URL} # 环境变量引用
|
||||
backend: memory # v1 仅 memory(redis/valkey 为 v2 预留)
|
||||
timeout_sec: 600 # 任务最长执行时间
|
||||
retry_default: 2 # 任务默认重试次数
|
||||
```
|
||||
@@ -164,12 +162,9 @@ embedding:
|
||||
cache_dir: /data/shared/models # 模型缓存目录
|
||||
|
||||
vector_store: # StorageAdapter 配置(rag-layer §9.4)
|
||||
adapter: chroma # chroma | qdrant
|
||||
adapter: chroma # v1 仅 chroma(qdrant 为 v2 预留)
|
||||
chroma:
|
||||
persist_dir: /data/shared/rules-handbook/chroma
|
||||
qdrant:
|
||||
url: http://qdrant:6333
|
||||
api_key: ${QDRANT_API_KEY} # 可选
|
||||
|
||||
chunking:
|
||||
word_max_tokens: 512 # Word chunk 上限
|
||||
@@ -203,7 +198,7 @@ services:
|
||||
command: uvicorn app.main:app --host 0.0.0.0 --port 8000
|
||||
```
|
||||
|
||||
### 6.2 完整(生产,队列 + 可选 Qdrant)
|
||||
### 6.2 生产(v1 单容器;worker/queue 为 v2 预留)
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
@@ -215,35 +210,10 @@ services:
|
||||
volumes:
|
||||
- ./data:/data
|
||||
- ./config:/config
|
||||
depends_on:
|
||||
- queue
|
||||
command: uvicorn app.main:app --host 0.0.0.0 --port 8000
|
||||
|
||||
worker:
|
||||
build: .
|
||||
env_file: .env
|
||||
volumes:
|
||||
- ./data:/data
|
||||
- ./config:/config
|
||||
depends_on:
|
||||
- queue
|
||||
command: python -m app.worker
|
||||
|
||||
queue:
|
||||
image: valkey/valkey:8 # 零许可风险;或 redis:7(内部使用合法)
|
||||
volumes:
|
||||
- queue_data:/data
|
||||
|
||||
# 可选:切换 Qdrant 时启用
|
||||
# qdrant:
|
||||
# image: qdrant/qdrant
|
||||
# ports: ["6333:6333"]
|
||||
# volumes:
|
||||
# - qdrant_data:/qdrant/storage
|
||||
|
||||
volumes:
|
||||
queue_data:
|
||||
# qdrant_data:
|
||||
# worker / queue(valkey): v2 预留(Scope 缩减裁定移除 Redis/Valkey 双实现)
|
||||
# qdrant: v2 预留(Qdrant 切换已移除)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
+2
-2
@@ -707,7 +707,7 @@ Parser 处理时分为:
|
||||
|
||||
| 设计点 | 决策 |
|
||||
|--------|------|
|
||||
| 向量数据库 | Chroma 默认 + 可配置切换 Qdrant |
|
||||
| 向量数据库 | Chroma(v1 唯一;Qdrant 切换为 v2 预留,Scope 缩减裁定)|
|
||||
| Embedding | bge-small-zh-v1.5(本地),可切换 bge-m3 |
|
||||
| 实现方式 | 手写(chromadb + rank_bm25 + sentence-transformers)|
|
||||
| 分割策略 | 按格式适配(Word 标题层级 / Excel 规则块 / PPT 1-2 页)|
|
||||
@@ -1233,7 +1233,7 @@ QA 输出:
|
||||
#### 8.4.1 任务管理
|
||||
|
||||
```
|
||||
TaskQueue(抽象接口,默认 InMemoryQueue,生产可切 Redis/Valkey)
|
||||
TaskQueue(抽象接口,v1 仅 InMemoryQueue;Redis/Valkey 为 v2 预留,Scope 缩减裁定)
|
||||
├── task:generate-chapter-1
|
||||
│ status: completed
|
||||
│ result: {chapter: "功能一览", html: "...", time_ms: 23000}
|
||||
|
||||
@@ -49,7 +49,7 @@ RAG 层存储三类内容,分类在 Parser 解析时完成:
|
||||
|
||||
| 选型点 | 决策 | 说明 |
|
||||
|--------|------|------|
|
||||
| 向量数据库 | **混合方案**:Chroma 默认 + 可配置切换 Qdrant | 初期用 Chroma(轻量本地,嵌入进程,Docker 部署最简);通过 Storage Adapter 抽象,未来可切换 Qdrant |
|
||||
| 向量数据库 | **Chroma(v1 唯一)** | 初期用 Chroma(轻量本地,嵌入进程,Docker 部署最简);通过 Storage Adapter 抽象保留接口,Qdrant 切换为 v2 预留(Scope 缩减裁定,T5 整改)|
|
||||
| Embedding 模型 | **bge-small-zh-v1.5**(本地运行) | 中文小模型(1024维,~100MB),CPU 可跑;统一配置 `config/rag.yaml` 的 `embedding.model`(见 docs/config-design.md §5)可切换为 `BAAI/bge-m3`(多语言更好) |
|
||||
| 实现方式 | **手写实现**(不引入 LangChain/LlamaIndex) | chromadb + rank_bm25 + sentence-transformers 直接实现;依赖轻、可控性强、与现有轻量技术栈一致 |
|
||||
|
||||
@@ -536,7 +536,7 @@ class ConflictHandler:
|
||||
|
||||
### 9.1 定位
|
||||
|
||||
向量存储访问的**统一抽象层**。RAG 业务逻辑(分割/检索/融合)不直接依赖具体向量数据库,而是通过 Storage Adapter 访问。初期使用 Chroma,未来可切换 Qdrant,**业务层无需改动**。
|
||||
向量存储访问的**统一抽象层**。RAG 业务逻辑(分割/检索/融合)不直接依赖具体向量数据库,而是通过 Storage Adapter 访问。v1 仅实现 **ChromaAdapter**(本地持久化,零外部依赖)。(T5 架构审查整改:Scope 缩减裁定移除 Qdrant 可切换抽象,QdrantAdapter 为 v2 预留。)
|
||||
|
||||
### 9.2 接口定义
|
||||
|
||||
@@ -584,28 +584,17 @@ class VectorHit:
|
||||
|
||||
| 实现 | 说明 | 使用场景 |
|
||||
|------|------|---------|
|
||||
| **ChromaAdapter** | 默认实现,chromadb 本地持久化(`/data/shared/rules-handbook/chroma/`)| 默认 |
|
||||
| **QdrantAdapter** | 可选实现,通过 Qdrant HTTP/gRPC API | 切换时启用 |
|
||||
| **ChromaAdapter** | v1 唯一实现,chromadb 本地持久化(`/data/shared/rules-handbook/chroma/`)| 默认 |
|
||||
| **QdrantAdapter** | v2 预留(不实现)| Scope 缩减裁定移除;接口保留供 v2 扩展 |
|
||||
|
||||
### 9.4 配置切换
|
||||
### 9.4 配置
|
||||
|
||||
```yaml
|
||||
# config/inference.yaml 或 config/rag.yaml
|
||||
vector_store:
|
||||
adapter: chroma # "chroma" | "qdrant"
|
||||
adapter: chroma # v1 仅 "chroma"(Scope 缩减裁定)
|
||||
chroma:
|
||||
persist_dir: /data/shared/rules-handbook/chroma
|
||||
qdrant:
|
||||
url: http://qdrant:6333
|
||||
api_key: ${QDRANT_API_KEY}
|
||||
```
|
||||
|
||||
```
|
||||
切换流程:
|
||||
1. 修改配置 adapter: qdrant
|
||||
2. 系统启动时通过 StorageAdapterFactory 创建对应实现
|
||||
3. 已有规则手册数据需迁移(重新构建索引)或通过脚本复制
|
||||
4. 业务层(检索引擎/版本管理)无感知
|
||||
```
|
||||
|
||||
### 9.5 工厂与依赖注入
|
||||
@@ -614,9 +603,7 @@ vector_store:
|
||||
class StorageAdapterFactory:
|
||||
@staticmethod
|
||||
def create(config: dict) -> VectorStoreAdapter:
|
||||
adapter = config["vector_store"]["adapter"]
|
||||
if adapter == "qdrant":
|
||||
return QdrantAdapter(config["vector_store"]["qdrant"])
|
||||
# v1 仅 ChromaAdapter(Qdrant 分支 v2 预留)
|
||||
return ChromaAdapter(config["vector_store"]["chroma"])
|
||||
|
||||
# 使用: RagService / RuleHandbookManager 通过构造注入 adapter
|
||||
@@ -628,7 +615,7 @@ rag_service = RagService(
|
||||
|
||||
### 9.6 一致性保证
|
||||
|
||||
- ChromaAdapter 与 QdrantAdapter 对同一数据(chunks/embeddings/metadata)的操作结果一致
|
||||
- v1 仅 ChromaAdapter(无跨实现一致性要求;v2 新增实现时需保证对同一数据的操作结果一致)
|
||||
- 单元测试中可注入 **MockAdapter**(内存实现),使检索逻辑测试不依赖真实向量库
|
||||
|
||||
---
|
||||
|
||||
@@ -391,13 +391,12 @@
|
||||
|
||||
## 4. 技术设计
|
||||
|
||||
### 4.1 任务管理与队列抽象(修订 v1.1)
|
||||
### 4.1 任务管理与队列抽象(修订 v1.1 + T5 整改)
|
||||
|
||||
```
|
||||
TaskQueue(抽象接口,默认实现 InMemoryQueue)
|
||||
├── InMemoryQueue # 开发/测试/演示默认(零依赖)
|
||||
├── RedisQueue # 生产可选(redis-py)
|
||||
└── ValkeyQueue # 生产可选(Valkey,Redis 协议兼容)
|
||||
TaskQueue(抽象接口,v1 仅 InMemoryQueue;RedisQueue/ValkeyQueue 为 v2 预留,Scope 缩减裁定)
|
||||
├── InMemoryQueue # v1 唯一实现(零依赖)
|
||||
# RedisQueue / ValkeyQueue: v2 预留
|
||||
|
||||
任务队列条目:
|
||||
task:generate-chapter-1
|
||||
@@ -405,7 +404,7 @@ TaskQueue(抽象接口,默认实现 InMemoryQueue)
|
||||
result: {chapter: "章节", html: "...", time_ms: 23000}
|
||||
```
|
||||
|
||||
- 队列实现由配置 `task_queue.backend` 决定(memory / redis / valkey),详见 `docs/api-design.md` §1 架构决策与 `docs/config-design.md`
|
||||
- v1 队列实现固定为 `task_queue.backend=memory`(InMemoryQueue),详见 `docs/api-design.md` §1 架构决策与 `docs/config-design.md`
|
||||
- Web UI 无需关心后端实现,仅消费统一任务状态
|
||||
|
||||
### 4.2 会话管理(SQLite)
|
||||
|
||||
Reference in New Issue
Block a user