145 lines
7.0 KiB
Markdown
145 lines
7.0 KiB
Markdown
# 07 · LLM 对话
|
||
|
||
本节讲怎么接 LLM、两条协议(OpenAI 兼容 / Anthropic)的差别、常见错误码、长什么样。
|
||
|
||
## 1. 配置文件在哪里
|
||
|
||
存在 `~/.live2D/live2d.conf.json` 里,但**改完必须重启**(见 §5.1)。
|
||
|
||
```jsonc
|
||
{
|
||
"llm_provider": "openai", // "openai" 或 "anthropic"
|
||
"llm_model": "gpt-4o-mini",
|
||
"llm_api_key": "sk-...",
|
||
"llm_base_url": "https://api.openai.com"
|
||
}
|
||
```
|
||
|
||
**修改入口**:桌宠 → 工具栏 ⚙ → 配置中心 → 「🤖 LLM 对话设置」区。
|
||
|
||
## 2. 两条协议对照
|
||
|
||
| 项 | OpenAI 兼容 | Anthropic |
|
||
|---|---|---|
|
||
| **端点** | `POST {base_url}/v1/chat/completions` | `POST {base_url}/v1/messages` |
|
||
| **鉴权 Header** | `Authorization: Bearer <key>` | `x-api-key: <key>` + `anthropic-version: 2023-06-01` |
|
||
| **system 消息位置** | `messages: [{role:"system", content:...}]` | 提到顶层 `system: "..."` 字段 |
|
||
| **messages[0] 限制** | 无 | 必须是 `user`(后端有兜底,强制补一条) |
|
||
| **max_tokens** | 可选(默认 1024) | **必填**(默认 1024) |
|
||
| **响应** | `choices[0].message.content` | `content[*].text`(按 type 过滤) |
|
||
| **多模态** | `content: [{type:"text"}, {type:"image_url", image_url:{url:"data:..."}}]` | `content: [{type:"text"}, {type:"image", source:{type:"base64", media_type, data}}]` |
|
||
| **请求超时** | 180 秒 | 180 秒 |
|
||
| **代理** | `no_proxy()`(不走 HTTP_PROXY) | `no_proxy()`(不走 HTTP_PROXY) |
|
||
|
||
> 💡 **OpenAI 兼容** = 任何实现同一协议的服务:OpenAI 官方、Azure OpenAI、OpenRouter、DeepSeek、Moonshot、智谱 GLM(兼容端点)、自部署 vLLM / Ollama(`/v1` 端点)、LM Studio 等。
|
||
|
||
## 3. 常用 Base URL + Model 速查
|
||
|
||
| 服务 | Provider 选项 | Base URL | 常用 Model |
|
||
|---|---|---|---|
|
||
| OpenAI 官方 | `openai` | `https://api.openai.com` | `gpt-4o-mini`, `gpt-4o`, `o1-mini` |
|
||
| Anthropic Claude | `anthropic` | `https://api.anthropic.com` | `claude-3-5-sonnet-20241022`, `claude-3-5-haiku-20241022` |
|
||
| DeepSeek | `openai` | `https://api.deepseek.com/v1` | `deepseek-chat` |
|
||
| Moonshot | `openai` | `https://api.moonshot.cn/v1` | `moonshot-v1-8k`, `moonshot-v1-32k` |
|
||
| 智谱 GLM | `openai` | `https://open.bigmodel.cn/api/paas/v4` | `glm-4-flash`, `glm-4` |
|
||
| Ollama(本地) | `openai` | `http://localhost:11434/v1` | 任何已 pull 的模型 |
|
||
| LM Studio(本地) | `openai` | `http://localhost:1234/v1` | 加载的模型 |
|
||
| 自部署 vLLM | `openai` | 你的 URL | 部署时定的名字 |
|
||
|
||
> ⚠️ **如果你在走代理(clash-verge / sing-box 等),且 LLM 端点是内网 / Tailscale IP**,注意 `no_proxy()` 已在代码里强制加上,但**你自己的系统环境变量**如果有错可能让请求出问题。详细见 [09-常见问题FAQ.md](09-常见问题FAQ.md)。
|
||
|
||
## 4. 错误码
|
||
|
||
LLM 返回非 2xx 时,会在气泡里显示一条 `system` 错误,格式:`[<状态码>] <友好前缀>: <API 原始消息>`。
|
||
|
||
### 4.1 OpenAI 兼容
|
||
| 状态码 | 含义 |
|
||
|---|---|
|
||
| 401 | API key 无效或未授权 |
|
||
| 403 | API key 权限不足 |
|
||
| 404 | API 端点或模型不存在(检查 base_url 和 model 名) |
|
||
| 429 | 请求频率超限或余额不足 |
|
||
| 5xx | API 服务异常 |
|
||
| 60s | "请求超时"(注意:实际超时是 180s,错误文案是历史遗留) |
|
||
| connect | "无法连接到 API 服务" |
|
||
|
||
### 4.2 Anthropic
|
||
| 状态码 | 含义 |
|
||
|---|---|
|
||
| 401 | API key 无效或未授权 |
|
||
| 403 | API key 权限不足 |
|
||
| 404 | 模型不存在 |
|
||
| 429 | 请求频率超限 |
|
||
| 529 | 服务过载(Overloaded) |
|
||
| 5xx | 服务异常 |
|
||
|
||
## 5. 关键限制
|
||
|
||
### 5.1 改完配置必须重启 ⚠️
|
||
|
||
LLM 客户端(`OpenAiProvider` / `AnthropicProvider`)在 `main()` 里**一次性创建**:
|
||
```rust
|
||
let llm_provider: Arc<dyn LLMProvider> = match provider_kind.as_str() {
|
||
"anthropic" => Arc::new(AnthropicProvider::new(...)),
|
||
_ => Arc::new(OpenAiProvider::new(...)),
|
||
};
|
||
```
|
||
|
||
这个 `Arc` 整个进程生命周期里都是同一个对象。`get_llm_status` 读到的是**磁盘最新配置**,但实际请求的还是启动时的 provider。
|
||
|
||
**所以**:
|
||
- 改了 provider / model / api_key / base_url **任何一项** → 重启软件
|
||
- 在配置中心保存时按钮会变绿显示「✅ 已保存」,但**状态点变色**和**实际能用**是**两回事**
|
||
|
||
### 5.2 流式输出不支持 ❌
|
||
当前是**整段返回**:等 LLM 全推完才一次性显示。
|
||
- 小模型(< 3B)体验还行
|
||
- 大模型(7B+、Claude Sonnet 等)会有一段"静默"等待期
|
||
- 输入框会一直 disabled,底部出现"桌宠正在思考…"
|
||
|
||
### 5.3 max_tokens 硬编码 = 1024
|
||
对话回复超过 1024 token 会被截断。**当前版本没有 UI 让你改这个**。
|
||
|
||
### 5.4 多模态(图片)支持
|
||
- **支持**:发截图给 LLM 看 → 见 [04-桌宠窗口使用.md §4](04-桌宠窗口使用.md)
|
||
- **JPEG 预览优先**(不是 PNG 原图,节省 10× 体积)
|
||
- **只支持 image_url 形式**(OpenAI)/ **image base64 形式**(Anthropic),不支持音频/视频
|
||
|
||
### 5.5 思考块(DeepSeek / QwQ / o1)
|
||
LLM 回复里含 `<think>...</think>` 时**自动折叠**为可点开的小标签。详细见 [05-聊天功能.md §3.2](05-聊天功能.md)。
|
||
|
||
### 5.6 动作标签(`[MOTION: xxx]`)
|
||
**当前版本不再注入**动作标签指令进 system prompt。
|
||
- 历史:2026-06-12 曾经让 LLM 在回复末尾附 `[MOTION: idle]` 等
|
||
- 当前:脑里不再加这个 prompt,LLM 不会主动回动作标签
|
||
- 情绪仍然通过**事件注入**(interact / praise 等)驱动模型动作
|
||
|
||
### 5.7 RAG 记忆的真相
|
||
- 架构上**有** RAG(SQLite + 向量索引)
|
||
- 实际 **embedder 是 `DummyEmbedder`**(基于 hash 的伪 384 维向量)— **不是真实语义嵌入**
|
||
- 所以"长期记忆"功能**当前没意义**:检索结果随机性强,不实用
|
||
- 状态:架构已就位,等接入真实 embedder 才能用
|
||
|
||
> 💡 如果你接的是 OpenAI 兼容服务,**可以让你的 LLM 端点自带 embedding 能力**(如支持 `/v1/embeddings`),把 `dummy` 换成真实调用即可——但这是改源码的事,本手册不展开。
|
||
|
||
### 5.8 base_url 末尾 `/v1` 处理
|
||
- OpenAI 兼容:自动剥末尾的 `/` 和 `/v1`,请求时统一拼 `{base}/v1/chat/completions`
|
||
- Anthropic:只剥末尾 `/`
|
||
- 举例:填 `https://api.deepseek.com/v1` 和 `https://api.deepseek.com` 都对
|
||
|
||
## 6. 多模态请求超时 = 180 秒
|
||
|
||
- 普通对话:理论几秒-几十秒
|
||
- 多模态(截图)请求:图片 base64 上传 + 视觉编码 + 文本生成,**实测 30-90 秒很常见**
|
||
- 如果 LLM 端点很慢,可以把图片压得更小([04-桌宠窗口使用.md §4.3](04-桌宠窗口使用.md)),但不能改超时
|
||
|
||
## 7. 自部署网关的兼容性提示
|
||
|
||
某些自部署 OpenAI 兼容网关**严格校验 `detail` 字段**。代码**已主动不传** `detail` 字段(默认行为是 OpenAI 官方默认 `auto`),所以兼容性好。
|
||
|
||
如果你的网关还报 `invalid image detail: auto (2013)`,**前端清缓存**(关掉重开),确认版本是 **2026-06-14 之后**。
|
||
|
||
---
|
||
|
||
下一步:[08-数据存储与备份.md](08-数据存储与备份.md)。
|