自动更新多个 LLM Provider 的免费模型列表,生成统一的 providers.json 配置文件。
| Provider | 数据来源 | 连通性测试 | 说明 |
|---|---|---|---|
| OpenRouter | API (/models) |
有 API Key 时测试 | 获取所有 :free 后缀的免费模型 |
| ZAI (智谱) | 文档解析 (llms.txt) |
有 API Key 时测试 | 从智谱文档站提取免费模型列表 |
| ModelScope (魔搭) | 网页爬取 (Playwright) | 有 API Key 时串行测试 | 爬取文本生成和多模态模型各前10个 |
当 .env 中配置了对应 Provider 的 API Key 时,程序会在获取模型列表后逐个测试模型是否可以正常响应:
- ModelScope:必须配置
MODELSCOPE_API_KEY,对爬取到的模型逐个发送聊天请求,仅保留可以正常响应的模型 - OpenRouter:配置
OPENROUTER_API_KEY时测试,未配置时跳过测试直接保存 - ZAI:配置
ZAI_API_KEY时测试,未配置时跳过测试直接保存
测试逻辑:
- 发送
hi消息到/chat/completions,max_tokens=1 - HTTP 200 视为通过
- HTTP 401/403 视为端点可用(认证问题)
- 超时视为模型可用(模型响应慢但不代表不可用)
- HTTP 404 视为不可用(模型不存在)
pip install -r requirements.txt
playwright install chromium复制 .env.example 为 .env 并填入密钥:
cp .env.example .env.env 文件内容:
OPENROUTER_API_KEY=sk-xxx # OpenRouter API 密钥(可选,无密钥也能获取模型列表)
ZAI_API_KEY=xxx.xxx # 智谱 API 密钥(可选,有密钥时会测试模型连通性)
MODELSCOPE_API_KEY=ms-xxx # ModelScope API 密钥(必须,用于测试模型连通性)
# 单次运行
python main.py
# 定时运行(默认每60分钟)
python main.py --schedule
# 定时运行(每30分钟)
python main.py --schedule 30freerouter-providers/
├── main.py # 主程序入口
├── config/
│ └── providers.json # 输出配置文件
├── providers/
│ ├── __init__.py # 自动发现与注册 Provider
│ ├── base.py # 抽象基类(Model, ProviderConfig, BaseProvider)
│ ├── openrouter.py # OpenRouter Provider
│ ├── zai.py # ZAI (智谱) Provider
│ └── modelscope.py # ModelScope Provider
├── utils/
│ ├── __init__.py
│ └── logger.py # 日志配置
├── .env # API 密钥(不纳入版本控制)
├── .env.example # 密钥模板
└── requirements.txt # Python 依赖
config/providers.json 示例:
{
"providers": [
{
"name": "OpenRouter",
"base_url": "https://openrouter.ai/api/v1",
"models": [
{ "id": "google/gemma-3-27b-it:free", "name": "Google: Gemma 3 27B (free)" },
{ "id": "meta-llama/llama-3.3-70b-instruct:free", "name": "Meta: Llama 3.3 70B Instruct (free)" }
],
"updated_at": "2026-04-12T08:10:19Z",
"status": "success"
},
{
"name": "ZAI",
"base_url": "https://open.bigmodel.cn/api/paas/v4",
"models": [
{ "id": "glm-4.7-flash", "name": "GLM 4.7 Flash" },
{ "id": "glm-4v-flash", "name": "GLM 4v Flash" }
],
"updated_at": "2026-04-12T08:10:18Z",
"status": "success"
},
{
"name": "ModelScope",
"base_url": "https://api-inference.modelscope.cn/v1/",
"models": [
{ "id": "Qwen/Qwen3-8B", "name": "Qwen/Qwen3-8B" },
{ "id": "ZhipuAI/GLM-5", "name": "ZhipuAI/GLM-5" }
],
"updated_at": "2026-04-12T08:10:36Z",
"status": "success"
}
]
}- 单个 Provider 更新失败时,保留旧的模型数据,
status设为"failed",并记录error信息 - 并行执行各 Provider 更新,互不影响
- 详细的日志输出,包含每个 Provider 的更新状态和连通性测试结果
- 在
providers/目录下创建新文件,继承BaseProvider:
from providers.base import BaseProvider, Model
class MyProvider(BaseProvider):
name = "MyProvider"
base_url = "https://api.example.com/v1"
def __init__(self, api_key: str | None = None):
self.api_key = api_key
async def fetch_free_models(self) -> list[Model]:
# 实现获取免费模型的逻辑
return [Model(id="model-id", name="Model Name")]
@property
def should_test_connectivity(self) -> bool:
return bool(self.api_key)-
无需修改其他文件,
providers/__init__.py会自动发现并注册新 Provider。 -
在
config/providers.json中添加对应的初始配置:
{ "name": "MyProvider", "base_url": "https://api.example.com/v1", "models": [] }- 在
.env中添加对应的 API Key(如需连通性测试)。