新增功能: - 对话页面 (/chat) - 选择不同模型进行对话 - 历史对话保存和加载 - 支持继续历史对话 API: - GET /api/chat/models - 获取可用模型 - GET /api/chat/list - 获取对话列表 - GET /api/chat/<id> - 获取对话详情 - POST /api/chat/send - 发送消息 - DELETE /api/chat/<id> - 删除对话 - POST /api/chat/<id>/clear - 清空对话
792 lines
24 KiB
Python
792 lines
24 KiB
Python
"""
|
||
大模型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 (
|
||
DEFAULT_PROVIDERS, DEFAULT_MODEL_ALIASES, DEFAULT_AUTO_PROFILES,
|
||
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, get_auto_profiles, get_auto_profile,
|
||
add_auto_profile, update_auto_profile, delete_auto_profile
|
||
)
|
||
|
||
app = Flask(__name__)
|
||
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 = {}
|
||
|
||
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():
|
||
"""加载统计数据"""
|
||
if STATS_FILE.exists():
|
||
return json.loads(STATS_FILE.read_text(encoding='utf-8'))
|
||
return {
|
||
'total_requests': 0,
|
||
'total_success': 0,
|
||
'total_errors': 0,
|
||
'total_tokens': 0,
|
||
'requests_today': 0,
|
||
'providers': {},
|
||
'last_updated': None
|
||
}
|
||
|
||
def save_stats(stats):
|
||
"""保存统计数据"""
|
||
stats['last_updated'] = datetime.now().isoformat()
|
||
STATS_FILE.write_text(json.dumps(stats, ensure_ascii=False, indent=2), encoding='utf-8')
|
||
|
||
# ============ 页面路由 ============
|
||
|
||
@app.route('/')
|
||
def index():
|
||
return render_template('index.html')
|
||
|
||
@app.route('/providers')
|
||
def providers_page():
|
||
return render_template('providers.html')
|
||
|
||
@app.route('/models')
|
||
def models_page():
|
||
return render_template('models.html')
|
||
|
||
@app.route('/logs')
|
||
def logs_page():
|
||
return render_template('logs.html')
|
||
|
||
@app.route('/config')
|
||
def config_page():
|
||
return render_template('config.html')
|
||
|
||
@app.route('/chat')
|
||
def chat_page():
|
||
return render_template('chat.html')
|
||
|
||
@app.route('/auto-profiles')
|
||
def auto_profiles_page():
|
||
return render_template('auto-profiles.html')
|
||
|
||
# ============ API路由 ============
|
||
|
||
@app.route('/api/stats')
|
||
def api_stats():
|
||
"""获取统计数据"""
|
||
stats = load_stats()
|
||
providers = get_providers()
|
||
refresh_provider_status()
|
||
|
||
# 统计提供商状态
|
||
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(providers),
|
||
'available_providers': available_count,
|
||
'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(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),
|
||
'request_count': p_stats.get('request_count', 0),
|
||
'success_count': p_stats.get('success_count', 0),
|
||
'error_count': p_status.get('error_count', 0),
|
||
'last_error': p_status.get('last_error'),
|
||
'last_check': p_status.get('last_check'),
|
||
})
|
||
|
||
return jsonify(providers_data)
|
||
|
||
@app.route('/api/providers/<provider_id>', methods=['GET'])
|
||
def api_provider_detail(provider_id):
|
||
"""获取提供商详情"""
|
||
provider = get_provider(provider_id)
|
||
|
||
if not provider:
|
||
return jsonify({'error': 'Provider not found'}), 404
|
||
|
||
stats = load_stats()
|
||
p_stats = stats.get('providers', {}).get(provider['name'], {})
|
||
p_status = provider_status.get(provider['name'], {})
|
||
|
||
return jsonify({
|
||
**provider,
|
||
'status': {
|
||
'available': p_status.get('available', True),
|
||
'error_count': p_status.get('error_count', 0),
|
||
'last_error': p_status.get('last_error'),
|
||
'request_count': p_stats.get('request_count', 0),
|
||
'success_count': p_stats.get('success_count', 0),
|
||
}
|
||
})
|
||
|
||
@app.route('/api/providers', methods=['POST'])
|
||
def api_add_provider():
|
||
"""添加新提供商"""
|
||
data = request.get_json()
|
||
|
||
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/<provider_id>', 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/<provider_id>', 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/<provider_id>/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/<provider_id>/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
|
||
|
||
try:
|
||
# 测试模型列表接口
|
||
url = f"{provider['base_url'].rstrip('/')}/models"
|
||
headers = {"Authorization": f"Bearer {provider['api_key']}"}
|
||
|
||
response = requests.get(url, headers=headers, timeout=10)
|
||
|
||
if response.status_code == 200:
|
||
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[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()
|
||
|
||
# 添加auto
|
||
models_list.append({
|
||
'alias': 'auto',
|
||
'target': 'auto',
|
||
'description': '自动选择可用模型(按优先级)'
|
||
})
|
||
added.add('auto')
|
||
|
||
# 从提供商获取模型
|
||
for provider in sorted(providers, key=lambda x: x['priority']):
|
||
for model in provider['models']:
|
||
if model not in added:
|
||
models_list.append({
|
||
'alias': model,
|
||
'target': model,
|
||
'provider': provider['name'],
|
||
'priority': provider['priority'],
|
||
})
|
||
added.add(model)
|
||
|
||
# 添加别名
|
||
for alias, target in aliases.items():
|
||
if alias != 'auto' and alias not in added:
|
||
# 找到目标模型对应的提供商
|
||
provider_name = None
|
||
for p in providers:
|
||
if target in p['models']:
|
||
provider_name = p['name']
|
||
break
|
||
|
||
models_list.append({
|
||
'alias': alias,
|
||
'target': target,
|
||
'provider': provider_name,
|
||
})
|
||
|
||
return jsonify(models_list)
|
||
|
||
@app.route('/api/logs')
|
||
def api_logs():
|
||
"""获取日志"""
|
||
log_file = LOGS_DIR / 'proxy.log'
|
||
|
||
lines = []
|
||
if log_file.exists():
|
||
content = log_file.read_text(encoding='utf-8')
|
||
lines = content.strip().split('\n')[-100:] # 最近100条
|
||
|
||
return jsonify({
|
||
'logs': lines,
|
||
'total_lines': len(lines)
|
||
})
|
||
|
||
@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 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'})
|
||
|
||
|
||
# ============ 对话功能 ============
|
||
|
||
CHATS_FILE = DATA_DIR / 'chats.json'
|
||
|
||
def load_chats():
|
||
"""加载对话数据"""
|
||
if CHATS_FILE.exists():
|
||
return json.loads(CHATS_FILE.read_text(encoding='utf-8'))
|
||
return {'chats': []}
|
||
|
||
def save_chats(data):
|
||
"""保存对话数据"""
|
||
CHATS_FILE.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding='utf-8')
|
||
|
||
|
||
@app.route('/api/chat/models')
|
||
def api_chat_models():
|
||
"""获取可用模型列表"""
|
||
providers = get_providers()
|
||
profiles = get_auto_profiles()
|
||
|
||
models = []
|
||
added = set()
|
||
|
||
# 添加所有auto配置
|
||
for name, profile in profiles.items():
|
||
if name not in added:
|
||
models.append({
|
||
'id': name,
|
||
'description': profile.get('description', 'Auto-select')
|
||
})
|
||
added.add(name)
|
||
|
||
# 添加提供商的模型
|
||
for provider in providers:
|
||
if not provider['enabled']:
|
||
continue
|
||
for model in provider['models']:
|
||
if model not in added:
|
||
models.append({
|
||
'id': model,
|
||
'description': provider['name']
|
||
})
|
||
added.add(model)
|
||
|
||
return jsonify(models)
|
||
|
||
|
||
@app.route('/api/chat/list')
|
||
def api_chat_list():
|
||
"""获取对话列表"""
|
||
data = load_chats()
|
||
|
||
chats = []
|
||
for chat in data.get('chats', []):
|
||
chats.append({
|
||
'id': chat['id'],
|
||
'title': chat.get('title', '新对话'),
|
||
'model': chat.get('model', 'auto'),
|
||
'message_count': len(chat.get('messages', [])),
|
||
'created_at': chat.get('created_at'),
|
||
'updated_at': chat.get('updated_at')
|
||
})
|
||
|
||
# 按更新时间倒序
|
||
chats.sort(key=lambda x: x.get('updated_at', ''), reverse=True)
|
||
|
||
return jsonify(chats)
|
||
|
||
|
||
@app.route('/api/chat/<chat_id>')
|
||
def api_chat_detail(chat_id):
|
||
"""获取对话详情"""
|
||
data = load_chats()
|
||
|
||
for chat in data.get('chats', []):
|
||
if chat['id'] == chat_id:
|
||
return jsonify(chat)
|
||
|
||
return jsonify({'error': 'Chat not found'}), 404
|
||
|
||
|
||
@app.route('/api/chat/send', methods=['POST'])
|
||
def api_chat_send():
|
||
"""发送消息"""
|
||
req = request.get_json()
|
||
|
||
user_message = req.get('message', '')
|
||
model = req.get('model', 'auto')
|
||
chat_id = req.get('chat_id')
|
||
|
||
if not user_message:
|
||
return jsonify({'error': 'Message is required'}), 400
|
||
|
||
data = load_chats()
|
||
|
||
# 查找或创建对话
|
||
chat = None
|
||
if chat_id:
|
||
for c in data['chats']:
|
||
if c['id'] == chat_id:
|
||
chat = c
|
||
break
|
||
|
||
if not chat:
|
||
chat_id = str(uuid.uuid4())[:8]
|
||
chat = {
|
||
'id': chat_id,
|
||
'title': '新对话',
|
||
'model': model,
|
||
'messages': [],
|
||
'created_at': datetime.now().isoformat(),
|
||
'updated_at': datetime.now().isoformat()
|
||
}
|
||
data['chats'].append(chat)
|
||
|
||
# 添加用户消息
|
||
chat['messages'].append({
|
||
'role': 'user',
|
||
'content': user_message,
|
||
'time': datetime.now().isoformat()
|
||
})
|
||
|
||
# 调用LLM API
|
||
try:
|
||
proxy_url = f"http://localhost:{SERVER_CONFIG['port']}/v1/chat/completions"
|
||
|
||
# 构建消息历史
|
||
messages = []
|
||
for msg in chat['messages'][-20:]: # 最多保留20条历史
|
||
messages.append({
|
||
'role': msg['role'],
|
||
'content': msg['content']
|
||
})
|
||
|
||
response = requests.post(proxy_url, json={
|
||
'model': model,
|
||
'messages': messages,
|
||
'stream': False
|
||
}, timeout=120)
|
||
|
||
if response.status_code == 200:
|
||
result = response.json()
|
||
assistant_message = result['choices'][0]['message']['content']
|
||
used_model = result.get('model', model)
|
||
|
||
# 添加助手消息
|
||
chat['messages'].append({
|
||
'role': 'assistant',
|
||
'content': assistant_message,
|
||
'model': used_model,
|
||
'time': datetime.now().isoformat()
|
||
})
|
||
|
||
# 更新标题(如果是第一条消息)
|
||
if len(chat['messages']) == 2:
|
||
chat['title'] = user_message[:30] + ('...' if len(user_message) > 30 else '')
|
||
|
||
chat['updated_at'] = datetime.now().isoformat()
|
||
save_chats(data)
|
||
|
||
return jsonify({
|
||
'success': True,
|
||
'chat_id': chat_id,
|
||
'response': assistant_message,
|
||
'model': used_model,
|
||
'title': chat['title']
|
||
})
|
||
else:
|
||
error_msg = response.json().get('error', {}).get('message', 'Unknown error')
|
||
return jsonify({'error': error_msg}), response.status_code
|
||
|
||
except Exception as e:
|
||
return jsonify({'error': str(e)}), 500
|
||
|
||
|
||
@app.route('/api/chat/<chat_id>', methods=['DELETE'])
|
||
def api_delete_chat(chat_id):
|
||
"""删除对话"""
|
||
data = load_chats()
|
||
data['chats'] = [c for c in data['chats'] if c['id'] != chat_id]
|
||
save_chats(data)
|
||
return jsonify({'success': True})
|
||
|
||
|
||
@app.route('/api/chat/<chat_id>/clear', methods=['POST'])
|
||
def api_clear_chat(chat_id):
|
||
"""清空对话消息"""
|
||
data = load_chats()
|
||
|
||
for chat in data['chats']:
|
||
if chat['id'] == chat_id:
|
||
chat['messages'] = []
|
||
chat['updated_at'] = datetime.now().isoformat()
|
||
save_chats(data)
|
||
return jsonify({'success': True})
|
||
|
||
return jsonify({'error': 'Chat not found'}), 404
|
||
|
||
@app.route('/api/requests/recent')
|
||
def api_recent_requests():
|
||
"""获取最近请求记录"""
|
||
# 模拟数据
|
||
return jsonify([])
|
||
|
||
|
||
# ============ Auto配置管理 ============
|
||
|
||
@app.route('/api/auto-profiles')
|
||
def api_auto_profiles():
|
||
"""获取所有Auto配置"""
|
||
profiles = get_auto_profiles()
|
||
providers = get_providers()
|
||
|
||
result = []
|
||
for name, profile in profiles.items():
|
||
# 解析允许的提供商信息
|
||
allowed_providers = profile.get('providers', ['*'])
|
||
provider_details = []
|
||
|
||
if '*' in allowed_providers:
|
||
provider_details = [{'id': '*', 'name': '所有启用的提供商'}]
|
||
else:
|
||
for p in providers:
|
||
if p.get('id') in allowed_providers or p['name'] in allowed_providers:
|
||
provider_details.append({
|
||
'id': p.get('id'),
|
||
'name': p['name'],
|
||
'priority': p['priority']
|
||
})
|
||
|
||
result.append({
|
||
'name': name,
|
||
'display_name': profile.get('name', name),
|
||
'description': profile.get('description', ''),
|
||
'strategy': profile.get('strategy', 'priority'),
|
||
'providers': allowed_providers,
|
||
'provider_details': provider_details,
|
||
})
|
||
|
||
return jsonify(result)
|
||
|
||
|
||
@app.route('/api/auto-profiles/<profile_name>', methods=['GET'])
|
||
def api_auto_profile_detail(profile_name):
|
||
"""获取单个Auto配置详情"""
|
||
profile = get_auto_profile(profile_name)
|
||
|
||
if not profile:
|
||
return jsonify({'error': 'Profile not found'}), 404
|
||
|
||
providers = get_providers()
|
||
allowed_providers = profile.get('providers', ['*'])
|
||
provider_details = []
|
||
|
||
if '*' in allowed_providers:
|
||
provider_details = [{'id': '*', 'name': '所有启用的提供商', 'selected': True}]
|
||
for p in providers:
|
||
provider_details.append({
|
||
'id': p.get('id'),
|
||
'name': p['name'],
|
||
'priority': p['priority'],
|
||
'selected': True
|
||
})
|
||
else:
|
||
for p in providers:
|
||
selected = p.get('id') in allowed_providers or p['name'] in allowed_providers
|
||
provider_details.append({
|
||
'id': p.get('id'),
|
||
'name': p['name'],
|
||
'priority': p['priority'],
|
||
'selected': selected
|
||
})
|
||
|
||
return jsonify({
|
||
'name': profile_name,
|
||
'display_name': profile.get('name', profile_name),
|
||
'description': profile.get('description', ''),
|
||
'strategy': profile.get('strategy', 'priority'),
|
||
'providers': allowed_providers,
|
||
'provider_details': provider_details,
|
||
})
|
||
|
||
|
||
@app.route('/api/auto-profiles', methods=['POST'])
|
||
def api_add_auto_profile():
|
||
"""添加新的Auto配置"""
|
||
data = request.get_json()
|
||
|
||
if not data or not data.get('name'):
|
||
return jsonify({'error': 'Missing profile name'}), 400
|
||
|
||
profile_name = data['name'].lower().replace(' ', '-').replace('.', '-')
|
||
|
||
if profile_name in get_auto_profiles():
|
||
return jsonify({'error': 'Profile already exists'}), 400
|
||
|
||
profile_data = {
|
||
'name': data.get('display_name', data['name']),
|
||
'description': data.get('description', ''),
|
||
'providers': data.get('providers', ['*']),
|
||
'strategy': data.get('strategy', 'priority'),
|
||
}
|
||
|
||
result = add_auto_profile(profile_name, profile_data)
|
||
|
||
return jsonify({'success': True, 'profile': {profile_name: profile_data}})
|
||
|
||
|
||
@app.route('/api/auto-profiles/<profile_name>', methods=['PUT'])
|
||
def api_update_auto_profile(profile_name):
|
||
"""更新Auto配置"""
|
||
data = request.get_json()
|
||
|
||
if not data:
|
||
return jsonify({'error': 'Invalid request body'}), 400
|
||
|
||
profile_data = {}
|
||
if 'display_name' in data:
|
||
profile_data['name'] = data['display_name']
|
||
if 'description' in data:
|
||
profile_data['description'] = data['description']
|
||
if 'providers' in data:
|
||
profile_data['providers'] = data['providers']
|
||
if 'strategy' in data:
|
||
profile_data['strategy'] = data['strategy']
|
||
|
||
result = update_auto_profile(profile_name, profile_data)
|
||
|
||
if not result:
|
||
return jsonify({'error': 'Profile not found'}), 404
|
||
|
||
return jsonify({'success': True, 'profile': result})
|
||
|
||
|
||
@app.route('/api/auto-profiles/<profile_name>', methods=['DELETE'])
|
||
def api_delete_auto_profile(profile_name):
|
||
"""删除Auto配置"""
|
||
result = delete_auto_profile(profile_name)
|
||
|
||
if not result:
|
||
return jsonify({'error': 'Cannot delete default auto profile or profile not found'}), 400
|
||
|
||
return jsonify({'success': True})
|
||
|
||
if __name__ == '__main__':
|
||
print("=" * 50)
|
||
print("大模型API中转系统 - 后台管理")
|
||
print("=" * 50)
|
||
print(f"访问地址: http://localhost:19008")
|
||
print(f"前台地址: http://localhost:19007")
|
||
print("=" * 50)
|
||
|
||
app.run(host='0.0.0.0', port=19008, debug=True) |