|
13 | 13 |
|
14 | 14 | from openai import APITimeoutError, AuthenticationError, NotFoundError, BadRequestError |
15 | 15 |
|
| 16 | +from utility.utils import parse_data_url, resize_base64_image |
16 | 17 | from .chat import Chat |
17 | 18 | from .listener import SendMessageListener |
18 | 19 | from .error import StreamNotAllowedError, ResponsesApiRequiredError |
19 | 20 |
|
| 21 | + |
20 | 22 | class ChatOpenAIBase(Chat): |
| 23 | + MAX_IMAGE_SIZE_MB = 10.0 |
| 24 | + |
21 | 25 | # メッセージを送信して回答を得る(同期処理、一度きりの質問) |
22 | 26 | def send_onetime_message(self, text:str): |
23 | 27 | messages = [] |
@@ -67,10 +71,11 @@ def send_message_completions_streaming( |
67 | 71 | if text: |
68 | 72 | content.append({"type": "text", "text": text}) |
69 | 73 |
|
70 | | - for b64 in images: |
71 | | - if not b64.startswith("data:"): |
72 | | - b64 = f"data:image/png;base64,{b64}" |
73 | | - content.append({"type": "image_url", "image_url": {"url": b64}}) |
| 74 | + for image in images: |
| 75 | + media_type, subtype, b64 = parse_data_url(image) |
| 76 | + b64 = resize_base64_image(b64, max_size_mb=self.MAX_IMAGE_SIZE_MB, output_format=subtype) |
| 77 | + data_url = f"data:{media_type};base64,{b64}" |
| 78 | + content.append({"type": "image_url", "image_url": {"url": data_url}}) |
74 | 79 |
|
75 | 80 | messages.append({"role": "user", "content": content}) |
76 | 81 |
|
@@ -169,10 +174,11 @@ def send_message_completions_not_streaming( |
169 | 174 | if text: |
170 | 175 | content.append({"type": "text", "text": text}) |
171 | 176 |
|
172 | | - for b64 in images: |
173 | | - if not b64.startswith("data:"): |
174 | | - b64 = f"data:image/png;base64,{b64}" |
175 | | - content.append({"type": "image_url", "image_url": {"url": b64}}) |
| 177 | + for image in images: |
| 178 | + media_type, subtype, b64 = parse_data_url(image) |
| 179 | + b64 = resize_base64_image(b64, max_size_mb=self.MAX_IMAGE_SIZE_MB, output_format=subtype) |
| 180 | + data_url = f"data:{media_type};base64,{b64}" |
| 181 | + content.append({"type": "image_url", "image_url": {"url": data_url}}) |
176 | 182 |
|
177 | 183 | messages.append({"role": "user", "content": content}) |
178 | 184 |
|
@@ -269,7 +275,10 @@ def convert_message(m): |
269 | 275 | if images and len(images) > 0: |
270 | 276 | last_message = responses_input[-1] |
271 | 277 | for image in images: |
272 | | - last_message["content"].append({"type": "input_image", "image_url": image}) |
| 278 | + media_type, subtype, b64 = parse_data_url(image) |
| 279 | + b64 = resize_base64_image(b64, max_size_mb=self.MAX_IMAGE_SIZE_MB, output_format=subtype) |
| 280 | + data_url = f"data:{media_type};base64,{b64}" |
| 281 | + last_message["content"].append({"type": "input_image", "image_url": data_url}) |
273 | 282 |
|
274 | 283 | content = "" |
275 | 284 | sentence = "" |
@@ -327,10 +336,14 @@ def convert_message(m): |
327 | 336 | listener.on_end_response(self.bad_response) |
328 | 337 | return self.bad_response |
329 | 338 |
|
330 | | - final_response = stream.get_final_response() |
331 | | - if final_response and final_response.output: |
332 | | - # Responses API は output 内に role が入っている |
333 | | - role = final_response.output[0].role or "assistant" |
| 339 | + # final_response.output配列には複数のタイプのコンテンツが含まれる可能性があるため、 |
| 340 | + # エラーになる場合があるためコメントアウト |
| 341 | + # roleはassistantで固定で問題ないが、参考のために残しておく |
| 342 | + # |
| 343 | + #final_response = stream.get_final_response() |
| 344 | + #if final_response and final_response.output: |
| 345 | + # # Responses API は output 内に role が入っている |
| 346 | + # role = final_response.output[0].role or "assistant" |
334 | 347 |
|
335 | 348 | if sentence: |
336 | 349 | listener.on_receive_sentence(sentence) |
@@ -400,7 +413,10 @@ def convert_message(m): |
400 | 413 | if images and len(images) > 0: |
401 | 414 | last_message = responses_input[-1] |
402 | 415 | for image in images: |
403 | | - last_message["content"].append({"type": "input_image", "image_url": image}) |
| 416 | + media_type, subtype, b64 = parse_data_url(image) |
| 417 | + b64 = resize_base64_image(b64, max_size_mb=self.MAX_IMAGE_SIZE_MB, output_format=subtype) |
| 418 | + data_url = f"data:{media_type};base64,{b64}" |
| 419 | + last_message["content"].append({"type": "input_image", "image_url": data_url}) |
404 | 420 |
|
405 | 421 | response = self.client.responses.create( |
406 | 422 | model=self.model, |
|
0 commit comments