Multi-tenant platform design with unified LLM provider abstraction, RAG knowledge base, and tenant-isolated data storage. MVP uses SQLite + ChromaDB, with planned migration to PostgreSQL + pgvector. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
598 lines
22 KiB
Markdown
598 lines
22 KiB
Markdown
# 数字员工平台设计文档
|
||
|
||
> 日期:2026-05-05
|
||
> 状态:已批准
|
||
|
||
## 1. 背景与目标
|
||
|
||
### 1.1 背景
|
||
|
||
企业对 AI 数字员工的需求日益增长,但不同企业的业务场景、知识体系、合规要求各不相同。现有解决方案要么是通用聊天机器人(缺乏企业定制),要么是单点 SaaS 产品(数据隔离弱、模型选择受限)。需要一个多租户平台,让每家企业能配置专属数字员工,接入自选 LLM,使用私有知识库。
|
||
|
||
### 1.2 目标
|
||
|
||
- 构建多租户数字员工平台,支持企业级数据隔离与独立计费
|
||
- 统一 LLM Provider 抽象层,企业可自选模型提供商(OpenAI / 通义千问 / 可扩展)
|
||
- RAG 知识库支持企业私有文档上传与检索增强生成
|
||
- 提供管理后台与对话前端,形成完整可演示链路
|
||
|
||
### 1.3 成功标准
|
||
|
||
| 指标 | MVP 目标 |
|
||
|------|----------|
|
||
| 租户隔离 | 企业间数据零泄露,API Key 独立计费 |
|
||
| 对话延迟 | 首 token 响应 < 3s(不含 LLM 调用开销) |
|
||
| RAG 准确性 | 知识库内问题 Top-3 召回率 > 80% |
|
||
| 可演示性 | 管理后台 + 对话界面端到端可用 |
|
||
| Provider 扩展 | 新增 Provider 实现工作量 < 1 天 |
|
||
|
||
## 2. 范围
|
||
|
||
### 2.1 MVP 范围(P0)
|
||
|
||
1. 企业租户管理(CRUD + API Key 配置)
|
||
2. 数字员工人设配置(角色、语气、专业知识描述)
|
||
3. 对话接口(实时聊天,SSE 流式响应)
|
||
4. RAG 知识库(上传文档 → 分块嵌入 → 检索增强生成)
|
||
5. 对话历史存储与查询
|
||
|
||
### 2.2 MVP 基础版(P1)
|
||
|
||
6. 管理后台 UI(企业管理、员工配置、对话监控)
|
||
7. 对话前端 UI(聊天界面)
|
||
|
||
### 2.3 后续迭代(P2)
|
||
|
||
8. 用量统计 / 计费
|
||
9. 权限控制(企业管理员 vs 普通用户)
|
||
|
||
### 2.4 拓展功能(P3,按价值排序)
|
||
|
||
1. **对话质量评估**:自动评估 RAG 回答的准确性与相关性
|
||
2. **数字员工模板市场**:预置客服/HR/销售等角色模板,一键启用
|
||
3. **多渠道接入**:微信/钉钉/飞书/Web 统一对话接口
|
||
4. **审批工作流**:敏感操作前需人类确认
|
||
5. **审计日志与合规**:完整对话审计链路
|
||
|
||
### 2.5 非目标
|
||
|
||
- 自训练/微调模型
|
||
- 实时语音对话
|
||
- 多模态输入(图片/视频)
|
||
- 移动端原生 App
|
||
|
||
## 3. 方案对比
|
||
|
||
### 3.1 方案 A:轻量直连架构
|
||
|
||
```
|
||
FastAPI → Provider 抽象层 → OpenAI/通义千问 API
|
||
→ SQLite + ChromaDB(嵌入式向量库)
|
||
→ 文件存储(对话历史)
|
||
```
|
||
|
||
- 零外部依赖,`pip install` 即跑
|
||
- 开发周期 1-2 周
|
||
- 单机部署,不适合大规模
|
||
|
||
### 3.2 方案 B:LangChain 编排架构
|
||
|
||
```
|
||
FastAPI → LangChain/LangGraph → 多 LLM Provider
|
||
→ PostgreSQL + pgvector
|
||
→ Redis(缓存/会话)
|
||
```
|
||
|
||
- LangChain 500+ 集成,LangGraph 支持多步 Agent
|
||
- 重依赖,升级频繁有 breaking change
|
||
- 生产维护成本高
|
||
|
||
### 3.3 方案 C:自研编排 + PostgreSQL 全栈
|
||
|
||
```
|
||
FastAPI → 自研 Provider 抽象 + RAG Pipeline
|
||
→ PostgreSQL + pgvector(统一存储)
|
||
→ Redis(会话/缓存)
|
||
```
|
||
|
||
- 完全可控,无重框架依赖
|
||
- PostgreSQL 统一关系数据 + 向量检索
|
||
- RAG pipeline 需自建,初始工作量较大
|
||
|
||
### 3.4 决策:方案 A 先行,演进到方案 C
|
||
|
||
| 阶段 | 存储 | 向量库 | 缓存 | 理由 |
|
||
|------|------|--------|------|------|
|
||
| MVP | SQLite | ChromaDB | 无 | 零外部依赖,快速验证 |
|
||
| V1 | PostgreSQL | pgvector | Redis | 生产级,统一存储 |
|
||
|
||
## 4. 推荐方案详细设计
|
||
|
||
### 4.1 系统架构总览
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ 前端层 (TypeScript) │
|
||
│ ┌──────────────┐ ┌──────────────┐ ┌───────────────┐ │
|
||
│ │ 管理后台 UI │ │ 对话前端 UI │ │ 模板市场 UI │ │
|
||
│ └──────┬───────┘ └──────┬───────┘ └───────┬───────┘ │
|
||
└─────────┼─────────────────┼──────────────────┼──────────┘
|
||
│ │ │
|
||
▼ ▼ ▼
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ API 网关层 (FastAPI) │
|
||
│ ┌──────────┐ ┌───────────┐ ┌──────────┐ ┌───────────┐ │
|
||
│ │ 租户管理 │ │ 员工配置 │ │ 对话接口 │ │ 知识库管理 │ │
|
||
│ └──────────┘ └───────────┘ └──────────┘ └───────────┘ │
|
||
└─────────────────────┬───────────────────────────────────┘
|
||
│
|
||
┌───────────┴───────────┐
|
||
▼ ▼
|
||
┌──────────────────┐ ┌─────────────────────┐
|
||
│ 对话编排层 │ │ RAG Pipeline │
|
||
│ ┌─────────────┐ │ │ ┌─────────────────┐ │
|
||
│ │ 会话管理 │ │ │ │ 文档解析/分块 │ │
|
||
│ │ Prompt 构建 │ │ │ │ 嵌入生成 │ │
|
||
│ │ 流式响应 │ │ │ │ 向量检索 │ │
|
||
│ └─────────────┘ │ │ │ 上下文注入 │ │
|
||
│ ┌─────────────┐ │ │ └─────────────────┘ │
|
||
│ │ Provider │ │ └─────────────────────┘
|
||
│ │ 抽象层 │ │
|
||
│ │ ┌────────┐ │ │
|
||
│ │ │ OpenAI │ │ │
|
||
│ │ │ 通义 │ │ │
|
||
│ │ │ ... │ │ │
|
||
│ │ └────────┘ │ │
|
||
│ └─────────────┘ │
|
||
└──────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ 存储层 │
|
||
│ MVP: SQLite + ChromaDB + 文件存储 │
|
||
│ V1: PostgreSQL + pgvector + Redis │
|
||
└─────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 4.2 核心模块设计
|
||
|
||
#### 4.2.1 租户管理模块
|
||
|
||
**数据模型:**
|
||
|
||
```python
|
||
class Tenant:
|
||
id: UUID # 租户 ID
|
||
name: str # 企业名称
|
||
slug: str # URL 标识(唯一)
|
||
status: TenantStatus # active / suspended / deleted
|
||
created_at: datetime
|
||
updated_at: datetime
|
||
|
||
class TenantConfig:
|
||
id: UUID
|
||
tenant_id: UUID # 关联租户
|
||
llm_provider: str # openai / qwen / anthropic
|
||
llm_api_key: str # 加密存储的 API Key
|
||
llm_model: str # gpt-4o / qwen-max / ...
|
||
llm_base_url: str | None # 自定义 API 端点(可选)
|
||
max_tokens_per_month: int # 用量限制
|
||
created_at: datetime
|
||
updated_at: datetime
|
||
```
|
||
|
||
**API 端点:**
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| POST | `/api/v1/tenants` | 创建租户 |
|
||
| GET | `/api/v1/tenants/{id}` | 获取租户详情 |
|
||
| PUT | `/api/v1/tenants/{id}` | 更新租户 |
|
||
| DELETE | `/api/v1/tenants/{id}` | 删除租户(软删除) |
|
||
| PUT | `/api/v1/tenants/{id}/config` | 更新 LLM 配置 |
|
||
|
||
**安全约束:**
|
||
- API Key 使用 AES-256 加密存储,密钥从环境变量读取
|
||
- 租户间数据严格隔离,所有查询强制带 `tenant_id` 过滤
|
||
- 软删除策略,删除后 30 天可恢复
|
||
|
||
#### 4.2.2 数字员工配置模块
|
||
|
||
**数据模型:**
|
||
|
||
```python
|
||
class DigitalEmployee:
|
||
id: UUID
|
||
tenant_id: UUID # 所属租户
|
||
name: str # 员工名称(如"客服小助手")
|
||
role: str # 角色:customer_service / hr / sales / ...
|
||
avatar_url: str | None # 头像
|
||
system_prompt: str # 人设系统提示词
|
||
greeting: str | None # 开场白
|
||
temperature: float # 生成温度 0.0-1.0
|
||
max_context_messages: int # 上下文窗口消息数
|
||
knowledge_base_ids: list[UUID] # 关联知识库
|
||
status: EmployeeStatus # active / inactive
|
||
created_at: datetime
|
||
updated_at: datetime
|
||
```
|
||
|
||
**API 端点:**
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| POST | `/api/v1/tenants/{tid}/employees` | 创建数字员工 |
|
||
| GET | `/api/v1/tenants/{tid}/employees` | 列出数字员工 |
|
||
| GET | `/api/v1/tenants/{tid}/employees/{eid}` | 获取详情 |
|
||
| PUT | `/api/v1/tenants/{tid}/employees/{eid}` | 更新配置 |
|
||
| DELETE | `/api/v1/tenants/{tid}/employees/{eid}` | 删除 |
|
||
|
||
#### 4.2.3 对话接口模块
|
||
|
||
**对话流程:**
|
||
|
||
```
|
||
用户消息
|
||
→ 会话加载(历史上下文)
|
||
→ RAG 检索(如果员工关联了知识库)
|
||
→ 查询向量化
|
||
→ ChromaDB/pgvector 相似度检索 Top-K
|
||
→ 上下文注入到 Prompt
|
||
→ Prompt 构建(system + 知识上下文 + 历史消息 + 用户消息)
|
||
→ LLM Provider 调用(流式)
|
||
→ SSE 流式响应
|
||
→ 持久化对话记录
|
||
```
|
||
|
||
**数据模型:**
|
||
|
||
```python
|
||
class Conversation:
|
||
id: UUID
|
||
tenant_id: UUID
|
||
employee_id: UUID
|
||
user_id: str # 外部用户标识
|
||
title: str | None
|
||
created_at: datetime
|
||
updated_at: datetime
|
||
|
||
class Message:
|
||
id: UUID
|
||
conversation_id: UUID
|
||
role: MessageRole # user / assistant / system
|
||
content: str
|
||
token_count: int | None
|
||
sources: list[dict] | None # RAG 引用来源
|
||
created_at: datetime
|
||
```
|
||
|
||
**API 端点:**
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| POST | `/api/v1/tenants/{tid}/employees/{eid}/conversations` | 创建对话 |
|
||
| GET | `/api/v1/tenants/{tid}/conversations` | 列出对话 |
|
||
| GET | `/api/v1/tenants/{tid}/conversations/{cid}` | 获取对话详情(含消息) |
|
||
| POST | `/api/v1/tenants/{tid}/conversations/{cid}/messages` | 发送消息(SSE 流式响应) |
|
||
| DELETE | `/api/v1/tenants/{tid}/conversations/{cid}` | 删除对话 |
|
||
|
||
**SSE 响应格式:**
|
||
|
||
```
|
||
event: message_start
|
||
data: {"conversation_id": "...", "message_id": "..."}
|
||
|
||
event: token
|
||
data: {"content": "你"}
|
||
|
||
event: token
|
||
data: {"content": "好"}
|
||
|
||
event: sources
|
||
data: {"documents": [{"title": "...", "snippet": "...", "score": 0.92}]}
|
||
|
||
event: message_end
|
||
data: {"token_count": 156}
|
||
|
||
event: error
|
||
data: {"code": "provider_error", "message": "..."}
|
||
```
|
||
|
||
#### 4.2.4 RAG 知识库模块
|
||
|
||
**处理流程:**
|
||
|
||
```
|
||
文档上传
|
||
→ 文件类型检测(PDF / DOCX / TXT / MD)
|
||
→ 文档解析(提取纯文本)
|
||
→ 文本分块(RecursiveCharacterTextSplitter)
|
||
→ chunk_size: 500, overlap: 50
|
||
→ 嵌入生成(调用 Embedding API)
|
||
→ 向量存储(ChromaDB,按 tenant_id 隔离命名空间)
|
||
→ 元数据存储(文档标题、来源、分块偏移量)
|
||
```
|
||
|
||
**数据模型:**
|
||
|
||
```python
|
||
class KnowledgeBase:
|
||
id: UUID
|
||
tenant_id: UUID
|
||
name: str
|
||
description: str | None
|
||
embedding_model: str # text-embedding-3-small / ...
|
||
chunk_count: int
|
||
created_at: datetime
|
||
updated_at: datetime
|
||
|
||
class Document:
|
||
id: UUID
|
||
knowledge_base_id: UUID
|
||
tenant_id: UUID
|
||
filename: str
|
||
file_type: str # pdf / docx / txt / md
|
||
file_size: int
|
||
chunk_count: int
|
||
status: DocumentStatus # processing / ready / failed
|
||
error_message: str | None
|
||
created_at: datetime
|
||
```
|
||
|
||
**API 端点:**
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| POST | `/api/v1/tenants/{tid}/knowledge-bases` | 创建知识库 |
|
||
| POST | `/api/v1/tenants/{tid}/knowledge-bases/{kid}/documents` | 上传文档 |
|
||
| GET | `/api/v1/tenants/{tid}/knowledge-bases/{kid}/documents` | 列出文档 |
|
||
| DELETE | `/api/v1/tenants/{tid}/knowledge-bases/{kid}/documents/{did}` | 删除文档 |
|
||
| GET | `/api/v1/tenants/{tid}/knowledge-bases` | 列出知识库 |
|
||
| DELETE | `/api/v1/tenants/{tid}/knowledge-bases/{kid}` | 删除知识库 |
|
||
|
||
#### 4.2.5 LLM Provider 抽象层
|
||
|
||
**设计原则:**
|
||
- 统一接口,Provider 可插拔
|
||
- 每个企业独立 API Key,按租户路由
|
||
- 支持流式和非流式调用
|
||
- 统一错误处理与重试
|
||
|
||
```python
|
||
from abc import ABC, abstractmethod
|
||
from dataclasses import dataclass
|
||
|
||
@dataclass
|
||
class LLMMessage:
|
||
role: str # system / user / assistant
|
||
content: str
|
||
|
||
@dataclass
|
||
class LLMResponse:
|
||
content: str
|
||
token_usage: dict
|
||
model: str
|
||
finish_reason: str
|
||
|
||
class BaseLLMProvider(ABC):
|
||
"""LLM Provider 抽象基类"""
|
||
|
||
@abstractmethod
|
||
async def chat(
|
||
self,
|
||
messages: list[LLMMessage],
|
||
model: str,
|
||
temperature: float = 0.7,
|
||
max_tokens: int = 2048,
|
||
**kwargs,
|
||
) -> LLMResponse:
|
||
...
|
||
|
||
@abstractmethod
|
||
async def chat_stream(
|
||
self,
|
||
messages: list[LLMMessage],
|
||
model: str,
|
||
temperature: float = 0.7,
|
||
max_tokens: int = 2048,
|
||
**kwargs,
|
||
) -> AsyncIterator[str]:
|
||
...
|
||
|
||
@abstractmethod
|
||
async def embed(self, texts: list[str], model: str) -> list[list[float]]:
|
||
...
|
||
|
||
class OpenAIProvider(BaseLLMProvider):
|
||
"""OpenAI / 兼容 OpenAI 接口的 Provider"""
|
||
|
||
class QwenProvider(BaseLLMProvider):
|
||
"""通义千问 Provider(兼容 OpenAI 接口格式)"""
|
||
|
||
# Provider 注册表
|
||
PROVIDERS: dict[str, type[BaseLLMProvider]] = {
|
||
"openai": OpenAIProvider,
|
||
"qwen": QwenProvider,
|
||
}
|
||
|
||
def get_provider(provider_name: str, api_key: str, base_url: str | None = None) -> BaseLLMProvider:
|
||
provider_cls = PROVIDERS.get(provider_name)
|
||
if not provider_cls:
|
||
raise ValueError(f"Unknown provider: {provider_name}")
|
||
return provider_cls(api_key=api_key, base_url=base_url)
|
||
```
|
||
|
||
**Provider 配置约定:**
|
||
|
||
| Provider | chat model | embedding model | 特殊说明 |
|
||
|----------|-----------|----------------|---------|
|
||
| openai | gpt-4o / gpt-4o-mini | text-embedding-3-small | 标准 OpenAI API |
|
||
| qwen | qwen-max / qwen-plus | text-embedding-v3 | 兼容 OpenAI SDK 格式 |
|
||
|
||
### 4.3 安全设计
|
||
|
||
#### 4.3.1 数据隔离
|
||
|
||
- 所有数据表包含 `tenant_id` 字段
|
||
- 所有查询强制 `WHERE tenant_id = :current_tenant`
|
||
- API 中间件自动注入 `tenant_id`,业务代码无法绕过
|
||
- ChromaDB 使用 tenant_id 作为 collection namespace 隔离向量数据
|
||
|
||
#### 4.3.2 API Key 安全
|
||
|
||
- LLM API Key 使用 AES-256-GCM 加密存储
|
||
- 加密密钥从环境变量 `ENCRYPTION_KEY` 读取,不入库不入日志
|
||
- 运行时解密仅用于发起 LLM 调用,不返回给前端
|
||
|
||
#### 4.3.3 输入校验
|
||
|
||
- 所有 API 入参使用 Pydantic 校验
|
||
- 文档上传限制:单文件 < 20MB,仅允许 pdf/docx/txt/md
|
||
- 对话消息长度限制:单条 < 10000 字符
|
||
- 速率限制:每租户每分钟 60 次请求
|
||
|
||
### 4.4 技术栈
|
||
|
||
| 层 | MVP 技术选型 | V1 演进 |
|
||
|----|------------|---------|
|
||
| 后端框架 | FastAPI 0.115+ | FastAPI |
|
||
| 数据库 | SQLite (aiosqlite) | PostgreSQL 16 |
|
||
| 向量库 | ChromaDB 0.5+ | pgvector |
|
||
| 缓存 | 无 | Redis |
|
||
| ORM | SQLAlchemy 2.0+ (async) | SQLAlchemy 2.0+ |
|
||
| 嵌入/LLM | openai SDK | openai SDK |
|
||
| 文档解析 | PyPDF2 + python-docx | 同左 |
|
||
| 前端框架 | React + TypeScript + Vite | 同左 |
|
||
| 前端 UI | Ant Design | Ant Design |
|
||
| 对话前端 | 自研 Chat UI 组件 | 同左 |
|
||
|
||
### 4.5 项目结构
|
||
|
||
```
|
||
digital-employee-platform/
|
||
├── backend/
|
||
│ ├── app/
|
||
│ │ ├── __init__.py
|
||
│ │ ├── main.py # FastAPI 入口
|
||
│ │ ├── config.py # 配置管理
|
||
│ │ ├── database.py # 数据库连接
|
||
│ │ ├── models/ # SQLAlchemy 模型
|
||
│ │ │ ├── __init__.py
|
||
│ │ │ ├── tenant.py
|
||
│ │ │ ├── employee.py
|
||
│ │ │ ├── conversation.py
|
||
│ │ │ └── knowledge.py
|
||
│ │ ├── schemas/ # Pydantic 请求/响应模型
|
||
│ │ │ ├── __init__.py
|
||
│ │ │ ├── tenant.py
|
||
│ │ │ ├── employee.py
|
||
│ │ │ ├── conversation.py
|
||
│ │ │ └── knowledge.py
|
||
│ │ ├── api/ # API 路由
|
||
│ │ │ ├── __init__.py
|
||
│ │ │ ├── v1/
|
||
│ │ │ │ ├── __init__.py
|
||
│ │ │ │ ├── tenants.py
|
||
│ │ │ │ ├── employees.py
|
||
│ │ │ │ ├── conversations.py
|
||
│ │ │ │ └── knowledge.py
|
||
│ │ │ └── deps.py # 依赖注入
|
||
│ │ ├── services/ # 业务逻辑
|
||
│ │ │ ├── __init__.py
|
||
│ │ │ ├── tenant_service.py
|
||
│ │ │ ├── employee_service.py
|
||
│ │ │ ├── conversation_service.py
|
||
│ │ │ ├── knowledge_service.py
|
||
│ │ │ └── rag_service.py
|
||
│ │ ├── providers/ # LLM Provider 抽象层
|
||
│ │ │ ├── __init__.py
|
||
│ │ │ ├── base.py
|
||
│ │ │ ├── openai_provider.py
|
||
│ │ │ └── qwen_provider.py
|
||
│ │ └── middleware/ # 中间件
|
||
│ │ ├── __init__.py
|
||
│ │ └── tenant.py # 租户隔离中间件
|
||
│ ├── tests/ # 测试
|
||
│ │ ├── __init__.py
|
||
│ │ ├── conftest.py
|
||
│ │ ├── test_tenants.py
|
||
│ │ ├── test_employees.py
|
||
│ │ ├── test_conversations.py
|
||
│ │ ├── test_knowledge.py
|
||
│ │ └── test_providers.py
|
||
│ ├── alembic/ # 数据库迁移
|
||
│ │ └── ...
|
||
│ ├── pyproject.toml
|
||
│ └── .env.example
|
||
├── frontend/
|
||
│ ├── src/
|
||
│ │ ├── api/ # API 客户端
|
||
│ │ ├── components/ # 通用组件
|
||
│ │ ├── pages/
|
||
│ │ │ ├── admin/ # 管理后台页面
|
||
│ │ │ │ ├── Tenants.tsx
|
||
│ │ │ │ ├── Employees.tsx
|
||
│ │ │ │ └── Knowledge.tsx
|
||
│ │ │ └── chat/ # 对话前端页面
|
||
│ │ │ └── Chat.tsx
|
||
│ │ ├── App.tsx
|
||
│ │ └── main.tsx
|
||
│ ├── package.json
|
||
│ ├── tsconfig.json
|
||
│ └── vite.config.ts
|
||
└── docs/
|
||
└── plans/
|
||
```
|
||
|
||
## 5. 错误处理
|
||
|
||
| 错误类型 | 处理策略 | HTTP 状态码 |
|
||
|---------|---------|------------|
|
||
| LLM Provider 调用失败 | 指数退避重试 2 次,记录日志,返回降级提示 | 502 |
|
||
| LLM API Key 无效/过期 | 返回配置错误提示,不重试 | 401 |
|
||
| 租户 API 限流 | 返回 429,附带 Retry-After 头 | 429 |
|
||
| 文档解析失败 | 标记文档状态为 failed,记录错误信息 | 200(异步) |
|
||
| RAG 无相关结果 | 正常返回,不注入知识上下文,LLM 按通用知识回答 | - |
|
||
| 向量库写入失败 | 重试 1 次,失败则文档标记 failed | 200(异步) |
|
||
| 数据库连接失败 | 返回 503,记录告警 | 503 |
|
||
|
||
## 6. 测试策略
|
||
|
||
### 6.1 单元测试
|
||
|
||
- Provider 抽象层:mock LLM API 响应,验证接口一致性
|
||
- 服务层:mock 数据库,验证业务逻辑
|
||
- RAG Pipeline:mock embedding,验证分块、检索逻辑
|
||
|
||
### 6.2 集成测试
|
||
|
||
- 端到端对话流:使用真实 LLM API(测试 Key),验证完整链路
|
||
- 租户隔离:创建两个租户,验证数据不互渗
|
||
- RAG 问答:上传文档后提问,验证回答包含文档内容
|
||
|
||
### 6.3 安全测试
|
||
|
||
- 越权访问:租户 A 尝试访问租户 B 资源,必须 403
|
||
- API Key 不出现在日志和 API 响应中
|
||
- 文档上传类型和大小限制
|
||
|
||
### 6.4 性能测试
|
||
|
||
- 对话接口:p99 < 3s(不含 LLM 调用)
|
||
- 文档上传:10MB PDF 解析 < 30s
|
||
- 并发:单租户 10 并发对话无异常
|
||
|
||
## 7. 演进路径
|
||
|
||
```
|
||
MVP (方案 A) V1 (方案 C)
|
||
───────────── ──────────────
|
||
SQLite + ChromaDB ──迁移──→ PostgreSQL + pgvector
|
||
文件存储对话历史 ──迁移──→ PostgreSQL JSONB
|
||
无缓存 ──新增──→ Redis 会话缓存
|
||
单实例部署 ──演进──→ Docker Compose 多服务
|
||
基础对话 ──新增──→ 对话质量评估
|
||
无模板 ──新增──→ 数字员工模板市场
|
||
Web 对话 ──新增──→ 多渠道接入
|
||
```
|