""" 大模型配置管理 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/', 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/', 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//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