本项目 UI 中的文本滚动动效由 Smart Ticker 提供支持。
| 特性 | 描述 |
|---|---|
| 🤖 20+ 厂商 | OpenAI, Claude, Gemini, DeepSeek... 可自定义扩展 |
| ⚡ 智能模型发现 | 自动获取厂商最新模型列表,无需手动维护 |
| 📡 连接诊断 | 一键测试 API 连通性与延迟 |
| � AES 加密存储 | API Key 加密保存到 localStorage,非明文 |
| 🎨 开箱即用 UI | Tailwind CSS 设计系统,深色模式,中英双语 |
| 🔌 React + Vue | 双框架适配器,核心逻辑共享 |
| 🧩 Headless 模式 | 只用 useAIConfig Hook,完全自定义 UI |
| 🔄 零后端可选 | 支持前端直连 / 后端代理 / 自定义 fetcher |
💡 支持通过
config.custom添加自定义增删改厂商
| 参数名 | 类型 | 可选 | 默认值 | 描述 |
|---|---|---|---|---|
proxyUrl |
string |
✅ | - | 代理地址,留空则使用直连模式 |
title |
string |
✅ | - | 表单标题 |
language |
'zh' | 'en' |
✅ | 'zh' |
界面语言 |
showPreview |
boolean |
✅ | false |
显示配置预览 |
disabled |
boolean |
✅ | false |
禁用表单 |
| 参数名 | 类型 | 可选 | 描述 |
|---|---|---|---|
config |
ProviderConfig |
✅ | 厂商过滤与自定义 |
initialConfig |
Partial<AIConfig> |
✅ | 初始配置 |
modelFetcher |
ModelFetcher |
✅ | 自定义请求处理器 |
| 事件名 | 类型 | 可选 | 描述 |
|---|---|---|---|
onSave |
(config) => void |
✅ | 保存时触发 |
onChange |
(config) => void |
✅ | 配置变化时触发 |
onTestResult |
(result) => void |
✅ | 测试完成时触发 |
// React
import { AIConfigForm } from '@tombcato/ai-selector-react';
import '@tombcato/ai-selector-react/style.css'; // ⚠️ 务必引入样式
// Vue
import { AIConfigForm } from '@tombcato/ai-selector-vue';
import '@tombcato/ai-selector-vue/style.css'; // ⚠️ 务必引入样式
<AIConfigForm
proxyUrl="" // 空字符串表示直连模式,或填入后端代理地址
showPreview // 是否显示配置预览 JSON
language="zh" // 界面语言 'zh' | 'en'
title="AI Configuration" // 自定义卡片标题
/>通过 config 属性,你可以过滤显示的厂商、修改现有配置或添加全新的自定义厂商。
// 示例配置
const providerConfig: ProviderConfig = {
mode: 'default', // 可选值: 'default' | 'customOnly'
// custom: customProviders as Record<string, CustomProviderDefinition>, //导入自定义provider
// ========================================================================
// 场景 1: 只显示指定的 Provider (白名单过滤)
// ========================================================================
include: ['openai', 'anthropic'],
exclude: ['gemini'], // 或者使用黑名单过滤
// ========================================================================
// 场景 2: 覆盖/添加自定义 Provider
// ========================================================================
custom: {
// 覆盖内置配置
openai: {
name: 'Enterprise OpenAI',
baseUrl: 'https://gateway.company.com/openai/v1',
apiFormat: 'openai',
needsApiKey: true,
models: [{ id: 'gpt-4o', name: 'GPT-4o' }]
},
// 添加新厂商
deepseeksssss: {
name: 'DeepSeekssssss',
baseUrl: 'https://api.deepseek.com',
apiFormat: 'openai',
needsApiKey: true,
icon: 'https://avatars.githubusercontent.com/u/148330874',
models: [{ id: 'deepseek-chat', name: 'DeepSeek Chat' }]
}
},
// ========================================================================
// 场景 3: 仅显示自定义 Provider
// ========================================================================
mode: 'customOnly',
custom: {
'my-private-model': {
name: 'Internal AI',
baseUrl: 'http://localhost:8080/v1',
apiFormat: 'openai',
needsApiKey: false,
icon: 'https://placehold.co/32x32?text=INT',
models: [
{ id: 'llama-3-8b', name: 'Llama 3 8B' },
{ id: 'mistral-7b', name: 'Mistral 7B' }
]
}
}
}
<AIConfigForm
config={providerConfig}
// ...其他参数
/>前端直接请求 AI 厂商 API,无需任何后端服务。
浏览器 ────────────► AI 厂商 API
- ✅ 零配置,开箱即用
- ✅ 无需部署后端
⚠️ API Key 会暴露在浏览器 Network 中⚠️ 部分厂商可能不支持浏览器跨域请求,导致接口失败
import ...
<AIConfigForm
proxyUrl="" //不设置代理
/>通过后端代理转发请求,推荐生产环境使用。
浏览器 ───► 后端代理 ───► AI 厂商 API
- ✅ 隐藏 API Key
- ✅ 绕过 CORS 限制
- ✅ 前后端架构分离
- 📦 需要部署
backend/server.py,或把相关逻辑集成到你自己的后端服务中,server.py实现三个api:/test /models /chat
import ...
<AIConfigForm
proxyUrl="后端代理地址" //backend server.py本地代理为http://localhost:8000
/>推荐使用代理的场景:
- 生产环境部署
- 需要隐藏 API Key
- 遇到 CORS 错误
完全自定义请求逻辑,由开发者接管所有 API 调用。
import ...
<AIConfigForm
proxyUrl="" //不设置代理
modelFetcher={async (params) => {
// 自定义实现模型列表获取、连接测试等
if (params.type === 'fetchModels') {
return await yourCustomFetch(params);
}
}}
/>- ✅ 完全控制请求逻辑
- ✅ 可对接任意后端架构
- 💻 需要开发者实现
npm install @tombcato/ai-selector-core
# Optional: Framework Adapters
npm install @tombcato/ai-selector-react
npm install @tombcato/ai-selector-vuegit clone https://github.com/tombcato/ai-selector.git
cd ai-selector
npm install# React Demo
npm run dev -w packages/react
# Vue Demo
npm run dev -w packages/vue打开 http://localhost:5173 即可体验(默认直连模式)。
# 1. 启动后端
cd backend
pip install -r requirements.txt
python server.py
# 2. 配置代理地址
# 创建 packages/react/.env.local 文件:
VITE_PROXY_URL=http://localhost:8000💡 无需重启前端,Vite 会自动加载
.env.local中的环境变量。
如果你不需要内置 UI,只想使用配置逻辑,可以直接使用 useAIConfig Hook:
import { useAIConfig } from '@tombcato/ai-selector-react';
function MyCustomUI() {
const {
// 状态
providerId, // 当前选中的 Provider ID
apiKey, // API Key
model, // 当前选中的 Model ID
modelName, // Model 显示名称
baseUrl, // 自定义 Base URL
models, // 可用模型列表
provider, // 当前 Provider 对象
providers, // 所有可用 Providers
isValid, // 配置是否完整有效
testStatus, // 测试状态: 'idle' | 'testing' | 'success' | 'error'
testResult, // 测试结果对象
isFetchingModels, // 是否正在获取模型列表
fetchModelError, // 获取模型错误信息
config, // 完整配置对象
// 方法
setProviderId, // 设置 Provider
setApiKey, // 设置 API Key
selectModel, // 选择 Model (id, name)
setBaseUrl, // 设置 Base URL
runTest, // 执行连接测试
save, // 保存配置到 Storage
} = useAIConfig({
proxyUrl: '', // 可选:代理地址
providerConfig: {}, // 可选:Provider 配置
initialConfig: {}, // 可选:初始配置
onSerialize: (data) => data, // 可选:序列化钩子
onDeserialize: (data) => data, // 可选:反序列化钩子
modelFetcher: async () => [], // 可选:自定义模型获取
});
// 使用这些状态和方法构建你自己的 UI
return (
<div>
<select value={providerId} onChange={e => setProviderId(e.target.value)}>
{providers.map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
</select>
{/* ... 你的自定义 UI */}
</div>
);
}<script setup lang="ts">
import { useAIConfig } from '@tombcato/ai-selector-vue';
const {
providerId, apiKey, model, models, providers, isValid,
setProviderId, setApiKey, selectModel, runTest, save
} = useAIConfig({ proxyUrl: '' });
</script>
<template>
<!-- 你的自定义 UI -->
</template>配置默认使用 AES 加密存储到 localStorage,防止 API Key 明文泄露。
import {
createConfigStorage,
encryptedStorageAdapter, // 默认,AES 加密
plainStorageAdapter // 明文(不推荐)
} from '@tombcato/ai-selector-core';
// 默认使用加密
const storage = createConfigStorage();
// 使用明文(不推荐)
const plainStorage = createConfigStorage(plainStorageAdapter);
// 自定义序列化
const customStorage = createConfigStorage(encryptedStorageAdapter, {
serialize: (data) => JSON.stringify(data),
deserialize: (data) => JSON.parse(data),
});
⚠️ 加密密钥默认为'aiselector',适合防止普通用户直接查看,不适用于高安全场景。
ai-provider-selector/
├── packages/
│ ├── core/ # 核心逻辑 (框架无关)
│ ├── react/ # React 适配器
│ └── vue/ # Vue 适配器
├── backend/ # Python 代理服务
│ ├── server.py
│ └── strategies.py
├── index.html # Landing Page
└── logo.svg
MIT License © 2026 AI Selector