160 lines
5.4 KiB
Python
160 lines
5.4 KiB
Python
"""
|
|||
|
|
大模型配置管理 API 路由
|
||
|
|
支持新增、编辑、删除、切换、测试大模型接口
|
||
|
|
"""
|
||
|
|
from flask import Blueprint, jsonify, request
|
||
|
|
from services.llm_client import llm_client
|
||
|
|
import logging
|
||
|
|
|
||
|
|
logger = logging.getLogger('llm_api')
|
||
|
|
|
||
|
|
bp = Blueprint('llm', __name__, url_prefix='/api/llm')
|
||
|
|
|
||
|
|
|
||
|
|
@bp.route('/configs', methods=['GET'])
|
||
|
|
def get_configs():
|
||
|
|
"""获取所有大模型配置"""
|
||
|
|
try:
|
||
|
|
configs = llm_client.get_all_configs()
|
||
|
|
# 隐藏完整 api_key,只显示掩码
|
||
|
|
for cfg in configs:
|
||
|
|
if cfg.get('api_key'):
|
||
|
|
key = cfg['api_key']
|
||
|
|
if len(key) > 8:
|
||
|
|
cfg['api_key_masked'] = key[:4] + '****' + key[-4:]
|
||
|
|
else:
|
||
|
|
cfg['api_key_masked'] = '****'
|
||
|
|
cfg['api_key'] = ''
|
||
|
|
return jsonify({
|
||
|
|
'success': True,
|
||
|
|
'configs': configs
|
||
|
|
})
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"获取大模型配置失败: {e}")
|
||
|
|
return jsonify({'success': False, 'error': str(e)}), 500
|
||
|
|
|
||
|
|
|
||
|
|
@bp.route('/configs/active', methods=['GET'])
|
||
|
|
def get_active_config():
|
||
|
|
"""获取当前激活的大模型配置"""
|
||
|
|
try:
|
||
|
|
config = llm_client.get_active_config()
|
||
|
|
return jsonify({
|
||
|
|
'success': True,
|
||
|
|
'config': config
|
||
|
|
})
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"获取激活配置失败: {e}")
|
||
|
|
return jsonify({'success': False, 'error': str(e)}), 500
|
||
|
|
|
||
|
|
|
||
|
|
@bp.route('/configs', methods=['POST'])
|
||
|
|
def add_config():
|
||
|
|
"""新增大模型配置"""
|
||
|
|
try:
|
||
|
|
data = request.get_json() or {}
|
||
|
|
name = data.get('name', '').strip()
|
||
|
|
base_url = data.get('base_url', '').strip().rstrip('/')
|
||
|
|
api_key = data.get('api_key', '').strip()
|
||
|
|
model_name = data.get('model_name', '').strip()
|
||
|
|
max_context = int(data.get('max_context', 262144) or 262144)
|
||
|
|
|
||
|
|
if not name:
|
||
|
|
return jsonify({'success': False, 'error': '请填写配置名称'}), 400
|
||
|
|
if not base_url:
|
||
|
|
return jsonify({'success': False, 'error': '请填写接口地址 base_url'}), 400
|
||
|
|
if not model_name:
|
||
|
|
return jsonify({'success': False, 'error': '请填写模型名称'}), 400
|
||
|
|
|
||
|
|
config_id = llm_client.add_config(
|
||
|
|
name=name,
|
||
|
|
base_url=base_url,
|
||
|
|
api_key=api_key,
|
||
|
|
model_name=model_name,
|
||
|
|
max_context=max_context
|
||
|
|
)
|
||
|
|
|
||
|
|
return jsonify({
|
||
|
|
'success': True,
|
||
|
|
'message': f'大模型配置「{name}」已添加',
|
||
|
|
'config_id': config_id
|
||
|
|
})
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"添加大模型配置失败: {e}")
|
||
|
|
return jsonify({'success': False, 'error': str(e)}), 500
|
||
|
|
|
||
|
|
|
||
|
|
@bp.route('/configs/<int:config_id>', methods=['PUT'])
|
||
|
|
def update_config(config_id):
|
||
|
|
"""更新大模型配置"""
|
||
|
|
try:
|
||
|
|
data = request.get_json() or {}
|
||
|
|
kwargs = {}
|
||
|
|
for key in ['name', 'base_url', 'api_key', 'model_name', 'max_context']:
|
||
|
|
if key in data and data[key] is not None:
|
||
|
|
kwargs[key] = data[key].strip() if isinstance(data[key], str) else data[key]
|
||
|
|
|
||
|
|
if not kwargs:
|
||
|
|
return jsonify({'success': False, 'error': '没有需要更新的字段'}), 400
|
||
|
|
|
||
|
|
# 去掉 base_url 末尾的 /
|
||
|
|
if 'base_url' in kwargs:
|
||
|
|
kwargs['base_url'] = kwargs['base_url'].rstrip('/')
|
||
|
|
|
||
|
|
llm_client.update_config(config_id, **kwargs)
|
||
|
|
return jsonify({
|
||
|
|
'success': True,
|
||
|
|
'message': '配置已更新'
|
||
|
|
})
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"更新大模型配置失败: {e}")
|
||
|
|
return jsonify({'success': False, 'error': str(e)}), 500
|
||
|
|
|
||
|
|
|
||
|
|
@bp.route('/configs/<int:config_id>', methods=['DELETE'])
|
||
|
|
def delete_config(config_id):
|
||
|
|
"""删除大模型配置"""
|
||
|
|
try:
|
||
|
|
ok, message = llm_client.delete_config(config_id)
|
||
|
|
if ok:
|
||
|
|
return jsonify({'success': True, 'message': message})
|
||
|
|
return jsonify({'success': False, 'error': message}), 400
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"删除大模型配置失败: {e}")
|
||
|
|
return jsonify({'success': False, 'error': str(e)}), 500
|
||
|
|
|
||
|
|
|
||
|
|
@bp.route('/configs/<int:config_id>/activate', methods=['POST'])
|
||
|
|
def activate_config(config_id):
|
||
|
|
"""切换激活的大模型配置"""
|
||
|
|
try:
|
||
|
|
if llm_client.set_active(config_id):
|
||
|
|
cfg = llm_client.get_active_config(force=True)
|
||
|
|
return jsonify({
|
||
|
|
'success': True,
|
||
|
|
'message': f'已切换到大模型「{cfg.get("name")}」',
|
||
|
|
'config': cfg
|
||
|
|
})
|
||
|
|
return jsonify({'success': False, 'error': '切换失败,配置不存在'}), 404
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"切换大模型配置失败: {e}")
|
||
|
|
return jsonify({'success': False, 'error': str(e)}), 500
|
||
|
|
|
||
|
|
|
||
|
|
@bp.route('/test', methods=['POST'])
|
||
|
|
def test_connection():
|
||
|
|
"""测试大模型连接(可指定配置,不指定则测试当前激活配置)"""
|
||
|
|
try:
|
||
|
|
data = request.get_json() or {}
|
||
|
|
config = None
|
||
|
|
if data.get('config'):
|
||
|
|
config = data['config']
|
||
|
|
|
||
|
|
ok, message = llm_client.test_connection(config)
|
||
|
|
return jsonify({
|
||
|
|
'success': ok,
|
||
|
|
'message': message
|
||
|
|
})
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"测试大模型连接失败: {e}")
|
||
|
|
return jsonify({'success': False, 'error': str(e)}), 500
|