-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fixup! ✨(backend) create ai endpoint
- Loading branch information
Showing
6 changed files
with
328 additions
and
242 deletions.
There are no files selected for viewing
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
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
Empty file.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
"""AI services.""" | ||
|
||
import json | ||
import re | ||
|
||
from django.conf import settings | ||
|
||
import requests | ||
from openai import OpenAI, OpenAIError | ||
from rest_framework import serializers | ||
|
||
ACTION_CONFIGS = { | ||
"prompt": { | ||
"system_content": ( | ||
"Answer the prompt in markdown format. Return JSON: " | ||
'{"answer": "Your markdown answer"}.' | ||
"Do not provide any other information." | ||
), | ||
"response_key": "answer", | ||
}, | ||
"correct": { | ||
"system_content": ( | ||
"Correct grammar and spelling of the markdown text, " | ||
"preserving language and markdown formatting. " | ||
'Return JSON: {"answer": "your corrected markdown text"}.' | ||
"Do not provide any other information." | ||
), | ||
"response_key": "answer", | ||
}, | ||
"rephrase": { | ||
"system_content": ( | ||
"Rephrase the given markdown text, " | ||
"preserving language and markdown formatting. " | ||
'Return JSON: {"answer": "your rephrased markdown text"}.' | ||
"Do not provide any other information." | ||
), | ||
"response_key": "answer", | ||
}, | ||
"summarize": { | ||
"system_content": ( | ||
"Summarize the markdown text, preserving language and markdown formatting. " | ||
'Return JSON: {"answer": "your markdown summary"}.' | ||
"Do not provide any other information." | ||
), | ||
"response_key": "answer", | ||
}, | ||
"translate_en": { | ||
"system_content": ( | ||
"Translate the markdown text to English, preserving markdown formatting. " | ||
'Return JSON: {"answer": "Your translated markdown text in English"}.' | ||
"Do not provide any other information." | ||
), | ||
"response_key": "answer", | ||
}, | ||
"translate_de": { | ||
"system_content": ( | ||
"Translate the markdown text to German, preserving markdown formatting. " | ||
'Return JSON: {"answer": "Your translated markdown text in German"}.' | ||
"Do not provide any other information." | ||
), | ||
"response_key": "answer", | ||
}, | ||
"translate_fr": { | ||
"system_content": ( | ||
"Translate the markdown text to French, preserving markdown formatting. " | ||
'Return JSON: {"answer": "Your translated markdown text in French"}.' | ||
"Do not provide any other information." | ||
), | ||
"response_key": "answer", | ||
}, | ||
} | ||
|
||
|
||
class AIService: | ||
"""Service class for AI-related operations.""" | ||
|
||
@staticmethod | ||
def check_configuration(): | ||
"""Ensure that the AI configuration is set properly.""" | ||
if ( | ||
settings.AI_BASE_URL is None | ||
or settings.AI_API_KEY is None | ||
or settings.AI_MODEL is None | ||
): | ||
raise serializers.ValidationError("AI configuration not set") | ||
|
||
@staticmethod | ||
def call_openai_api(action, text): | ||
"""Call the OpenAI API and return the response.""" | ||
AIService.check_configuration() | ||
|
||
try: | ||
system_content = ACTION_CONFIGS[action]["system_content"] | ||
client = OpenAI(base_url=settings.AI_BASE_URL, api_key=settings.AI_API_KEY) | ||
response_client = client.chat.completions.create( | ||
model=settings.AI_MODEL, | ||
response_format={"type": "json_object"}, | ||
messages=[ | ||
{"role": "system", "content": system_content}, | ||
{"role": "user", "content": json.dumps({"markdown_input": text})}, | ||
], | ||
) | ||
except OpenAIError as e: | ||
raise serializers.ValidationError(f"OpenAI API Error: {str(e)}") from e | ||
except requests.exceptions.RequestException as e: | ||
raise serializers.ValidationError(f"Network Error: {str(e)}") from e | ||
except Exception as e: | ||
raise serializers.ValidationError(f"Unexpected Error: {str(e)}") from e | ||
|
||
content = response_client.choices[0].message.content | ||
sanitized_content = re.sub(r"(?<!\\)\n", "\\\\n", content) | ||
sanitized_content = re.sub(r"(?<!\\)\t", "\\\\t", sanitized_content) | ||
|
||
try: | ||
json_response = json.loads(sanitized_content) | ||
except json.JSONDecodeError as e: | ||
raise serializers.ValidationError( | ||
f"AI response could not be parsed as JSON: {str(e)}" | ||
) from e | ||
|
||
if "answer" not in json_response: | ||
raise serializers.ValidationError("AI response does not contain an answer") | ||
|
||
return json_response |
Oops, something went wrong.