Skip to content

Commit 6531e5e

Browse files
authored
Merge pull request #147 from ql-link/feature/llm-config-refactor
适配新版 LLM 配置结构
2 parents 8849097 + 0b3e366 commit 6531e5e

23 files changed

Lines changed: 884 additions & 661 deletions

.env.example

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ REDIS_PASSWORD=your_redis_password
2626
# 安全配置 (Security)
2727
# ==========================================
2828
# 【关键】用于解密从数据库 llm_user_config 表取出的 API Key 密文
29-
# 需要与 Java 管理端的加密 Secret / 离散算法保持完全一致
30-
API_KEY_ENCRYPTION_SECRET=your_encryption_secret
29+
# 需要与 Java 管理端的 AES/GCM Secret 保持完全一致:64 位 hex,解码后 32 字节
30+
# 下方为本地占位示例,生产必须覆盖
31+
API_KEY_ENCRYPTION_SECRET=0000000000000000000000000000000000000000000000000000000000000000
3132

3233
# ==========================================
3334
# 系统级兜底 LLM 配置 (Platform Default Fallback LLMs)

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ tests/api_keys.json
7777

7878
/requirements
7979

80+
# 本地 Docker Compose 覆盖(KRaft Kafka、无认证),不入 Git
81+
docker-compose.override.yml
82+
8083
/.specs/
8184
/.kiro/
8285
/blog/

docs/api/schemas/mysql.md

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ ORM 与 migration 不一致时,以 migration 为准并修正 ORM;scripts/db/
1010

1111
## 表清单
1212

13-
按业务域共 12 张表:
13+
按业务域共 14 张表:
1414

1515
| 业务域 || 主键 ID 起始 |
1616
| --- | --- | --- |
1717
| [用户](#1-用户) | `sys_user` | 10000 |
18-
| [LLM 配置与用量](#2-llm-配置与用量) | `llm_system_provider`, `llm_user_config`, `llm_usage_log` | 10000 |
18+
| [LLM 配置与用量](#2-llm-配置与用量) | `llm_system_provider`, `llm_provider_model`, `llm_system_preset`, `llm_user_config`, `llm_usage_log` | 10000 |
1919
| [数据集与对话](#3-数据集与对话) | `dataset`, `chat_conversation`, `chat_message` | 10000 |
2020
| [文档解析](#4-文档解析) | `document_original_file`, `document_parse_file`, `document_parsed_log`, `document_parse_pipeline` | 10000 |
2121
| [知识索引](#5-知识索引) | `kb_document_chunk` | 10000 |
@@ -60,14 +60,47 @@ ORM:[`SystemProviderDB`](../../src/models/db_models.py)
6060
| `provider_type` | VARCHAR(32) UNIQUE | `openai` / `claude` / `glm` / `deepseek`|
6161
| `provider_name` | VARCHAR(64) | 厂商展示名 |
6262
| `api_base_url` | VARCHAR(512) | 官方默认 API 地址 |
63-
| `supported_models` | JSON | 支持模型与能力映射 |
64-
| `config_schema` | JSON | 配置参数 Schema |
6563
| `is_active` | BOOLEAN | 是否启用 |
6664
| `priority` | INT | 厂商优先级(1-100),默认 50 |
6765
| `created_at` / `updated_at` | DATETIME | 创建 / 更新时间 |
6866

6967
索引:`uk_provider_type`
7068

69+
### `llm_provider_model` — 厂商模型能力目录
70+
71+
ORM:[`ProviderModelDB`](../../src/models/db_models.py)
72+
73+
| 字段 | 类型 | 说明 |
74+
| --- | --- | --- |
75+
| `id` | BIGINT UNSIGNED PK | 主键 |
76+
| `provider_id` | BIGINT UNSIGNED | 关联 `llm_system_provider.id` |
77+
| `model_name` | VARCHAR(128) | 模型名 |
78+
| `capability` | VARCHAR(32) | 单能力;一模型多能力拆成多行 |
79+
| `is_active` | BOOLEAN | 该模型能力是否上架 |
80+
| `created_at` / `updated_at` | DATETIME | 创建 / 更新时间 |
81+
82+
索引:
83+
- `uk_provider_model_cap(provider_id, model_name, capability)`
84+
- `idx_provider_cap(provider_id, capability)`
85+
86+
### `llm_system_preset` — 系统预设模板
87+
88+
ORM:[`SystemPresetDB`](../../src/models/db_models.py)
89+
90+
| 字段 | 类型 | 说明 |
91+
| --- | --- | --- |
92+
| `id` | BIGINT UNSIGNED PK | 主键 |
93+
| `provider_id` | BIGINT UNSIGNED | 关联 `llm_system_provider.id` |
94+
| `model_name` | VARCHAR(128) | 模型名 |
95+
| `capability` | VARCHAR(32) | 能力标识 |
96+
| `api_key` | VARCHAR(512) | 平台 Key,**加密存储** |
97+
| `is_active` | BOOLEAN | 是否对新用户下发 |
98+
| `created_at` / `updated_at` | DATETIME | 创建 / 更新时间 |
99+
100+
索引:`uk_preset_provider_model_cap(provider_id, model_name, capability)`
101+
102+
说明:Python 运行时不直接读取本表决定生效配置;Java 注册时会将 active 预设复制进 `llm_user_config`
103+
71104
### `llm_user_config` — 用户级 LLM 配置
72105

73106
ORM:[`UserLLMConfigDB`](../../src/models/db_models.py)
@@ -77,28 +110,32 @@ ORM:[`UserLLMConfigDB`](../../src/models/db_models.py)
77110
| `id` | BIGINT UNSIGNED PK | 配置唯一标识 |
78111
| `user_id` | BIGINT UNSIGNED | 所属用户 |
79112
| `provider_id` | BIGINT UNSIGNED | 关联 `llm_system_provider.id` |
80-
| `provider_type` | VARCHAR(32) | 厂商类型快照 |
81-
| `provider_name` | VARCHAR(64) | 厂商名快照 |
82-
| `config_name` | VARCHAR(64) | 用户自定义配置名 |
113+
| `provider_type` | VARCHAR(32) | 厂商类型快照,用于下游路由到对应 SDK |
83114
| `api_key` | VARCHAR(512) | **加密存储**,由 `API_KEY_ENCRYPTION_SECRET` 解密 |
84-
| `custom_api_base_url` | VARCHAR(512) | 自定义 API 地址 |
115+
| `api_base_url` | VARCHAR(512) | 实际生效地址 |
85116
| `model_name` | VARCHAR(128) | 具体模型名 |
86-
| `priority` | INT | 优先级 1-100 |
87-
| `is_active` | BOOLEAN | 是否启用 |
88-
| `is_default` | BOOLEAN | 是否默认配置 |
89-
| `timeout_ms` | INT | 超时(毫秒),默认 60000 |
90-
| `max_retries` | INT | 最大重试次数,默认 3 |
91-
| `stream_enabled` | BOOLEAN | 是否支持流式输出 |
92-
| `capability` | VARCHAR(32) | `CHAT` / `EMBEDDING` / `RERANK` / `OCR`,默认 `CHAT` |
93-
| `default_marker` | INT,生成列 | `default+active` 时为 `1`,否则 `NULL`,仅用于唯一约束(应用层不写入) |
94-
| `extra_config` | JSON | 扩展配置 |
117+
| `capability` | VARCHAR(32) | `CHAT` / `EMBEDDING` / `RERANK` / `OCR` / `VISION` 等,默认 `CHAT` |
118+
| `is_active` | BOOLEAN | 模型启停 + 生效过滤 |
119+
| `is_default` | BOOLEAN | 该能力是否生效 |
120+
| `is_system_preset` | BOOLEAN | 是否系统预设行 |
95121
| `created_at` / `updated_at` | DATETIME | 创建 / 更新时间 |
96122

97123
索引:
98-
- `uk_user_provider_model(user_id, provider_id, model_name)`
124+
- `uk_user_provider_model_capability(user_id, provider_id, model_name, capability, is_system_preset)`
99125
- `idx_user_active_default(user_id, is_active, is_default)`
100126
- `idx_user_provider_cap(user_id, provider_type, capability)`
101-
- `uq_user_default_per_capability(user_id, provider_type, capability, default_marker)` — 唯一键。借助生成列 `default_marker`(默认+启用时为 1,否则 NULL)与 MySQL「唯一索引中 NULL 不计重复」语义,保证每个 `(user_id, provider_type, capability)` 至多一条默认且启用的配置;非默认/停用配置不受限(迁移 0012)
127+
128+
运行时读取生效配置:
129+
130+
```sql
131+
SELECT *
132+
FROM llm_user_config
133+
WHERE user_id = :user_id
134+
AND capability = :capability
135+
AND is_default = TRUE
136+
AND is_active = TRUE
137+
LIMIT 1;
138+
```
102139

103140
### `llm_usage_log` — LLM 调用用量日志
104141

docs/ops/configure.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
| --- | --- |
3131
| `DB_HOST` / `DB_PORT` / `DB_USER` / `DB_PASSWORD` / `DB_NAME` | MySQL 连接 |
3232
| `REDIS_HOST` / `REDIS_PORT` | Redis 连接 |
33-
| `API_KEY_ENCRYPTION_SECRET` | API Key 加密 Secret,必须与 Java 管理端一致 |
33+
| `API_KEY_ENCRYPTION_SECRET` | API Key 加密 Secret,必须与 Java 管理端一致;64 位 hex,解码后 32 字节,用于 AES-256-GCM |
3434
| `SYSTEM_LLM_PROVIDER` / `SYSTEM_LLM_API_KEY` / `SYSTEM_LLM_API_BASE` | 系统级兜底 LLM |
3535
| `KAFKA_BOOTSTRAP_SERVERS` 等(若 `MQ_VENDOR=kafka`| Kafka 接入信息 |
3636
| `MINIO_*`(若 `STORAGE_TYPE=minio`| 对象存储凭据 |

docs/ops/deploy.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ uvicorn src.main:app --host 0.0.0.0 --port 8000
5757
常见失败:
5858

5959
- **应用启动卡在 Kafka**:通常是 `KAFKA_BOOTSTRAP_SERVERS` 配置错或 broker 未起来。本地用 docker-compose 时此地址应为 `127.0.0.1:9092`(容器内部连接用 `tolink-kafka:29092`)。
60-
- **API 调用 LLM 报解密失败**`API_KEY_ENCRYPTION_SECRET` 必须与 Java 管理端的加密 Secret 一致,否则 `llm_user_config` 表中的密文无法解密。
60+
- **API 调用 LLM 报解密失败**`API_KEY_ENCRYPTION_SECRET` 必须与 Java 管理端的加密 Secret 一致,格式为 64 位 hex(解码后 32 字节),否则 `llm_user_config` 表中的密文无法解密。
6161
- **解析任务消费不到**:检查 `INIT_KAFKA_TOPICS_ON_STARTUP` 是否被关闭,且 topic(`PARSE_TASK_TOPIC` 默认 `tolink-document-pares`)是否已存在。
6262

6363
## 生产部署注意事项

0 commit comments

Comments
 (0)