跳转至

Fusion 架构

本文描述 Fusion 的目标模块架构,用来约束后续实现收口。Fusion 的业务主线仍然围绕 Agent draft、published AgentVersion snapshot 和 FusionRun ledger 展开,但内部代码边界收敛到 clean architecture:

  • interfaces
  • domain
  • application
  • infrastructure

本页描述的是最终态,不包含兼容壳、过渡目录或“双边界并存”的临时方案。

业务主线

flowchart LR
  Draft["Agent Draft"] --> Snapshot["Published AgentVersion Snapshot"]
  Snapshot --> Run["Fusion Run Ledger"]
  Run --> Worker["Worker Claim / Lease / Heartbeat"]
  Run --> Governance["Governance Context Snapshot"]
  Run --> Inputs["Persisted Inputs"]
  Worker --> Execution["One Run Execution"]
  Execution --> Outputs["Persisted Outputs"]

这条主线表达的是产品对象和运行事实:

  • Agent Draft 是可编辑草稿
  • AgentVersion Snapshot 是不可变执行快照
  • Fusion Run Ledger 是一次执行的账本真相
  • worker 只 claim ledger,不持有额外的内存真相
  • governance、inputs、outputs 都是 run 的持久化证据

目标模块架构

flowchart TB
  AppRoot["ai_service/api/app.py<br/>Composition Root"]

  subgraph Fusion["ai_service/fusion/"]
    direction TB

    subgraph Interfaces["interfaces"]
      Http["interfaces/http/router.py"]
      Presenter["interfaces/http requests / responses / presenters"]
      Lifecycle["interfaces/lifecycle.py"]
    end

    subgraph Application["application"]
      UseCases["use_cases"]
    end

    subgraph Domain["domain"]
      Contracts["contracts / profiles / value objects"]
      Ports["ports"]
      Rules["business rules"]
    end

    subgraph Infrastructure["infrastructure"]
      Persistence["persistence"]
      Runtime["runtime"]
      Adapters["adapters"]
      Workers["workers"]
    end
  end

  DB["storage/model_domains/fusion.py"]
  External["Model / RAG / MCP / Storage Providers"]

  AppRoot --> Http
  AppRoot --> Lifecycle
  Http --> Presenter
  Http --> UseCases
  Lifecycle --> Workers
  Workers --> UseCases
  UseCases --> Contracts
  UseCases --> Ports
  Rules --> Contracts
  Persistence --> DB
  Runtime --> Contracts
  Runtime --> Ports
  Adapters --> Ports
  Adapters --> External
  UseCases -.implemented by.-> Persistence
  UseCases -.implemented by.-> Runtime
  UseCases -.implemented by.-> Adapters

这张图表达的不是“谁调用得更多”,而是最终依赖方向:

  • app.py 只负责装配,不持有 Fusion transport 细节
  • interfaces 负责 HTTP 和 lifecycle 入口
  • application 负责用例编排
  • domain 负责业务规则和端口定义
  • infrastructure 负责 SQLAlchemy、LangGraph、worker、外部 provider 适配

分层职责

目标路径 负责什么 不负责什么
Interfaces ai_service/fusion/interfaces/ HTTP route、multipart/request parsing、response serialization、presenter、lifecycle wiring 不持有业务规则,不直接操作 ORM helper,不直接写运行图
Domain ai_service/fusion/domain/ contract、structured output profile、value object、error、port 定义、核心业务规则 不依赖 FastAPI、SQLAlchemy、LangGraph、MinIO、threading
Application ai_service/fusion/application/ create/list/get/execute/recover 等用例编排 不直接 import storage.models,不直接处理 HTTP transport
Infrastructure ai_service/fusion/infrastructure/ persistence adapter、runtime engine、worker loop、model/rag/mcp/storage adapter 不定义业务边界,不拥有 API contract

依赖规则

最终态只允许以下依赖方向:

  1. interfaces -> application
  2. application -> domain
  3. infrastructure -> domain
  4. infrastructure -> application-defined ports
  5. app.py -> interfacesapp.py -> infrastructure/lifecycle wiring

明确禁止:

  1. domain -> FastAPI / SQLAlchemy / LangGraph / MinIO / threading
  2. application -> ai_service.storage.models
  3. application -> FastAPI request/response
  4. application -> infrastructure
  5. domain -> application

目录收口要求不作为“可选禁止项”表达,而是以下文“最终态约束”为准。

当前代码到目标目录的映射

旧边界 目标归属
仓库级 Fusion HTTP router ai_service/fusion/interfaces/http/router.py
混合 contract / DTO schema ai_service/fusion/domain/*ai_service/fusion/interfaces/http/* 拆分
structured output profile 注册 ai_service/fusion/domain/*
run / definition / agent link 等 service 逻辑 ai_service/fusion/application/use_cases/*
governance snapshot 归一化 ai_service/fusion/infrastructure/adapters/governance.py
worker lifecycle 与调度线程 ai_service/fusion/infrastructure/workers/*
LangGraph runtime 执行骨架 ai_service/fusion/infrastructure/runtime/*
model / rag / mcp / storage / image adapter ai_service/fusion/infrastructure/adapters/*
持久化真相源 继续保留 ai_service/storage/model_domains/fusion.py,由 infrastructure/persistence/* 包装

为什么同时保留 Draft、Snapshot 和 Run

如果只有 live draft,没有 immutable snapshot,历史 run 就失去解释性。Fusion 的业务对象仍然保持:

  • draft 可以继续演进
  • snapshot 是固定执行快照
  • run 永远绑定确定的 agent_version_id

clean architecture 改的是代码边界,不改这条运行时事实链。

最终态约束

本次实现完成后,Fusion 架构图对应的落地结果必须满足:

  • 旧的仓库级 Fusion router 已删除
  • ai_service/fusion/interfaces/http/router.py 是唯一 Fusion HTTP 入口
  • ai_service/fusion/ 内只保留 interfaces / domain / application / infrastructure
  • 不存在 compatibility import、temporary facade、legacy shim 或“后续删除”的过渡层
  • app.py 只承担 composition root 和 router / lifecycle 注册
  • domain 不依赖任何 transport、ORM、runtime engine 或线程实现
  • application 不直接依赖 storage.models

验证

  • uv run pytest tests/integration/test_fusion_runtime.py tests/integration/test_fusion_agent_api.py -q
  • uv run mkdocs build