Files
zhuyongxin c86045b33f archive: Phase 1 基础设施搭建归档
归档信息:
- 变更名称:phase-1-infrastructure
- 工作流:spec-driven
- 归档位置:openspec/changes/archive/2026-06-23-phase-1-infrastructure/

完成情况:
- ✅ 所有产物完成(proposal, design, specs, tasks)
- ✅ 任务完成:33/35 (94%)
- ⚠️ 2 个任务跳过(混合检索、集成测试,有充分理由)

验收结果:
- ✅ 静态验证:编译通过
- ✅ 脚本验证:16/16 单元测试通过
- ✅ 端到端验证:上传→索引→检索→删除完整流程

Delta Specs:
- 跳过同步(用户选择)
- functional-specs.md 保留在归档目录中

devflow 档案:
- ✅ 已完整回填(brief, evidence, decisions, acceptance)
- ✅ devflow/index.md 状态更新为 archived
2026-06-23 19:20:05 +08:00

8.6 KiB
Raw Permalink Blame History

Phase 1 Infrastructure - Design

架构设计

1. 数据持久化层

┌─────────────────────────────────────────┐
│           Application Layer             │
│  (Service / Controller / Agent)         │
└──────────────┬──────────────────────────┘
               │
               ↓
┌─────────────────────────────────────────┐
│         Repository Layer (JPA)          │
│  - DiagnosisRecordRepository            │
│  - CaseLibraryRepository                │
│  - ApiDocumentRepository                │
└──────────────┬──────────────────────────┘
               │
               ↓
┌─────────────────────────────────────────┐
│            MySQL 8.0+                   │
│  - diagnosis_record (诊断记录)          │
│  - case_library (案例库)                │
│  - api_document (文档元数据)            │
│  - flyway_schema_history (版本管理)     │
└─────────────────────────────────────────┘

Flyway 迁移流程:

  1. 启动时自动扫描 db/migration/V*.sql
  2. 检查 flyway_schema_history 表
  3. 执行未运行的脚本
  4. 记录版本号

2. 会话管理层

┌─────────────────────────────────────────┐
│        Diagnosis Flow                   │
└──────────────┬──────────────────────────┘
               │
               ↓
┌─────────────────────────────────────────┐
│      SessionManager (Interface)         │
└──────────────┬──────────────────────────┘
               │
               ↓
┌─────────────────────────────────────────┐
│     RedisSessionManager (Impl)          │
│  - get(sessionId): SessionContext       │
│  - save(context): void                  │
│  - delete(sessionId): void              │
└──────────────┬──────────────────────────┘
               │
               ↓
┌─────────────────────────────────────────┐
│            Redis 6.0+                   │
│  Key: session:{sessionId}               │
│  Value: SessionContext (JSON)           │
│  TTL: 30 minutes                        │
└─────────────────────────────────────────┘

SessionContext 结构:

{
  "sessionId": "uuid",
  "diagnosisId": "uuid",
  "currentStep": "queryOrder",
  "collectedEvidence": {
    "orderInfo": {...},
    "logs": [...]
  },
  "toolCallHistory": [
    {
      "toolName": "queryOrder",
      "params": {...},
      "result": {...},
      "timestamp": "2026-06-23T10:00:00"
    }
  ],
  "intentType": "诊断",
  "createdAt": "2026-06-23T09:55:00",
  "lastAccessAt": "2026-06-23T10:00:00"
}

3. 包结构设计

com.superbiz.agent/
├── SuperBizAgentApplication.java       # 启动类
│
├── controller/                         # REST 控制器
│   ├── DiagnosisController.java
│   ├── DocumentController.java
│   └── CaseController.java
│
├── service/                            # 业务服务
│   ├── DiagnosisService.java
│   ├── DocumentService.java
│   ├── CaseService.java
│   ├── TextExtractor.java              # 文本提取
│   └── VectorService.java              # 向量化服务
│
├── repository/                         # 数据访问
│   ├── DiagnosisRecordRepository.java
│   ├── CaseLibraryRepository.java
│   └── ApiDocumentRepository.java
│
├── domain/                             # 领域模型
│   ├── entity/                         # JPA 实体
│   │   ├── DiagnosisRecord.java
│   │   ├── CaseLibrary.java
│   │   └── ApiDocument.java
│   ├── dto/                            # 数据传输对象
│   │   ├── DiagnosisRequest.java
│   │   ├── DiagnosisResponse.java
│   │   ├── DocumentUploadRequest.java
│   │   └── DocumentQueryResponse.java
│   └── enums/                          # 枚举
│       ├── FaultCategory.java
│       ├── DiagnosisStatus.java
│       └── SourceType.java
│
├── session/                            # 会话管理
│   ├── SessionManager.java             # 接口
│   ├── RedisSessionManager.java        # Redis 实现
│   ├── SessionContext.java             # 会话上下文
│   └── ToolCall.java                   # 工具调用记录
│
├── tool/                               # 工具层
│   ├── DocumentSearchTool.java         # 混合检索
│   └── (其他 tool 保留 Phase 2)
│
├── config/                             # 配置
│   ├── JpaConfig.java
│   ├── RedisConfig.java
│   ├── MilvusConfig.java               # 保留现有
│   └── DashScopeConfig.java            # 保留现有
│
└── exception/                          # 异常处理
    ├── GlobalExceptionHandler.java
    ├── SessionNotFoundException.java
    └── DocumentProcessException.java

4. 文档管理流程

文档上传流程:
User → POST /api/documents/upload
  ↓
DocumentController.upload()
  ↓
DocumentService.uploadDocument()
  ↓ (并行)
  ├─→ TextExtractor.extract()          # 提取文本
  ├─→ chunkText()                       # 分块
  ├─→ VectorService.embed()             # 向量化
  ├─→ ApiDocumentRepository.save()      # 存 MySQL
  └─→ MilvusClient.insert()             # 存 Milvus
  ↓
返回 document_id
混合检索流程:
Agent → DocumentSearchTool.search(errorCode, province)
  ↓
  ├─→ MySQL 精确匹配
  │   SELECT * FROM api_document
  │   WHERE error_code = ? AND province = ?
  │
  ├─→ Milvus 语义检索
  │   向量化查询 → 相似度搜索 → Top 10
  │
  └─→ RRF 融合排序
      (精确匹配优先 + 语义补漏)
  ↓
返回 Top 3 文档片段

5. 数据库配置

application.yml 新增:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/superbiz_agent?useUnicode=true&characterEncoding=utf8mb4&serverTimezone=Asia/Shanghai
    username: ${DB_USERNAME:root}
    password: ${DB_PASSWORD:your-password}
    driver-class-name: com.mysql.cj.jdbc.Driver
  
  jpa:
    hibernate:
      ddl-auto: validate                # 生产用 validate,Flyway 管理表结构
    show-sql: true
    properties:
      hibernate:
        format_sql: true
        dialect: org.hibernate.dialect.MySQL8Dialect
  
  flyway:
    enabled: true
    baseline-on-migrate: true
    locations: classpath:db/migration
  
  data:
    redis:
      host: localhost
      port: 6379
      password: ${REDIS_PASSWORD:}
      database: 0
      timeout: 3000
      lettuce:
        pool:
          max-active: 8
          max-idle: 8
          min-idle: 0

6. 测试策略

Repository 测试:

  • 使用 @DataJpaTest + H2 内存数据库
  • 测试 CRUD + 自定义查询

Service 测试:

  • 使用 @SpringBootTest + Mockito
  • Mock Repository 和外部依赖

Controller 测试:

  • 使用 @WebMvcTest + MockMvc
  • Mock Service 层

集成测试:

  • 使用 @SpringBootTest + Testcontainers(可选)
  • 测试完整流程

技术决策

Flyway vs Liquibase

选择:Flyway

理由:

  • 更简单,SQL-first
  • Spring Boot 官方推荐
  • 社区活跃

Jackson vs Gson

选择:Jackson(Spring Boot 默认)

理由:

  • Spring Boot 内置
  • 性能更好
  • 与 Spring MVC 集成好

Lettuce vs Jedis

选择:Lettuce(Spring Data Redis 默认)

理由:

  • 异步支持
  • 线程安全
  • Spring Boot 默认