smgc commited on
Commit
889a28b
1 Parent(s): 2950611

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +66 -60
app.py CHANGED
@@ -6,18 +6,27 @@ import random
6
  import logging
7
  import sys
8
  import re
 
9
 
10
  app = Flask(__name__)
11
 
12
  # 配置日志
13
- logging.basicConfig(
14
- level=logging.DEBUG,
15
- format='%(asctime)s [%(levelname)s] %(message)s',
16
- handlers=[
17
- logging.StreamHandler(sys.stdout)
18
- ]
 
 
19
  )
20
- logger = logging.getLogger(__name__)
 
 
 
 
 
 
21
 
22
  SYSTEM_ASSISTANT = """作为 Stable Diffusion Prompt 提示词专家,您将从关键词中创建提示,通常来自 Danbooru 等数据库。
23
  提示通常描述图像,使用常见词汇,按重要性排列,并用逗号分隔。避免使用"-"或".",但可以接受空格和自然语言。避免词汇重复。
@@ -59,7 +68,7 @@ def get_random_token(auth_header):
59
  tokens = [token.strip() for token in auth_header.split(',') if token.strip()]
60
  if not tokens:
61
  return None
62
- return f"Bearer {random.choice(tokens)}"
63
 
64
  def translate_and_enhance_prompt(prompt, auth_token):
65
  translate_url = 'https://api.siliconflow.cn/v1/chat/completions'
@@ -72,24 +81,13 @@ def translate_and_enhance_prompt(prompt, auth_token):
72
  }
73
  headers = {
74
  'Content-Type': 'application/json',
75
- 'Authorization': auth_token
76
  }
77
 
78
- logger.info(f"Sending request to {translate_url}")
79
- logger.info(f"Request headers: {headers}")
80
- logger.info(f"Request body: {json.dumps(translate_body, ensure_ascii=False)}")
81
-
82
- try:
83
- response = requests.post(translate_url, headers=headers, json=translate_body, timeout=30)
84
- logger.info(f"Response status code: {response.status_code}")
85
- logger.info(f"Response content: {response.text}")
86
-
87
- response.raise_for_status()
88
- result = response.json()
89
- return result['choices'][0]['message']['content']
90
- except requests.exceptions.RequestException as e:
91
- logger.error(f"Error in translate_and_enhance_prompt: {str(e)}")
92
- raise
93
 
94
  def extract_params_from_prompt(prompt):
95
  size_match = re.search(r'-s\s+(\S+)', prompt)
@@ -107,11 +105,34 @@ def extract_params_from_prompt(prompt):
107
  clean_prompt = re.sub(r'-o', '', clean_prompt).strip()
108
 
109
  image_size = RATIO_MAP.get(size, RATIO_MAP["16:9"])
110
- return image_size, clean_prompt, use_original
111
 
112
  @app.route('/')
113
  def index():
114
- return "text-to-image with siliconflow", 200
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
 
116
  @app.route('/ai/v1/chat/completions', methods=['POST'])
117
  def handle_request():
@@ -124,20 +145,17 @@ def handle_request():
124
  return jsonify({"error": "Bad Request: Missing required fields"}), 400
125
 
126
  prompt = messages[-1]['content']
127
- image_size, clean_prompt, use_original = extract_params_from_prompt(prompt)
128
 
129
- random_token = get_random_token(request.headers.get('Authorization'))
 
130
  if not random_token:
131
  return jsonify({"error": "Unauthorized: Invalid or missing Authorization header"}), 401
132
 
133
  if use_original:
134
  enhanced_prompt = clean_prompt
135
  else:
136
- try:
137
- enhanced_prompt = translate_and_enhance_prompt(clean_prompt, random_token)
138
- except Exception as e:
139
- logger.error(f"Error in translate_and_enhance_prompt: {str(e)}")
140
- return jsonify({"error": "Failed to enhance prompt"}), 500
141
 
142
  new_url = f'https://api.siliconflow.cn/v1/{model}/text-to-image'
143
  new_request_body = {
@@ -151,50 +169,38 @@ def handle_request():
151
  headers = {
152
  'accept': 'application/json',
153
  'content-type': 'application/json',
154
- 'Authorization': random_token
155
  }
156
 
157
- logger.info(f"Sending request to {new_url}")
158
- logger.info(f"Request headers: {headers}")
159
- logger.info(f"Request body: {json.dumps(new_request_body, ensure_ascii=False)}")
160
 
161
- try:
162
- response = requests.post(new_url, headers=headers, json=new_request_body, timeout=60)
163
- logger.info(f"Response status code: {response.status_code}")
164
- logger.info(f"Response content: {response.text}")
165
-
166
- response.raise_for_status()
167
- response_body = response.json()
168
-
169
- if 'images' in response_body and response_body['images'] and 'url' in response_body['images'][0]:
170
- image_url = response_body['images'][0]['url']
171
- logger.info(f"Successfully retrieved image URL: {image_url}")
172
- else:
173
- logger.error(f"Unexpected response structure: {response_body}")
174
- return jsonify({"error": "Unexpected response structure from image generation API"}), 500
175
- except requests.exceptions.RequestException as e:
176
- logger.error(f"Error in image generation request: {str(e)}")
177
- return jsonify({"error": "Failed to generate image"}), 500
178
- except (KeyError, IndexError, ValueError) as e:
179
- logger.error(f"Error parsing image generation response: {str(e)}")
180
- return jsonify({"error": "Failed to parse image generation response"}), 500
181
 
182
- unique_id = str(int(time.time() * 1000)) # 生成字符串类型的 unique_id
183
  current_timestamp = int(time.time())
184
  system_fingerprint = "fp_" + ''.join(random.choices('abcdefghijklmnopqrstuvwxyz0123456789', k=9))
185
 
186
  image_data = {'data': [{'url': image_url}]}
187
 
 
 
 
 
 
188
  if stream:
189
  return stream_response(unique_id, image_data, clean_prompt, enhanced_prompt, image_size, current_timestamp, model, system_fingerprint, use_original)
190
  else:
191
  return non_stream_response(unique_id, image_data, clean_prompt, enhanced_prompt, image_size, current_timestamp, model, system_fingerprint, use_original)
192
  except Exception as e:
193
- logger.error(f"Unexpected error in handle_request: {str(e)}")
194
  return jsonify({"error": f"Internal Server Error: {str(e)}"}), 500
195
 
196
  def stream_response(unique_id, image_data, original_prompt, translated_prompt, size, created, model, system_fingerprint, use_original):
197
- logger.debug("Starting stream response")
198
  return Response(stream_with_context(generate_stream(unique_id, image_data, original_prompt, translated_prompt, size, created, model, system_fingerprint, use_original)), content_type='text/event-stream')
199
 
200
  def generate_stream(unique_id, image_data, original_prompt, translated_prompt, size, created, model, system_fingerprint, use_original):
 
6
  import logging
7
  import sys
8
  import re
9
+ from logging.handlers import RotatingFileHandler
10
 
11
  app = Flask(__name__)
12
 
13
  # 配置日志
14
+ class RequestFormatter(logging.Formatter):
15
+ def format(self, record):
16
+ record.url = request.url
17
+ record.remote_addr = request.remote_addr
18
+ return super().format(record)
19
+
20
+ formatter = RequestFormatter(
21
+ '%(asctime)s - %(remote_addr)s - %(url)s - %(levelname)s - %(message)s'
22
  )
23
+
24
+ handler = RotatingFileHandler('app.log', maxBytes=10000, backupCount=3)
25
+ handler.setFormatter(formatter)
26
+ handler.setLevel(logging.INFO)
27
+
28
+ app.logger.addHandler(handler)
29
+ app.logger.setLevel(logging.INFO)
30
 
31
  SYSTEM_ASSISTANT = """作为 Stable Diffusion Prompt 提示词专家,您将从关键词中创建提示,通常来自 Danbooru 等数据库。
32
  提示通常描述图像,使用常见词汇,按重要性排列,并用逗号分隔。避免使用"-"或".",但可以接受空格和自然语言。避免词汇重复。
 
68
  tokens = [token.strip() for token in auth_header.split(',') if token.strip()]
69
  if not tokens:
70
  return None
71
+ return random.choice(tokens)
72
 
73
  def translate_and_enhance_prompt(prompt, auth_token):
74
  translate_url = 'https://api.siliconflow.cn/v1/chat/completions'
 
81
  }
82
  headers = {
83
  'Content-Type': 'application/json',
84
+ 'Authorization': f'Bearer {auth_token}'
85
  }
86
 
87
+ response = requests.post(translate_url, headers=headers, json=translate_body, timeout=30)
88
+ response.raise_for_status()
89
+ result = response.json()
90
+ return result['choices'][0]['message']['content']
 
 
 
 
 
 
 
 
 
 
 
91
 
92
  def extract_params_from_prompt(prompt):
93
  size_match = re.search(r'-s\s+(\S+)', prompt)
 
105
  clean_prompt = re.sub(r'-o', '', clean_prompt).strip()
106
 
107
  image_size = RATIO_MAP.get(size, RATIO_MAP["16:9"])
108
+ return image_size, clean_prompt, use_original, size
109
 
110
  @app.route('/')
111
  def index():
112
+ usage = """
113
+ Welcome to the text-to-image API with siliconflow!
114
+
115
+ Usage:
116
+ 1. Send a POST request to /ai/v1/chat/completions
117
+ 2. Include your prompt in the 'content' field of the last message
118
+ 3. Optional parameters:
119
+ -s <ratio>: Set image size ratio (e.g., -s 1:1, -s 16:9)
120
+ -o: Use original prompt without enhancement
121
+
122
+ Example:
123
+ {
124
+ "model": "flux",
125
+ "messages": [
126
+ {
127
+ "role": "user",
128
+ "content": "A beautiful landscape -s 16:9"
129
+ }
130
+ ]
131
+ }
132
+
133
+ For more details, please refer to the API documentation.
134
+ """
135
+ return usage, 200
136
 
137
  @app.route('/ai/v1/chat/completions', methods=['POST'])
138
  def handle_request():
 
145
  return jsonify({"error": "Bad Request: Missing required fields"}), 400
146
 
147
  prompt = messages[-1]['content']
148
+ image_size, clean_prompt, use_original, size_param = extract_params_from_prompt(prompt)
149
 
150
+ auth_header = request.headers.get('Authorization')
151
+ random_token = get_random_token(auth_header)
152
  if not random_token:
153
  return jsonify({"error": "Unauthorized: Invalid or missing Authorization header"}), 401
154
 
155
  if use_original:
156
  enhanced_prompt = clean_prompt
157
  else:
158
+ enhanced_prompt = translate_and_enhance_prompt(clean_prompt, random_token)
 
 
 
 
159
 
160
  new_url = f'https://api.siliconflow.cn/v1/{model}/text-to-image'
161
  new_request_body = {
 
169
  headers = {
170
  'accept': 'application/json',
171
  'content-type': 'application/json',
172
+ 'Authorization': f'Bearer {random_token}'
173
  }
174
 
175
+ response = requests.post(new_url, headers=headers, json=new_request_body, timeout=60)
176
+ response.raise_for_status()
177
+ response_body = response.json()
178
 
179
+ if 'images' in response_body and response_body['images'] and 'url' in response_body['images'][0]:
180
+ image_url = response_body['images'][0]['url']
181
+ else:
182
+ raise ValueError("Unexpected response structure from image generation API")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
 
184
+ unique_id = str(int(time.time() * 1000))
185
  current_timestamp = int(time.time())
186
  system_fingerprint = "fp_" + ''.join(random.choices('abcdefghijklmnopqrstuvwxyz0123456789', k=9))
187
 
188
  image_data = {'data': [{'url': image_url}]}
189
 
190
+ # Log the key information
191
+ params = f"-s {size_param}" if size_param != "16:9" else ""
192
+ params += " -o" if use_original else ""
193
+ app.logger.info(f"Status: 200 - Token: {random_token[:6]}... - Params: {params} - Image URL: {image_url}")
194
+
195
  if stream:
196
  return stream_response(unique_id, image_data, clean_prompt, enhanced_prompt, image_size, current_timestamp, model, system_fingerprint, use_original)
197
  else:
198
  return non_stream_response(unique_id, image_data, clean_prompt, enhanced_prompt, image_size, current_timestamp, model, system_fingerprint, use_original)
199
  except Exception as e:
200
+ app.logger.error(f"Error: {str(e)}")
201
  return jsonify({"error": f"Internal Server Error: {str(e)}"}), 500
202
 
203
  def stream_response(unique_id, image_data, original_prompt, translated_prompt, size, created, model, system_fingerprint, use_original):
 
204
  return Response(stream_with_context(generate_stream(unique_id, image_data, original_prompt, translated_prompt, size, created, model, system_fingerprint, use_original)), content_type='text/event-stream')
205
 
206
  def generate_stream(unique_id, image_data, original_prompt, translated_prompt, size, created, model, system_fingerprint, use_original):