Files
2026Technology-Competition/docs/api-design.md
T

16 KiB
Raw Blame History

API 与编排接口设计

版本: v1.0 | 日期: 2026-07-30 | 状态: 初版

本文档定义 Web 后端(FastAPI Orchestrator)的 REST API 端点、WebSocket 事件通道、编排调用链与部署拓扑。是 docs/design.md §8Web UI)与 docs/agent-runtime-design.md §3(编排能力)的接口级展开。


目录

  1. 定位与架构
  2. REST API 端点清单
  3. WebSocket 事件通道
  4. 编排调用链
  5. 任务队列抽象
  6. 部署拓扑
  7. 错误码约定
  8. 与各文档的关系

1. 定位与架构

浏览器 (React UI)
      │  REST API (JSON) + WebSocket (实时事件)
      ▼
FastAPI Orchestrator(单进程,默认)
      │
      ├── SessionManager(会话状态机,见 agent-runtime §3
      ├── Agent 调度(Parser / Impact / Writer / QA
      ├── TaskQueue 抽象(默认 InMemory,可切 Redis/Valkey
      └── RagService 调用(规则检索)

架构决策(与用户确认):

  • 编排形态:抽象 TaskQueue 接口 + 双实现。默认 InMemoryQueue(开发/测试/演示零依赖);部署时可切换 RedisQueue / ValkeyQueueRedis 协议兼容,redis-py 客户端通用)。
  • 许可说明Redis 内部使用合法(RSALv2/SSPLv1 仅限制「提供 Redis 托管服务给第三方」);若需完全开源无限制,使用 Valkey(BSD-3),代码无需改动。
  • 所有 API 返回 JSON;长任务(解析/影响调查/生成)采用「异步启动 + 轮询/推送」模式。

2. REST API 端点清单

2.1 会话管理

Method Path 说明 请求体 响应 触发状态转移
POST /api/sessions 创建会话 {user_id} {session_id, status, locked_rule_version} → uploading
GET /api/sessions/{id} 获取会话详情 会话对象(状态/步骤/进度摘要) 只读
DELETE /api/sessions/{id} 删除会话 {deleted: true} 终态清理
GET /api/sessions 会话列表(按用户) ?user_id= [{session_id, status, updated_at}] 只读

2.2 文件上传

Method Path 说明 请求体 响应 触发状态转移
POST /api/sessions/{id}/files 上传文件(multipart file + file_typerequirements/template/write_instruction/rules/existing_system {file_id, file_name, size} uploading 保持

file_type 取值说明(v1.1 修订,随 web-ui-design §3.1 补齐大赛输入资料):

  • requirements — 要件定义 Excel(核心数据源)
  • template — 概要设计模板 docx(输出结构/样式)
  • write_instruction — 概要设计做成说明书 docx(各章作成指引;RAG 归类 Type A 写入规则,Parser 解析)
  • rules — 记入规则 / 图表规则等规则文档(可多个)
  • existing_system — 现系统源码或既有设计书(追加/改修场景) | POST | /api/sessions/{id}/start-parse | 开始解析(全部文件上传完成后) | {} | {task_id}(解析异步执行) | uploading → parsing | | GET | /api/sessions/{id}/parse-result | 获取解析结果 | — | {structured_summary, sheets, template_sections} | 只读 |

2.3 解析确认

Method Path 说明 请求体 响应 触发状态转移
POST /api/sessions/{id}/confirm-parse 确认解析结果 {sheet_fixes?, template_fixes?} {ok: true} awaiting_parse_confirm → impact_running
POST /api/sessions/{id}/reparse 修正后重新解析 {sheet_overrides} {task_id} awaiting_parse_confirm → parsing

2.4 影响调查

Method Path 说明 请求体 响应 触发状态转移
POST /api/sessions/{id}/start-impact 启动影响调查 {} {task_id} impact_running 保持
GET /api/sessions/{id}/impact-result 获取影响调查结果 ImpactReport JSON 只读
POST /api/sessions/{id}/impact-edits 逐条修正关联 {edits: [{type, id, action, data}]} {ok: true, correction_history_id} awaiting_impact_confirm 保持
POST /api/sessions/{id}/confirm-impact 确认影响调查 {} {ok: true} awaiting_impact_confirm → writing
POST /api/sessions/{id}/reject-impact 打回(重推或回到解析) {target: "impact" | "parse"} {ok: true} awaiting_impact_confirm → impact_running | awaiting_parse_confirm

2.5 生成(Writer + QA

Method Path 说明 请求体 响应 触发状态转移
POST /api/sessions/{id}/generate 启动章节生成 {} {task_ids: [逐章]} writing 保持
GET /api/sessions/{id}/generation-status 各章生成进度 [{chapter_id, status, duration_ms}] 只读
GET /api/sessions/{id}/chapters/{chapter_id} 获取单章内容块 ContentBlock JSON 只读
POST /api/sessions/{id}/regenerate-chapter 单章重生成 {chapter_id, reason} {task_id} writing 保持
POST /api/sessions/{id}/run-qa 启动 QA 校验 {} {task_id} writing → qa
GET /api/sessions/{id}/qa-result QA 校验结果 QAReport JSON 只读
POST /api/sessions/{id}/writer-fix QA 发现问题后反馈 Writer 重生成 {issues: [...]} {task_ids} qa → writing
POST /api/sessions/{id}/rollback-to-impact 回退到影响调查(writing 阶段用户要求调整关联/不确定处) {} {ok: true} writing → awaiting_impact_confirm

2.6 结果与下载

Method Path 说明 请求体 响应 触发状态转移
GET /api/sessions/{id}/result/preview HTML 预览 {html} 只读
GET /api/sessions/{id}/result/download 下载 docx application/vnd.openxmlformats...(文件流) 只读
GET /api/sessions/{id}/result/qa-report 下载 QA 报告 application/json 只读
GET /api/sessions/{id}/result/impact-report 下载影响调查书 application/json 只读

2.7 规则管理

Method Path 说明 请求体 响应 触发状态转移
GET /api/rules/versions 规则手册版本列表 [{version_id, active, created_at, doc_count}] 只读
POST /api/rules/update 触发规则手册重建 {files, categories} {version_id | "no_change"} 不涉及会话
POST /api/rules/rollback 回退到指定版本 {version_id} {ok: true} 不涉及会话
GET /api/rules/conflicts 待决策的规则冲突 ?session_id= [{conflict_id, topic, chunks}] 只读
POST /api/rules/conflicts/{id}/resolve 冲突决策 {session_id, decision} {ok: true} 继续该章生成

2.8 设置与状态

Method Path 说明 请求体 响应
GET /api/settings 获取配置(脱敏) {models, vector_store, limits}
GET /api/health 健康检查 {status: "ok", version}
POST /api/sessions/{id}/cancel 取消当前任务 {task_id?} {ok: true}
GET /api/sessions/{id}/logs 获取会话事件日志 ?event_type= [{event_type, ...}]

3. WebSocket 事件通道

3.1 端点

WS /api/ws/sessions/{id}

3.2 事件类型(服务端 → 客户端)

事件 载荷 时机
status_change {from, to, at} 状态机转移时
progress {task_id, chapter_id?, percent?, detail} 任务进度更新
tool_call {tool, args_summary, status, duration_ms} 工具调用(runtime §5.7
llm_call {model, prompt_version, status, duration_ms, input_tokens, output_tokens} LLM 调用(runtime §6.1
conflict_pending {conflict_id, topic, chapter_id} 规则冲突待用户决策
qa_completed {summary: {pass, fail, warnings}} QA 完成
error {code, message, options: ["retry","skip","abort"]} 任务失败(异常 UX
done {download_url} 全部完成

3.3 客户端 → 服务端

事件 载荷 说明
ping 心跳(保持连接)
request_status 请求当前完整状态(断线重连时同步)

4. 编排调用链

4.1 正常流程时序

客户端               Orchestrator                 Agent / 基础设施
  │  POST /sessions       │                              │
  │──────────────────────►│ 创建会话 → uploading          │
  │  POST /files          │                              │
  │──────────────────────►│                              │
  │  POST /start-parse    │                              │
  │──────────────────────►│ 投递解析任务 ────────────────►│ Parser
  │◄───WS progress────────│                              │
  │◄───WS status_change───│ parsing → awaiting_parse_confirm
  │  POST /confirm-parse  │                              │
  │──────────────────────►│ → impact_running             │
  │  POST /start-impact   │ 投递影响调查 ────────────────►│ Impact
  │◄───WS status_change───│ → awaiting_impact_confirm    │
  │  POST /confirm-impact │                              │
  │──────────────────────►│ → writing                    │
  │  POST /generate       │ 投递逐章任务 ────────────────►│ Writer
  │◄───WS progress(章)────│                              │
  │  POST /run-qa         │ 投递 QA 任务 ────────────────►│ QA
  │◄───WS qa_completed────│ → done(或 qa → writing 反馈)│
  │  GET /result/download │                              │
  │──────────────────────►│ 返回 docx 文件流              │

4.2 Orchestrator 职责边界

  • 不做业务逻辑(解析/推理/生成/校验在各 Agent)
  • :状态机推进、任务调度、事件收集与推送、异常路由(重试/跳过/中断)、规则版本锁定、会话持久化

4.3 进程内调用 vs 队列

默认(InMemoryQueue:
  Orchestrator 进程内 asyncio 任务池消费队列
  状态与任务结果共享内存(FastAPI 进程内)

切换(RedisQueue/ValkeyQueue:
  Orchestrator 投递 → Redis/Valkey Stream
  worker 进程消费 → 执行 → 状态写回 SQLite / 事件回传
  需额外部署 worker 容器(见 §6)

5. 任务队列抽象

5.1 接口定义

class TaskQueue(ABC):
    """统一任务队列抽象(内存 / Redis / Valkey 实现)"""

    @abstractmethod
    def enqueue(self, task: TaskSpec) -> TaskHandle: ...
        # TaskSpec = {task_id, session_id, step, chapter_id?, payload, idempotency_key}

    @abstractmethod
    def poll(self, session_id: str) -> list[TaskHandle]: ...

    @abstractmethod
    def update_status(self, handle: TaskHandle, status: str, result: Any = None) -> None: ...
        # status: pending | running | completed | failed

    @abstractmethod
    def get(self, task_id: str) -> TaskHandle | None: ...

    @abstractmethod
    def cancel(self, task_id: str) -> bool: ...

    @abstractmethod
    def close(self) -> None: ...

5.2 实现类

实现 依赖 使用场景 说明
InMemoryQueue 开发 / 测试 / 演示(默认) asyncio 任务池,进程内状态
RedisQueue redis-py 生产部署 Redis StreamsRSALv2,内部使用合法)
ValkeyQueue redis-py(兼容) 生产部署(零许可风险) Valkey 兼容 Redis 协议,代码同 RedisQueue

5.3 幂等去重

  • 任务幂等键:(session_id, step, chapter_id)runtime §7.3
  • 重复 enqueue 同一幂等键 → 已完成直接返回缓存结果;进行中则返回原 handle
  • InMemoryQueueRedisQueue 行为一致(单测以 MockAdapter 风格覆盖双实现)

6. 部署拓扑

6.1 默认(单容器,InMemoryQueue

docker-compose.yml(最小):
  services:
    api:
      build: .
      ports: ["8000:8000"]
      env_file: .env
      volumes:
        - ./data:/data            # 用户数据 + 规则手册
        - ./config:/config        # inference.yaml / rag.yaml
      command: uvicorn app.main:app --host 0.0.0.0 --port 8000

6.2 生产(Redis/Valkey 可选)

docker-compose.yml(扩展):
  services:
    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"]

6.3 目录结构

/data/
├── users/{user_id}/            # 用户隔离(web-ui-design §4.3
│   ├── uploads/
│   └── outputs/
├── shared/
│   ├── rules-handbook/          # 规则手册(RAG 层)
│   │   ├── chroma/              # Chroma 持久化
│   │   ├── manifest.json
│   │   └── v1/ v2/ ...          # 版本目录
│   └── templates/               # 公共模板
└── db/                          # SQLitesessions/events/snapshots

7. 错误码约定

错误码 HTTP 含义 用户选项 来源
FILE_TYPE_INVALID 400 文件类型不支持 更换文件
FILE_TOO_LARGE 400 超过 100MB 限制 压缩/分割
STATE_TRANSITION_INVALID 409 非法状态转移(如 uploading 直接 generate 提示正确流程
LLM_TIMEOUT 502 LLM 调用超时 retry / skip / abort exceptions.LLMTimeoutError
LLM_NOT_CONFIGURED 503 LLM Key 未配置 配置 Key exceptions.LLMNotConfiguredError
LLM_PARSE_ERROR 502 结构化输出解析失败 retry exceptions.LLMResponseError
EMBEDDING_FAILED 503 Embedding 服务故障(降级为 BM25 继续(降级提示)
RULES_HANDBOOK_MISSING 404 规则手册不存在 上传规则文档
CHAPTER_NOT_FOUND 404 章节不存在
CONFLICT_PENDING 409 规则冲突待用户决策 决策后继续
INTERNAL_ERROR 500 未知错误 重试/联系支持

8. 与各文档的关系

文档 关系
docs/design.md §8 Web UI 页面设计;本文档为后端 API 的接口级展开
docs/agent-runtime-design.md §3 状态机与任务队列抽象;本文档定义 REST/WS 入口
docs/web-ui-design.md 前端各页面调用本文档的端点
docs/config-design.md 部署配置(env / yaml / docker-compose