Last active
January 9, 2025 10:17
-
-
Save rodrigobdz/8175885eb690f9bb5483ddabebc6a426 to your computer and use it in GitHub Desktop.
Parse JSON response from OpenAI API containing content or refusal
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
import logging | |
# Set up logger | |
logging.basicConfig(level=logging.WARNING) | |
logger = logging.getLogger(__name__) | |
# Modified JSON from https://platform.openai.com/docs/api-reference/chat/object | |
response_str = json.dumps({ | |
"id": "chatcmpl-123456", | |
"object": "chat.completion", | |
"created": 1728933352, | |
"model": "gpt-4o-2024-08-06", | |
"choices": [ | |
{ | |
"index": 0, | |
"message": { | |
"role": "assistant", | |
"content": None, | |
"refusal": "Refusing to answer" | |
}, | |
"logprobs": None, | |
"finish_reason": "stop" | |
} | |
], | |
"usage": { | |
"prompt_tokens": 19, | |
"completion_tokens": 10, | |
"total_tokens": 29, | |
"prompt_tokens_details": { | |
"cached_tokens": 0 | |
}, | |
"completion_tokens_details": { | |
"reasoning_tokens": 0, | |
"accepted_prediction_tokens": 0, | |
"rejected_prediction_tokens": 0 | |
} | |
}, | |
"system_fingerprint": "fp_6b68a8204b" | |
}) | |
class JSONObject: | |
def __init__(self, dictionary): | |
for key, value in dictionary.items(): | |
if isinstance(value, dict): | |
setattr(self, key, JSONObject(value)) | |
elif isinstance(value, list): | |
setattr(self, key, [JSONObject(item) if isinstance(item, dict) else item for item in value]) | |
else: | |
setattr(self, key, value) | |
def __repr__(self): | |
return str(self.__dict__) # Provides a readable string representation of the object | |
# Convert JSON string to custom objects | |
response = json.loads(response_str, object_hook=lambda d: JSONObject(d)) | |
# Parse content or refusal in API response | |
try: | |
# Ensure there are choices in the response | |
if not response.choices: | |
raise ValueError(f"The response does not contain any choices.") | |
# Extract the first choice and its message | |
first_choice = response.choices[0] | |
message = getattr(first_choice, "message", None) | |
# Ensure the message has the required attributes | |
if not message or not hasattr(message, "role"): | |
raise ValueError(f"The response message lacks the required 'role' field. Response:\n{response}") | |
# Use content if available, otherwise fallback to refusal | |
content = getattr(message, "content", None) | |
refusal = getattr(message, "refusal", None) | |
if not content and refusal: | |
logger.warning(f"Message content is empty. Using 'refusal' instead. Response:\n{response}") | |
if not content and not refusal: | |
raise ValueError(f"Content and refusal empty in response. Response:\n{response}") | |
print('Content or refusal: ', content or refusal) | |
except (AttributeError, IndexError, TypeError) as e: | |
raise ValueError(f"Invalid response structure. Response:\n{response}") from e |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Expected output: