From 82100cdf008ea7602c914849cf57872ed1e62810 Mon Sep 17 00:00:00 2001 From: hubian <908234780@qq.com> Date: Wed, 8 Apr 2026 18:14:09 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=90=8E=E5=8F=B0=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=8F=90=E4=BE=9B=E5=95=86=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增:添加新的大模型接口提供商 - 新增:编辑已有提供商的参数(API地址、Key、模型列表等) - 新增:删除提供商 - 新增:拖拽排序调整auto模式的优先级顺序 - 新增:启用/禁用提供商开关 - 优化:主服务动态读取配置,后台修改实时生效 --- admin/app.py | 247 +++++++++++++++---- admin/templates/providers.html | 427 ++++++++++++++++++++++++++++++--- app.py | 95 +++++--- config/settings.py | 139 +++++++++-- data/config.json | 35 +++ 5 files changed, 819 insertions(+), 124 deletions(-) create mode 100644 data/config.json diff --git a/admin/app.py b/admin/app.py index 014d096..d3ce915 100644 --- a/admin/app.py +++ b/admin/app.py @@ -1,20 +1,27 @@ """ 大模型API中转系统 - 后台管理系统 +支持动态添加、编辑、删除提供商和优先级调整 """ from flask import Flask, render_template, jsonify, request from flask_cors import CORS import json import time +import uuid from datetime import datetime from pathlib import Path import sys +import requests # 添加父目录到路径 sys.path.insert(0, str(Path(__file__).parent.parent)) from config.settings import ( - UPSTREAM_PROVIDERS, MODEL_ALIASES, SERVER_CONFIG, - LOG_CONFIG, RETRY_CONFIG + DEFAULT_PROVIDERS, DEFAULT_MODEL_ALIASES, + SERVER_CONFIG, LOG_CONFIG, RETRY_CONFIG, + load_config, save_config, get_providers, + get_provider, add_provider, update_provider, + delete_provider, update_priority, get_model_aliases, + update_model_alias ) app = Flask(__name__) @@ -24,20 +31,26 @@ CORS(app) DATA_DIR = Path(__file__).parent.parent / 'data' DATA_DIR.mkdir(exist_ok=True) STATS_FILE = DATA_DIR / 'stats.json' +CONFIG_FILE = DATA_DIR / 'config.json' LOGS_DIR = Path(__file__).parent.parent / 'logs' -# 提供商状态(从主程序同步) +# 提供商状态缓存 provider_status = {} -for provider in UPSTREAM_PROVIDERS: - provider_status[provider['name']] = { - 'available': True, - 'last_check': None, - 'error_count': 0, - 'last_error': None, - 'request_count': 0, - 'success_count': 0, - 'total_tokens': 0, - } + +def refresh_provider_status(): + """刷新提供商状态""" + providers = get_providers() + for provider in providers: + if provider['name'] not in provider_status: + provider_status[provider['name']] = { + 'available': True, + 'last_check': None, + 'error_count': 0, + 'last_error': None, + 'request_count': 0, + 'success_count': 0, + 'total_tokens': 0, + } def load_stats(): """加载统计数据""" @@ -86,40 +99,43 @@ def config_page(): def api_stats(): """获取统计数据""" stats = load_stats() + providers = get_providers() + refresh_provider_status() # 统计提供商状态 - available_count = sum(1 for p in UPSTREAM_PROVIDERS if provider_status.get(p['name'], {}).get('available', True)) - - # 今日请求 - today = datetime.now().strftime('%Y-%m-%d') + available_count = sum(1 for p in providers if provider_status.get(p['name'], {}).get('available', True)) return jsonify({ 'total_requests': stats.get('total_requests', 0), 'total_success': stats.get('total_success', 0), 'total_errors': stats.get('total_errors', 0), 'total_tokens': stats.get('total_tokens', 0), - 'providers_count': len(UPSTREAM_PROVIDERS), + 'providers_count': len(providers), 'available_providers': available_count, - 'models_count': len(MODEL_ALIASES), + 'models_count': len(get_model_aliases()), 'uptime': time.time(), }) @app.route('/api/providers') def api_providers(): """获取提供商列表""" + providers = get_providers() + refresh_provider_status() stats = load_stats() providers_data = [] - for provider in sorted(UPSTREAM_PROVIDERS, key=lambda x: x['priority']): + for provider in sorted(providers, key=lambda x: x['priority']): p_stats = stats.get('providers', {}).get(provider['name'], {}) p_status = provider_status.get(provider['name'], {}) providers_data.append({ + 'id': provider.get('id', provider['name'].lower().replace(' ', '-')), 'name': provider['name'], 'priority': provider['priority'], 'enabled': provider['enabled'], 'available': p_status.get('available', True), 'base_url': provider['base_url'], + 'api_key': provider['api_key'], 'models': provider['models'], 'default_model': provider['default_model'], 'timeout': provider.get('timeout', 120), @@ -132,17 +148,17 @@ def api_providers(): return jsonify(providers_data) -@app.route('/api/providers/', methods=['GET']) -def api_provider_detail(name): +@app.route('/api/providers/', methods=['GET']) +def api_provider_detail(provider_id): """获取提供商详情""" - provider = next((p for p in UPSTREAM_PROVIDERS if p['name'] == name), None) + provider = get_provider(provider_id) if not provider: return jsonify({'error': 'Provider not found'}), 404 stats = load_stats() - p_stats = stats.get('providers', {}).get(name, {}) - p_status = provider_status.get(name, {}) + p_stats = stats.get('providers', {}).get(provider['name'], {}) + p_status = provider_status.get(provider['name'], {}) return jsonify({ **provider, @@ -155,18 +171,117 @@ def api_provider_detail(name): } }) -@app.route('/api/providers//toggle', methods=['POST']) -def api_toggle_provider(name): - """切换提供商启用状态""" - # 这里需要修改配置文件,简化处理只返回成功 - return jsonify({'success': True, 'message': f'Provider {name} toggled'}) - -@app.route('/api/providers//test', methods=['POST']) -def api_test_provider(name): - """测试提供商连接""" - import requests +@app.route('/api/providers', methods=['POST']) +def api_add_provider(): + """添加新提供商""" + data = request.get_json() - provider = next((p for p in UPSTREAM_PROVIDERS if p['name'] == name), None) + if not data: + return jsonify({'error': 'Invalid request body'}), 400 + + # 验证必填字段 + required = ['name', 'base_url', 'api_key', 'models'] + for field in required: + if not data.get(field): + return jsonify({'error': f'Missing required field: {field}'}), 400 + + # 构建提供商数据 + providers = get_providers() + max_priority = max([p['priority'] for p in providers]) if providers else 0 + + new_provider = { + 'id': data.get('id') or data['name'].lower().replace(' ', '-').replace('.', '-'), + 'name': data['name'], + 'priority': data.get('priority', max_priority + 1), + 'base_url': data['base_url'].rstrip('/'), + 'api_key': data['api_key'], + 'models': data['models'] if isinstance(data['models'], list) else data['models'].split(','), + 'default_model': data.get('default_model', data['models'][0] if isinstance(data['models'], list) else data['models'].split(',')[0]), + 'timeout': data.get('timeout', 120), + 'enabled': data.get('enabled', True), + } + + # 添加到配置 + result = add_provider(new_provider) + + # 初始化状态 + provider_status[result['name']] = { + 'available': True, + 'last_check': None, + 'error_count': 0, + 'last_error': None, + } + + return jsonify({'success': True, 'provider': result}) + +@app.route('/api/providers/', methods=['PUT']) +def api_update_provider(provider_id): + """更新提供商""" + data = request.get_json() + + if not data: + return jsonify({'error': 'Invalid request body'}), 400 + + # 处理models字段 + if 'models' in data and isinstance(data['models'], str): + data['models'] = [m.strip() for m in data['models'].split(',') if m.strip()] + + result = update_provider(provider_id, data) + + if not result: + return jsonify({'error': 'Provider not found'}), 404 + + return jsonify({'success': True, 'provider': result}) + +@app.route('/api/providers/', methods=['DELETE']) +def api_delete_provider(provider_id): + """删除提供商""" + result = delete_provider(provider_id) + + if not result: + return jsonify({'error': 'Provider not found'}), 404 + + # 清理状态 + providers = get_providers() + for p in providers: + if p.get('id') == provider_id: + if p['name'] in provider_status: + del provider_status[p['name']] + break + + return jsonify({'success': True}) + +@app.route('/api/providers/priority', methods=['POST']) +def api_update_priority(): + """更新优先级顺序(拖拽排序)""" + data = request.get_json() + + if not data or 'order' not in data: + return jsonify({'error': 'Missing order field'}), 400 + + # order 是提供商ID列表,按新顺序排列 + provider_ids = data['order'] + result = update_priority(provider_ids) + + return jsonify({'success': True, 'providers': result}) + +@app.route('/api/providers//toggle', methods=['POST']) +def api_toggle_provider(provider_id): + """切换提供商启用状态""" + provider = get_provider(provider_id) + + if not provider: + return jsonify({'error': 'Provider not found'}), 404 + + new_enabled = not provider.get('enabled', True) + result = update_provider(provider_id, {'enabled': new_enabled}) + + return jsonify({'success': True, 'enabled': new_enabled}) + +@app.route('/api/providers//test', methods=['POST']) +def api_test_provider(provider_id): + """测试提供商连接""" + provider = get_provider(provider_id) if not provider: return jsonify({'success': False, 'error': 'Provider not found'}), 404 @@ -179,23 +294,52 @@ def api_test_provider(name): response = requests.get(url, headers=headers, timeout=10) if response.status_code == 200: - provider_status[name]['available'] = True - provider_status[name]['last_check'] = datetime.now().isoformat() - return jsonify({'success': True, 'message': 'Connection successful'}) + provider_status[provider['name']] = { + 'available': True, + 'last_check': datetime.now().isoformat(), + 'error_count': 0, + 'last_error': None, + } + # 尝试解析返回的模型列表 + models_data = [] + try: + resp_json = response.json() + models_data = resp_json.get('data', []) + except: + pass + + return jsonify({ + 'success': True, + 'message': 'Connection successful', + 'models_count': len(models_data) + }) else: + provider_status[provider['name']] = { + 'available': False, + 'last_check': datetime.now().isoformat(), + 'error_count': provider_status.get(provider['name'], {}).get('error_count', 0) + 1, + 'last_error': f'HTTP {response.status_code}', + } return jsonify({ 'success': False, 'error': f'HTTP {response.status_code}: {response.text[:200]}' }) except Exception as e: - provider_status[name]['available'] = False - provider_status[name]['last_error'] = str(e) + provider_status[provider['name']] = { + 'available': False, + 'last_check': datetime.now().isoformat(), + 'error_count': provider_status.get(provider['name'], {}).get('error_count', 0) + 1, + 'last_error': str(e), + } return jsonify({'success': False, 'error': str(e)}) @app.route('/api/models') def api_models(): """获取模型列表""" + providers = get_providers() + aliases = get_model_aliases() + models_list = [] added = set() @@ -208,7 +352,7 @@ def api_models(): added.add('auto') # 从提供商获取模型 - for provider in UPSTREAM_PROVIDERS: + for provider in sorted(providers, key=lambda x: x['priority']): for model in provider['models']: if model not in added: models_list.append({ @@ -220,11 +364,11 @@ def api_models(): added.add(model) # 添加别名 - for alias, target in MODEL_ALIASES.items(): + for alias, target in aliases.items(): if alias != 'auto' and alias not in added: # 找到目标模型对应的提供商 provider_name = None - for p in UPSTREAM_PROVIDERS: + for p in providers: if target in p['models']: provider_name = p['name'] break @@ -255,22 +399,33 @@ def api_logs(): @app.route('/api/config') def api_config(): """获取配置""" + providers = get_providers() + aliases = get_model_aliases() + return jsonify({ 'providers': [{ + 'id': p.get('id', p['name'].lower().replace(' ', '-')), 'name': p['name'], 'priority': p['priority'], 'base_url': p['base_url'], 'models': p['models'], 'timeout': p.get('timeout', 120), 'enabled': p['enabled'], - } for p in UPSTREAM_PROVIDERS], - 'model_aliases': MODEL_ALIASES, + } for p in providers], + 'model_aliases': aliases, 'retry_config': RETRY_CONFIG, 'server_config': { 'port': SERVER_CONFIG['port'], } }) +@app.route('/api/reload', methods=['POST']) +def api_reload_config(): + """通知主服务重新加载配置""" + # 这个接口可以被主服务调用以重新加载配置 + # 这里只返回成功,实际重载由主服务自己处理 + return jsonify({'success': True, 'message': 'Config saved, restart main service to apply'}) + @app.route('/api/requests/recent') def api_recent_requests(): """获取最近请求记录""" diff --git a/admin/templates/providers.html b/admin/templates/providers.html index 28073a5..cd22010 100644 --- a/admin/templates/providers.html +++ b/admin/templates/providers.html @@ -8,6 +8,8 @@ @@ -40,58 +42,162 @@
-

提供商管理

+ +
+
+

提供商管理

+

拖拽卡片调整优先级顺序(auto模式选择顺序)

+
+ +
- +

加载中...

+ + +
+ + Auto模式优先级: 当使用 model="auto" 时,系统会按优先级顺序依次尝试可用的提供商。拖拽上方卡片可调整顺序。 +
+ + + diff --git a/app.py b/app.py index 7245861..1939fe3 100644 --- a/app.py +++ b/app.py @@ -16,13 +16,39 @@ import sys # 添加配置路径 sys.path.insert(0, str(Path(__file__).parent)) from config.settings import ( - UPSTREAM_PROVIDERS, MODEL_ALIASES, SERVER_CONFIG, + get_providers, get_model_aliases, SERVER_CONFIG, LOG_CONFIG, RETRY_CONFIG ) app = Flask(__name__) CORS(app) +# 配置缓存时间(秒) +CONFIG_CACHE_TTL = 5 +_last_config_load = 0 +_cached_providers = [] +_cached_aliases = {} + +def refresh_config(): + """动态刷新配置(支持后台管理修改)""" + global _last_config_load, _cached_providers, _cached_aliases, provider_status + + current_time = time.time() + if current_time - _last_config_load > CONFIG_CACHE_TTL: + _cached_providers = get_providers() + _cached_aliases = get_model_aliases() + _last_config_load = current_time + + # 更新提供商状态缓存(新增的提供商) + for provider in _cached_providers: + if provider['name'] not in provider_status: + provider_status[provider['name']] = { + 'available': True, + 'last_check': None, + 'error_count': 0, + 'last_error': None, + } + # 配置日志 log_dir = Path(__file__).parent / LOG_CONFIG['log_dir'] log_dir.mkdir(exist_ok=True) @@ -39,31 +65,29 @@ logger = logging.getLogger(__name__) # 提供商状态缓存 provider_status = {} -for provider in UPSTREAM_PROVIDERS: - provider_status[provider['name']] = { - 'available': True, - 'last_check': None, - 'error_count': 0, - 'last_error': None, - } + +# 初始化 +refresh_config() def get_provider_for_model(model_name): """根据模型名获取提供商""" + refresh_config() + # 解析别名 - resolved_model = MODEL_ALIASES.get(model_name, model_name) + resolved_model = _cached_aliases.get(model_name, model_name) # auto模式:按优先级选择可用提供商 if resolved_model == 'auto': return get_available_provider() # 查找支持该模型的提供商 - sorted_providers = sorted(UPSTREAM_PROVIDERS, key=lambda x: x['priority']) + sorted_providers = sorted(_cached_providers, key=lambda x: x['priority']) for provider in sorted_providers: if not provider['enabled']: continue - if not provider_status[provider['name']]['available']: + if not provider_status.get(provider['name'], {}).get('available', True): continue if resolved_model in provider['models']: return provider, resolved_model @@ -72,7 +96,7 @@ def get_provider_for_model(model_name): for provider in sorted_providers: if not provider['enabled']: continue - if not provider_status[provider['name']]['available']: + if not provider_status.get(provider['name'], {}).get('available', True): continue for m in provider['models']: if resolved_model.lower() in m.lower() or m.lower() in resolved_model.lower(): @@ -83,10 +107,12 @@ def get_provider_for_model(model_name): def get_available_provider(): """获取可用的提供商(按优先级)""" - sorted_providers = sorted(UPSTREAM_PROVIDERS, key=lambda x: x['priority']) + refresh_config() + + sorted_providers = sorted(_cached_providers, key=lambda x: x['priority']) for provider in sorted_providers: - if provider['enabled'] and provider_status[provider['name']]['available']: + if provider['enabled'] and provider_status.get(provider['name'], {}).get('available', True): return provider, provider['default_model'] # 如果都不可用,返回第一个尝试(让错误信息传递) @@ -194,10 +220,12 @@ def index(): @app.route('/v1/models', methods=['GET']) def list_models(): """列出可用模型""" + refresh_config() + models_list = [] added_models = set() - for provider in UPSTREAM_PROVIDERS: + for provider in _cached_providers: if not provider['enabled']: continue for model in provider['models']: @@ -328,21 +356,26 @@ def chat_completions(): @app.route('/v1/embeddings', methods=['POST']) def embeddings(): """嵌入API(简单转发)""" + refresh_config() + try: data = request.get_json() model = data.get('model', 'text-embedding-ada-002') # 使用第一个可用提供商 - provider = UPSTREAM_PROVIDERS[0] - - url = f"{provider['base_url'].rstrip('/')}/embeddings" - headers = { - "Content-Type": "application/json", - "Authorization": f"Bearer {provider['api_key']}" - } - - response = requests.post(url, headers=headers, json=data, timeout=60) - return jsonify(response.json()), response.status_code + if _cached_providers: + provider = _cached_providers[0] + + url = f"{provider['base_url'].rstrip('/')}/embeddings" + headers = { + "Content-Type": "application/json", + "Authorization": f"Bearer {provider['api_key']}" + } + + response = requests.post(url, headers=headers, json=data, timeout=60) + return jsonify(response.json()), response.status_code + else: + return jsonify({"error": "No providers available"}), 503 except Exception as e: return jsonify({"error": str(e)}), 500 @@ -367,9 +400,11 @@ def health(): @app.route('/status', methods=['GET']) def status(): """详细状态""" + refresh_config() + providers_detail = [] - for provider in UPSTREAM_PROVIDERS: + for provider in _cached_providers: status_info = provider_status.get(provider['name'], {}) providers_detail.append({ "name": provider['name'], @@ -385,7 +420,7 @@ def status(): "version": "1.0.0", "uptime": time.time(), "providers": providers_detail, - "model_aliases": MODEL_ALIASES, + "model_aliases": _cached_aliases, }) @@ -405,6 +440,8 @@ def engine_completions(model): if __name__ == '__main__': + refresh_config() + print("=" * 60) print("大模型API中转系统") print("=" * 60) @@ -412,12 +449,12 @@ if __name__ == '__main__': print(f"API端点: http://localhost:{SERVER_CONFIG['port']}/v1/chat/completions") print("=" * 60) print("上游提供商:") - for p in sorted(UPSTREAM_PROVIDERS, key=lambda x: x['priority']): + for p in sorted(_cached_providers, key=lambda x: x['priority']): print(f" [{p['priority']}] {p['name']}: {p['base_url']}") print(f" 模型: {', '.join(p['models'])}") print("=" * 60) print("支持的模型别名:") - for alias, target in MODEL_ALIASES.items(): + for alias, target in _cached_aliases.items(): print(f" {alias} -> {target}") print("=" * 60) diff --git a/config/settings.py b/config/settings.py index 71a436e..a33bdb6 100644 --- a/config/settings.py +++ b/config/settings.py @@ -1,12 +1,19 @@ """ -大模型API中转系统配置 +大模型API中转系统配置 - 支持动态修改 """ -# 上游模型配置(按优先级排序,从高到低) -UPSTREAM_PROVIDERS = [ +import json +from pathlib import Path + +# 配置文件路径 +CONFIG_FILE = Path(__file__).parent.parent / 'data' / 'config.json' + +# 默认上游模型配置 +DEFAULT_PROVIDERS = [ { - "name": "local-qwen", - "priority": 1, # 数字越小优先级越高 + "id": "local-qwen", + "name": "Local Qwen", + "priority": 1, "base_url": "http://192.168.2.5:1234/v1", "api_key": "sk-lm-fuP5tGU8:Hi7YU87jHyDP6Ay8Tl2j", "models": ["qwen3.5-4b", "qwen3.5", "qwen"], @@ -15,7 +22,8 @@ UPSTREAM_PROVIDERS = [ "enabled": True, }, { - "name": "siliconflow-deepseek", + "id": "siliconflow-deepseek", + "name": "SiliconFlow DeepSeek", "priority": 2, "base_url": "https://api.siliconflow.cn/v1", "api_key": "sk-fhpoexpptvjghpnphtaxbkhjwulzovoqfffbckcfscjmwhcg", @@ -26,22 +34,118 @@ UPSTREAM_PROVIDERS = [ }, ] -# 模型别名映射 -MODEL_ALIASES = { - # auto 自动选择可用模型 +# 默认模型别名 +DEFAULT_MODEL_ALIASES = { "auto": "auto", - - # Qwen别名 "qwen": "qwen3.5-4b", "qwen3.5": "qwen3.5-4b", "qwen3.5-4b": "qwen3.5-4b", - - # DeepSeek别名 "deepseek": "Pro/deepseek-ai/DeepSeek-V3.2", "deepseek-v3": "Pro/deepseek-ai/DeepSeek-V3.2", "deepseek-v3.2": "Pro/deepseek-ai/DeepSeek-V3.2", } +def load_config(): + """加载配置""" + if CONFIG_FILE.exists(): + try: + data = json.loads(CONFIG_FILE.read_text(encoding='utf-8')) + return data + except: + pass + return { + "providers": DEFAULT_PROVIDERS, + "model_aliases": DEFAULT_MODEL_ALIASES, + } + +def save_config(config): + """保存配置""" + CONFIG_FILE.parent.mkdir(parents=True, exist_ok=True) + CONFIG_FILE.write_text(json.dumps(config, ensure_ascii=False, indent=2), encoding='utf-8') + +def get_providers(): + """获取提供商列表""" + config = load_config() + return config.get("providers", DEFAULT_PROVIDERS) + +def get_provider(provider_id): + """获取单个提供商""" + providers = get_providers() + for p in providers: + if p.get("id") == provider_id: + return p + return None + +def add_provider(provider): + """添加提供商""" + config = load_config() + providers = config.get("providers", []) + + # 生成ID + if not provider.get("id"): + provider["id"] = provider["name"].lower().replace(" ", "-").replace(".", "-") + + providers.append(provider) + config["providers"] = providers + save_config(config) + return provider + +def update_provider(provider_id, data): + """更新提供商""" + config = load_config() + providers = config.get("providers", []) + + for i, p in enumerate(providers): + if p.get("id") == provider_id: + providers[i] = {**p, **data} + config["providers"] = providers + save_config(config) + return providers[i] + return None + +def delete_provider(provider_id): + """删除提供商""" + config = load_config() + providers = config.get("providers", []) + providers = [p for p in providers if p.get("id") != provider_id] + config["providers"] = providers + save_config(config) + return True + +def update_priority(provider_ids): + """更新优先级顺序""" + config = load_config() + providers = config.get("providers", []) + + # 按新顺序设置优先级 + for i, pid in enumerate(provider_ids): + for p in providers: + if p.get("id") == pid: + p["priority"] = i + 1 + + config["providers"] = providers + save_config(config) + return providers + +def get_model_aliases(): + """获取模型别名""" + config = load_config() + return config.get("model_aliases", DEFAULT_MODEL_ALIASES) + +def update_model_alias(alias, target): + """更新模型别名""" + config = load_config() + aliases = config.get("model_aliases", {}) + aliases[alias] = target + config["model_aliases"] = aliases + save_config(config) + return aliases + +# 初始化配置 +config = load_config() +UPSTREAM_PROVIDERS = config.get("providers", DEFAULT_PROVIDERS) +MODEL_ALIASES = config.get("model_aliases", DEFAULT_MODEL_ALIASES) + # 服务配置 SERVER_CONFIG = { "host": "0.0.0.0", @@ -59,18 +163,11 @@ LOG_CONFIG = { # 重试配置 RETRY_CONFIG = { "max_retries": 3, - "retry_delay": 1, # 秒 + "retry_delay": 1, "retry_on_errors": [ "connection_error", "timeout", "rate_limit", "server_error", ], -} - -# 健康检查配置 -HEALTH_CHECK = { - "enabled": True, - "interval": 60, # 秒 - "timeout": 10, } \ No newline at end of file diff --git a/data/config.json b/data/config.json new file mode 100644 index 0000000..ecb7825 --- /dev/null +++ b/data/config.json @@ -0,0 +1,35 @@ +{ + "providers": [ + { + "id": "local-qwen", + "name": "Local Qwen", + "priority": 1, + "base_url": "http://192.168.2.5:1234/v1", + "api_key": "sk-lm-fuP5tGU8:Hi7YU87jHyDP6Ay8Tl2j", + "models": ["qwen3.5-4b", "qwen3.5", "qwen"], + "default_model": "qwen3.5-4b", + "timeout": 120, + "enabled": true + }, + { + "id": "siliconflow-deepseek", + "name": "SiliconFlow DeepSeek", + "priority": 2, + "base_url": "https://api.siliconflow.cn/v1", + "api_key": "sk-fhpoexpptvjghpnphtaxbkhjwulzovoqfffbckcfscjmwhcg", + "models": ["Pro/deepseek-ai/DeepSeek-V3.2", "deepseek-v3", "deepseek"], + "default_model": "Pro/deepseek-ai/DeepSeek-V3.2", + "timeout": 120, + "enabled": true + } + ], + "model_aliases": { + "auto": "auto", + "qwen": "qwen3.5-4b", + "qwen3.5": "qwen3.5-4b", + "qwen3.5-4b": "qwen3.5-4b", + "deepseek": "Pro/deepseek-ai/DeepSeek-V3.2", + "deepseek-v3": "Pro/deepseek-ai/DeepSeek-V3.2", + "deepseek-v3.2": "Pro/deepseek-ai/DeepSeek-V3.2" + } +} \ No newline at end of file