I don’t understand programming, and my system is entirely built by me describing the requirements, with GPT helping me complete all the code work.
I have already completed the development of the linear system, and it runs properly.
Now I want to transform it into a concurrent system, but I’m encountering this error, and after repeated debugging, I can’t get it to work. I hope someone can help me figure out how to complete the process of transmitting a large number of images using URLs, base64 encoding, and sending them concurrently to GPT.
I have sent the program’s runtime feedback to GPT, and it mentioned that three components are involved. I have uploaded all of them. Many thanks to the forum members for your help.
first_round_interaction.py
# -*- coding: utf-8 -*-
from logger_config import setup_logger
from image_processor import imageBase64
from schema_validator import validate_extracted_content
import os
logger = setup_logger(__name__)
class FirstRoundInteraction:
def __init__(self, model_factory, prompt_manager, data_access_manager, schema, config):
self.model_factory = model_factory
self.prompt_manager = prompt_manager
self.data_access_manager = data_access_manager
self.schema = schema
self.config = config
def process(self, image_path, student_id, image_uuid, image_filename):
try:
if self.data_access_manager.is_image_processed(image_filename, student_id):
logger.info(f"Image {image_filename} for student {student_id} already processed, skipping.")
return {'success': True, 'item': image_filename, 'status': 'skipped'}
image_data_url = imageBase64(image_path)
prompt, prompt_name = self.prompt_manager.get_prompt_for_round(1)
model = self.model_factory.get_model('first_round')
response = model.generate_response(prompt, image_data_url)
if validate_extracted_content(response, self.schema):
for problem in response['problems']:
problem_uuid = self.data_access_manager.store_problem_data(problem, image_filename, image_path,
student_id, image_uuid)
self.data_access_manager.record_interaction(problem_uuid, 1, prompt_name, model.model_name)
self.data_access_manager.mark_image_as_processed(image_filename, student_id)
return {'success': True, 'item': image_filename, 'status': 'processed'}
else:
return {'success': False, 'item': image_filename, 'status': 'invalid_response'}
except Exception as e:
logger.error(f"Error processing image {image_path}: {str(e)}", exc_info=True)
return {'success': False, 'item': image_filename, 'status': 'error', 'error': str(e)}
model_factory.py
# -*- coding: utf-8 -*-
import openai
import json
from logger_config import setup_logger
from tenacity import retry, stop_after_attempt, wait_exponential
logger = setup_logger(__name__)
def get_image_mime_type(self, image_path):
extension = image_path.lower().split('.')[-1]
mime_types = {
'jpg': 'image/jpeg',
'jpeg': 'image/jpeg',
'png': 'image/png',
'gif': 'image/gif',
'bmp': 'image/bmp',
'webp': 'image/webp',
'tiff': 'image/tiff',
'svg': 'image/svg+xml'
}
return mime_types.get(extension, 'application/octet-stream')
class GPT4oModel:
def __init__(self, api_key, base_url, model_name, max_tokens, temperature, top_p):
self.client = openai.OpenAI(api_key=api_key, base_url=base_url)
self.model_name = model_name
self.max_tokens = max_tokens
self.temperature = temperature
self.top_p = top_p
@retry(stop=stop_after_attempt(5), wait=wait_exponential(multiplier=1, min=4, max=60))
def generate_response(self, prompt, input_data=None, is_image=False):
try:
if is_image and input_data and input_data.startswith('data:image'):
messages = [
{
"role": "user",
"content": [
{
"type": "text",
"text": prompt
},
{
"type": "image_url",
"image_url": {
"url": input_data
}
}
]
}
]
full_prompt = prompt
else:
full_prompt = prompt + "\n\nInput Data:\n" + json.dumps(input_data, ensure_ascii=False, indent=2)
messages = [
{
"role": "user",
"content": full_prompt
}
]
logger.info(f"Prompt sent to GPT (first 50 chars): {full_prompt[:50]}")
response = self.client.chat.completions.create(
model=self.model_name,
messages=messages,
max_tokens=self.max_tokens,
temperature=self.temperature,
top_p=self.top_p,
response_format={"type": "json_object"},
timeout=30
)
if hasattr(response, 'choices') and len(response.choices) > 0:
content = response.choices[0].message.content
return json.loads(content)
else:
raise ValueError("Unexpected response structure")
except openai.APIError as e:
logger.error(f"OpenAI API error: {str(e)}", exc_info=True)
raise
except openai.APIConnectionError as e:
logger.error(f"OpenAI API connection error: {str(e)}", exc_info=True)
raise
except openai.RateLimitError as e:
logger.error(f"OpenAI API rate limit error: {str(e)}", exc_info=True)
raise
except Exception as e:
logger.error(f"Unexpected error generating response: {str(e)}", exc_info=True)
raise
class ModelFactory:
def __init__(self, config):
self.config = config
def get_model(self, subject_area):
model_config = self.config['model_prompt_mapping'].get(subject_area.lower(),
self.config['model_prompt_mapping']['other'])
model_name = model_config['model']
api_key = self.config['api']['key']
return GPT4oModel(
api_key=api_key,
base_url=self.config['api']['base_url'],
model_name=model_name,
max_tokens=self.config['gpt']['max_tokens'],
temperature=self.config['gpt']['temperature'],
top_p=self.config['gpt']['top_p']
)
image_processor.py
# -*- coding: utf-8 -*-
import base64
import os
import logging
import shutil
from logger_config import setup_logger, log_exception
import mimetypes
logger = setup_logger(__name__)
def imageBase64(path_of_image):
try:
with open(path_of_image, "rb") as image_file:
encoded_string = base64.b64encode(image_file.read()).decode('utf-8')
mime_type, _ = mimetypes.guess_type(path_of_image)
if mime_type is None:
mime_type = 'application/octet-stream'
data_url = f"data:{mime_type};base64,{encoded_string}"
logger.info(f"Successfully encoded image: {path_of_image}")
return data_url
except Exception as e:
log_exception(logger, e)
raise
def is_image_processed(image_name, process_log_file):
try:
if not os.path.exists(process_log_file):
logger.info(f"Process log file not found: {process_log_file}")
return False
with open(process_log_file, 'r') as file:
processed_images = file.read().splitlines()
is_processed = image_name in processed_images
logger.info(f"Image {image_name} processed status: {is_processed}")
return is_processed
except Exception as e:
log_exception(logger, e)
return False
def log_processed_image(image_name, process_log_file):
try:
os.makedirs(os.path.dirname(process_log_file), exist_ok=True)
with open(process_log_file, 'a') as file:
file.write(image_name + '\n')
logger.info(f"Logged processed image: {image_name}")
except Exception as e:
log_exception(logger, e)
raise
def move_processed_image(image_path, processed_dir):
try:
if not os.path.exists(processed_dir):
os.makedirs(processed_dir)
image_name = os.path.basename(image_path)
destination = os.path.join(processed_dir, image_name)
shutil.move(image_path, destination)
logger.info(f"Moved processed image to: {destination}")
except Exception as e:
log_exception(logger, e)
raise
Return after running the main program
INFO:model_factory:Prompt sent to GPT (first 50 chars): Extract the content from the image, focusing on th
INFO:model_factory:Prompt sent to GPT (first 50 chars): Extract the content from the image, focusing on th
ERROR:model_factory:OpenAI API error: Error code: 400 - {'error': {'message': "This model's maximum context length is 128000 tokens. However, your messages resulted in 129650 tokens. Please reduce the length of the messages. (request id: 2024090820385878799855776406962)", 'type': 'invalid_request_error', 'param': 'messages', 'code': 'context_length_exceeded'}}
Traceback (most recent call last):
File "E:\SS-learning-system\system-step-by-step\system-py-one-by-one\image-info\pythonProject\model_factory.py", line 64, in generate_response
response = self.client.chat.completions.create(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\hong\anaconda3\Lib\site-packages\openai\_utils\_utils.py", line 274, in wrapper
return func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\hong\anaconda3\Lib\site-packages\openai\resources\chat\completions.py", line 668, in create
return self._post(
^^^^^^^^^^^
File "C:\Users\hong\anaconda3\Lib\site-packages\openai\_base_client.py", line 1259, in post
return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\hong\anaconda3\Lib\site-packages\openai\_base_client.py", line 936, in request
return self._request(
^^^^^^^^^^^^^^
File "C:\Users\hong\anaconda3\Lib\site-packages\openai\_base_client.py", line 1040, in _request
raise self._make_status_error_from_response(err.response) from None
openai.BadRequestError: Error code: 400 - {'error': {'message': "This model's maximum context length is 128000 tokens. However, your messages resulted in 129650 tokens. Please reduce the length of the messages. (request id: 2024090820385878799855776406962)", 'type': 'invalid_request_error', 'param': 'messages', 'code': 'context_length_exceeded'}}