seedream4 / api /routes.py
wapadil
fix(app_simple): apply critical fixes to production deployment
76ee88a
"""
API Routes - 简化的路由处理
消除复杂的异步状态管理,直接返回结果
"""
import base64
from flask import Blueprint, request, jsonify
from .fal_client import FALClient, get_api_key_from_request, validate_generation_request, prepare_fal_arguments
from monitoring import log_api_call, log_generation_metrics, log_error, get_health_status, log_request_id
api = Blueprint('api', __name__)
@api.route('/generate', methods=['POST'])
@log_api_call
def generate():
"""
图像生成接口 - 简化为同步处理
消除复杂的请求跟踪和状态管理
"""
try:
# 验证请求数据
data = request.json
validation = validate_generation_request(data)
if not validation['valid']:
return jsonify({'error': validation['error']}), 400
# 获取API密钥
api_key = get_api_key_from_request(request)
if not api_key:
return jsonify({'error': 'API key not provided'}), 401
# 获取模型端点
model_endpoint = request.headers.get('X-Model-Endpoint', 'fal-ai/bytedance/seedream/v4/edit')
# 准备参数
fal_arguments = prepare_fal_arguments(data, model_endpoint)
# 记录生成指标
log_generation_metrics(
model_endpoint,
len(data.get('prompt', '')),
len(data.get('image_urls', []))
)
# 提交到队列,返回request_id供轮询
client = FALClient(api_key)
result = client.generate_image(model_endpoint, fal_arguments)
if result['success']:
# 明确记录 request_id 到日志,用于后续提取和删除
log_request_id(
result['request_id'],
action="generated",
model=model_endpoint,
prompt=data.get('prompt', '')
)
return jsonify({
'status': 'submitted',
'request_id': result['request_id']
}), 200
else:
return jsonify({
'status': 'error',
'error': result['error'],
'request_id': result['request_id']
}), 500
except Exception as e:
return jsonify({'error': str(e)}), 500
@api.route('/status/<request_id>', methods=['GET'])
@log_api_call
def check_status(request_id):
"""
检查生成状态 - 解决FAL子路径问题
按照专家建议,正确处理model endpoint的子路径
"""
try:
# 获取API密钥
api_key = get_api_key_from_request(request)
if not api_key:
return jsonify({'error': 'API key not provided'}), 401
# 获取模型端点(需要知道原始模型以便正确查询状态)
model_endpoint = request.headers.get('X-Model-Endpoint', 'fal-ai/bytedance/seedream/v4/edit')
# 查询状态
client = FALClient(api_key)
result = client.get_status(model_endpoint, request_id)
if result['success']:
response = {
'request_id': request_id,
'status': result['status'], # 已经是小写,不需要再次转换
'logs': result['logs']
}
# 添加队列位置信息
if 'queue_position' in result:
response['queue_position'] = result['queue_position']
# 如果已完成,包含结果
if result.get('result'):
response['result'] = result['result']
return jsonify(response), 200
else:
# ✅ 返回200而不是500,让前端显示错误信息
return jsonify({
'request_id': request_id,
'status': 'error',
'error': result['error']
}), 200
except Exception as e:
# ✅ 返回200而不是500,让前端显示错误信息
return jsonify({
'request_id': request_id,
'status': 'error',
'error': str(e)
}), 200
@api.route('/upload', methods=['POST'])
def upload_file():
"""文件上传接口 - 简化处理"""
try:
if 'file' not in request.files:
return jsonify({'error': 'No file provided'}), 400
file = request.files['file']
if file.filename == '':
return jsonify({'error': 'No file selected'}), 400
# 转换为base64 data URL
file_content = file.read()
file_type = file.content_type or 'application/octet-stream'
base64_content = base64.b64encode(file_content).decode('utf-8')
data_url = f"data:{file_type};base64,{base64_content}"
return jsonify({'url': data_url}), 200
except Exception as e:
return jsonify({'error': str(e)}), 500
@api.route('/upload-to-fal', methods=['POST'])
def upload_to_fal():
"""上传到FAL存储 - 简化处理"""
try:
data = request.json
if 'image_data' not in data:
return jsonify({'error': 'No image data provided'}), 400
# 获取API密钥
api_key = get_api_key_from_request(request)
if not api_key:
return jsonify({'error': 'API key not provided'}), 401
# 上传文件
client = FALClient(api_key)
result = client.upload_file(data['image_data'])
if result['success']:
return jsonify({'url': result['url']}), 200
else:
return jsonify({'error': result['error']}), 500
except Exception as e:
return jsonify({'error': str(e)}), 500
@api.route('/health', methods=['GET'])
def health_check():
"""健康检查"""
return jsonify(get_health_status()), 200