27 KiB
模型服务商配置与路由设计文档
1. 文档信息
| 项目 | 内容 |
|---|---|
| 所属项目 | Common Agent |
| 文档类型 | 设计文档 |
| 编写日期 | 2026-05-25 |
| 对应需求 | docs/MODEL_PROVIDER_REQUIREMENTS.md |
| 目标阶段 | RAG 向量导入与模型网关基础能力 |
2. 设计目标
本设计用于在 Common Agent 中新增模型服务商配置与模型路由能力,使系统可以统一接入 Ollama、硅基流动、百炼、OpenAI 等模型服务,并为 RAG 和后续 Agent 运行时提供统一模型调用入口。
核心设计目标:
- 业务模块只依赖平台内部模型网关,不直接依赖具体服务商。
- 首期优先支持 OpenAI-compatible 协议,减少多服务商适配成本。
- 支持本地模型和云端模型混用,实现成本控制。
- 支持 RAG Embedding 模型配置化,并保证同一知识库向量模型一致。
- 支持调用日志,为排障、统计和后续成本分析打基础。
3. 总体架构
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. 包结构设计
建议新增后端包:
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 模型服务商表
用于保存服务商基础配置。
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 模型配置表
用于保存服务商下的具体模型。
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 模型路由规则表
用于根据任务类型和范围选择模型。
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 模型和维度,避免同一知识库混用向量空间。
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 模型调用日志表
用于记录模型调用行为。
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 配置管理服务
public interface IModelProviderService extends IService<ModelProvider> {
List<ModelProviderResponse> query(ModelProviderQueryRequest request);
ModelProviderResponse getResponseById(Long id);
boolean saveOrUpdate(ModelProviderSaveRequest request);
boolean checkHealth(Long id);
}
public interface IModelConfigService extends IService<ModelConfig> {
List<ModelConfigResponse> query(ModelConfigQueryRequest request);
ModelConfigResponse getResponseById(Long id);
boolean saveOrUpdate(ModelConfigSaveRequest request);
ModelConfig getEnabledModel(Long modelId);
}
7.2 路由服务
public interface IModelRouteService {
ModelRouteDecision route(ModelRouteContext context);
}
ModelRouteContext 应包含:
taskTypematchScopescopeIdrequiredModelTypepreferredLocalrequiredEmbeddingDimensionbizTypebizId
ModelRouteDecision 应包含:
- 主模型。
- 备用模型列表。
- 路由策略。
- 决策原因。
7.3 模型网关
public interface EmbeddingModelGateway {
EmbeddingResult embed(EmbeddingRequest request);
}
public interface ChatModelGateway {
ChatResult chat(ChatRequest request);
}
EmbeddingRequest 应包含:
- 文本列表。
- 任务类型。
- 匹配范围。
- 范围 ID。
- 业务类型。
- 业务 ID。
- 期望维度。
EmbeddingResult 应包含:
- 模型 ID。
- 模型名称。
- 维度。
- 向量列表。
- 调用日志 ID。
8. 客户端设计
首期优先实现 OpenAiCompatibleModelClient,统一调用以下接口:
POST /v1/embeddingsPOST /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 地址:
http://<ollama-host>: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 路由优先级
模型路由按以下顺序匹配:
- 业务范围精确规则,例如某个知识库或某个 Agent。
- 任务类型规则,例如
RAG_EMBEDDING。 - 全局默认规则。
- 模型类型默认模型。
如果没有匹配到模型,应返回清晰错误,不隐式选择不确定模型。
9.2 策略说明
| 策略 | 行为 |
|---|---|
MANUAL |
使用规则中指定的主模型 |
LOCAL_FIRST |
优先选择本地模型,失败后使用备用云端模型 |
COST_FIRST |
在可用模型中优先选择成本低的模型 |
QUALITY_FIRST |
优先选择质量更高或优先级更高的模型 |
首期可以只实现 MANUAL 和 LOCAL_FIRST,其余策略先完成数据结构和枚举。
9.3 失败兜底
主模型调用失败时:
- 记录主模型失败日志。
- 判断是否存在备用模型。
- 按备用模型顺序重试。
- 若备用模型成功,返回结果并记录
FALLBACK_SUCCESS。 - 若全部失败,返回最后一次错误,并将业务状态更新为失败。
RAG 向量导入首期应谨慎使用 fallback。Embedding 模型 fallback 只有在维度和语义模型族一致时才允许自动切换,否则应失败并提示重建或重新配置。
10. RAG 向量导入设计
10.1 当前 RAG 状态
当前项目已有:
rag_documentrag_document_parse_resultrag_chunkrag_chunk_embeddingRagDocumentParseServiceImplRagDocumentChunkServiceImplFixedLengthChunkerDelimiterChunker
下一步需要把切片服务和 Embedding 网关串起来。
10.2 目标流程
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 流转:
PENDING -> INDEXING -> INDEXED
PENDING -> INDEXING -> FAILED
INDEXED -> INDEXING -> INDEXED
INDEXED -> INDEXING -> FAILED
失败时应写入 rag_document.error_message。
10.4 切片与向量写入规则
- 生成新切片前,先删除当前文档旧向量,再删除旧切片。
- 新切片保存成功后,再批量调用 Embedding。
- Embedding 成功后写入
rag_chunk_embedding。 - 每条 embedding 记录保存
embedding_model、embedding_dimension、content_hash。 embedding字段以 pgvector 可接受的字符串格式保存,例如[0.1,0.2,0.3]。- 向量数量必须等于切片数量,否则本次索引失败。
10.5 知识库模型绑定
RAG 索引选择模型的优先级:
rag_store_model_config中该知识库绑定的 Embedding 模型。model_route_rule中match_scope=RAG_STORE的规则。model_route_rule中task_type=RAG_EMBEDDING的全局规则。- 全局默认 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<T>。 - 请求对象使用业务语义明确的
Request类,例如ModelProviderSaveRequest。 - 响应对象使用业务语义明确的
Response类,例如ModelProviderResponse。 - 响应 DTO 提供
fromEntity()静态转换。 - Long ID 输出给前端时使用
ToStringSerializer。
ModelProviderResponse 不包含完整密钥,只包含:
secretRefhasApiKeyauthType
13. 密钥处理设计
13.1 推荐方式
首期推荐使用 secret_ref:
model_provider.secret_ref = SILICONFLOW_API_KEY
运行时从环境变量读取:
SILICONFLOW_API_KEY=sk-***
优点:
- 数据库不保存密钥。
- 本地、测试、生产可以使用不同环境变量。
- 实现简单,风险较低。
13.2 可选加密方式
如需在数据库中保存密钥,应保存 api_key_cipher,并使用环境变量中的主密钥加解密:
COMMON_AGENT_SECRET_KEY=<secret-from-environment>
约束:
- 主密钥不入库。
- 前端不返回密钥明文。
- 修改密钥时只允许写入,不允许读取原文。
14. 调用日志与费用估算
调用日志记录在 model_call_log。
费用估算规则:
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 第一阶段:配置数据结构
- 新增 SQL 脚本。
- 新增实体、Mapper、Service、Controller。
- 新增枚举并同步
sys_enum测试。 - 新增结构稳定性测试。
19.2 第二阶段:Embedding 网关
- 新增
EmbeddingModelGateway。 - 新增 OpenAI-compatible Embedding 客户端。
- 新增密钥解析器。
- 新增调用日志服务。
- 完成 Mock 单元测试。
19.3 第三阶段:RAG 向量导入
- 扩展
RagDocumentChunkServiceImpl。 - 切片后调用 Embedding 网关。
- 写入
rag_chunk_embedding。 - 更新
indexStatus。 - 完成失败回滚和日志记录。
19.4 第四阶段:路由与前端
- 新增路由规则服务。
- RAG 按知识库配置或路由规则选择模型。
- 接入前端模型配置页面。
- 接入调用日志查询页面。
20. 配置示例
20.1 Ollama 服务商
{
"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 模型
{
"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 路由规则
{
"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