GzDoc 系统架构设计
1. 架构概览
GzDoc 采用**“平台 + 插件”微服务架构**,分为五层:
- 用户层: Web端、移动端、开放API
- 接入层: Nginx + API Gateway
- 业务服务层:
- 平台层(通用能力):用户、文档、问答基础服务
- 场景层(垂直插件):金融、法律、医疗等垂直场景
- AI服务层: Python FastAPI
- 数据层: PostgreSQL + Weaviate + Redis + MinIO + Kafka + ES
1.1 核心设计理念
“平台化 + 垂直场景插件化”
┌─────────────────────────────────────────────────────────────┐
│ 通用平台层(稳定、不变) │
├─────────────────────────────────────────────────────────────┤
│ gzdoc-common │ 通用工具、实体、常量 │
│ gzdoc-gateway │ 统一网关、鉴权、限流 │
│ gzdoc-auth │ 用户、租户、权限管理 │
│ gzdoc-document │ 文档上传、存储、管理 │
│ gzdoc-qa │ 通用问答、RAG基础能力 │
└─────────────────────────────────────────────────────────────┘
↓ 依赖
┌─────────────────────────────────────────────────────────────┐
│ 垂直场景层(插件式、可扩展) │
├─────────────────────────────────────────────────────────────┤
│ gzdoc-finance │ 金融研报:解析、对比、投资建议 │
│ gzdoc-legal │ 法律合同:条款提取、风险识别(未来) │
│ gzdoc-medical │ 医疗影像:报告解读、对比分析(未来) │
│ gzdoc-engineer │ 工程图纸:规范审查、变更追踪(未来) │
└─────────────────────────────────────────────────────────────┘
关键特性:
- ✅ 不侵入:场景层不修改平台层代码
- ✅ 可复用:场景层复用平台层通用能力
- ✅ 独立部署:场景服务可独立扩展、按需部署
- ✅ 灵活定价:按场景模块收费
2. 核心服务
2.1 平台层服务 (Java) - 通用能力
gzdoc-gateway (API网关)
- 职责: 统一入口、路由转发、鉴权、限流
- 技术: Spring Cloud Gateway
- 端口: 8080
- 特点: 所有请求统一入口,路由到平台层或场景层
gzdoc-auth (用户服务)
- 职责: 用户注册登录、权限管理、租户管理
- 技术: Spring Security + JWT
- 端口: 8081
- 特点: 平台级服务,所有场景共享
gzdoc-document (文档服务)
- 职责: 文档上传、管理、预览
- 技术: Spring Boot + MinIO
- 端口: 8082
- 特点: 通用文档能力,支持所有场景
gzdoc-qa (问答服务)
- 职责: 问答接口、历史记录、反馈管理
- 技术: Spring Boot + gRPC (调用AI服务)
- 端口: 8083
- 特点: 基础RAG能力,场景层可扩展
gzdoc-common (公共模块)
- 职责: 公共工具类、实体类、常量
- 特点: 所有服务的基础依赖
2.2 场景层服务 (Java) - 垂直插件
gzdoc-finance (金融研报服务) ⭐ 首个场景
- 职责:
- 研报解析(提取基本信息、财务数据、估值)
- 横向对比(多研报对比分析)
- 趋势分析(时间序列分析)
- 投资建议(AI生成)
- 技术: Spring Boot + 复用平台层服务
- 端口: 8084
- 依赖:
- gzdoc-common(公共能力)
- gzdoc-document(文档管理)
- gzdoc-qa(问答能力)
- 数据表:
- t_finance_report(研报表)
- t_finance_data(财务数据)
- t_finance_comparison(对比记录)
服务调用示例:
@Service
public class FinanceReportService {
@Autowired
private DocumentService documentService; // 复用平台层
@Autowired
private AIService aiService; // 复用平台层
public void processReport(Long reportId) {
// 1. 获取文档(平台层)
Document doc = documentService.getDocument(reportId);
// 2. 金融专用解析
ReportData data = parseFinanceReport(doc);
// 3. 保存金融数据(场景层)
saveFinanceData(data);
}
}
gzdoc-legal (法律合同服务) - 未来规划
- 职责: 合同条款提取、风险识别、合同对比
- 端口: 8085
gzdoc-medical (医疗影像服务) - 未来规划
- 职责: 影像报告解读、历史对比、就医建议
- 端口: 8086
2.3 AI服务 (Python)
ai-service
- 职责: OCR、文档解析、Embedding、向量检索、LLM调用
- 技术: FastAPI + LangChain + PaddleOCR
- 端口: 8000
核心模块:
app/api: API路由app/core: 核心配置app/models: 数据模型app/services: 业务逻辑- 通用服务:
ocr_service.py: OCR识别parser_service.py: 文档解析embedding_service.py: 向量化retrieval_service.py: 向量检索llm_service.py: LLM调用rag_service.py: RAG编排
- 场景服务 (新增):
finance/: 金融专用AI能力report_parser.py: 研报解析table_extractor.py: 表格提取entity_recognizer.py: 实体识别comparison_engine.py: 对比引擎investment_advisor.py: 投资建议
- 通用服务:
3. 数据流
3.1 通用文档处理流程
用户上传文档
↓
文档服务 (gzdoc-document) - 平台层
↓
存储到 MinIO
↓
发送消息到 Kafka (topic: document-upload)
↓
AI服务消费消息
↓
1. 格式检测
2. OCR识别 (如果是图片)
3. 文档解析 (Unstructured)
4. 智能分块
5. Embedding生成 (BGE-M3)
6. 向量入库 (Weaviate)
7. 元数据提取
8. 全文索引 (ElasticSearch)
↓
更新文档状态 (处理完成)
↓
通知用户 (WebSocket)
3.2 金融研报处理流程(场景层扩展)
用户上传金融研报
↓
API Gateway → 金融服务 (gzdoc-finance)
↓
1. 调用文档服务上传(复用平台层)
documentService.upload()
↓
2. 发送消息到 Kafka (topic: finance-report-upload)
↓
3. AI服务消费消息(场景专用处理)
├─ 研报解析(提取基本信息)
├─ 表格识别(财务数据)
├─ 实体提取(公司名、指标)
└─ 向量化(复用平台层)
↓
4. 保存金融专用数据
├─ t_finance_report(研报表)
└─ t_finance_data(财务数据)
↓
5. 更新状态 + 通知用户
关键点:
- ✅ 复用平台层的文档上传、存储能力
- ✅ 扩展场景专用的解析、提取能力
- ✅ 数据分层存储(通用表 + 场景表)
3.3 智能问答流程(平台层 + 场景层)
通用问答流程
用户提问
↓
问答服务 (gzdoc-qa) - 平台层
↓
调用 AI服务 (gRPC)
↓
1. 问题理解
- 意图识别
- 实体提取
- Query扩展
↓
2. 混合检索
- 向量检索 (Weaviate) - Top 50
- 全文检索 (ES) - Top 50
- 结果融合 (RRF)
- Rerank (BGE-Reranker) - Top 10
↓
3. 答案生成
- 上下文构建 (Top 5)
- Prompt组装
- LLM调用 (流式输出)
- 答案后处理
↓
返回答案 + 引用
↓
保存问答历史
金融问答流程(场景层增强)
用户提问(关于某只股票)
↓
金融服务 (gzdoc-finance) - 场景层
↓
1. 场景过滤(只查询该股票的研报)
reportIds = getReportsByStockCode(stockCode)
↓
2. 调用平台层问答服务
response = qaService.ask(question, reportIds)
↓
3. 场景增强(添加金融专用信息)
├─ 最新财务数据
├─ 估值数据
└─ 历史趋势
↓
返回增强后的答案
4. 数据库设计
4.1 PostgreSQL (业务数据)
平台层数据表
用户表 (t_user)
CREATE TABLE t_user (
id BIGSERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
email VARCHAR(100),
phone VARCHAR(20),
tenant_id BIGINT NOT NULL,
role VARCHAR(20) NOT NULL,
status SMALLINT DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
租户表 (t_tenant)
CREATE TABLE t_tenant (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
code VARCHAR(50) UNIQUE NOT NULL,
plan VARCHAR(20) NOT NULL,
status SMALLINT DEFAULT 1,
expired_at TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
文档表 (t_document) - 通用
CREATE TABLE t_document (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
name VARCHAR(255) NOT NULL,
file_path VARCHAR(500) NOT NULL,
file_size BIGINT,
file_type VARCHAR(50),
page_count INT,
scene_type VARCHAR(20), -- 场景类型:finance/legal/medical/general
status SMALLINT DEFAULT 0, -- 0:上传中 1:处理中 2:完成 3:失败
process_progress INT DEFAULT 0,
error_msg TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_tenant_id (tenant_id),
INDEX idx_scene_type (scene_type)
);
问答记录表 (t_qa_record) - 通用
CREATE TABLE t_qa_record (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
scene_type VARCHAR(20), -- 场景类型
question TEXT NOT NULL,
answer TEXT,
sources JSONB, -- 引用来源
feedback SMALLINT, -- 1:好 -1:差
token_count INT,
cost DECIMAL(10, 4),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_tenant_scene (tenant_id, scene_type)
);
场景层数据表 - 金融
研报表 (t_finance_report)
CREATE TABLE t_finance_report (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL,
document_id BIGINT NOT NULL, -- 关联通用文档表
-- 基本信息
title VARCHAR(500) NOT NULL,
institution VARCHAR(100), -- 机构(中信证券)
analyst VARCHAR(100), -- 分析师
publish_date DATE,
-- 核心数据
stock_code VARCHAR(20), -- 股票代码(600519)
stock_name VARCHAR(100), -- 股票名称(贵州茅台)
rating VARCHAR(20), -- 评级(买入/增持/中性)
target_price DECIMAL(10, 2), -- 目标价
-- 结构化数据(JSON)
core_views JSONB, -- 核心观点
financial_data JSONB, -- 财务数据
valuation JSONB, -- 估值数据
risks JSONB, -- 风险提示
-- 状态
parse_status SMALLINT DEFAULT 0, -- 0:未解析 1:解析中 2:完成 3:失败
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (document_id) REFERENCES t_document(id),
INDEX idx_stock_code (stock_code),
INDEX idx_publish_date (publish_date),
INDEX idx_institution (institution)
);
财务数据表 (t_finance_data) - 时间序列
CREATE TABLE t_finance_data (
id BIGSERIAL PRIMARY KEY,
report_id BIGINT NOT NULL,
stock_code VARCHAR(20) NOT NULL,
-- 时间
year INT NOT NULL,
quarter SMALLINT, -- 1/2/3/4 或 NULL(年度)
-- 财务指标
revenue DECIMAL(15, 2), -- 营收(亿元)
net_profit DECIMAL(15, 2), -- 净利润
gross_margin DECIMAL(5, 2), -- 毛利率
roe DECIMAL(5, 2), -- ROE
-- 估值指标
pe DECIMAL(10, 2),
pb DECIMAL(10, 2),
ps DECIMAL(10, 2),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (report_id) REFERENCES t_finance_report(id),
UNIQUE (stock_code, year, quarter),
INDEX idx_stock_year (stock_code, year)
);
对比记录表 (t_finance_comparison)
CREATE TABLE t_finance_comparison (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
stock_code VARCHAR(20) NOT NULL,
report_ids BIGINT[], -- 对比的研报ID数组
comparison_result JSONB, -- 对比结果
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_stock_code (stock_code)
);
设计要点:
- ✅ 通用表(t_document, t_qa_record)支持所有场景
- ✅ 场景表(t_finance_*)通过 document_id 关联通用表
- ✅ 场景表独立,不影响平台层
- ✅ 支持未来扩展(t_legal_, t_medical_)
4.2 Weaviate (向量数据)
通用 Schema: Document
{
"class": "Document",
"description": "通用文档向量数据",
"properties": [
{"name": "tenant_id", "dataType": ["int"]},
{"name": "document_id", "dataType": ["int"]},
{"name": "scene_type", "dataType": ["string"]},
{"name": "chunk_id", "dataType": ["string"]},
{"name": "content", "dataType": ["text"]},
{"name": "page_number", "dataType": ["int"]},
{"name": "metadata", "dataType": ["object"]}
],
"vectorizer": "none"
}
场景 Schema: FinanceReport
{
"class": "FinanceReport",
"description": "金融研报向量数据(场景专用)",
"properties": [
{"name": "tenant_id", "dataType": ["int"]},
{"name": "report_id", "dataType": ["int"]},
{"name": "document_id", "dataType": ["int"]},
{"name": "stock_code", "dataType": ["string"]},
{"name": "stock_name", "dataType": ["string"]},
{"name": "institution", "dataType": ["string"]},
{"name": "publish_date", "dataType": ["date"]},
{"name": "chunk_id", "dataType": ["string"]},
{"name": "chunk_type", "dataType": ["string"]},
{"name": "content", "dataType": ["text"]},
{"name": "page_number", "dataType": ["int"]},
{"name": "metadata", "dataType": ["object"]}
],
"vectorizer": "none",
"moduleConfig": {
"generative-openai": {}
}
}
设计要点:
- ✅ 通用 Schema 支持所有场景
- ✅ 场景 Schema 添加专用字段(股票代码、机构等)
- ✅ chunk_type 分类(核心观点/财务数据/风险提示)
- ✅ 支持按场景过滤检索
5. 技术选型理由
5.1 为什么选”平台+插件”架构?
- ✅ 快速试错:新场景不行可以直接删除模块
- ✅ 灵活定价:按场景收费(基础版 + 金融版 + 法律版)
- ✅ 降低风险:场景层不影响平台层稳定性
- ✅ 并行开发:多个场景可以同时开发
- ✅ 技术债低:废弃场景直接删除,不留遗留代码
5.2 为什么选Spring Cloud?
- 成熟的微服务生态
- 丰富的组件支持
- 社区活跃,文档完善
- 适合企业级应用
5.3 为什么选FastAPI?
- 高性能(基于Starlette + Pydantic)
- 自动生成API文档
- 类型提示支持
- 异步支持
5.4 为什么选Weaviate?
- 原生支持混合检索
- 性能优秀
- 支持多租户
- 易于部署
5.5 为什么选Kafka?
- 高吞吐量
- 持久化消息
- 支持消息回溯
- 适合异步处理
6. 场景扩展示例
6.1 如何新增一个场景?
以”法律合同”场景为例:
Step 1: 创建服务模块
cd backend
mkdir gzdoc-legal
# 复制 gzdoc-finance 的结构
Step 2: 定义数据表
CREATE TABLE t_legal_contract (
id BIGSERIAL PRIMARY KEY,
document_id BIGINT NOT NULL,
contract_type VARCHAR(50),
parties JSONB,
clauses JSONB,
risks JSONB,
...
FOREIGN KEY (document_id) REFERENCES t_document(id)
);
Step 3: 实现业务逻辑
@Service
public class LegalContractService {
@Autowired
private DocumentService documentService; // 复用平台层
public void processContract(Long contractId) {
// 1. 获取文档
Document doc = documentService.getDocument(contractId);
// 2. 法律专用解析
ContractData data = parseContract(doc);
// 3. 保存法律数据
saveLegalData(data);
}
}
Step 4: 添加AI能力
# ai-service/app/services/legal/
# - contract_parser.py
# - clause_extractor.py
# - risk_analyzer.py
Step 5: 部署
# docker-compose.yml
gzdoc-legal:
image: gzdoc-legal:1.0
ports: ["8085:8085"]
关键:全程不需要修改平台层代码!
7. 非功能需求
7.1 性能指标
- 文档上传: 支持100MB文件
- 文档处理: 100页PDF < 30秒
- 问答响应: P99 < 3秒
- 并发支持: 1000 QPS
- 系统可用性: 99.9%
7.2 安全要求
- 数据加密: TLS 1.3 + AES-256
- 身份认证: JWT + 双因素认证
- 权限控制: RBAC + 数据权限
- 审计日志: 所有操作可追溯
7.3 可扩展性
- 水平扩展: 所有服务无状态
- 数据库: 读写分离 + 分库分表
- 缓存: Redis Cluster
- 存储: MinIO分布式部署
- 场景扩展: 插件式新增场景,不影响现有服务
8. 部署架构
8.1 开发环境
- Docker Compose
- 单机部署
- 快速启动
8.2 生产环境
- Kubernetes
- 多节点部署
- 高可用
- 按场景部署: 可选择性部署场景服务
# 示例:只部署金融场景
kubectl apply -f k8s/platform/ # 平台层(必须)
kubectl apply -f k8s/finance/ # 金融场景(可选)
# kubectl apply -f k8s/legal/ # 法律场景(不部署)
9. 监控体系
9.1 业务监控
- 文档处理成功率
- 问答准确率
- 响应时间 (P50/P95/P99)
- Token消耗趋势
- 场景监控: 各场景独立监控指标
9.2 系统监控
- 服务健康检查
- CPU/内存/磁盘
- 数据库连接池
- 消息队列积压
9.3 AI监控
- 模型推理延迟
- 向量检索耗时
- LLM调用失败率
- 幻觉检测
10. 商业模式
10.1 按场景定价
基础版:$99/月
- 平台层所有功能
- 通用文档管理
- 基础问答
金融版:$499/月
- 基础版 +
- 研报解析
- 横向对比
- 投资建议
企业版:$2999/月
- 金融版 +
- 法律合同
- 医疗影像
- 私有部署
10.2 按需部署
客户可以选择:
- 只部署平台层(通用能力)
- 平台层 + 金融场景
- 平台层 + 法律场景
- 平台层 + 多个场景
优势:
- ✅ 降低客户成本(按需付费)
- ✅ 降低运维成本(不部署不用的服务)
- ✅ 提高销售灵活性(模块化销售)
11. 架构演进路线
Phase 1: MVP (Month 1-3)
- ✅ 平台层基础服务
- ✅ 通用文档处理
- ✅ 基础RAG问答
Phase 2: 首个场景 (Month 4-6)
- ✅ 金融研报场景
- ✅ 验证”平台+插件”架构
- ✅ 积累场景开发经验
Phase 3: 场景扩展 (Month 7-9)
- ✅ 法律合同场景
- ✅ 医疗影像场景
- ✅ 完善平台能力
Phase 4: 商业化 (Month 10-12)
- ✅ 多场景组合销售
- ✅ 私有化部署方案
- ✅ 企业级特性
12. 下一步
- 架构设计完成
- 详细设计每个服务的API
- 设计数据库表结构(已完成基础设计)
- 设计消息队列Topic
- 设计缓存策略
- 设计监控指标
- 开始实施: 创建 gzdoc-finance 模块