Used main as base branch in the last time
This commit is contained in:
3
.env
3
.env
@@ -1,5 +1,6 @@
|
|||||||
OPENAI_API_KEY=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
|
OPENAI_API_KEY=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
|
||||||
JWT_SECRET_KEY=6e9c124ba92e8814719dcb0f21200c8aa4d0f119a994ac5e06eb90a366c83ab2
|
JWT_SECRET_KEY=6e9c124ba92e8814719dcb0f21200c8aa4d0f119a994ac5e06eb90a366c83ab2
|
||||||
JWT_TEST_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0In0.Emrs2D3BmMP4b3zMjw0fJTPeyMwWEBDbxx2vvaWguO0
|
JWT_TEST_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0In0.Emrs2D3BmMP4b3zMjw0fJTPeyMwWEBDbxx2vvaWguO0
|
||||||
GOOGLE_APPLICATION_CREDENTIALS=firebase-configs/storied-phalanx-349916.json
|
GOOGLE_APPLICATION_CREDENTIALS=firebase-configs/test_firebase.json
|
||||||
HEY_GEN_TOKEN=MjY4MDE0MjdjZmNhNDFmYTlhZGRkNmI3MGFlMzYwZDItMTY5NTExNzY3MA==
|
HEY_GEN_TOKEN=MjY4MDE0MjdjZmNhNDFmYTlhZGRkNmI3MGFlMzYwZDItMTY5NTExNzY3MA==
|
||||||
|
GPT_ZERO_API_KEY=0195b9bb24c5439899f71230809c74af
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@ __pycache__
|
|||||||
.idea
|
.idea
|
||||||
.env
|
.env
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
/firebase-configs/test_firebase.json
|
||||||
|
|||||||
8
.idea/.gitignore
generated
vendored
8
.idea/.gitignore
generated
vendored
@@ -1,8 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
# Editor-based HTTP Client requests
|
|
||||||
/httpRequests/
|
|
||||||
# Datasource local storage ignored files
|
|
||||||
/dataSources/
|
|
||||||
/dataSources.local.xml
|
|
||||||
20
.idea/ielts-be.iml
generated
20
.idea/ielts-be.iml
generated
@@ -1,24 +1,14 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<module type="PYTHON_MODULE" version="4">
|
<module type="PYTHON_MODULE" version="4">
|
||||||
<component name="Flask">
|
|
||||||
<option name="enabled" value="true" />
|
|
||||||
</component>
|
|
||||||
<component name="NewModuleRootManager">
|
<component name="NewModuleRootManager">
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Python 3.9" jdkType="Python SDK" />
|
<orderEntry type="jdk" jdkName="Python 3.11 (ielts-be)" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PackageRequirementsSettings">
|
<component name="PyDocumentationSettings">
|
||||||
<option name="versionSpecifier" value="Don't specify version" />
|
<option name="format" value="GOOGLE" />
|
||||||
</component>
|
<option name="myDocStringFormat" value="Google" />
|
||||||
<component name="TemplatesService">
|
|
||||||
<option name="TEMPLATE_CONFIGURATION" value="Jinja2" />
|
|
||||||
<option name="TEMPLATE_FOLDERS">
|
|
||||||
<list>
|
|
||||||
<option value="$MODULE_DIR$/../flaskProject\templates" />
|
|
||||||
</list>
|
|
||||||
</option>
|
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
8
.idea/misc.xml
generated
8
.idea/misc.xml
generated
@@ -1,4 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9" project-jdk-type="Python SDK" />
|
<component name="Black">
|
||||||
|
<option name="sdkName" value="Python 3.11 (ielts-be)" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 (ielts-be)" project-jdk-type="Python SDK" />
|
||||||
|
<component name="PyCharmProfessionalAdvertiser">
|
||||||
|
<option name="shown" value="true" />
|
||||||
|
</component>
|
||||||
</project>
|
</project>
|
||||||
2
.idea/vcs.xml
generated
2
.idea/vcs.xml
generated
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
<mapping directory="" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
9
app.py
9
app.py
@@ -15,6 +15,7 @@ from helper.heygen_api import create_video, create_videos_and_save_to_db
|
|||||||
from helper.openai_interface import *
|
from helper.openai_interface import *
|
||||||
from helper.question_templates import *
|
from helper.question_templates import *
|
||||||
from helper.speech_to_text_helper import *
|
from helper.speech_to_text_helper import *
|
||||||
|
from helper.gpt_zero import GPTZero
|
||||||
from heygen.AvatarEnum import AvatarEnum
|
from heygen.AvatarEnum import AvatarEnum
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
@@ -30,6 +31,8 @@ FIREBASE_BUCKET = os.getenv('FIREBASE_BUCKET')
|
|||||||
|
|
||||||
firebase_admin.initialize_app(cred)
|
firebase_admin.initialize_app(cred)
|
||||||
|
|
||||||
|
gpt_zero = GPTZero(os.getenv('GPT_ZERO_API_KEY'))
|
||||||
|
|
||||||
thread_event = threading.Event()
|
thread_event = threading.Event()
|
||||||
|
|
||||||
# Configure logging
|
# Configure logging
|
||||||
@@ -309,6 +312,9 @@ def grade_writing_task_1():
|
|||||||
response["perfect_answer"] = get_perfect_answer(question, 150)["perfect_answer"]
|
response["perfect_answer"] = get_perfect_answer(question, 150)["perfect_answer"]
|
||||||
response["overall"] = fix_writing_overall(response["overall"], response["task_response"])
|
response["overall"] = fix_writing_overall(response["overall"], response["task_response"])
|
||||||
response['fixed_text'] = get_fixed_text(answer)
|
response['fixed_text'] = get_fixed_text(answer)
|
||||||
|
ai_detection = gpt_zero.run_detection(answer)
|
||||||
|
if ai_detection is not None:
|
||||||
|
response['ai_detection'] = ai_detection
|
||||||
return response
|
return response
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
@@ -449,6 +455,9 @@ def grade_writing_task_2():
|
|||||||
response["perfect_answer"] = get_perfect_answer(question, 250)["perfect_answer"]
|
response["perfect_answer"] = get_perfect_answer(question, 250)["perfect_answer"]
|
||||||
response["overall"] = fix_writing_overall(response["overall"], response["task_response"])
|
response["overall"] = fix_writing_overall(response["overall"], response["task_response"])
|
||||||
response['fixed_text'] = get_fixed_text(answer)
|
response['fixed_text'] = get_fixed_text(answer)
|
||||||
|
ai_detection = gpt_zero.run_detection(answer)
|
||||||
|
if ai_detection is not None:
|
||||||
|
response['ai_detection'] = ai_detection
|
||||||
return response
|
return response
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
|
|||||||
49
helper/gpt_zero.py
Normal file
49
helper/gpt_zero.py
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
from logging import getLogger
|
||||||
|
from typing import Dict, Optional
|
||||||
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
class GPTZero:
|
||||||
|
_GPT_ZERO_ENDPOINT = 'https://api.gptzero.me/v2/predict/text'
|
||||||
|
|
||||||
|
def __init__(self, gpt_zero_key: str):
|
||||||
|
self._logger = getLogger(__name__)
|
||||||
|
if gpt_zero_key is None:
|
||||||
|
self._logger.warning('GPT Zero key was not included! Skipping ai detection when grading.')
|
||||||
|
self._gpt_zero_key = gpt_zero_key
|
||||||
|
self._header = {
|
||||||
|
'x-api-key': gpt_zero_key
|
||||||
|
}
|
||||||
|
|
||||||
|
def run_detection(self, text: str):
|
||||||
|
if self._gpt_zero_key is None:
|
||||||
|
return None
|
||||||
|
data = {
|
||||||
|
'document': text,
|
||||||
|
'version': '',
|
||||||
|
'multilingual': False
|
||||||
|
}
|
||||||
|
response = requests.post(self._GPT_ZERO_ENDPOINT, headers=self._header, json=data)
|
||||||
|
if response.status_code != 200:
|
||||||
|
return None
|
||||||
|
return self._parse_detection(response.json())
|
||||||
|
|
||||||
|
def _parse_detection(self, response: Dict) -> Optional[Dict]:
|
||||||
|
try:
|
||||||
|
text_scan = response["documents"][0]
|
||||||
|
filtered_sentences = [
|
||||||
|
{
|
||||||
|
"sentence": item["sentence"],
|
||||||
|
"highlight_sentence_for_ai": item["highlight_sentence_for_ai"]
|
||||||
|
}
|
||||||
|
for item in text_scan["sentences"]
|
||||||
|
]
|
||||||
|
return {
|
||||||
|
"class_probabilities": text_scan["class_probabilities"],
|
||||||
|
"confidence_category": text_scan["confidence_category"],
|
||||||
|
"predicted_class": text_scan["predicted_class"],
|
||||||
|
"sentences": filtered_sentences
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
self._logger.error(f'Failed to parse GPT\'s Zero response: {str(e)}')
|
||||||
|
return None
|
||||||
@@ -1,17 +1,19 @@
|
|||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import time
|
import time
|
||||||
|
from logging import getLogger
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
import app
|
|
||||||
from helper.constants import *
|
from helper.constants import *
|
||||||
from helper.firebase_helper import upload_file_firebase_get_url, save_to_db_with_id
|
from helper.firebase_helper import upload_file_firebase_get_url, save_to_db_with_id
|
||||||
from heygen.AvatarEnum import AvatarEnum
|
from heygen.AvatarEnum import AvatarEnum
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
|
logger = getLogger(__name__)
|
||||||
|
|
||||||
# Get HeyGen token
|
# Get HeyGen token
|
||||||
TOKEN = os.getenv("HEY_GEN_TOKEN")
|
TOKEN = os.getenv("HEY_GEN_TOKEN")
|
||||||
FIREBASE_BUCKET = os.getenv('FIREBASE_BUCKET')
|
FIREBASE_BUCKET = os.getenv('FIREBASE_BUCKET')
|
||||||
@@ -37,7 +39,7 @@ def create_videos_and_save_to_db(exercises, template, id):
|
|||||||
if found_exercises_1:
|
if found_exercises_1:
|
||||||
exercise_1 = found_exercises_1[0]
|
exercise_1 = found_exercises_1[0]
|
||||||
sp1_questions = []
|
sp1_questions = []
|
||||||
app.app.logger.info('Creating video for speaking part 1')
|
logger.info('Creating video for speaking part 1')
|
||||||
for question in exercise_1["questions"]:
|
for question in exercise_1["questions"]:
|
||||||
sp1_result = create_video(question, avatar)
|
sp1_result = create_video(question, avatar)
|
||||||
if sp1_result is not None:
|
if sp1_result is not None:
|
||||||
@@ -51,7 +53,7 @@ def create_videos_and_save_to_db(exercises, template, id):
|
|||||||
}
|
}
|
||||||
sp1_questions.append(video)
|
sp1_questions.append(video)
|
||||||
else:
|
else:
|
||||||
app.app.logger.error("Failed to create video for part 1 question: " + exercise_1["question"])
|
logger.error("Failed to create video for part 1 question: " + exercise_1["question"])
|
||||||
template["exercises"][0]["prompts"] = sp1_questions
|
template["exercises"][0]["prompts"] = sp1_questions
|
||||||
template["exercises"][0]["first_title"] = exercise_1["first_topic"]
|
template["exercises"][0]["first_title"] = exercise_1["first_topic"]
|
||||||
template["exercises"][0]["second_title"] = exercise_1["second_topic"]
|
template["exercises"][0]["second_title"] = exercise_1["second_topic"]
|
||||||
@@ -62,7 +64,7 @@ def create_videos_and_save_to_db(exercises, template, id):
|
|||||||
# Check if any elements were found
|
# Check if any elements were found
|
||||||
if found_exercises_2:
|
if found_exercises_2:
|
||||||
exercise_2 = found_exercises_2[0]
|
exercise_2 = found_exercises_2[0]
|
||||||
app.app.logger.info('Creating video for speaking part 2')
|
logger.info('Creating video for speaking part 2')
|
||||||
sp2_result = create_video(exercise_2["question"], avatar)
|
sp2_result = create_video(exercise_2["question"], avatar)
|
||||||
if sp2_result is not None:
|
if sp2_result is not None:
|
||||||
sound_file_path = VIDEO_FILES_PATH + sp2_result
|
sound_file_path = VIDEO_FILES_PATH + sp2_result
|
||||||
@@ -76,7 +78,7 @@ def create_videos_and_save_to_db(exercises, template, id):
|
|||||||
template["exercises"][1]["video_url"] = sp2_video_url
|
template["exercises"][1]["video_url"] = sp2_video_url
|
||||||
template["exercises"][1]["video_path"] = sp2_video_path
|
template["exercises"][1]["video_path"] = sp2_video_path
|
||||||
else:
|
else:
|
||||||
app.app.logger.error("Failed to create video for part 2 question: " + exercise_2["question"])
|
logger.error("Failed to create video for part 2 question: " + exercise_2["question"])
|
||||||
|
|
||||||
# Speaking 3
|
# Speaking 3
|
||||||
# Using list comprehension to find the element with the desired value in the 'type' field
|
# Using list comprehension to find the element with the desired value in the 'type' field
|
||||||
@@ -85,7 +87,7 @@ def create_videos_and_save_to_db(exercises, template, id):
|
|||||||
if found_exercises_3:
|
if found_exercises_3:
|
||||||
exercise_3 = found_exercises_3[0]
|
exercise_3 = found_exercises_3[0]
|
||||||
sp3_questions = []
|
sp3_questions = []
|
||||||
app.app.logger.info('Creating videos for speaking part 3')
|
logger.info('Creating videos for speaking part 3')
|
||||||
for question in exercise_3["questions"]:
|
for question in exercise_3["questions"]:
|
||||||
result = create_video(question, avatar)
|
result = create_video(question, avatar)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
@@ -99,7 +101,7 @@ def create_videos_and_save_to_db(exercises, template, id):
|
|||||||
}
|
}
|
||||||
sp3_questions.append(video)
|
sp3_questions.append(video)
|
||||||
else:
|
else:
|
||||||
app.app.logger.error("Failed to create video for part 3 question: " + question)
|
logger.error("Failed to create video for part 3 question: " + question)
|
||||||
template["exercises"][2]["prompts"] = sp3_questions
|
template["exercises"][2]["prompts"] = sp3_questions
|
||||||
template["exercises"][2]["title"] = exercise_3["topic"]
|
template["exercises"][2]["title"] = exercise_3["topic"]
|
||||||
|
|
||||||
@@ -111,7 +113,7 @@ def create_videos_and_save_to_db(exercises, template, id):
|
|||||||
template["exercises"].pop(0)
|
template["exercises"].pop(0)
|
||||||
|
|
||||||
save_to_db_with_id("speaking", template, id)
|
save_to_db_with_id("speaking", template, id)
|
||||||
app.app.logger.info('Saved speaking to DB with id ' + id + " : " + str(template))
|
logger.info('Saved speaking to DB with id ' + id + " : " + str(template))
|
||||||
|
|
||||||
|
|
||||||
def create_video(text, avatar):
|
def create_video(text, avatar):
|
||||||
@@ -132,8 +134,8 @@ def create_video(text, avatar):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
response = requests.post(create_video_url, headers=POST_HEADER, json=data)
|
response = requests.post(create_video_url, headers=POST_HEADER, json=data)
|
||||||
app.app.logger.info(response.status_code)
|
logger.info(response.status_code)
|
||||||
app.app.logger.info(response.json())
|
logger.info(response.json())
|
||||||
|
|
||||||
# GET TO CHECK STATUS AND GET VIDEO WHEN READY
|
# GET TO CHECK STATUS AND GET VIDEO WHEN READY
|
||||||
video_id = response.json()["data"]["video_id"]
|
video_id = response.json()["data"]["video_id"]
|
||||||
@@ -152,11 +154,11 @@ def create_video(text, avatar):
|
|||||||
error = response_data["data"]["error"]
|
error = response_data["data"]["error"]
|
||||||
|
|
||||||
if status != "completed" and error is None:
|
if status != "completed" and error is None:
|
||||||
app.app.logger.info(f"Status: {status}")
|
logger.info(f"Status: {status}")
|
||||||
time.sleep(10) # Wait for 10 second before the next request
|
time.sleep(10) # Wait for 10 second before the next request
|
||||||
|
|
||||||
app.app.logger.info(response.status_code)
|
logger.info(response.status_code)
|
||||||
app.app.logger.info(response.json())
|
logger.info(response.json())
|
||||||
|
|
||||||
# DOWNLOAD VIDEO
|
# DOWNLOAD VIDEO
|
||||||
download_url = response.json()['data']['video_url']
|
download_url = response.json()['data']['video_url']
|
||||||
@@ -170,8 +172,8 @@ def create_video(text, avatar):
|
|||||||
output_path = os.path.join(output_directory, output_filename)
|
output_path = os.path.join(output_directory, output_filename)
|
||||||
with open(output_path, 'wb') as f:
|
with open(output_path, 'wb') as f:
|
||||||
f.write(response.content)
|
f.write(response.content)
|
||||||
app.app.logger.info(f"File '{output_filename}' downloaded successfully.")
|
logger.info(f"File '{output_filename}' downloaded successfully.")
|
||||||
return output_filename
|
return output_filename
|
||||||
else:
|
else:
|
||||||
app.app.logger.error(f"Failed to download file. Status code: {response.status_code}")
|
logger.error(f"Failed to download file. Status code: {response.status_code}")
|
||||||
return None
|
return None
|
||||||
|
|||||||
Reference in New Issue
Block a user