From 705034d41b1a8ffabae2e34dd6f2ff3c27538f94 Mon Sep 17 00:00:00 2001 From: bruce Date: Mon, 25 May 2026 00:39:00 +0800 Subject: [PATCH] =?UTF-8?q?docs(model-provider):=20=E8=A1=A5=E5=85=85?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E6=9C=8D=E5=8A=A1=E5=95=86=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E4=B8=8E=E8=B7=AF=E7=94=B1=E8=AE=BE=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/MODEL_PROVIDER_DESIGN.md | 898 ++++++++++++++++++++++++++++ docs/MODEL_PROVIDER_REQUIREMENTS.md | 448 ++++++++++++++ 2 files changed, 1346 insertions(+) create mode 100644 docs/MODEL_PROVIDER_DESIGN.md create mode 100644 docs/MODEL_PROVIDER_REQUIREMENTS.md diff --git a/docs/MODEL_PROVIDER_DESIGN.md b/docs/MODEL_PROVIDER_DESIGN.md new file mode 100644 index 0000000..1c94fba --- /dev/null +++ b/docs/MODEL_PROVIDER_DESIGN.md @@ -0,0 +1,898 @@ +# 模型服务商配置与路由设计文档 + +## 1. 文档信息 + +| 项目 | 内容 | +|------|------| +| 所属项目 | Common Agent | +| 文档类型 | 设计文档 | +| 编写日期 | 2026-05-25 | +| 对应需求 | `docs/MODEL_PROVIDER_REQUIREMENTS.md` | +| 目标阶段 | RAG 向量导入与模型网关基础能力 | + +## 2. 设计目标 + +本设计用于在 Common Agent 中新增模型服务商配置与模型路由能力,使系统可以统一接入 Ollama、硅基流动、百炼、OpenAI 等模型服务,并为 RAG 和后续 Agent 运行时提供统一模型调用入口。 + +核心设计目标: + +1. 业务模块只依赖平台内部模型网关,不直接依赖具体服务商。 +2. 首期优先支持 OpenAI-compatible 协议,减少多服务商适配成本。 +3. 支持本地模型和云端模型混用,实现成本控制。 +4. 支持 RAG Embedding 模型配置化,并保证同一知识库向量模型一致。 +5. 支持调用日志,为排障、统计和后续成本分析打基础。 + +## 3. 总体架构 + +```mermaid +flowchart TD + Admin["管理控制台"] --> ProviderApi["模型配置 API"] + Rag["RAG 模块"] --> ModelGateway["ModelGateway"] + Agent["Agent 模块"] --> ModelGateway + ModelGateway --> Router["ModelRouteService"] + Router --> Config["模型配置与路由表"] + ModelGateway --> ClientFactory["ModelClientFactory"] + ClientFactory --> Ollama["Ollama OpenAI-compatible"] + ClientFactory --> SiliconFlow["SiliconFlow OpenAI-compatible"] + ClientFactory --> DashScope["DashScope OpenAI-compatible"] + ClientFactory --> Other["其他 OpenAI-compatible 服务"] + ModelGateway --> Log["ModelCallLogService"] + Rag --> RagChunk["rag_chunk"] + Rag --> RagEmbedding["rag_chunk_embedding"] +``` + +设计上将模型平台能力拆成四层: + +| 层级 | 职责 | +|------|------| +| 配置层 | 管理服务商、模型、路由规则和知识库模型绑定 | +| 路由层 | 根据任务类型、范围和策略选择具体模型 | +| 调用层 | 通过统一客户端调用 Chat、Embedding、Rerank 等能力 | +| 观测层 | 记录调用日志、耗时、token、费用估算和错误信息 | + +## 4. 包结构设计 + +建议新增后端包: + +```text +src/main/java/com/bruce/modelprovider +├── controller +├── dto +│ ├── request +│ └── response +├── entity +├── enums +├── mapper +├── service +│ └── impl +├── gateway +├── client +└── config +``` + +各包职责: + +| 包 | 职责 | +|----|------| +| `controller` | 对外暴露服务商、模型、路由规则、日志查询接口 | +| `dto` | 请求和响应对象,不直接暴露实体 | +| `entity` | 数据库实体,继承 `BaseEntity` | +| `enums` | 服务商类型、模型类型、任务类型、路由策略、调用状态 | +| `mapper` | MyBatis-Plus `BaseMapper` | +| `service` | 配置管理、路由选择、调用日志 | +| `gateway` | 面向业务模块的模型调用入口 | +| `client` | 具体协议客户端,例如 OpenAI-compatible 客户端 | +| `config` | 模型平台配置,例如默认超时、批量大小、密钥加密开关 | + +## 5. 核心数据模型 + +### 5.1 `model_provider` 模型服务商表 + +用于保存服务商基础配置。 + +```sql +CREATE TABLE model_provider ( + id BIGSERIAL PRIMARY KEY, + provider_code VARCHAR(64) NOT NULL, + provider_name VARCHAR(100) NOT NULL, + provider_type VARCHAR(50) NOT NULL, + protocol_type VARCHAR(50) NOT NULL DEFAULT 'OPENAI_COMPATIBLE', + base_url VARCHAR(500) NOT NULL, + auth_type VARCHAR(50) NOT NULL DEFAULT 'BEARER_TOKEN', + secret_ref VARCHAR(200), + api_key_cipher TEXT, + timeout_ms INTEGER NOT NULL DEFAULT 60000, + priority INTEGER NOT NULL DEFAULT 100, + enabled BOOLEAN NOT NULL DEFAULT TRUE, + health_status VARCHAR(50) NOT NULL DEFAULT 'UNKNOWN', + last_health_check_time TIMESTAMP, + version INTEGER NOT NULL DEFAULT 1, + create_time TIMESTAMP, + update_time TIMESTAMP, + remark VARCHAR(500) DEFAULT '', + create_by VARCHAR(64), + update_by VARCHAR(64), + CONSTRAINT uk_model_provider_code UNIQUE (provider_code) +); +``` + +字段说明: + +| 字段 | 说明 | +|------|------| +| `provider_code` | 服务商编码,例如 `ollama-main`、`siliconflow` | +| `provider_type` | 服务商类型,例如 `OLLAMA`、`SILICONFLOW`、`DASHSCOPE`、`OPENAI`、`CUSTOM` | +| `protocol_type` | 协议类型,首期使用 `OPENAI_COMPATIBLE` | +| `base_url` | API 基础地址,例如 `https://api.siliconflow.cn/v1` | +| `secret_ref` | 密钥引用,例如环境变量名或配置中心键 | +| `api_key_cipher` | 可选的加密密钥内容,前端不返回 | +| `health_status` | 健康检查状态 | + +### 5.2 `model_config` 模型配置表 + +用于保存服务商下的具体模型。 + +```sql +CREATE TABLE model_config ( + id BIGSERIAL PRIMARY KEY, + provider_id BIGINT NOT NULL, + model_code VARCHAR(100) NOT NULL, + model_name VARCHAR(200) NOT NULL, + upstream_model VARCHAR(200) NOT NULL, + model_type VARCHAR(50) NOT NULL, + context_window INTEGER, + max_output_tokens INTEGER, + embedding_dimension INTEGER, + input_price_per_1k NUMERIC(12, 8), + output_price_per_1k NUMERIC(12, 8), + local_model BOOLEAN NOT NULL DEFAULT FALSE, + default_model BOOLEAN NOT NULL DEFAULT FALSE, + capabilities_json JSONB NOT NULL DEFAULT '{}'::jsonb, + options_json JSONB NOT NULL DEFAULT '{}'::jsonb, + enabled BOOLEAN NOT NULL DEFAULT TRUE, + version INTEGER NOT NULL DEFAULT 1, + create_time TIMESTAMP, + update_time TIMESTAMP, + remark VARCHAR(500) DEFAULT '', + create_by VARCHAR(64), + update_by VARCHAR(64), + CONSTRAINT uk_model_config_provider_code UNIQUE (provider_id, model_code), + CONSTRAINT fk_model_config_provider_id FOREIGN KEY (provider_id) REFERENCES model_provider (id) +); +``` + +字段说明: + +| 字段 | 说明 | +|------|------| +| `model_code` | 平台内部模型编码 | +| `model_name` | 展示名称 | +| `upstream_model` | 上游真实模型名,例如 `Qwen/Qwen3-Embedding-0.6B`、`qwen2.5:7b` | +| `model_type` | `CHAT`、`EMBEDDING`、`RERANK`、`MULTIMODAL` | +| `embedding_dimension` | Embedding 输出维度,RAG 首期使用 1024 | +| `capabilities_json` | 能力标签,例如是否支持工具调用、视觉、JSON 输出 | +| `options_json` | 模型调用默认参数,例如 `temperature`、`topP`、`dimensions` | + +### 5.3 `model_route_rule` 模型路由规则表 + +用于根据任务类型和范围选择模型。 + +```sql +CREATE TABLE model_route_rule ( + id BIGSERIAL PRIMARY KEY, + route_code VARCHAR(100) NOT NULL, + route_name VARCHAR(100) NOT NULL, + task_type VARCHAR(50) NOT NULL, + match_scope VARCHAR(50) NOT NULL DEFAULT 'GLOBAL', + scope_id BIGINT, + primary_model_id BIGINT NOT NULL, + fallback_model_ids_json JSONB NOT NULL DEFAULT '[]'::jsonb, + route_strategy VARCHAR(50) NOT NULL DEFAULT 'MANUAL', + max_latency_ms INTEGER, + enabled BOOLEAN NOT NULL DEFAULT TRUE, + version INTEGER NOT NULL DEFAULT 1, + create_time TIMESTAMP, + update_time TIMESTAMP, + remark VARCHAR(500) DEFAULT '', + create_by VARCHAR(64), + update_by VARCHAR(64), + CONSTRAINT uk_model_route_rule_code UNIQUE (route_code), + CONSTRAINT fk_model_route_primary_model_id FOREIGN KEY (primary_model_id) REFERENCES model_config (id) +); +``` + +字段说明: + +| 字段 | 说明 | +|------|------| +| `task_type` | 任务类型,例如 `RAG_EMBEDDING`、`CHAT_SIMPLE`、`AGENT_PLANNING` | +| `match_scope` | 匹配范围,例如 `GLOBAL`、`RAG_STORE`、`AGENT` | +| `scope_id` | 范围 ID,例如知识库 ID 或 Agent ID | +| `primary_model_id` | 主模型 | +| `fallback_model_ids_json` | 备用模型 ID 列表 | +| `route_strategy` | `LOCAL_FIRST`、`COST_FIRST`、`QUALITY_FIRST`、`MANUAL` | + +### 5.4 `rag_store_model_config` 知识库模型绑定表 + +用于固定知识库的 Embedding 模型和维度,避免同一知识库混用向量空间。 + +```sql +CREATE TABLE rag_store_model_config ( + id BIGSERIAL PRIMARY KEY, + store_id BIGINT NOT NULL, + embedding_model_id BIGINT NOT NULL, + embedding_dimension INTEGER NOT NULL DEFAULT 1024, + chunk_strategy INTEGER, + chunk_size INTEGER, + chunk_overlap INTEGER, + delimiter VARCHAR(50), + active BOOLEAN NOT NULL DEFAULT TRUE, + index_version INTEGER NOT NULL DEFAULT 1, + version INTEGER NOT NULL DEFAULT 1, + create_time TIMESTAMP, + update_time TIMESTAMP, + remark VARCHAR(500) DEFAULT '', + create_by VARCHAR(64), + update_by VARCHAR(64), + CONSTRAINT uk_rag_store_model_config_store_active UNIQUE (store_id, active), + CONSTRAINT fk_rag_store_model_config_store_id FOREIGN KEY (store_id) REFERENCES rag_store (id), + CONSTRAINT fk_rag_store_model_config_embedding_model_id FOREIGN KEY (embedding_model_id) REFERENCES model_config (id) +); +``` + +设计约束: + +- 首期每个知识库只有一个生效配置。 +- 更换 Embedding 模型或维度时,`index_version` 增加,并触发重建索引。 +- 检索时只使用当前生效配置对应的向量。 + +### 5.5 `model_call_log` 模型调用日志表 + +用于记录模型调用行为。 + +```sql +CREATE TABLE model_call_log ( + id BIGSERIAL PRIMARY KEY, + request_id VARCHAR(64) NOT NULL, + provider_id BIGINT, + model_id BIGINT, + task_type VARCHAR(50) NOT NULL, + biz_type VARCHAR(50), + biz_id VARCHAR(100), + call_type VARCHAR(50) NOT NULL, + status VARCHAR(50) NOT NULL, + prompt_tokens INTEGER, + completion_tokens INTEGER, + total_tokens INTEGER, + estimated_cost NUMERIC(14, 8), + duration_ms INTEGER, + request_hash VARCHAR(64), + error_code VARCHAR(100), + error_message VARCHAR(1000), + create_time TIMESTAMP, + remark VARCHAR(500) DEFAULT '', + CONSTRAINT uk_model_call_log_request_id UNIQUE (request_id) +); +``` + +字段说明: + +| 字段 | 说明 | +|------|------| +| `request_id` | 单次模型调用请求 ID | +| `task_type` | 任务类型 | +| `biz_type` | 业务类型,例如 `RAG_DOCUMENT_INDEX` | +| `biz_id` | 业务 ID,例如文档 ID | +| `call_type` | `CHAT`、`EMBEDDING`、`RERANK` | +| `status` | `SUCCESS`、`FAILED`、`TIMEOUT`、`FALLBACK_SUCCESS` | +| `request_hash` | 请求内容哈希,用于排障和幂等分析,不保存完整敏感内容 | + +## 6. 枚举设计 + +新增枚举应实现现有 `PersistableSysEnumDefinition`,并同步到 `sys_enum`。 + +| 枚举 | 值 | +|------|----| +| `ModelProviderTypeEnum` | `OLLAMA`、`SILICONFLOW`、`DASHSCOPE`、`OPENAI`、`CUSTOM` | +| `ModelProtocolTypeEnum` | `OPENAI_COMPATIBLE` | +| `ModelTypeEnum` | `CHAT`、`EMBEDDING`、`RERANK`、`MULTIMODAL` | +| `ModelTaskTypeEnum` | `RAG_EMBEDDING`、`RAG_QUERY_EMBEDDING`、`RAG_ANSWER`、`CHAT_SIMPLE`、`CHAT_COMPLEX`、`AGENT_PLANNING`、`RERANK` | +| `ModelRouteStrategyEnum` | `LOCAL_FIRST`、`COST_FIRST`、`QUALITY_FIRST`、`MANUAL` | +| `ModelCallStatusEnum` | `SUCCESS`、`FAILED`、`TIMEOUT`、`FALLBACK_SUCCESS` | +| `ModelHealthStatusEnum` | `UNKNOWN`、`HEALTHY`、`UNHEALTHY` | + +## 7. 服务接口设计 + +### 7.1 配置管理服务 + +```java +public interface IModelProviderService extends IService { + List query(ModelProviderQueryRequest request); + ModelProviderResponse getResponseById(Long id); + boolean saveOrUpdate(ModelProviderSaveRequest request); + boolean checkHealth(Long id); +} +``` + +```java +public interface IModelConfigService extends IService { + List query(ModelConfigQueryRequest request); + ModelConfigResponse getResponseById(Long id); + boolean saveOrUpdate(ModelConfigSaveRequest request); + ModelConfig getEnabledModel(Long modelId); +} +``` + +### 7.2 路由服务 + +```java +public interface IModelRouteService { + ModelRouteDecision route(ModelRouteContext context); +} +``` + +`ModelRouteContext` 应包含: + +- `taskType` +- `matchScope` +- `scopeId` +- `requiredModelType` +- `preferredLocal` +- `requiredEmbeddingDimension` +- `bizType` +- `bizId` + +`ModelRouteDecision` 应包含: + +- 主模型。 +- 备用模型列表。 +- 路由策略。 +- 决策原因。 + +### 7.3 模型网关 + +```java +public interface EmbeddingModelGateway { + EmbeddingResult embed(EmbeddingRequest request); +} +``` + +```java +public interface ChatModelGateway { + ChatResult chat(ChatRequest request); +} +``` + +`EmbeddingRequest` 应包含: + +- 文本列表。 +- 任务类型。 +- 匹配范围。 +- 范围 ID。 +- 业务类型。 +- 业务 ID。 +- 期望维度。 + +`EmbeddingResult` 应包含: + +- 模型 ID。 +- 模型名称。 +- 维度。 +- 向量列表。 +- 调用日志 ID。 + +## 8. 客户端设计 + +首期优先实现 `OpenAiCompatibleModelClient`,统一调用以下接口: + +- `POST /v1/embeddings` +- `POST /v1/chat/completions` + +OpenAI-compatible 客户端输入来自数据库配置: + +| 配置来源 | 字段 | +|----------|------| +| `model_provider.base_url` | 服务基础地址 | +| `model_provider.secret_ref` / `api_key_cipher` | 鉴权信息 | +| `model_config.upstream_model` | 上游模型名 | +| `model_config.options_json` | 调用参数 | +| `model_config.embedding_dimension` | Embedding 维度 | + +### 8.1 Spring AI 使用方式 + +项目可以在两个阶段使用 Spring AI: + +第一阶段:使用项目自定义 `ModelGateway` 和 OpenAI-compatible HTTP 客户端,优先解决多服务商动态配置问题。 + +第二阶段:在稳定后引入 Spring AI 的 `EmbeddingModel`、`ChatModel` 抽象或适配器,将动态客户端包装为平台内部统一接口。 + +这样设计的原因是 Spring Boot 自动配置更适合单默认服务商,而本项目需要从数据库动态选择多个 provider。业务层保持 `ModelGateway` 抽象,后续替换底层实现不会影响 RAG 和 Agent。 + +### 8.2 Ollama 适配 + +Ollama 使用 OpenAI-compatible 地址: + +```text +http://:11434/v1 +``` + +配置示例: + +| 字段 | 示例 | +|------|------| +| `provider_code` | `ollama-main` | +| `provider_type` | `OLLAMA` | +| `protocol_type` | `OPENAI_COMPATIBLE` | +| `base_url` | `http://10.0.0.10:11434/v1` | +| `auth_type` | `NONE` 或 `BEARER_TOKEN` | +| `model_config.upstream_model` | `qwen2.5:7b` | + +部署建议: + +- 开发环境可以通过内网访问。 +- 生产环境不要直接开放 11434 到公网。 +- 推荐使用 VPN、Tailscale、Cloudflare Tunnel、Nginx 鉴权反向代理或安全网关。 +- 如果必须公网访问,需要 HTTPS、鉴权、IP 白名单和访问日志。 + +### 8.3 硅基流动适配 + +配置示例: + +| 字段 | 示例 | +|------|------| +| `provider_code` | `siliconflow` | +| `provider_type` | `SILICONFLOW` | +| `protocol_type` | `OPENAI_COMPATIBLE` | +| `base_url` | `https://api.siliconflow.cn/v1` | +| `secret_ref` | `SILICONFLOW_API_KEY` | +| `model_config.upstream_model` | `Qwen/Qwen3-Embedding-0.6B` | +| `embedding_dimension` | `1024` | + +RAG 首期推荐使用 1024 维 Embedding,匹配当前 `rag_chunk_embedding.embedding VECTOR(1024)`。 + +### 8.4 百炼适配 + +百炼 OpenAI-compatible 配置示例: + +| 字段 | 示例 | +|------|------| +| `provider_code` | `dashscope` | +| `provider_type` | `DASHSCOPE` | +| `protocol_type` | `OPENAI_COMPATIBLE` | +| `base_url` | `https://dashscope.aliyuncs.com/compatible-mode/v1` | +| `secret_ref` | `DASHSCOPE_API_KEY` | +| `model_config.upstream_model` | `text-embedding-v4` | +| `embedding_dimension` | `1024` | + +## 9. 路由策略设计 + +### 9.1 路由优先级 + +模型路由按以下顺序匹配: + +1. 业务范围精确规则,例如某个知识库或某个 Agent。 +2. 任务类型规则,例如 `RAG_EMBEDDING`。 +3. 全局默认规则。 +4. 模型类型默认模型。 + +如果没有匹配到模型,应返回清晰错误,不隐式选择不确定模型。 + +### 9.2 策略说明 + +| 策略 | 行为 | +|------|------| +| `MANUAL` | 使用规则中指定的主模型 | +| `LOCAL_FIRST` | 优先选择本地模型,失败后使用备用云端模型 | +| `COST_FIRST` | 在可用模型中优先选择成本低的模型 | +| `QUALITY_FIRST` | 优先选择质量更高或优先级更高的模型 | + +首期可以只实现 `MANUAL` 和 `LOCAL_FIRST`,其余策略先完成数据结构和枚举。 + +### 9.3 失败兜底 + +主模型调用失败时: + +1. 记录主模型失败日志。 +2. 判断是否存在备用模型。 +3. 按备用模型顺序重试。 +4. 若备用模型成功,返回结果并记录 `FALLBACK_SUCCESS`。 +5. 若全部失败,返回最后一次错误,并将业务状态更新为失败。 + +RAG 向量导入首期应谨慎使用 fallback。Embedding 模型 fallback 只有在维度和语义模型族一致时才允许自动切换,否则应失败并提示重建或重新配置。 + +## 10. RAG 向量导入设计 + +### 10.1 当前 RAG 状态 + +当前项目已有: + +- `rag_document` +- `rag_document_parse_result` +- `rag_chunk` +- `rag_chunk_embedding` +- `RagDocumentParseServiceImpl` +- `RagDocumentChunkServiceImpl` +- `FixedLengthChunker` +- `DelimiterChunker` + +下一步需要把切片服务和 Embedding 网关串起来。 + +### 10.2 目标流程 + +```mermaid +sequenceDiagram + participant User as 用户/后台 + participant Doc as RagDocumentService + participant Parse as RagDocumentParseService + participant Chunk as RagDocumentChunkService + participant Gateway as EmbeddingModelGateway + participant Provider as 上游模型服务 + participant DB as PostgreSQL + + User->>Doc: 上传文档 + Doc->>Parse: 自动解析 + Parse->>DB: 保存解析快照 + Parse->>DB: 更新 parseStatus=PARSED + Doc->>Chunk: 提交切片索引任务 + Chunk->>DB: 更新 indexStatus=INDEXING + Chunk->>DB: 读取解析快照 + Chunk->>DB: 删除旧切片和旧向量 + Chunk->>DB: 写入 rag_chunk + Chunk->>Gateway: 批量生成 Embedding + Gateway->>Provider: POST /v1/embeddings + Provider-->>Gateway: 返回向量 + Gateway->>DB: 记录 model_call_log + Chunk->>DB: 写入 rag_chunk_embedding + Chunk->>DB: 更新 indexStatus=INDEXED +``` + +### 10.3 状态流转 + +`rag_document.index_status` 流转: + +```text +PENDING -> INDEXING -> INDEXED +PENDING -> INDEXING -> FAILED +INDEXED -> INDEXING -> INDEXED +INDEXED -> INDEXING -> FAILED +``` + +失败时应写入 `rag_document.error_message`。 + +### 10.4 切片与向量写入规则 + +1. 生成新切片前,先删除当前文档旧向量,再删除旧切片。 +2. 新切片保存成功后,再批量调用 Embedding。 +3. Embedding 成功后写入 `rag_chunk_embedding`。 +4. 每条 embedding 记录保存 `embedding_model`、`embedding_dimension`、`content_hash`。 +5. `embedding` 字段以 pgvector 可接受的字符串格式保存,例如 `[0.1,0.2,0.3]`。 +6. 向量数量必须等于切片数量,否则本次索引失败。 + +### 10.5 知识库模型绑定 + +RAG 索引选择模型的优先级: + +1. `rag_store_model_config` 中该知识库绑定的 Embedding 模型。 +2. `model_route_rule` 中 `match_scope=RAG_STORE` 的规则。 +3. `model_route_rule` 中 `task_type=RAG_EMBEDDING` 的全局规则。 +4. 全局默认 Embedding 模型。 + +如果以上都不存在,索引任务失败并提示需要配置 Embedding 模型。 + +## 11. API 设计 + +### 11.1 服务商接口 + +| 方法 | 路径 | 说明 | +|------|------|------| +| POST | `/api/model/providers/query` | 查询服务商 | +| GET | `/api/model/providers/detail` | 服务商详情 | +| POST | `/api/model/providers/save` | 新增或修改服务商 | +| POST | `/api/model/providers/delete` | 删除服务商 | +| POST | `/api/model/providers/checkHealth` | 健康检查 | + +服务商详情接口不返回 `apiKeyCipher` 明文。 + +### 11.2 模型接口 + +| 方法 | 路径 | 说明 | +|------|------|------| +| POST | `/api/model/configs/query` | 查询模型 | +| GET | `/api/model/configs/detail` | 模型详情 | +| POST | `/api/model/configs/save` | 新增或修改模型 | +| POST | `/api/model/configs/delete` | 删除模型 | + +### 11.3 路由规则接口 + +| 方法 | 路径 | 说明 | +|------|------|------| +| POST | `/api/model/routes/query` | 查询路由规则 | +| GET | `/api/model/routes/detail` | 路由规则详情 | +| POST | `/api/model/routes/save` | 新增或修改路由规则 | +| POST | `/api/model/routes/delete` | 删除路由规则 | + +### 11.4 调用日志接口 + +| 方法 | 路径 | 说明 | +|------|------|------| +| POST | `/api/model/call-logs/query` | 查询调用日志 | +| GET | `/api/model/call-logs/detail` | 调用日志详情 | + +### 11.5 RAG 模型配置接口 + +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/api/rag/store/modelConfig` | 查询知识库模型配置 | +| POST | `/api/rag/store/modelConfig/save` | 保存知识库模型配置 | +| POST | `/api/rag/store/rebuildIndex` | 重建知识库索引 | + +## 12. DTO 设计要点 + +所有 API 保持现有项目规范: + +- Controller 返回 `RequestResult`。 +- 请求对象使用业务语义明确的 `Request` 类,例如 `ModelProviderSaveRequest`。 +- 响应对象使用业务语义明确的 `Response` 类,例如 `ModelProviderResponse`。 +- 响应 DTO 提供 `fromEntity()` 静态转换。 +- Long ID 输出给前端时使用 `ToStringSerializer`。 + +`ModelProviderResponse` 不包含完整密钥,只包含: + +- `secretRef` +- `hasApiKey` +- `authType` + +## 13. 密钥处理设计 + +### 13.1 推荐方式 + +首期推荐使用 `secret_ref`: + +```text +model_provider.secret_ref = SILICONFLOW_API_KEY +``` + +运行时从环境变量读取: + +```text +SILICONFLOW_API_KEY=sk-*** +``` + +优点: + +- 数据库不保存密钥。 +- 本地、测试、生产可以使用不同环境变量。 +- 实现简单,风险较低。 + +### 13.2 可选加密方式 + +如需在数据库中保存密钥,应保存 `api_key_cipher`,并使用环境变量中的主密钥加解密: + +```text +COMMON_AGENT_SECRET_KEY= +``` + +约束: + +- 主密钥不入库。 +- 前端不返回密钥明文。 +- 修改密钥时只允许写入,不允许读取原文。 + +## 14. 调用日志与费用估算 + +调用日志记录在 `model_call_log`。 + +费用估算规则: + +```text +estimatedCost = promptTokens / 1000 * inputPricePer1k + + completionTokens / 1000 * outputPricePer1k +``` + +Embedding 模型通常只使用输入 token 费用。若上游不返回 token 信息,首期可以记录空值,后续通过本地 tokenizer 或文本长度估算。 + +日志脱敏规则: + +- 不记录完整 API Key。 +- 不默认记录完整 prompt。 +- 可记录请求哈希。 +- 错误信息截断到 1000 字以内。 + +## 15. 健康检查设计 + +健康检查目标是判断服务商是否可用。 + +首期检查方式: + +- OpenAI-compatible 服务调用 `/v1/models`。 +- Ollama 同样可通过 OpenAI-compatible `/v1/models` 检查。 +- 如果服务商不支持 `/v1/models`,可配置跳过健康检查或使用轻量模型调用。 + +健康状态: + +| 状态 | 说明 | +|------|------| +| `UNKNOWN` | 尚未检查 | +| `HEALTHY` | 最近一次检查成功 | +| `UNHEALTHY` | 最近一次检查失败 | + +## 16. 异常处理设计 + +常见异常: + +| 场景 | 处理方式 | +|------|----------| +| 服务商停用 | 路由阶段直接失败 | +| 模型停用 | 路由阶段跳过或失败 | +| 缺少 API Key | 调用前失败,提示密钥未配置 | +| 上游超时 | 记录 `TIMEOUT`,尝试备用模型 | +| 上游返回错误 | 记录 `FAILED`,保留错误码和摘要 | +| Embedding 维度不匹配 | RAG 索引失败,不写入向量 | +| 向量数量不匹配 | RAG 索引失败,清理本次中间数据 | + +## 17. 前端页面设计 + +前端延续当前后台风格,保持信息密度和可扫描性。 + +建议新增页面: + +| 页面 | 功能 | +|------|------| +| 模型服务商 | 服务商列表、启停用、健康检查、编辑 | +| 模型配置 | 模型列表、类型筛选、价格和能力配置 | +| 路由规则 | 按任务类型配置主模型和备用模型 | +| 调用日志 | 查询调用状态、耗时、服务商、模型、错误 | +| 知识库模型配置 | 在知识库详情中配置 Embedding 模型和重建索引 | + +首期后端优先,前端可以在 RAG 最小闭环完成后接入。 + +## 18. 测试设计 + +### 18.1 单元测试 + +需要覆盖: + +- 实体字段结构。 +- Mapper 和 Service 继承结构。 +- DTO 转换。 +- 服务商编码唯一校验。 +- 模型编码唯一校验。 +- 路由优先级。 +- 密钥引用解析。 +- Embedding 维度校验。 + +### 18.2 RAG 集成测试 + +需要覆盖: + +- 文档解析快照转切片。 +- 切片批量调用 Embedding 网关。 +- 向量数量与切片数量一致。 +- 向量写入 `rag_chunk_embedding`。 +- 索引状态成功流转。 +- Embedding 失败时索引状态为 `FAILED`。 + +### 18.3 客户端测试 + +OpenAI-compatible 客户端使用 Mock Web Server 或类似方式测试: + +- `/v1/embeddings` 成功响应。 +- `/v1/chat/completions` 成功响应。 +- 401 鉴权失败。 +- 429 限流。 +- 5xx 上游错误。 +- 超时。 + +## 19. 实施计划 + +### 19.1 第一阶段:配置数据结构 + +1. 新增 SQL 脚本。 +2. 新增实体、Mapper、Service、Controller。 +3. 新增枚举并同步 `sys_enum` 测试。 +4. 新增结构稳定性测试。 + +### 19.2 第二阶段:Embedding 网关 + +1. 新增 `EmbeddingModelGateway`。 +2. 新增 OpenAI-compatible Embedding 客户端。 +3. 新增密钥解析器。 +4. 新增调用日志服务。 +5. 完成 Mock 单元测试。 + +### 19.3 第三阶段:RAG 向量导入 + +1. 扩展 `RagDocumentChunkServiceImpl`。 +2. 切片后调用 Embedding 网关。 +3. 写入 `rag_chunk_embedding`。 +4. 更新 `indexStatus`。 +5. 完成失败回滚和日志记录。 + +### 19.4 第四阶段:路由与前端 + +1. 新增路由规则服务。 +2. RAG 按知识库配置或路由规则选择模型。 +3. 接入前端模型配置页面。 +4. 接入调用日志查询页面。 + +## 20. 配置示例 + +### 20.1 Ollama 服务商 + +```json +{ + "providerCode": "ollama-main", + "providerName": "远程 Ollama", + "providerType": "OLLAMA", + "protocolType": "OPENAI_COMPATIBLE", + "baseUrl": "http://10.0.0.10:11434/v1", + "authType": "NONE", + "timeoutMs": 120000, + "enabled": true +} +``` + +### 20.2 硅基流动 Embedding 模型 + +```json +{ + "providerId": "1001", + "modelCode": "siliconflow-qwen3-embedding-0_6b", + "modelName": "硅基流动 Qwen3 Embedding 0.6B", + "upstreamModel": "Qwen/Qwen3-Embedding-0.6B", + "modelType": "EMBEDDING", + "embeddingDimension": 1024, + "localModel": false, + "enabled": true, + "optionsJson": { + "dimensions": 1024, + "encoding_format": "float" + } +} +``` + +### 20.3 RAG Embedding 路由规则 + +```json +{ + "routeCode": "global-rag-embedding", + "routeName": "全局 RAG 向量模型", + "taskType": "RAG_EMBEDDING", + "matchScope": "GLOBAL", + "primaryModelId": "2001", + "fallbackModelIds": [], + "routeStrategy": "MANUAL", + "enabled": true +} +``` + +## 21. 风险与对策 + +| 风险 | 对策 | +|------|------| +| 动态多服务商与 Spring AI 自动配置存在差异 | 先用项目内部 `ModelGateway` 隔离,后续逐步适配 Spring AI | +| Ollama 远程服务暴露风险 | 文档和配置中明确生产环境必须通过安全通道访问 | +| Embedding 模型混用导致检索漂移 | 知识库绑定模型和维度,变更时重建索引 | +| 云端 API 费用不可控 | 路由策略、调用日志和费用估算逐步完善 | +| 上游接口返回格式差异 | 首期只承诺 OpenAI-compatible,特殊服务商后续单独适配 | +| 大批量向量化超时 | 支持批量大小配置、异步任务和失败重试 | + +## 22. 后续扩展 + +后续可以扩展: + +- Rerank 模型网关。 +- Agent 级模型配置。 +- 用户级额度和限流。 +- 模型质量评测。 +- 模型调用缓存。 +- Prompt 模板与模型绑定。 +- 多索引版本并存。 +- 调用日志聚合报表。 + +## 23. 参考资料 + +- Ollama OpenAI-compatible API: https://docs.ollama.com/api/openai-compatibility +- Ollama Embeddings: https://docs.ollama.com/capabilities/embeddings +- Spring AI OpenAI Embeddings: https://docs.spring.io/spring-ai/reference/api/embeddings/openai-embeddings.html +- SiliconFlow Embedding 模型列表: https://www.siliconflow.com/models/embedding diff --git a/docs/MODEL_PROVIDER_REQUIREMENTS.md b/docs/MODEL_PROVIDER_REQUIREMENTS.md new file mode 100644 index 0000000..b51cb05 --- /dev/null +++ b/docs/MODEL_PROVIDER_REQUIREMENTS.md @@ -0,0 +1,448 @@ +# 模型服务商配置与路由需求文档 + +## 1. 文档信息 + +| 项目 | 内容 | +|------|------| +| 所属项目 | Common Agent | +| 文档类型 | 需求文档 | +| 编写日期 | 2026-05-25 | +| 目标阶段 | RAG 最小检索闭环与模型平台化前置能力 | +| 相关模块 | `model-provider`、`rag-core`、`platform-admin` | + +## 2. 背景 + +Common Agent 的长期目标是建设一套可复用的企业级 AI 应用基础平台,后续需要支持 RAG、Agent 编排、工具调用、会话管理和模型统一接入。 + +当前项目已经完成基础工程、附件上传、文档解析、RAG 知识库和知识文档管理。下一步需要将解析结果切片、生成向量并写入 `rag_chunk_embedding`,再继续建设检索召回和 Agent 运行时。 + +在模型接入层面,项目需要同时支持: + +- 自建模型服务,例如云服务器上的 Ollama。 +- 云端模型平台,例如硅基流动、阿里云百炼、OpenAI 兼容服务。 +- 不同任务使用不同模型,例如简单任务走本地小模型,复杂推理走云端大模型。 +- RAG 向量化使用稳定且可控的 embedding 模型,并保证同一知识库内向量空间一致。 + +因此,本阶段需要建设一个轻量但可扩展的模型服务商配置与路由能力,作为 RAG 向量导入和后续 Agent 调用的统一入口。 + +## 3. 建设目标 + +### 3.1 业务目标 + +1. 支持在后台配置多个模型服务商,包括本地 Ollama、硅基流动、百炼和其他 OpenAI-compatible 服务。 +2. 支持在后台维护每个服务商下的具体模型,例如聊天模型、Embedding 模型、重排序模型。 +3. 支持按任务类型选择模型,达到“小任务本地处理,大任务云端处理”的成本控制目标。 +4. 支持 RAG 向量导入从配置中选择 Embedding 模型,不在代码中写死服务商和模型名。 +5. 支持记录模型调用日志,为后续成本统计、质量评估、失败排查和限流策略提供数据基础。 + +### 3.2 技术目标 + +1. 抽象统一的 `ModelGateway`,业务模块不直接依赖具体服务商 SDK。 +2. 优先兼容 OpenAI API 形态,降低接入 Ollama、硅基流动、百炼等平台的差异成本。 +3. 将 API Key 与业务配置解耦,避免密钥明文散落在业务代码或普通配置中。 +4. 为后续 Spring AI 接入、Agent 运行时和模型调用观测保留扩展点。 +5. 保持与当前项目风格一致:Spring Boot、MyBatis-Plus、DTO、统一返回体、结构化枚举。 + +## 4. 范围说明 + +### 4.1 本阶段范围 + +本阶段覆盖以下能力: + +- 模型服务商配置管理。 +- 模型配置管理。 +- 模型路由规则管理。 +- 模型调用日志记录。 +- Embedding 调用网关。 +- Chat 调用网关的基础接口设计。 +- RAG 切片向量导入接入模型网关。 +- Ollama 远程服务接入设计。 +- 硅基流动等 OpenAI-compatible 云服务接入设计。 + +### 4.2 本阶段不覆盖 + +本阶段不实现以下完整能力: + +- 完整 Agent 运行时。 +- 多租户权限体系。 +- 复杂模型质量评测平台。 +- 自动提示词优化。 +- 按用户或部门计费结算。 +- 高级模型编排工作流。 +- 完整密钥管理系统。 + +这些能力可以在模型服务商配置与路由能力稳定后继续扩展。 + +## 5. 术语定义 + +| 术语 | 说明 | +|------|------| +| 模型服务商 | 提供模型调用能力的上游服务,例如 Ollama、硅基流动、百炼、OpenAI | +| 模型配置 | 某个服务商下的具体模型配置,例如 `Qwen/Qwen3-Embedding-0.6B` | +| 模型路由 | 根据任务类型、成本、质量、可用性选择具体模型的规则 | +| OpenAI-compatible | 兼容 OpenAI API 风格的服务接口,通常包含 `/v1/chat/completions`、`/v1/embeddings` | +| 本地模型 | 由用户自行部署和维护的模型服务,例如云服务器上的 Ollama | +| 云端模型 | 第三方平台托管的模型服务,例如硅基流动或百炼 | +| Embedding | 将文本转换为向量,用于 RAG 检索召回 | +| Rerank | 对召回结果二次排序,提高检索结果相关性 | + +## 6. 当前问题 + +### 6.1 模型配置不可管理 + +当前项目尚未接入统一模型配置层。如果在 RAG 向量化阶段直接写死模型服务商、模型名和 API 地址,后续切换服务商会产生重复改造。 + +### 6.2 成本控制缺少入口 + +不同任务对模型能力要求不同。简单分类、标题生成、短文本摘要可以使用本地小模型,复杂推理、长上下文问答和 Agent 规划适合使用云端大模型。当前缺少统一路由层,无法系统性节省调用成本。 + +### 6.3 RAG 向量模型需要稳定约束 + +同一知识库中的向量必须来自同一个语义空间。随意混用不同 Embedding 模型或不同维度,会导致检索结果不稳定。当前 `rag_chunk_embedding` 已有模型名和维度字段,但缺少知识库级别的模型绑定和重建索引约束。 + +### 6.4 调用可观测性不足 + +模型调用需要记录耗时、状态、错误、token、费用估算和业务来源。当前没有统一日志表,后续无法分析失败原因、成本趋势和模型效果。 + +### 6.5 密钥管理需要提前约束 + +模型服务商通常需要 API Key。若直接明文存储在数据库或配置文件中,会带来泄露风险。项目早期可以简化实现,但必须明确密钥引用和加密策略。 + +## 7. 用户角色 + +| 角色 | 诉求 | +|------|------| +| 平台管理员 | 配置模型服务商、模型、路由规则和密钥引用 | +| 知识库维护者 | 为知识库选择 Embedding 模型,触发索引重建 | +| Agent 配置者 | 为不同 Agent 选择默认模型或路由策略 | +| 系统开发者 | 通过统一网关调用模型,不关心具体服务商差异 | +| 运维人员 | 查看模型服务可用性、调用失败、耗时和成本趋势 | + +## 8. 典型使用场景 + +### 8.1 RAG 使用硅基流动生成向量 + +管理员配置硅基流动服务商,添加 `Qwen/Qwen3-Embedding-0.6B` 模型,设置维度为 1024。知识库选择该模型作为 Embedding 模型。文档上传后,系统解析、切片、调用模型生成向量,并写入 `rag_chunk_embedding`。 + +### 8.2 简单任务使用远程 Ollama + +用户在云服务器部署 Ollama,并开放安全访问地址。管理员配置 Ollama 服务商和本地小模型,例如 `qwen2.5:7b`。系统在标题生成、短摘要、分类等任务中优先调用 Ollama,减少云端模型费用。 + +### 8.3 复杂任务使用云端大模型 + +当任务类型为复杂 Agent 规划、长上下文问答或工具调用编排时,路由规则选择云端大模型。若主模型调用失败,可以按规则切换到备用模型。 + +### 8.4 Embedding 模型变更触发索引重建 + +知识库已经使用某个 Embedding 模型完成索引。管理员切换该知识库的 Embedding 模型时,系统标记该知识库需要重建索引,并阻止新旧模型向量混合检索。 + +### 8.5 查看模型调用日志 + +运维人员进入模型调用日志页面,查看某段时间内的调用次数、失败率、平均耗时和费用估算,定位某个服务商或模型的异常。 + +## 9. 功能需求 + +### 9.1 模型服务商管理 + +系统应支持新增、编辑、启用、停用和查询模型服务商。 + +服务商至少包含: + +- 服务商编码。 +- 服务商名称。 +- 服务商类型。 +- API 基础地址。 +- 鉴权方式。 +- 密钥引用。 +- 超时时间。 +- 默认优先级。 +- 是否启用。 +- 备注。 + +服务商编码应全局唯一。 + +### 9.2 模型配置管理 + +系统应支持在服务商下维护具体模型。 + +模型至少包含: + +- 所属服务商。 +- 模型编码。 +- 上游模型名称。 +- 模型类型。 +- 上下文窗口。 +- 输出 token 上限。 +- Embedding 维度。 +- 是否本地模型。 +- 是否默认模型。 +- 能力标签。 +- 价格配置。 +- 是否启用。 + +同一服务商下模型编码应唯一。 + +### 9.3 模型路由规则管理 + +系统应支持按任务类型配置模型路由。 + +路由规则至少包含: + +- 任务类型。 +- 匹配范围。 +- 主模型。 +- 备用模型列表。 +- 路由策略。 +- 最大允许耗时。 +- 是否启用。 + +任务类型初始支持: + +- RAG 文档向量化。 +- RAG 查询向量化。 +- RAG 问答生成。 +- 简单文本处理。 +- 复杂文本处理。 +- Agent 规划。 +- Rerank。 + +### 9.4 模型网关 + +系统应提供统一模型网关,供业务模块调用。 + +模型网关应支持: + +- 根据任务类型选择模型。 +- 调用 Embedding 模型生成向量。 +- 调用 Chat 模型生成回复。 +- 记录调用日志。 +- 在主模型失败时按规则尝试备用模型。 +- 返回统一错误信息。 + +业务模块不应直接调用具体服务商接口。 + +### 9.5 RAG 向量导入 + +系统应将 RAG 文档索引流程接入模型网关。 + +向量导入流程应支持: + +1. 读取文档解析快照。 +2. 按切片策略生成 `rag_chunk`。 +3. 根据知识库或全局路由选择 Embedding 模型。 +4. 调用模型生成向量。 +5. 写入 `rag_chunk_embedding`。 +6. 更新文档索引状态。 +7. 记录模型调用日志。 + +同一知识库应固定 Embedding 模型和维度。模型变更时应触发重建索引流程。 + +### 9.6 Ollama 接入 + +系统应支持配置远程 Ollama 服务。 + +Ollama 接入要求: + +- 支持 OpenAI-compatible 地址,例如 `http://host:11434/v1`。 +- 支持 Chat 模型。 +- 支持 Embedding 模型。 +- 支持模型健康检查。 +- 支持设置本地模型标签。 + +Ollama 远程访问不应直接裸露在公网。生产环境应通过 VPN、内网、反向代理鉴权、Tailscale、Cloudflare Tunnel 或安全网关访问。 + +### 9.7 云端 OpenAI-compatible 服务接入 + +系统应支持硅基流动、百炼、OpenAI 或其他兼容接口。 + +接入要求: + +- 服务商可配置 `baseUrl`。 +- 服务商可配置 `apiKey` 引用。 +- 模型可配置上游模型名。 +- Embedding 支持设置维度。 +- Chat 支持设置温度、最大输出等参数。 + +### 9.8 调用日志 + +系统应记录模型调用日志。 + +日志至少包含: + +- 请求 ID。 +- 服务商。 +- 模型。 +- 任务类型。 +- 业务来源。 +- 调用状态。 +- 耗时。 +- token 数量。 +- 费用估算。 +- 错误码。 +- 错误消息。 +- 请求哈希。 +- 创建时间。 + +日志中不得记录完整 API Key。 + +### 9.9 后台管理界面 + +后台管理界面应逐步提供: + +- 服务商列表。 +- 模型列表。 +- 路由规则配置。 +- 调用日志查询。 +- 模型健康检查结果。 +- 知识库 Embedding 配置入口。 + +首期可先完成后端接口和 SQL 结构,前端在 RAG 最小闭环后接入。 + +## 10. 非功能需求 + +### 10.1 可扩展性 + +模型服务商接入应通过统一接口扩展。新增 OpenAI-compatible 服务商时,原则上只需要新增配置,不需要修改业务调用代码。 + +### 10.2 可用性 + +模型调用应支持超时控制和失败兜底。云端模型失败时,可以根据路由规则切换备用模型。本地 Ollama 不可用时,不应阻塞整个系统启动。 + +### 10.3 性能 + +Embedding 批量生成应支持批处理,减少网络请求次数。批量大小应可配置,避免超过上游接口限制。 + +### 10.4 可观测性 + +每次模型调用应有请求 ID,并记录耗时、状态和错误原因。后续可接入监控告警。 + +### 10.5 可维护性 + +新增核心代码应补充中文注释,说明类职责、关键分支和扩展边界。新增枚举应同步纳入系统枚举初始化测试。 + +## 11. 数据安全需求 + +1. API Key 不得写死在代码中。 +2. API Key 不应明文返回给前端。 +3. 数据库可保存 `secretRef` 或加密后的 `apiKeyCipher`。 +4. 若保存加密密钥,主加密密钥应来自环境变量或外部配置,不应存储在数据库。 +5. 调用日志不得保存完整请求正文中的敏感信息。 +6. 管理接口后续应接入权限控制。 +7. Ollama 远程服务应限制访问来源,避免未授权公网调用。 + +## 12. 成本控制需求 + +系统应支持以下成本控制策略: + +- 本地优先:简单任务优先走 Ollama。 +- 成本优先:优先选择单价较低的云模型。 +- 质量优先:复杂任务优先选择能力更强的模型。 +- 手动指定:某个知识库或 Agent 固定使用指定模型。 +- 失败兜底:主模型失败后切换备用模型。 + +调用日志应记录费用估算所需字段,为后续成本报表提供基础。 + +## 13. RAG 特殊约束 + +### 13.1 向量维度约束 + +当前 `rag_chunk_embedding.embedding` 使用 `VECTOR(1024)`。因此首期 Embedding 模型应统一输出 1024 维向量。 + +适配方向: + +- 硅基流动:可使用 `Qwen/Qwen3-Embedding-0.6B`,配置 1024 维。 +- Ollama:应选择输出维度与表结构匹配的 embedding 模型。 +- 百炼:可使用支持 1024 维的文本向量模型。 + +### 13.2 模型一致性约束 + +同一知识库同一索引版本内,应使用同一个 Embedding 模型和维度。 + +当知识库 Embedding 模型或维度变化时: + +- 已有索引应标记为需要重建。 +- 新索引写入前应清理旧切片向量,或写入新的索引版本。 +- 检索时应只使用当前生效模型生成的向量。 + +### 13.3 失败状态约束 + +向量生成失败时,文档 `indexStatus` 应更新为 `FAILED`,并记录失败原因。部分切片成功、部分失败时,首期按整个文档索引失败处理,避免半成品参与检索。 + +## 14. 验收标准 + +### 14.1 服务商配置验收 + +- 可以新增一个 Ollama 服务商。 +- 可以新增一个硅基流动服务商。 +- 可以为服务商配置至少一个 Chat 模型和一个 Embedding 模型。 +- 服务商编码和模型编码唯一性校验生效。 + +### 14.2 路由验收 + +- 可以为 RAG 文档向量化配置默认 Embedding 模型。 +- 可以为简单文本处理配置 Ollama 模型。 +- 可以为复杂文本处理配置云端模型。 +- 主模型不可用时,可以根据配置切换备用模型。 + +### 14.3 RAG 向量导入验收 + +- 文档解析完成后,可以生成切片。 +- 切片可以调用配置的 Embedding 模型生成 1024 维向量。 +- 向量可以写入 `rag_chunk_embedding`。 +- 文档索引状态可以从 `PENDING` 流转到 `INDEXING`、`INDEXED` 或 `FAILED`。 +- 调用日志可以记录 Embedding 调用信息。 + +### 14.4 安全验收 + +- 前端查询服务商详情时不返回明文 API Key。 +- 调用日志中不包含完整 API Key。 +- 未配置密钥时,云端服务调用失败信息清晰。 +- Ollama 远程地址可配置,但文档中明确生产环境访问安全要求。 + +### 14.5 测试验收 + +- 后端新增实体、Mapper、Service、Controller 结构测试。 +- 模型路由单元测试。 +- Embedding 网关单元测试。 +- RAG 向量导入服务单元测试。 +- 配置缺失、模型停用、服务商停用、调用失败等异常测试。 + +## 15. 分阶段里程碑 + +### 15.1 阶段一:模型配置基础 + +- 新增模型服务商表。 +- 新增模型配置表。 +- 新增基础 CRUD 接口。 +- 支持 OpenAI-compatible 服务商配置。 +- 支持密钥引用字段。 + +### 15.2 阶段二:Embedding 网关与 RAG 接入 + +- 新增 Embedding 调用网关。 +- 接入硅基流动或 Ollama Embedding。 +- RAG 切片后调用 Embedding 并写入 `rag_chunk_embedding`。 +- 更新文档索引状态。 +- 记录调用日志。 + +### 15.3 阶段三:模型路由与失败兜底 + +- 新增模型路由规则。 +- 支持按任务类型选择模型。 +- 支持主备模型调用。 +- 支持本地优先、成本优先、质量优先策略。 + +### 15.4 阶段四:后台管理与成本观测 + +- 前端接入服务商管理。 +- 前端接入模型管理。 +- 前端接入路由规则管理。 +- 前端接入调用日志查询。 +- 增加费用估算和调用趋势展示。 + +## 16. 参考资料 + +- Ollama OpenAI-compatible API: https://docs.ollama.com/api/openai-compatibility +- Ollama Embeddings: https://docs.ollama.com/capabilities/embeddings +- Spring AI OpenAI Embeddings: https://docs.spring.io/spring-ai/reference/api/embeddings/openai-embeddings.html +- SiliconFlow Embedding 模型列表: https://www.siliconflow.com/models/embedding