Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/chat-ai.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

### AI 服务预设

「新增服务」提供 14 项预设:DeepSeek、Claude、Kimi、OpenAI、Google Gemini、通义千问(阿里云百炼)、智谱 GLM、豆包(火山方舟)、硅基流动、OpenRouter、Groq、Ollama、LM Studio 和自定义。可以按名称或别名搜索,例如「谷歌」「千问」「GLM」「火山」;自定义入口排在列表末尾。
「新增服务」提供 15 项预设:DeepSeek、Claude、Kimi、OpenAI、Google Gemini、通义千问(阿里云百炼)、智谱 GLM、豆包(火山方舟)、硅基流动、OpenRouter、Requesty、Groq、Ollama、LM Studio 和自定义。可以按名称或别名搜索,例如「谷歌」「千问」「GLM」「火山」;自定义入口排在列表末尾。

预设会填写配置名称、API 地址和协议,地址仍可修改。国内平台默认使用国内通用 API 地址,不是 Coding Plan 专用入口。Gemini 使用 `/v1beta/openai` 兼容接口。切换预设会清空密钥、模型选择和图片能力,需要重新确认;不会复用原服务的密钥。

Expand Down
1 change: 1 addition & 0 deletions frontend/components/AiSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ const providerPresentation = {
doubao: { label: '豆包', caption: '火山方舟', hint: '火山方舟 · 国内通用接口', aliases: '字节 火山引擎 Volcengine Ark' },
siliconflow: { caption: 'SiliconCloud', hint: '硅基流动 · 国内模型服务', aliases: 'SiliconCloud' },
openrouter: { caption: '多模型聚合服务', hint: '聚合多个服务商的模型', aliases: '' },
requesty: { caption: '多模型聚合服务', hint: '聚合多个服务商的模型', aliases: '' },
groq: { hint: 'Groq 官方兼容接口', aliases: '' },
ollama: { caption: '本地模型服务', hint: '本地模型 · 默认端口 11434', aliases: '本机 local' },
lmstudio: { caption: '本地模型服务', hint: '本地模型 · 默认端口 1234', aliases: '本机 local' },
Expand Down
1 change: 1 addition & 0 deletions src/wechat_decrypt_tool/ai/providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def analysis_messages(prompt, schema=None, images=None):
{"provider": "doubao", "name": "豆包(火山方舟)", "base_url": "https://ark.cn-beijing.volces.com/api/v3", "protocol": "openai"},
{"provider": "siliconflow", "name": "硅基流动", "base_url": "https://api.siliconflow.cn/v1", "protocol": "openai"},
{"provider": "openrouter", "name": "OpenRouter", "base_url": "https://openrouter.ai/api/v1", "protocol": "openai"},
{"provider": "requesty", "name": "Requesty", "base_url": "https://router.requesty.ai/v1", "protocol": "openai"},
{"provider": "groq", "name": "Groq", "base_url": "https://api.groq.com/openai/v1", "protocol": "openai"},
{"provider": "ollama", "name": "Ollama", "base_url": "http://127.0.0.1:11434/v1", "protocol": "openai"},
{"provider": "lmstudio", "name": "LM Studio", "base_url": "http://127.0.0.1:1234/v1", "protocol": "openai"},
Expand Down
2 changes: 1 addition & 1 deletion src/wechat_decrypt_tool/ai/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class ProviderInput(BaseModel):
name: str = Field(min_length=1, max_length=80)
provider: Literal[
"deepseek", "xiaomi", "claude", "kimi", "openai", "gemini", "qwen", "zhipu",
"doubao", "siliconflow", "openrouter", "groq", "ollama", "lmstudio", "custom",
"doubao", "siliconflow", "openrouter", "requesty", "groq", "ollama", "lmstudio", "custom",
] = "deepseek"
protocol: Literal["openai", "anthropic"] = "openai"
base_url: str = Field(min_length=1, max_length=2048)
Expand Down
6 changes: 3 additions & 3 deletions tests/test_ai_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ def test_all_presets_can_be_created_read_and_edited(tmp_path):
async def run():
async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app, client=("127.0.0.1", 1)), base_url="http://localhost") as client:
presets = (await client.get("/api/ai/settings")).json()["presets"]
assert len(presets) == 15
assert {p["provider"] for p in presets} == {"deepseek", "xiaomi", "claude", "kimi", "custom", "openai", "gemini", "qwen", "zhipu", "doubao", "siliconflow", "openrouter", "groq", "ollama", "lmstudio"}
assert len(presets) == 16
assert {p["provider"] for p in presets} == {"deepseek", "xiaomi", "claude", "kimi", "custom", "openai", "gemini", "qwen", "zhipu", "doubao", "siliconflow", "openrouter", "requesty", "groq", "ollama", "lmstudio"}
assert presets[-1]["provider"] == "custom"
for preset in presets:
assert "model" not in preset
Expand All @@ -35,7 +35,7 @@ async def run():
settings = await client.get("/api/ai/settings")
assert "private-key" not in settings.text
profiles = settings.json()["profiles"]
assert len(profiles) == 15
assert len(profiles) == 16
assert all(p["name"] == "已编辑" and p["model"] == "another-model" for p in profiles)
assert {p["provider"] for p in profiles} == {p["provider"] for p in presets}
assert (await client.post("/api/ai/profiles", json={**presets[0], "provider": "unknown", "model": "test"})).status_code == 422
Expand Down