docs: freeze shared assets and seed V2 contracts

This commit is contained in:
2026-06-22 18:11:28 +08:00
parent 6842c239f7
commit 3176954a1d
9 changed files with 1438 additions and 3 deletions
-1
View File
@@ -1 +0,0 @@
+189
View File
@@ -0,0 +1,189 @@
# ADR 0001: V2 Technology Stack
Date: 2026-06-22
## Status
Accepted
## Context
V2 is a full rebuild. The old V1 system and old `shared-*` repositories are preserved as references, but new V2 development should avoid continuing multiple shared mainlines.
The product needs:
- A fast enterprise contract workflow.
- A reusable AI platform boundary.
- Strong database and tenant isolation.
- Contract-first API and SDK development.
- Simple local development and production deployment.
- A stack the team can maintain without carrying Python, Java, and vendored SDK variants at the same time.
## Decision
V2 will use a Python/TypeScript monorepo in `D:\yuqei-project\ai-contract-platform`.
### Frontend
- `apps/contract-web`
- Next.js + React + TypeScript
- Ant Design or a small internal design system wrapper during early MVP
- `packages/design-system` for tokens, layout primitives, workflow components, and UI conventions
Reason:
- The team already has Next.js experience from V1.
- It supports enterprise dashboards and route-level composition well.
- It keeps frontend/backend contract usage straightforward through generated TypeScript types.
### Backend
- `services/contract-api`
- Python 3.12+
- FastAPI
- SQLAlchemy 2.x
- Alembic
- Pydantic v2
Reason:
- The contract system is already Python/FastAPI oriented.
- AI, document parsing, RAG, SDK, and testing ecosystems are stronger and faster to iterate in Python.
- Avoids continuing Java and Python dual mainlines.
### AI Platform
- `services/ai-platform-api`
- Python 3.12+
- FastAPI
- Provider adapters behind an internal interface
- Model/provider configuration stored in database and reloadable at runtime
- All external model calls audited
Reason:
- AI behavior must be hot-configurable and testable.
- Legal QA and review need tight integration with RAG, citations, prompt versions, and audit trails.
- The AI platform is a service boundary, not a library hidden inside the contract backend.
### Worker
- `services/worker`
- Python 3.12+
- Redis queue initially
- Later can evolve to Celery/RQ/Arq depending on load
Responsibilities:
- OCR and document extraction
- Knowledge indexing
- Export generation
- Reminder jobs
- AI long-running jobs
### Database
- PostgreSQL 16+
- Multiple schemas in one primary database at first:
- `identity`
- `contract`
- `ai`
- `audit`
- `ops`
- Alembic migrations
- RLS or equivalent tenant isolation for core tenant-owned tables
Reason:
- Keeps early operations simpler than multiple databases.
- Still gives clear domain separation.
- Supports full-text search, JSONB, indexes, transactions, and mature backup tooling.
### Cache and Queue
- Redis 7+
Responsibilities:
- Cache
- Distributed locks
- Rate limiting
- Lightweight async queue
- SSE/session coordination if needed
### Object Storage
- MinIO for local and private deployment
- S3-compatible interface for future cloud migration
Responsibilities:
- Original documents
- Exported Word/PDF files
- Evidence attachments
- OCR source files
- Report artifacts
### Search
Phase 1:
- PostgreSQL full-text search and trigram indexes
Phase 2:
- Evaluate OpenSearch or Meilisearch when real data scale requires it
Reason:
- Avoids introducing a search cluster before core contract workflows are stable.
### API Contracts
- `packages/contract-openapi/openapi.yaml`
- `packages/ai-openapi/openapi.yaml`
- OpenAPI is the source of truth for cross-service and frontend-facing contracts.
- SDKs must align with these contracts.
### SDKs
- `sdks/python`
- `sdks/typescript`
Rules:
- Contract backend calls AI platform through Python SDK or generated OpenAPI client.
- Frontend calls contract API, not AI platform directly except for explicitly approved admin tooling.
- No vendored SDK copies.
### Infrastructure
- Docker Compose for local development and single-node deployment.
- Docker images per service.
- Nginx reverse proxy.
- Structured logs.
- Health checks for every service.
- Backup/restore scripts from day one.
## Explicit Non-Goals
- Do not continue expanding `shared-ai-platform-java`.
- Do not continue expanding the old Python `shared-ai-platform` as production.
- Do not introduce Java into V2 unless a future ADR reverses this decision.
- Do not put contract business workflows into shared modules.
- Do not make electronic signature integration part of the initial V2 MVP.
## Consequences
Positive:
- One V2 development line.
- Fewer cross-repo version mismatches.
- Contract system and AI platform still have a clear service boundary.
- SDK generation and testing become enforceable.
Tradeoffs:
- Old Java shared work will be used only as reference, not as production code.
- Some features already prototyped in old shared repositories must be reimplemented.
- The monorepo needs disciplined module boundaries to avoid becoming another mixed codebase.
-1
View File
@@ -1 +0,0 @@
+15
View File
@@ -0,0 +1,15 @@
# AI OpenAPI
This package is the source of truth for the V2 AI platform HTTP contract.
Primary file:
```text
openapi.yaml
```
Rules:
- AI platform server implementation must match this contract.
- Python and TypeScript SDKs must be generated or verified against this contract.
- Contract API may call AI platform only through SDK/OpenAPI clients.
+451
View File
@@ -0,0 +1,451 @@
openapi: 3.1.0
info:
title: Yuqei AI Platform API
version: 0.1.0
description: V2 AI platform contract for model routing, legal QA, legal review, knowledge bases, and AI audit.
servers:
- url: http://localhost:8101
description: Local AI platform
paths:
/health:
get:
operationId: getHealth
summary: Health check
responses:
"200":
description: Service health
content:
application/json:
schema:
$ref: "#/components/schemas/HealthResponse"
/api/v1/legal/qa:
post:
operationId: runLegalQa
summary: Answer a legal question with citations
parameters:
- $ref: "#/components/parameters/TraceIdHeader"
- $ref: "#/components/parameters/TenantIdHeader"
- $ref: "#/components/parameters/UserIdHeader"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/LegalQaRequest"
responses:
"200":
description: Legal QA answer
content:
application/json:
schema:
$ref: "#/components/schemas/LegalQaResponse"
/api/v1/legal/review:
post:
operationId: runLegalReview
summary: Review contract text and return structured risks
parameters:
- $ref: "#/components/parameters/TraceIdHeader"
- $ref: "#/components/parameters/TenantIdHeader"
- $ref: "#/components/parameters/UserIdHeader"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/LegalReviewRequest"
responses:
"200":
description: Legal review result
content:
application/json:
schema:
$ref: "#/components/schemas/LegalReviewResponse"
/api/v1/ai/chat/stream:
post:
operationId: streamChat
summary: Stream AI chat events
parameters:
- $ref: "#/components/parameters/TraceIdHeader"
- $ref: "#/components/parameters/TenantIdHeader"
- $ref: "#/components/parameters/UserIdHeader"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ChatStreamRequest"
responses:
"200":
description: Server-sent events stream
content:
text/event-stream:
schema:
type: string
/api/v1/knowledge-bases:
get:
operationId: listKnowledgeBases
summary: List knowledge bases
parameters:
- $ref: "#/components/parameters/TenantIdHeader"
- $ref: "#/components/parameters/Page"
- $ref: "#/components/parameters/PageSize"
responses:
"200":
description: Knowledge base page
content:
application/json:
schema:
$ref: "#/components/schemas/KnowledgeBasePage"
post:
operationId: createKnowledgeBase
summary: Create a knowledge base
parameters:
- $ref: "#/components/parameters/TenantIdHeader"
- $ref: "#/components/parameters/UserIdHeader"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CreateKnowledgeBaseRequest"
responses:
"200":
description: Created knowledge base
content:
application/json:
schema:
$ref: "#/components/schemas/KnowledgeBase"
/api/v1/knowledge-bases/{knowledge_base_id}/documents:
post:
operationId: uploadKnowledgeDocument
summary: Upload a knowledge document
parameters:
- $ref: "#/components/parameters/TenantIdHeader"
- $ref: "#/components/parameters/UserIdHeader"
- name: knowledge_base_id
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required:
- file
properties:
file:
type: string
format: binary
responses:
"200":
description: Uploaded document
content:
application/json:
schema:
$ref: "#/components/schemas/KnowledgeDocument"
/api/v1/audit/ai-runs:
get:
operationId: listAiRuns
summary: List AI audit runs
parameters:
- $ref: "#/components/parameters/TenantIdHeader"
- $ref: "#/components/parameters/Page"
- $ref: "#/components/parameters/PageSize"
responses:
"200":
description: AI run audit page
content:
application/json:
schema:
$ref: "#/components/schemas/AiRunPage"
components:
parameters:
TraceIdHeader:
name: X-Trace-Id
in: header
required: false
schema:
type: string
TenantIdHeader:
name: X-Tenant-Id
in: header
required: true
schema:
type: string
UserIdHeader:
name: X-User-Id
in: header
required: true
schema:
type: string
Page:
name: page
in: query
required: false
schema:
type: integer
minimum: 1
default: 1
PageSize:
name: page_size
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 100
default: 20
schemas:
HealthResponse:
type: object
required:
- status
properties:
status:
type: string
enum: [ok]
service:
type: string
LegalCitation:
type: object
required:
- source_type
- title
- reference
- quote
properties:
source_type:
type: string
enum: [law, regulation, judicial_interpretation, internal_policy, contract_clause, knowledge_document]
title:
type: string
reference:
type: string
description: Article, clause, section, or document locator.
quote:
type: string
url:
type: string
nullable: true
LegalQaRequest:
type: object
required:
- question
properties:
question:
type: string
matter_context:
type: string
nullable: true
knowledge_base_ids:
type: array
items:
type: string
LegalQaResponse:
type: object
required:
- answer
- citations
properties:
answer:
type: string
citations:
type: array
items:
$ref: "#/components/schemas/LegalCitation"
confidence:
type: number
format: float
nullable: true
LegalReviewRequest:
type: object
required:
- text
properties:
title:
type: string
nullable: true
text:
type: string
contract_type:
type: string
nullable: true
review_perspective:
type: string
enum: [party_a, party_b, neutral]
default: neutral
knowledge_base_ids:
type: array
items:
type: string
RiskItem:
type: object
required:
- id
- severity
- title
- description
properties:
id:
type: string
severity:
type: string
enum: [high, medium, low]
title:
type: string
description:
type: string
suggestion:
type: string
nullable: true
citations:
type: array
items:
$ref: "#/components/schemas/LegalCitation"
LegalReviewResponse:
type: object
required:
- risk_summary
- risk_items
- review_opinion
properties:
risk_summary:
type: object
required:
- high
- medium
- low
- overall
properties:
high:
type: integer
medium:
type: integer
low:
type: integer
overall:
type: string
enum: [high, medium, low, none]
risk_items:
type: array
items:
$ref: "#/components/schemas/RiskItem"
review_opinion:
type: string
recommendation:
type: string
nullable: true
ChatStreamRequest:
type: object
required:
- message
properties:
message:
type: string
conversation_id:
type: string
nullable: true
context:
type: object
additionalProperties: true
KnowledgeBase:
type: object
required:
- id
- name
- status
properties:
id:
type: string
name:
type: string
description:
type: string
nullable: true
status:
type: string
enum: [draft, indexing, active, archived]
KnowledgeBasePage:
type: object
required:
- items
- page
- page_size
- total
properties:
items:
type: array
items:
$ref: "#/components/schemas/KnowledgeBase"
page:
type: integer
page_size:
type: integer
total:
type: integer
CreateKnowledgeBaseRequest:
type: object
required:
- name
properties:
name:
type: string
description:
type: string
nullable: true
KnowledgeDocument:
type: object
required:
- id
- file_name
- status
properties:
id:
type: string
file_name:
type: string
status:
type: string
enum: [uploaded, extracting, indexed, failed]
failure_message:
type: string
nullable: true
AiRun:
type: object
required:
- id
- operation
- status
- created_at
properties:
id:
type: string
operation:
type: string
status:
type: string
enum: [pending, running, succeeded, failed, cancelled]
created_at:
type: string
format: date-time
AiRunPage:
type: object
required:
- items
- page
- page_size
- total
properties:
items:
type: array
items:
$ref: "#/components/schemas/AiRun"
page:
type: integer
page_size:
type: integer
total:
type: integer
-1
View File
@@ -1 +0,0 @@
+15
View File
@@ -0,0 +1,15 @@
# Contract OpenAPI
This package is the source of truth for the V2 contract platform HTTP contract.
Primary file:
```text
openapi.yaml
```
Rules:
- Contract Web should consume this contract through generated or typed clients.
- Contract API implementation must match this contract.
- Contract API calls AI Platform only through SDK/OpenAPI clients, not direct provider adapters.
+490
View File
@@ -0,0 +1,490 @@
openapi: 3.1.0
info:
title: Yuqei Contract Platform API
version: 0.1.0
description: V2 contract platform contract for enterprise contract drafting, review, workflow, repository, and audit.
servers:
- url: http://localhost:8100
description: Local contract API
paths:
/health:
get:
operationId: getHealth
summary: Health check
responses:
"200":
description: Service health
content:
application/json:
schema:
$ref: "#/components/schemas/HealthResponse"
/api/v1/auth/login:
post:
operationId: login
summary: Login
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/LoginRequest"
responses:
"200":
description: Login result
content:
application/json:
schema:
$ref: "#/components/schemas/LoginResponse"
/api/v1/workspace:
get:
operationId: getWorkspace
summary: Get current user's workspace summary
parameters:
- $ref: "#/components/parameters/TraceIdHeader"
responses:
"200":
description: Workspace summary
content:
application/json:
schema:
$ref: "#/components/schemas/WorkspaceSummary"
/api/v1/contracts:
get:
operationId: listContracts
summary: List contracts
parameters:
- $ref: "#/components/parameters/Page"
- $ref: "#/components/parameters/PageSize"
- name: status
in: query
required: false
schema:
type: string
- name: keyword
in: query
required: false
schema:
type: string
responses:
"200":
description: Contract page
content:
application/json:
schema:
$ref: "#/components/schemas/ContractPage"
post:
operationId: createContract
summary: Create a contract draft
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CreateContractRequest"
responses:
"200":
description: Created contract
content:
application/json:
schema:
$ref: "#/components/schemas/ContractDetail"
/api/v1/contracts/{contract_id}:
get:
operationId: getContractDetail
summary: Get contract detail
parameters:
- name: contract_id
in: path
required: true
schema:
type: string
responses:
"200":
description: Contract detail
content:
application/json:
schema:
$ref: "#/components/schemas/ContractDetail"
/api/v1/contracts/{contract_id}/review:
post:
operationId: startContractReview
summary: Start AI-assisted contract review
parameters:
- name: contract_id
in: path
required: true
schema:
type: string
responses:
"200":
description: Review task
content:
application/json:
schema:
$ref: "#/components/schemas/ReviewTask"
/api/v1/contracts/{contract_id}/approval/submit:
post:
operationId: submitApproval
summary: Submit contract for approval
parameters:
- name: contract_id
in: path
required: true
schema:
type: string
requestBody:
required: false
content:
application/json:
schema:
$ref: "#/components/schemas/SubmitApprovalRequest"
responses:
"200":
description: Approval timeline
content:
application/json:
schema:
$ref: "#/components/schemas/ApprovalTimeline"
/api/v1/search:
get:
operationId: search
summary: Unified search
parameters:
- name: keyword
in: query
required: true
schema:
type: string
- name: type
in: query
required: false
schema:
type: string
enum: [contract, review, file, template]
- name: sort
in: query
required: false
schema:
type: string
enum: [updated_at_desc, relevance]
default: updated_at_desc
responses:
"200":
description: Search results
content:
application/json:
schema:
$ref: "#/components/schemas/SearchResultPage"
/api/v1/files:
get:
operationId: listFiles
summary: List repository files
parameters:
- $ref: "#/components/parameters/Page"
- $ref: "#/components/parameters/PageSize"
- name: keyword
in: query
required: false
schema:
type: string
responses:
"200":
description: File page
content:
application/json:
schema:
$ref: "#/components/schemas/FilePage"
components:
parameters:
TraceIdHeader:
name: X-Trace-Id
in: header
required: false
schema:
type: string
Page:
name: page
in: query
required: false
schema:
type: integer
minimum: 1
default: 1
PageSize:
name: page_size
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 100
default: 20
schemas:
HealthResponse:
type: object
required:
- status
properties:
status:
type: string
enum: [ok]
service:
type: string
LoginRequest:
type: object
required:
- email
- password
properties:
email:
type: string
format: email
password:
type: string
LoginResponse:
type: object
required:
- access_token
- user
properties:
access_token:
type: string
user:
$ref: "#/components/schemas/UserProfile"
UserProfile:
type: object
required:
- id
- email
- role
properties:
id:
type: string
email:
type: string
name:
type: string
nullable: true
role:
type: string
enum: [admin, legal, business_submitter, approver, observer]
WorkspaceSummary:
type: object
required:
- pending_tasks
- quick_actions
properties:
pending_tasks:
type: array
items:
$ref: "#/components/schemas/WorkspaceTask"
quick_actions:
type: array
items:
type: string
WorkspaceTask:
type: object
required:
- id
- title
- type
- target_url
properties:
id:
type: string
title:
type: string
type:
type: string
target_url:
type: string
ContractListItem:
type: object
required:
- id
- title
- status
- updated_at
properties:
id:
type: string
title:
type: string
status:
type: string
enum: [draft, reviewing, approval_pending, approved, signed, archived, rejected]
counterparty:
type: string
nullable: true
updated_at:
type: string
format: date-time
ContractPage:
type: object
required:
- items
- page
- page_size
- total
properties:
items:
type: array
items:
$ref: "#/components/schemas/ContractListItem"
page:
type: integer
page_size:
type: integer
total:
type: integer
CreateContractRequest:
type: object
required:
- title
properties:
title:
type: string
contract_type:
type: string
nullable: true
counterparty:
type: string
nullable: true
source_text:
type: string
nullable: true
ContractDetail:
type: object
required:
- id
- title
- status
- next_actions
properties:
id:
type: string
title:
type: string
status:
type: string
body_preview:
type: string
nullable: true
next_actions:
type: array
items:
type: string
ReviewTask:
type: object
required:
- id
- status
properties:
id:
type: string
status:
type: string
enum: [queued, running, succeeded, failed]
SubmitApprovalRequest:
type: object
properties:
comment:
type: string
nullable: true
ApprovalTimeline:
type: object
required:
- items
properties:
items:
type: array
items:
$ref: "#/components/schemas/ApprovalTimelineItem"
ApprovalTimelineItem:
type: object
required:
- id
- action
- actor_name
- created_at
properties:
id:
type: string
action:
type: string
actor_name:
type: string
comment:
type: string
nullable: true
created_at:
type: string
format: date-time
SearchResult:
type: object
required:
- id
- type
- title
- url
properties:
id:
type: string
type:
type: string
enum: [contract, review, file, template]
title:
type: string
snippet:
type: string
nullable: true
url:
type: string
updated_at:
type: string
format: date-time
nullable: true
SearchResultPage:
type: object
required:
- items
properties:
items:
type: array
items:
$ref: "#/components/schemas/SearchResult"
FileItem:
type: object
required:
- id
- file_name
- status
properties:
id:
type: string
file_name:
type: string
status:
type: string
enum: [uploaded, processing, ready, failed]
related_contract_id:
type: string
nullable: true
FilePage:
type: object
required:
- items
- page
- page_size
- total
properties:
items:
type: array
items:
$ref: "#/components/schemas/FileItem"
page:
type: integer
page_size:
type: integer
total:
type: integer
@@ -0,0 +1,278 @@
# V2 旧 shared 资产盘点与迁移清单
日期:2026-06-22
## 1. 结论
`shared-*` 仓库不再作为 V2 的继续开发主线。
V2 采用当前仓库 `D:\yuqei-project\ai-contract-platform` 的 monorepo workspace,把 shared 能力重新落到:
- `services/ai-platform-api`
- `packages/ai-openapi`
- `sdks/python`
- `sdks/typescript`
- `services/worker`
- `packages/design-system`
旧 shared 仓库只作为历史参考、行为对照、迁移素材和测试样例来源。
## 2. 旧仓库当前状态
| 仓库 | 当前状态 | 未提交改动 | V2 处理策略 |
|---|---|---:|---|
| `shared-ai-platform` | Python 原型平台,含知识库、会话、任务、OCR、RAG、SDK 原型和大量文档 | 有 | 参考实现和数据处理经验,不继续扩展 |
| `shared-ai-platform-java` | Java 版共享 AI 平台,含 v0.2 contract、legal-review、knowledge、chat、prompt、provider-router | 有 | 参考模块边界、契约和测试,不迁移 Java 技术栈 |
| `shared-ai-python-sdk` | 形式化 Python SDK,默认 `/api/v0.2`,含 SSE、错误处理、legal-review、document extraction 测试 | 无 | 迁移 API 设计和测试思想,V2 在 `sdks/python` 重做 |
| `shared-java-libs` | Java 公共库,含 shared-ai-sdk、shared-web、shared-storage、shared-notify、shared-core | 有 | V2 不采用 Java 主线,仅参考公共能力边界 |
## 3. `shared-ai-platform` 盘点
### 3.1 可迁移资产
- OCR/文档解析经验:
- Tesseract 与 PaddleOCR 双引擎思路。
- 扫描件 PDF OCR 质量门禁。
- OCR 失败原因结构化返回。
- RAG/知识库经验:
- knowledge-bases。
- documents upload/retry。
- retrieval service。
- sync content。
- Chat/SSE 经验:
- conversations stream。
- conversations history。
- SSE 事件格式。
- 平台治理经验:
- apps。
- tasks/jobs。
- usage/costs。
- evals。
- ops/system。
- 测试样例:
- `tests/test_v0_2_conversations_api.py`
- `tests/test_v0_2_knowledge_api.py`
- `tests/test_v0_2_document_extraction_api.py`
- `tests/test_legal_review_domain_pack.py`
- `tests/test_python_sdk.py`
### 3.2 只参考不迁移
- 旧 Python 原型的目录结构。
-`app/api/v0_2` 具体路由实现。
- 本地 `_runtime``storage``local-knowledge`
- 旧部署脚本。
- 旧文档归档结构。
### 3.3 废弃
- 作为生产 AI 中台主线的定位。
- 与 V2 重复的 SDK 原型。
-`/api/v0.1` 兼容包袱。
### 3.4 当前未提交改动处理建议
当前未提交改动集中在:
- `app/core/config.py`
- `app/services/document_extraction_service.py`
- `requirements.txt`
内容是 PaddleOCR 支持和 OCR 引擎配置。
V2 处理建议:
- 不在旧仓库继续提交该功能。
- 将“可配置 OCR 引擎、OCR 质量门禁、OCR 失败结构化返回”作为 `services/worker` 的文档解析需求。
- PaddleOCR 是否启用作为 V2 技术栈 ADR 的可选项,默认不阻塞基础工程。
## 4. `shared-ai-platform-java` 盘点
### 4.1 可迁移资产
- v0.2 contract 文档思路:
- `shared-ai-platform-contract/docs/shared-ai-v0.2-contract.md`
- 统一请求头。
- 响应 envelope。
- 分页规范。
- snake_case 约定。
- legal-review v0.2 兼容思路:
- 同时支持 `/api/v0.1/domain-packs/legal-review`
-`/api/v0.2/domain-packs/legal-review`
- legal-review 结构化审查经验:
- 风险摘要。
- 风险项。
- 审查意见。
- 建议动作。
- confidence summary。
- 模块边界:
- provider-router。
- prompts。
- knowledge。
- chat。
- tasks。
- usage。
- domain-legal-review。
- API smoke test 思路:
- 同一测试覆盖 v0.1/v0.2 legal-review。
- SDK/服务端契约一致性。
### 4.2 只参考不迁移
- Spring Boot 多模块结构。
- Maven BOM/dependencies。
- Java DTO、Controller 和 Repository 实现。
- Java provider-router 具体代码。
### 4.3 废弃
- 作为 V2 生产 AI 中台主技术栈。
- 继续新增 V2 能力到旧 Java shared。
- 继续维护多套 shared 主线。
### 4.4 当前未提交改动处理建议
当前未提交改动集中在:
- `README.md`
- `PlatformLegalReviewController.java`
- `SharedAiPlatformApiSmokeTest.java`
- `shared-ai-platform-contract/docs/`
内容是 v0.2 contract 和 legal-review v0.2 兼容入口。
V2 处理建议:
- 不在旧 Java 仓库继续扩展。
- 把 v0.2 contract 的思想迁移到 `packages/ai-openapi/openapi.yaml`
- 把 legal-review v0.2 路径设计迁移为 V2 新接口,但路径统一为 `/api/v1/legal/review`,避免继续沿用 domain-pack 历史命名。
## 5. `shared-ai-python-sdk` 盘点
### 5.1 可迁移资产
- `SharedAIPlatformClient` 的基础结构。
- `RequestContext`
- SSE 解析:
- `parse_sse_payload`
- `iter_sse_events`
- 错误映射:
- transport error。
- envelope error。
- API prefix 归一化。
- 文件上传。
- knowledge sync。
- legal review client。
- tests
- `test_sse.py`
- `test_legal_review.py`
- `test_errors.py`
- `test_client_paths.py`
- `test_document_extraction.py`
### 5.2 只参考不迁移
- 包名 `shared-ai-platform-sdk`
-`/api/v0.2` 路径命名。
- 与 Java shared contract 绑定的 DTO 命名。
### 5.3 V2 迁移策略
V2 在 `sdks/python` 重新实现正式 SDK
- 包名建议:`yuqei-ai-sdk-python`
- Python import 建议:`yuqei_ai_sdk`
-`packages/ai-openapi/openapi.yaml` 生成基础类型。
- 手写业务友好封装。
- 默认调用 `/api/v1`
- 必须支持:
- timeout。
- retry。
- trace id。
- SSE。
- typed errors。
- contract tests。
## 6. `shared-java-libs` 盘点
### 6.1 可参考资产
- shared-web 的条件装配思路:
- trace id filter 可开关。
- request log filter 可开关。
- global exception handler 可开关。
- shared-storage 的抽象:
- local。
- MinIO。
- noop。
- shared-notify 的抽象:
- noop。
- logging。
- Aliyun SMS sandbox。
- shared-ai-sdk 的 Java 客户端边界。
- shared-core 的分页、错误码、响应模型思想。
### 6.2 不迁移内容
- Java 代码。
- Spring Boot starter。
- Maven 多模块结构。
- Java SDK。
### 6.3 V2 处理策略
V2 使用 Python/TypeScript 主线,因此只吸收“能力边界”和“默认不改变业务项目行为”的原则。
对应落地:
- `services/contract-api``services/ai-platform-api` 的 middleware 必须可配置。
- 错误响应必须标准化,但不能让 SDK 与 HTTP 状态混淆。
- storage/notify 作为应用内可替换 adapter,不做跨仓库 Java shared。
## 7. V2 迁移优先级
### P0:必须迁移
- AI 中台 OpenAPI 契约。
- 法律问答与法律审查接口边界。
- SDK 请求上下文和错误处理。
- SSE 事件格式。
- 知识库文档上传、解析、检索、同步的核心流程。
- AI 调用审计。
### P1:第二批迁移
- OCR 引擎配置与文档解析质量门禁。
- Prompt 模板版本管理。
- 任务/Job 状态机。
- 使用量和成本记录。
- 基础评测样本。
### P2:后续再做
- 多 domain-pack 插件体系。
- 复杂 provider-router。
- 复杂预算/限流/成本治理。
- 前端组件库抽象。
- Java SDK。
## 8. V2 废弃清单
V2 不再保留:
- `shared-ai-platform-java` 作为生产主线。
- `shared-ai-platform` 作为生产主线。
- V1 vendored SDK。
- 多套 `/api/v0.1``/api/v0.2` 历史路径。
- `domain-packs` 作为对外 API 路径。
- 未经第二个真实项目验证的业务流程 shared 化。
## 9. 后续执行项
1. 建立 V2 技术栈 ADR。
2. 建立 `packages/ai-openapi/openapi.yaml`
3. 建立 `packages/contract-openapi/openapi.yaml`
4. 初始化 `services/ai-platform-api`
5. 初始化 `sdks/python`
6. 迁移 SSE、错误处理、RequestContext 的测试思想。
7. 初始化合同系统只通过 SDK 调用 AI 中台的边界。