docs: freeze shared assets and seed V2 contracts
This commit is contained in:
@@ -1 +0,0 @@
|
||||
|
||||
@@ -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 +0,0 @@
|
||||
|
||||
@@ -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.
|
||||
@@ -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 +0,0 @@
|
||||
|
||||
@@ -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.
|
||||
@@ -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 中台的边界。
|
||||
Reference in New Issue
Block a user