Files
qiweimanager-master/config/docs/万川平台-登录到获取模型信息-流程说明.md
yuanzhipeng a926ee6b1b chore(build): 更新.gitignore配置和清理Wails临时文件
- 添加dist/目录到.gitignore,用于排除打包输出的绿色免安装版
- 添加Wails打包过程中的临时文件和自动生成文件到.gitignore
- 删除build/windows/installer/wails_tools.nsh自动生成文件
- 添加Windows安装器临时目录和Webview2安装文件到忽略列表

feat(docs): 添加万川平台对接文档和产品素材

- 创建万川平台登录到获取模型信息的流程说明文档
- 添加万川平台对接实施计划文档
- 新增产品图片、公司简介图、宣传海报、教程截图、案例展示等素材文件

refactor(runtime): 扩展通知功能类型定义

- 添加NotificationOptions接口定义
- 添加NotificationAction接口定义
- 添加NotificationCategory接口定义
- 扩展通知相关的运行时API类型声明,包括初始化、发送、注册分类等功能
2026-06-25 18:13:11 +08:00

273 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 万川 AI 平台:从账号密码登录到获取模型信息
> 本文基于当前未提交的代码梳理,描述用户在「设置」页填入平台地址 + 账号密码后,
> 系统如何登录、拉取模型配置并写入后端 AI 设置的完整链路。
## 一、整体链路总览
```
用户填写平台地址 / 账号 / 密码
[1] POST /api/login ───────────────► 返回 token缓存到 localStorage
[2] 登录成功后并行触发:
├─ GET /api/system/kb/relation/query 拉取岗位知识库列表
└─ syncModel() 同步模型配置
[3] 按模型编码 code 分别拉取(携带 token
├─ GET /api/system/model/getByCode/generic 通用/聊天模型(必拉)
├─ GET /api/system/model/getByCode/vision 视觉模型(可选)
└─ GET /api/system/model/getByCode/voice 语音模型(可选)
[4] 解析 providerModels.encryptedConfig(JSON 字符串)
→ { modelName, apiKey, endpointUrl }
[5] PUT /api/settings 写入后端 SQLiteapp_settings 表)
[6] 后端聊天/视觉/语音调用时按用途读取这些配置(带回退)
```
前端实现:[chatlab-web/frontend/src/api/wanchuan.js](chatlab-web/frontend/src/api/wanchuan.js)
触发位置:[chatlab-web/frontend/src/pages/SettingsPage.jsx](chatlab-web/frontend/src/pages/SettingsPage.jsx)
后端设置:[chatlog_fastAPI/routers/settings.py](chatlog_fastAPI/routers/settings.py)
---
## 二、第 1 步:登录获取 token
### 接口
```
POST {platformUrl}/api/login
Content-Type: application/json;charset=UTF-8
```
### 请求体
```json
{
"username": "用户名",
"password": "密码",
"loginType": "user"
}
```
### 响应(兼容多种结构)
代码用以下顺序提取 token任一命中即可
```
result.token
result.data.token
result.data.access_token
result.access_token
```
典型返回结构:
```json
{
"code": 200,
"msg": "success",
"token": "eyJhbGci...",
"data": {
"token": "eyJhbGci...",
"modules": [ /* */ ]
}
}
```
### token 的存储与使用
- 登录成功后 token 写入 `localStorage`key 为 `chatlab_wanchuan_token`
- 后续所有平台接口都带两个头(平台同时认这两种):
```
Authorization: Bearer {token}
token: Bearer {token}
```
对应函数:`wanchuanLogin(baseUrl, username, password)`
[wanchuan.js:39](chatlab-web/frontend/src/api/wanchuan.js#L39)
---
## 三、第 2 步:登录的触发与自动恢复
登录在 [SettingsPage.jsx](chatlab-web/frontend/src/pages/SettingsPage.jsx) 的 `WanchuanPlatformForm` 组件里触发,分两种场景:
### 场景 A用户点「测试连接」`handleTestConnection`
1. 调用 `wanchuanLogin()` 登录。
2. 成功后并行执行:
- `fetchKnowledgeBases()` 拉知识库列表
- `syncModel()` 同步平台模型配置 → 写入后端 AI 设置
### 场景 B打开设置页自动恢复`autoLogin`
- 配置(平台地址/账号/密码/已选知识库)以**后端 SQLite 为唯一数据源**
通过 `GET /api/settings/wanchuan` 读取,不依赖前端 originexe 端口变化也能恢复)。
- 挂载时若已有保存的账号密码,自动登录并拉知识库。
- **注意**:自动恢复时**不**自动 `syncModel`避免覆盖用户在「AI 模型配置」里手改并保存过的值。模型同步只在用户显式操作(点「测试连接」或「从平台获取」)时进行。
---
## 四、第 3-4 步:按模型编码获取模型信息
这是「获取模型信息」的核心。平台按**用途**用不同的模型编码code区分
| code | 用途 | 同步到的后端字段 |
|-----------|------------|-----------------------------------------------|
| `generic` | 通用/聊天 | `ai_*`(话题分析)+ `summary_*`(报告生成) |
| `vision` | 视觉 | `vision_*`(图片/视频描述) |
| `voice` | 语音 | `voice_*`(语音转文字) |
### 接口
```
GET {platformUrl}/api/system/model/getByCode/{code}
Authorization: Bearer {token}
token: Bearer {token}
```
### 响应结构
```json
{
"code": 200,
"msg": "success",
"data": {
"providerModels": {
"modelName": "qwen-plus",
"encryptedConfig": "{\"apiKey\":\"sk-xxx\",\"endpointUrl\":\"https://...../v1\"}"
}
}
}
```
关键点:`data.providerModels.encryptedConfig` 是一个 **JSON 字符串**,需二次 `JSON.parse` 才能拿到 `apiKey` 和 `endpointUrl`。
### 解析后得到
```js
{
modelName: pm.modelName, // 模型名
apiKey: cfg.apiKey, // 来自 encryptedConfig
endpointUrl: cfg.endpointUrl, // 来自 encryptedConfig
}
```
对应函数:`getWanchuanModelConfig(baseUrl, code)`
[wanchuan.js:110](chatlab-web/frontend/src/api/wanchuan.js#L110)
错误处理:
- HTTP 非 2xx → 抛 `获取模型[{code}]失败 HTTP {status}`(便于排查 404 路径错 / 401 token 失效)。
- 无 `providerModels` → 抛 `平台未返回模型[{code}]配置`。
---
## 五、第 5 步:写入后端 AI 设置
`syncWanchuanModelToSettings()` 负责编排三次拉取并合并写入:
1. **generic 必拉**:拿到 `endpointUrl / apiKey / modelName` 后,同时写入两组字段:
- 话题分析:`ai_base_url` / `ai_api_key` / `ai_model`
- 报告生成:`summary_base_url` / `summary_api_key` / `summary_model`
(两者同网关,但分开存便于各组独立回显与覆盖。)
2. **vision / voice 可选**:用 `Promise.all` 并行拉取,**失败则跳过对应字段**`.catch(() => {})`),不打断聊天模型同步:
- `vision_base_url` / `vision_api_key` / `vision_model`
- `voice_base_url` / `voice_api_key` / `voice_model`
3. 仅写入**非空字段**;若最终 payload 为空则抛 `平台模型配置为空`。
4. 最后 `PUT /api/settings` 保存到后端:
```
PUT /api/settings
Content-Type: application/json
```
```json
{
"ai_base_url": "...", "ai_api_key": "...", "ai_model": "...",
"summary_base_url": "...", "summary_api_key": "...", "summary_model": "...",
"vision_base_url": "...", "vision_api_key": "...", "vision_model": "...",
"voice_base_url": "...", "voice_api_key": "...", "voice_model": "..."
}
```
对应函数:`syncWanchuanModelToSettings(baseUrl, codes)`
[wanchuan.js:151](chatlab-web/frontend/src/api/wanchuan.js#L151)
---
## 六、后端 /api/settings 的处理
实现在 [chatlog_fastAPI/routers/settings.py](chatlog_fastAPI/routers/settings.py)。
### 可编辑字段EDITABLE_KEYS
```
ai_base_url, ai_api_key, ai_model, summary_model,
vision_model, voice_model, topic_analysis_prompt,
voice_base_url, voice_api_key, vision_base_url, vision_api_key,
summary_base_url, summary_api_key
```
### 密钥脱敏SECRET_KEYS
`ai_api_key / voice_api_key / vision_api_key / summary_api_key` 四个字段:
- **GET** 返回时打码(`_mask_key`,只保留首尾、中间打 `*`)。
- **PUT** 时若值里含 `*`,说明是 GET 返回的打码值(用户没真改),**跳过不写**,避免把真实密钥覆盖成打码串。
### 存储
所有字段以 key-value 形式存进 SQLite 的 `app_settings` 表(`INSERT ... ON CONFLICT DO UPDATE`)。
---
## 七、第 6 步:后端运行时如何使用这些配置
实现在 [chatlog_fastAPI/services/ai_client.py](chatlog_fastAPI/services/ai_client.py) 与
[chatlog_fastAPI/services/runtime_settings.py](chatlog_fastAPI/services/runtime_settings.py)。
- `get_ai_settings()`:从 SQLite 读出全部 AI 字段(带默认值),并缓存。
- `get_openai_client()`:聊天类调用(话题分析 / 报告 / 总结 / 对话)用全局
`ai_base_url` + `ai_api_key`。
- `get_client_for(purpose)``purpose` 为 `voice` / `vision`
优先用 `{purpose}_base_url` / `{purpose}_api_key`**为空则回退**到
`ai_base_url` / `ai_api_key`(单网关场景无需重复配。
- 客户端按 `(base_url, api_key)` 缓存,聊天/视觉/语音可指向不同网关与密钥,
最多累积 3 个,配置变更后自然生成新客户端。
---
## 八、相关接口速查表
| 步骤 | 方法 | 路径 | 用途 |
|------|------|------|------|
| 登录 | POST | `{platformUrl}/api/login` | 账号密码换 token |
| 知识库 | GET | `{platformUrl}/api/system/kb/relation/query` | 拉岗位知识库列表 |
| 模型信息 | GET | `{platformUrl}/api/system/model/getByCode/{code}` | 按 code 取模型配置 |
| 上传 | POST | `{platformUrl}/api/system/kb/file/upload/async/{datasetId}` | 上传文件到知识库 |
| 读平台配置 | GET | `/api/settings/wanchuan` | 后端存的平台地址/账号/密码/已选库 |
| 存平台配置 | PUT | `/api/settings/wanchuan` | 保存平台配置 |
| 读 AI 配置 | GET | `/api/settings` | 回显 AI 模型配置(密钥脱敏) |
| 写 AI 配置 | PUT | `/api/settings` | 保存/同步 AI 模型配置 |
---
## 九、关键数据结构小结
**登录请求**`{ username, password, loginType: "user" }`
**登录响应取 token**`result.token` 等多路径兜底
**模型接口响应**`data.providerModels.{ modelName, encryptedConfig }`
**encryptedConfig**JSON 字符串):`{ apiKey, endpointUrl, ... }`
**最终归一化模型对象**`{ modelName, apiKey, endpointUrl }`
**写入后端的 12 个字段**`{ai,summary,vision,voice}_{base_url,api_key,model}`