From 3526322811da197231ce2c44649d94370788e942 Mon Sep 17 00:00:00 2001 From: bruce Date: Mon, 1 Jun 2026 00:49:31 +0800 Subject: [PATCH] =?UTF-8?q?docs(model):=20=E8=A1=A5=E5=85=A8=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=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_SCHEMA.sql | 1 + script/sql/model_provider.sql | 131 +++++++++++++++++++++++ 前端实现文档/3.模型与路由模块前端实现.md | 30 ++++++ 后端实现文档/3.模型与路由模块后端实现.md | 41 +++++++ 数据库设计/3.模型与路由数据库设计.md | 37 +++++++ 设计文档/3.模型与路由模块设计.md | 47 ++++++++ 需求分析/3.模型与路由模块需求.md | 39 +++++++ 7 files changed, 326 insertions(+) create mode 100644 script/sql/model_provider.sql create mode 100644 前端实现文档/3.模型与路由模块前端实现.md create mode 100644 后端实现文档/3.模型与路由模块后端实现.md create mode 100644 数据库设计/3.模型与路由数据库设计.md create mode 100644 设计文档/3.模型与路由模块设计.md create mode 100644 需求分析/3.模型与路由模块需求.md diff --git a/docs/MODEL_PROVIDER_SCHEMA.sql b/docs/MODEL_PROVIDER_SCHEMA.sql index f0bc5a3..072005d 100644 --- a/docs/MODEL_PROVIDER_SCHEMA.sql +++ b/docs/MODEL_PROVIDER_SCHEMA.sql @@ -91,6 +91,7 @@ CREATE TABLE IF NOT EXISTS rag_store_model_config ( 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) ); diff --git a/script/sql/model_provider.sql b/script/sql/model_provider.sql new file mode 100644 index 0000000..fa29c67 --- /dev/null +++ b/script/sql/model_provider.sql @@ -0,0 +1,131 @@ +-- 模型平台核心表。 +-- 与 docs/MODEL_PROVIDER_SCHEMA.sql 保持一致,作为后续落库执行入口。 + +CREATE TABLE IF NOT EXISTS 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) +); + +CREATE TABLE IF NOT EXISTS 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) +); + +CREATE TABLE IF NOT EXISTS 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) +); + +CREATE TABLE IF NOT EXISTS 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) +); + +CREATE TABLE IF NOT EXISTS 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), + 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_call_log_request_id UNIQUE (request_id) +); + +CREATE INDEX IF NOT EXISTS idx_model_config_provider_id ON model_config (provider_id); +CREATE INDEX IF NOT EXISTS idx_model_config_model_type ON model_config (model_type); +CREATE INDEX IF NOT EXISTS idx_model_route_task_scope ON model_route_rule (task_type, match_scope, scope_id); +CREATE INDEX IF NOT EXISTS idx_rag_store_model_config_store_id ON rag_store_model_config (store_id); +CREATE INDEX IF NOT EXISTS idx_model_call_log_request_id ON model_call_log (request_id); +CREATE INDEX IF NOT EXISTS idx_model_call_log_task_type ON model_call_log (task_type); diff --git a/前端实现文档/3.模型与路由模块前端实现.md b/前端实现文档/3.模型与路由模块前端实现.md new file mode 100644 index 0000000..1efbcf0 --- /dev/null +++ b/前端实现文档/3.模型与路由模块前端实现.md @@ -0,0 +1,30 @@ +# 模型与路由模块前端实现 + +## 1. 页面 + +`ModelWorkspacePage.vue` 当前展示任务路由规则,保留 `model_provider`、`model_config`、`model_route_rule` 语义。 + +## 2. ViewModel + +`ModelRoutingView` 建议包含: + +- 服务商健康概览。 +- 模型配置列表。 +- 任务路由规则。 +- Fallback 关系。 +- 最近模型调用失败摘要。 + +## 3. 接口草案 + +- `POST /api/model-providers/query` +- `POST /api/model-configs/query` +- `POST /api/model-route-rules/query` +- `POST /api/model-route-rules/save` +- `GET /api/model-call-logs/query` + +## 4. 交互规则 + +- 禁用服务商时提示关联模型和路由受影响。 +- Embedding 模型维度变更时提示知识库需要重建索引。 +- 草稿路由不得用于生产发布就绪校验。 +- Fallback 模型为空时在发布检查中提示风险。 diff --git a/后端实现文档/3.模型与路由模块后端实现.md b/后端实现文档/3.模型与路由模块后端实现.md new file mode 100644 index 0000000..c33ef10 --- /dev/null +++ b/后端实现文档/3.模型与路由模块后端实现.md @@ -0,0 +1,41 @@ +# 模型与路由模块后端实现 + +## 1. 当前实现落点 + +当前实现位于 `com.bruce.modelprovider`,包含服务商、模型、路由、网关、客户端和调用日志。 + +## 2. Controller + +- `ModelProviderController` +- `ModelConfigController` +- `ModelRouteRuleController` +- `RagStoreModelConfigController` +- `ModelCallLogController` + +## 3. Service + +| Service | 职责 | +|---------|------| +| `IModelProviderService` | 服务商 CRUD 和健康检查 | +| `IModelConfigService` | 模型配置 CRUD | +| `IModelRouteRuleService` | 路由规则 CRUD | +| `IModelRouteService` | 根据任务上下文选择模型 | +| `IRagStoreModelConfigService` | 知识库模型绑定 | +| `IModelCallLogService` | 调用日志写入与查询 | + +## 4. 网关 + +业务模块只能依赖: + +- `ChatModelGateway` +- `EmbeddingModelGateway` + +不得直接依赖具体上游客户端。 + +## 5. 校验规则 + +- 服务商编码唯一。 +- 同一服务商下模型编码唯一。 +- 路由主模型必须启用。 +- 路由任务类型必须来自枚举。 +- 知识库 Embedding 维度必须与模型配置一致。 diff --git a/数据库设计/3.模型与路由数据库设计.md b/数据库设计/3.模型与路由数据库设计.md new file mode 100644 index 0000000..e6d2687 --- /dev/null +++ b/数据库设计/3.模型与路由数据库设计.md @@ -0,0 +1,37 @@ +# 模型与路由数据库设计 + +## 1. 表关系 + +| 表 | 说明 | +|----|------| +| `model_provider` | 模型服务商配置 | +| `model_config` | 服务商下具体模型 | +| `model_route_rule` | 任务路由规则 | +| `rag_store_model_config` | 知识库 Embedding 与切片配置 | +| `model_call_log` | 模型调用日志 | + +## 2. 关键约束 + +- `model_provider.provider_code` 全局唯一。 +- `model_config` 使用 `(provider_id, model_code)` 唯一。 +- `model_route_rule.route_code` 全局唯一。 +- `rag_store_model_config` 使用 `(store_id, active)` 约束一个知识库只有一个生效配置。 +- `model_call_log.request_id` 全局唯一。 + +## 3. 枚举组 + +| catalog | type | +|---------|------| +| `model_provider` | `provider_type` | +| `model_provider` | `protocol_type` | +| `model_provider` | `model_type` | +| `model_provider` | `task_type` | +| `model_provider` | `route_strategy` | +| `model_provider` | `call_status` | +| `model_provider` | `health_status` | + +## 4. 脚本 + +- `docs/MODEL_PROVIDER_SCHEMA.sql` 是完整 schema 快照。 +- `script/sql/model_provider.sql` 是后续执行入口。 +- 若模型枚举变更,需要同步 Java 枚举、初始化测试和 SQL 枚举脚本。 diff --git a/设计文档/3.模型与路由模块设计.md b/设计文档/3.模型与路由模块设计.md new file mode 100644 index 0000000..4ab9d62 --- /dev/null +++ b/设计文档/3.模型与路由模块设计.md @@ -0,0 +1,47 @@ +# 模型与路由模块设计 + +## 1. 分层设计 + +| 层 | 职责 | +|----|------| +| 配置层 | 管理服务商、模型、路由规则和知识库模型绑定 | +| 路由层 | 根据任务类型、范围和策略选择模型 | +| 调用层 | 通过 OpenAI-compatible 客户端调用 Chat/Embedding | +| 观测层 | 写入模型调用日志,供运行观测查询 | + +## 2. 路由输入 + +模型路由至少需要: + +- `taskType` +- `matchScope` +- `scopeId` +- `bizType` +- `bizId` +- 调用参数。 + +`matchScope` 初始支持 `GLOBAL`、`RAG_STORE`、`AGENT`。 + +## 3. 路由输出 + +路由结果包含: + +- 服务商。 +- 模型配置。 +- 上游模型名。 +- 超时时间。 +- Fallback 列表。 +- 调用选项。 + +## 4. 失败策略 + +- 主模型失败时按 Fallback 顺序重试。 +- 全部失败时返回统一错误。 +- 每次调用均写入 `model_call_log`。 +- Fallback 成功时状态记为 `FALLBACK_SUCCESS`。 + +## 5. 与其他模块关系 + +- 知识资产模块使用 Embedding 路由和知识库模型绑定。 +- Workflow 和 Agent 使用 Chat 路由。 +- 运行观测读取 `model_call_log`。 diff --git a/需求分析/3.模型与路由模块需求.md b/需求分析/3.模型与路由模块需求.md new file mode 100644 index 0000000..a720cb7 --- /dev/null +++ b/需求分析/3.模型与路由模块需求.md @@ -0,0 +1,39 @@ +# 模型与路由模块需求 + +## 1. 模块目标 + +模型与路由模块负责统一管理模型服务商、模型配置、任务路由、知识库模型绑定和模型调用日志,为 RAG、Workflow、Agent 和 Skill 提供统一模型入口。 + +## 2. 功能需求 + +- 支持配置 Ollama、硅基流动、百炼、OpenAI 和自定义 OpenAI-compatible 服务。 +- 支持维护 Chat、Embedding、Rerank、多模态模型。 +- 支持按任务类型配置主模型、Fallback 模型和路由策略。 +- 支持知识库固定 Embedding 模型、向量维度、切片策略和索引版本。 +- 支持记录模型调用状态、耗时、Token、成本和错误摘要。 + +## 3. 任务类型 + +初始任务类型包括: + +- RAG 文档向量化。 +- RAG 查询向量化。 +- RAG 问答生成。 +- 简单文本处理。 +- 复杂文本处理。 +- Agent 规划。 +- 重排序。 + +## 4. 验收标准 + +- 业务模块不直接调用上游模型服务。 +- 同一知识库不能混用不同 Embedding 向量空间。 +- 所有调用必须有 `request_id`,方便观测模块追踪。 +- 路由规则禁用时不能被选中。 + +## 5. 关联资料 + +- 表:`model_provider`、`model_config`、`model_route_rule`、`rag_store_model_config`、`model_call_log` +- 枚举:`model_provider/provider_type`、`protocol_type`、`model_type`、`task_type`、`route_strategy`、`call_status`、`health_status` +- 脚本:`docs/MODEL_PROVIDER_SCHEMA.sql`、`script/sql/model_provider.sql` +- 前端原型:`ModelWorkspacePage.vue`