Skip to content

Commit

Permalink
added grading function
Browse files Browse the repository at this point in the history
  • Loading branch information
aishwaryats committed Jul 10, 2024
1 parent e917d8a commit 0a5ff04
Show file tree
Hide file tree
Showing 7,762 changed files with 3,637,557 additions and 15 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
5 changes: 5 additions & 0 deletions .firebaserc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"projects": {
"default": "gradeease-57107"
}
}
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ dist-ssr
*.sln
*.sw?
.env

api/firebase-SA.json
api/gcloud-SA.json
api/openAPI
functions/firebase-SA.json
functions/gcloud.SA.json
Binary file added api/__pycache__/main.cpython-312.pyc
Binary file not shown.
Binary file added api/__pycache__/openAPI.cpython-312.pyc
Binary file not shown.
Binary file added api/__pycache__/read_from_db.cpython-312.pyc
Binary file not shown.
Binary file added api/__pycache__/readtrial.cpython-312.pyc
Binary file not shown.
Binary file added api/__pycache__/textrecog.cpython-312.pyc
Binary file not shown.
Binary file added api/__pycache__/write_to_db.cpython-312.pyc
Binary file not shown.
18 changes: 18 additions & 0 deletions api/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from typing import Union

from fastapi import FastAPI

#from readtrial import get_all_docs
from openAPI import main as openapimain

app = FastAPI()


@app.get("/read_firebase_data")
def read_firebase_data(param1: str, param2: str):
# Call the function from readtrial.py to read data from Firebase
#res=get_all_docs("trial1")
#return res
openapimain(param1,param2)
res="something"
return res
75 changes: 75 additions & 0 deletions api/openAPI.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import openai
import re
from firebase_admin import firestore
from read_from_db import main as readFromDb

# qnpaper_id='5'
# anspaper_id='ans002'
# doc_list=readFromDb(qnpaper_id,anspaper_id)

# API_KEY = open("openAPI", "r").read().strip()
# client = openai.OpenAI(api_key=API_KEY)

def extract_numbers(text):
# Use regular expression to find all numeric parts
numbers = re.findall(r'\d+', text)
# Convert the list of strings to integers
numbers = [int(num) for num in numbers]
return numbers

def update_documents(collection_name, qnpaper_id, anspaper_id, update_data, qn_no, db):
# Get a reference to the documents that match the query criteria
docs_ref = db.collection(collection_name).where("qnpaper_id", "==", qnpaper_id).where("anspaper_id", "==", anspaper_id).where("question_no", "==", qn_no).stream()

# Iterate over the documents and update each one
for doc in docs_ref:
doc_ref = db.collection(collection_name).document(doc.id)
doc_ref.update(update_data)

def main(qnpaper_id,anspaper_id):
# qnpaper_id='5'
# anspaper_id='ans002'

doc_list=readFromDb(qnpaper_id,anspaper_id)

API_KEY = open("openAPI", "r").read().strip()
client = openai.OpenAI(api_key=API_KEY)

response = client.chat.completions.create(model = "gpt-3.5-turbo",
messages = [{"role": "user","content":"Ignore all previous instructions. Assume you are a high school teacher who is going to grade the exam answer papers of your students. Problem=Analyze each answer with respect to the answer key, the question given and maximum marks. You have to grade the answers based on two factors: 1. Whether the content of the answer is aligned with what the question has asked and the keywords given in the answer key, 2. Whether the answer contains enough number of valid points corresponding to the maximum marks. Example, if the question is to 'write about the 3 types of rocks' for 6 marks, the student has to describe each of the three types of rocks with a minimum of 2 valid points. Another example, if the question is to 'differentiate between system software and application software for 3 marks, the student has to give a minimum of 3 valid points for each type of software in order to be awarded full marks. The output should only contain the marks awarded to that specific answer. Can you acknowledge that you have read my problem by saying READ and don't say anything else yet."}])

content = response.choices[0].message.content

print(content)

for doc_data in doc_list:
data=doc_data['doc_data']
qn=data['question']
qn_no=data['question_no']
ans_key=data['answer_key']
ans=data['student_answer']
print(ans)
max_marks=data['max_marks']


response = client.chat.completions.create(model = "gpt-3.5-turbo",
messages = [{"role": "user","content":f"Question= {qn},Student answer={ans},Answer key={ans_key},Maximum marks={max_marks}, How much marks will you give for this answer considering the question, the answer key and the maximun marks?Give full marks only if number of valid points equals the maximum marks. Otherwise reduce marks accordingly. Mention the score in number."}],
temperature=0.2,
max_tokens=100)

content = response.choices[0].message.content
print(content)
marks = extract_numbers(content)
obtained_marks=marks[0]
update_data={'obtained_marks':str(obtained_marks)}
print(update_data)
# Write data to Firestore with the specified document ID
db=firestore.client()
#MENTION THE CORRECT COLLECTION NAME
update_documents('gradingtrial', qnpaper_id, anspaper_id, update_data, qn_no,db)



if __name__ == "__main__":
main()

31 changes: 31 additions & 0 deletions api/read_from_db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from firebase_admin import firestore
from write_to_db import main as write2db

# cred = credentials.Certificate('firebase-SA.json')
# firebase_admin.initialize_app(cred)

def get_all_docs(collectionName,qnpaper_id, anspaper_id):
db=firestore.client()
docs = (
db.collection(collectionName)
.where("qnpaper_id", "==", qnpaper_id)
.where("anspaper_id", "==", anspaper_id)
.stream()
)

documents_list=[]
for doc in docs:
doc_data=doc.to_dict()
doc_data['id'] = doc.id
doc_data['doc_data']=doc._data
documents_list.append(doc_data)
return documents_list

def main(qnpaper_id,anspaper_id):

write2db(qnpaper_id,anspaper_id)

#MENTION THE CORRECT COLLECTION NAME
doc_list=get_all_docs("gradingtrial",qnpaper_id,anspaper_id)
print("Data read from DB")
return doc_list
107 changes: 107 additions & 0 deletions api/textrecog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import os
import firebase_admin
from firebase_admin import storage
from firebase_admin import firestore
from google.cloud import vision_v1
import cv2
import numpy as np
from firebase_admin import credentials

os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = r'gcloud-SA.json'

# Initialize the client with explicit credentials
client = vision_v1.ImageAnnotatorClient()

def download_image_from_storage(image_id):
bucket = storage.bucket()
#trial is the name of the folder in which thr images are uploaded. CHECK if its correct
blob = bucket.blob(f'trial/{image_id}.jpg') # Replace 'jpg' with the actual image format
image_data = blob.download_as_bytes()
return image_data

def preprocess_image(image_data):
# Convert byte data to numpy array for processing
np_array = np.frombuffer(image_data, np.uint8)
# Decode numpy array into an image
image = cv2.imdecode(np_array, cv2.IMREAD_GRAYSCALE)

# Preprocessing steps
# Noise reduction
denoised_image = cv2.fastNlMeansDenoising(image, None, h=10, templateWindowSize=7, searchWindowSize=21)

# Binarization
_, binary_image = cv2.threshold(denoised_image, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

return binary_image

def detect_text(image_data):
binary_image = preprocess_image(image_data)
image = vision_v1.Image(content=cv2.imencode('.jpg', binary_image)[1].tobytes())
response = client.text_detection(image=image)
return response.text_annotations[0].description if response.text_annotations else None

def parse_answers(text):
answers = {}
current_question = None
lines = text.split('\n')
for line in lines:
# Check if line starts with a numeric value followed by a period
if line.strip() and line.strip()[0].isdigit() and '.' in line:
question_number, answer = line.strip().split('.', 1)
current_question = int(question_number)
answers[current_question] = answer.strip()
elif current_question is not None:
# If current_question is set, append line to existing answer
answers[current_question] += ' ' + line.strip()
return answers

def retrieve_imgid(doc_id, key, collection_name):

# Access Firestore database
db = firestore.client()

# Get a reference to the document
doc_ref = db.collection(collection_name).document(doc_id)

# Get the document snapshot
doc = doc_ref.get()

# Check if the document exists
if doc.exists:
# Get the value corresponding to the key
value = doc.to_dict().get(key)
if value is not None:
print("Value for key '{}' in document '{}' in collection '{}': {}".format(key, doc_id, collection_name, value))
return value
else:
print("Key '{}' not found in document '{}' in collection '{}'.".format(key, doc_id, collection_name))
#following stmt can be removed
return value
else:
print("Document '{}' not found in collection '{}'.".format(doc_id, collection_name))
#following stmt can be removed
return value


def process_text(id, input,collectionName):
image_id_with_extension=retrieve_imgid(id, input, collectionName)
image_id = image_id_with_extension.split('.')[0]
image_data = download_image_from_storage(image_id)
detected_text = detect_text(image_data)
parsed_text = parse_answers(detected_text)
return parsed_text


def main(qnpaper_id,anspaper_id):

cred = credentials.Certificate('firebase-SA.json')
firebase_admin.initialize_app(cred,{
'storageBucket': 'gradeease-57107.appspot.com'
})


parsed_questions=process_text(qnpaper_id, "question_paper", "trial")
parsed_key=process_text(qnpaper_id, "answer_key", "trial")
parsed_answers=process_text(anspaper_id,"answer_paper", "anspapertrial")
print("*******Text Recognised...**********")
return parsed_questions, parsed_key, parsed_answers
41 changes: 41 additions & 0 deletions api/write_to_db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from firebase_admin import firestore
from textrecog import main as textrec

def convert_to_dict_qn(questions,answerkey,answers, qnpaper_id, anspaper_id):

db=firestore.client()
# Iterate over each question
for key, value in questions.items():
formatted_set = {}
question, marks = value.rsplit('(', 1)
# Remove ' marks)' from the marks part to get only the numeric value
marks = marks.replace(' marks)', '')
# Create the dictionary
formatted_set["qnpaper_id"] = qnpaper_id
formatted_set["anspaper_id"] = anspaper_id
formatted_set["question_no"] = key
formatted_set["question"] = question
formatted_set["max_marks"] = marks

formatted_set["answer_key"] = answerkey[key]

formatted_set["student_answer"] = answers[key]

# #for testing
# print("printing formatted set one by one")
# print("formatted_set: ", formatted_set)

#MENTION THE CORRECT COLLECTION NAME
doc_ref = db.collection("gradingtrial").document()
doc_ref.set(formatted_set)


def main(qnpaper_id, anspaper_id):

parsed_questions,parsed_key,parsed_answers = textrec(qnpaper_id,anspaper_id)
convert_to_dict_qn(parsed_questions,parsed_key,parsed_answers, qnpaper_id, anspaper_id)
print("Written to DB..")


# if __name__ == "__main__":
# main()
6 changes: 6 additions & 0 deletions database.rules.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"rules": {
".read": false,
".write": false
}
}
72 changes: 72 additions & 0 deletions firebase.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{
"database": {
"rules": "database.rules.json"
},
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
},
"functions": [
{
"source": "functions",
"codebase": "default",
"ignore": [
"venv",
".git",
"firebase-debug.log",
"firebase-debug.*.log"
]
}
],
"hosting": {
"public": "public",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
"storage": {
"rules": "storage.rules"
},
"emulators": {
"auth": {
"port": 9099
},
"functions": {
"port": 5001
},
"firestore": {
"port": 8080
},
"database": {
"port": 9000
},
"hosting": {
"port": 5000
},
"pubsub": {
"port": 8085
},
"storage": {
"port": 9199
},
"eventarc": {
"port": 9299
},
"ui": {
"enabled": true
},
"singleProjectMode": true
},
"remoteconfig": {
"template": "remoteconfig.template.json"
},
"extensions": {}
}
4 changes: 4 additions & 0 deletions firestore.indexes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"indexes": [],
"fieldOverrides": []
}
9 changes: 9 additions & 0 deletions firestore.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
rules_version = '2';

service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}
Empty file added functions/.gitignore
Empty file.
Binary file added functions/__pycache__/main.cpython-312.pyc
Binary file not shown.
Binary file added functions/__pycache__/openAPI.cpython-312.pyc
Binary file not shown.
Binary file not shown.
Binary file added functions/__pycache__/readtrial.cpython-312.pyc
Binary file not shown.
Binary file added functions/__pycache__/textrecog.cpython-312.pyc
Binary file not shown.
Binary file added functions/__pycache__/write_to_db.cpython-312.pyc
Binary file not shown.
Loading

0 comments on commit 0a5ff04

Please sign in to comment.