wapadil/seedream4
3
1"""2API Routes - 简化的路由处理3消除复杂的异步状态管理,直接返回结果4"""5import base646from flask import Blueprint, request, jsonify7from .fal_client import FALClient, get_api_key_from_request, validate_generation_request, prepare_fal_arguments8from monitoring import log_api_call, log_generation_metrics, log_error, get_health_status, log_request_id9 10api = Blueprint('api', __name__)11 12 13@api.route('/generate', methods=['POST'])14@log_api_call15def generate():16 """17 图像生成接口 - 简化为同步处理18 消除复杂的请求跟踪和状态管理19 """20 try:21 # 验证请求数据22 data = request.json23 validation = validate_generation_request(data)24 if not validation['valid']:25 return jsonify({'error': validation['error']}), 40026 27 # 获取API密钥28 api_key = get_api_key_from_request(request)29 if not api_key:30 return jsonify({'error': 'API key not provided'}), 40131 32 # 获取模型端点33 model_endpoint = request.headers.get('X-Model-Endpoint', 'fal-ai/bytedance/seedream/v4/edit')34 35 # 准备参数36 fal_arguments = prepare_fal_arguments(data, model_endpoint)37 38 # 记录生成指标39 log_generation_metrics(40 model_endpoint,41 len(data.get('prompt', '')),42 len(data.get('image_urls', []))43 )44 45 # 提交到队列,返回request_id供轮询46 client = FALClient(api_key)47 result = client.generate_image(model_endpoint, fal_arguments)48 49 if result['success']:50 # 明确记录 request_id 到日志,用于后续提取和删除51 log_request_id(52 result['request_id'],53 action="generated",54 model=model_endpoint,55 prompt=data.get('prompt', '')56 )57 58 return jsonify({59 'status': 'submitted',60 'request_id': result['request_id']61 }), 20062 else:63 return jsonify({64 'status': 'error',65 'error': result['error'],66 'request_id': result['request_id']67 }), 50068 69 except Exception as e:70 return jsonify({'error': str(e)}), 50071 72 73@api.route('/status/<request_id>', methods=['GET'])74@log_api_call75def check_status(request_id):76 """77 检查生成状态 - 解决FAL子路径问题78 按照专家建议,正确处理model endpoint的子路径79 """80 try:81 # 获取API密钥82 api_key = get_api_key_from_request(request)83 if not api_key:84 return jsonify({'error': 'API key not provided'}), 40185 86 # 获取模型端点(需要知道原始模型以便正确查询状态)87 model_endpoint = request.headers.get('X-Model-Endpoint', 'fal-ai/bytedance/seedream/v4/edit')88 89 # 查询状态90 client = FALClient(api_key)91 result = client.get_status(model_endpoint, request_id)92 93 if result['success']:94 response = {95 'request_id': request_id,96 'status': result['status'], # 已经是小写,不需要再次转换97 'logs': result['logs']98 }99 100 # 添加队列位置信息101 if 'queue_position' in result:102 response['queue_position'] = result['queue_position']103 104 # 如果已完成,包含结果105 if result.get('result'):106 response['result'] = result['result']107 108 return jsonify(response), 200109 else:110 # ✅ 返回200而不是500,让前端显示错误信息111 return jsonify({112 'request_id': request_id,113 'status': 'error',114 'error': result['error']115 }), 200116 117 except Exception as e:118 # ✅ 返回200而不是500,让前端显示错误信息119 return jsonify({120 'request_id': request_id,121 'status': 'error',122 'error': str(e)123 }), 200124 125 126@api.route('/upload', methods=['POST'])127def upload_file():128 """文件上传接口 - 简化处理"""129 try:130 if 'file' not in request.files:131 return jsonify({'error': 'No file provided'}), 400132 133 file = request.files['file']134 if file.filename == '':135 return jsonify({'error': 'No file selected'}), 400136 137 # 转换为base64 data URL138 file_content = file.read()139 file_type = file.content_type or 'application/octet-stream'140 base64_content = base64.b64encode(file_content).decode('utf-8')141 data_url = f"data:{file_type};base64,{base64_content}"142 143 return jsonify({'url': data_url}), 200144 145 except Exception as e:146 return jsonify({'error': str(e)}), 500147 148 149@api.route('/upload-to-fal', methods=['POST'])150def upload_to_fal():151 """上传到FAL存储 - 简化处理"""152 try:153 data = request.json154 if 'image_data' not in data:155 return jsonify({'error': 'No image data provided'}), 400156 157 # 获取API密钥158 api_key = get_api_key_from_request(request)159 if not api_key:160 return jsonify({'error': 'API key not provided'}), 401161 162 # 上传文件163 client = FALClient(api_key)164 result = client.upload_file(data['image_data'])165 166 if result['success']:167 return jsonify({'url': result['url']}), 200168 else:169 return jsonify({'error': result['error']}), 500170 171 except Exception as e:172 return jsonify({'error': str(e)}), 500173 174 175@api.route('/health', methods=['GET'])176def health_check():177 """健康检查"""178 return jsonify(get_health_status()), 200