Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Integration with Google Forms #23

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ Model_training/AnswerAwareQG/fine_tuned_t5_tokenizer_aaqg_2
backend/models
backend/tokenizers
backend/sample_input.py
extension/pdfjs-3.9.179-dist
extension/pdfjs-3.9.179-dist
backend/credentials.json
backend/token.json
Binary file not shown.
Binary file not shown.
206 changes: 142 additions & 64 deletions backend/server.py
Original file line number Diff line number Diff line change
@@ -1,114 +1,192 @@
import http.server
import json
import socketserver
import urllib.parse
import torch
from models.modelC.distractor_generator import DistractorGenerator
from transformers import T5ForConditionalGeneration, T5Tokenizer, pipeline
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
import json

IP='127.0.0.1'
PORT=8000
import webbrowser

def summarize(text):
summarizer=pipeline('summarization')
return summarizer(text,max_length=110)[0]['summary_text']
from apiclient import discovery
from httplib2 import Http
from oauth2client import client, file, tools

IP = "127.0.0.1"
PORT = 8000


def generate_question(context,answer,model_path, tokenizer_path):
def summarize(text):
summarizer = pipeline("summarization")
return summarizer(text, max_length=110)[0]["summary_text"]

def generate_question(context, answer, model_path, tokenizer_path):
model = T5ForConditionalGeneration.from_pretrained(model_path)
tokenizer = T5Tokenizer.from_pretrained(tokenizer_path)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)

input_text=f'answer: {answer} context: {context}'
input_text = f"answer: {answer} context: {context}"

inputs=tokenizer.encode_plus(
inputs = tokenizer.encode_plus(
input_text,
padding='max_length',
padding="max_length",
truncation=True,
max_length=512,
return_tensors='pt'
return_tensors="pt",
)

input_ids=inputs['input_ids'].to(device)
attention_mask=inputs['attention_mask'].to(device)
input_ids = inputs["input_ids"].to(device)
attention_mask = inputs["attention_mask"].to(device)

with torch.no_grad():
output=model.generate(
input_ids=input_ids,
attention_mask=attention_mask,
max_length=32
output = model.generate(
input_ids=input_ids, attention_mask=attention_mask, max_length=32
)

generated_question = tokenizer.decode(output[0], skip_special_tokens=True)
return generated_question

def generate_keyphrases(abstract, model_path,tokenizer_path):
device= torch.device('cuda' if torch.cuda.is_available() else 'cpu')

def generate_keyphrases(abstract, model_path, tokenizer_path):
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = T5ForConditionalGeneration.from_pretrained(model_path)
tokenizer = T5Tokenizer.from_pretrained(tokenizer_path)
model.to(device)
# tokenizer.to(device)
input_text=f'detect keyword: abstract: {abstract}'
input_ids=tokenizer.encode(input_text, truncation=True,padding='max_length',max_length=512,return_tensors='pt').to(device)
output=model.generate(input_ids)
keyphrases= tokenizer.decode(output[0],skip_special_tokens=True).split(',')
return [x.strip() for x in keyphrases if x != '']

def generate_qa(text):

# text_summary=summarize(text)
text_summary=text


modelA, modelB='./models/modelA','./models/modelB'
# tokenizerA, tokenizerB= './tokenizers/tokenizerA', './tokenizers/tokenizerB'
tokenizerA, tokenizerB= 't5-base', 't5-base'

answers=generate_keyphrases(text_summary, modelA, tokenizerA)

qa={}
for answer in answers:
question= generate_question(text_summary, answer, modelB, tokenizerB)
qa[question]=answer

return qa



input_text = f"detect keyword: abstract: {abstract}"
input_ids = tokenizer.encode(
input_text,
truncation=True,
padding="max_length",
max_length=512,
return_tensors="pt",
).to(device)
output = model.generate(input_ids)
keyphrases = tokenizer.decode(output[0], skip_special_tokens=True).split(",")
return [x.strip() for x in keyphrases if x != ""]


def generate_qa(self, text, question_type):
modelA, modelB = "./models/modelA", "./models/modelB"
tokenizerA, tokenizerB = "t5-base", "t5-base"
if question_type == "text":
text_summary = text
answers = generate_keyphrases(text_summary, modelA, tokenizerA)
qa = {}
for answer in answers:
question = generate_question(text_summary, answer, modelB, tokenizerB)
qa[question] = answer

return qa
if question_type == "form":
text_summary = text
answers = generate_keyphrases(text_summary, modelA, tokenizerA)
qa = {}
for answer in answers:
question = generate_question(text_summary, answer, modelB, tokenizerB)
qa[question] = answer
SCOPES = "https://www.googleapis.com/auth/forms.body"
DISCOVERY_DOC = "https://forms.googleapis.com/$discovery/rest?version=v1"

store = file.Storage("token.json")
creds = None
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets("credentials.json", SCOPES)
creds = tools.run_flow(flow, store)

form_service = discovery.build(
"forms",
"v1",
http=creds.authorize(Http()),
discoveryServiceUrl=DISCOVERY_DOC,
static_discovery=False,
)
NEW_FORM = {
"info": {
"title": "EduAid form",
}
}
requests_list = []

for index, (question, answer) in enumerate(qa.items()):
request = {
"createItem": {
"item": {
"title": question,
"questionItem": {
"question": {
"required": True,
"textQuestion": {},
}
},
},
"location": {"index": index},
}
}
requests_list.append(request)

NEW_QUESTION = {"requests": requests_list}

result = form_service.forms().create(body=NEW_FORM).execute()
question_setting = (
form_service.forms()
.batchUpdate(formId=result["formId"], body=NEW_QUESTION)
.execute()
)

edit_url = result["responderUri"]
qa["edit_url"] = edit_url
webbrowser.open_new_tab(
"https://docs.google.com/forms/d/" + result["formId"] + "/edit"
)
return qa


class QARequestHandler(http.server.BaseHTTPRequestHandler):

def do_POST(self):
def do_OPTIONS(self):
self.send_response(200)
self.send_header("Access-Control-Allow-Origin", "*")
self.send_header("Access-Control-Allow-Methods", "POST, OPTIONS")
self.send_header("Access-Control-Allow-Headers", "Content-Type")
self.send_header("Content-Length", "0")
self.end_headers()

def do_POST(self):
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()

content_length=int(self.headers["Content-Length"])
post_data=self.rfile.read(content_length).decode('utf-8')

# parsed_data=urllib.parse.parse_qs(post_data)
content_length = int(self.headers["Content-Length"])
post_data = self.rfile.read(content_length).decode("utf-8")
parsed_data = json.loads(post_data)
if self.path == "/":
input_text = parsed_data.get("input_text")
question_type = self.headers.get("Question-Type", "text")

qa = generate_qa(self, input_text, question_type)

input_text=parsed_data.get('input_text')
self.wfile.write(json.dumps(qa).encode("utf-8"))
self.wfile.flush()

qa=generate_qa(input_text)

class CustomRequestHandler(QARequestHandler):
def __init__(self, *args, **kwargs):
self.distractor_generator = kwargs.pop("distractor_generator")
super().__init__(*args, **kwargs)


self.wfile.write(json.dumps(qa).encode("utf-8"))
self.wfile.flush()

def main():
with socketserver.TCPServer((IP, PORT), QARequestHandler) as server:
print(f'Server started at http://{IP}:{PORT}')
distractor_generator = DistractorGenerator()
with socketserver.TCPServer(
(IP, PORT),
lambda x, y, z: CustomRequestHandler(
x, y, z, distractor_generator=distractor_generator
),
) as server:
print(f"Server started at http://{IP}:{PORT}")
server.serve_forever()

if __name__=="__main__":
main()


if __name__ == "__main__":
main()
5 changes: 1 addition & 4 deletions extension/html/text_input.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
<html>
<head>
<title>EduAid: Text Input</title>
<!-- <link href="https://fonts.googleapis.com/css?family=Roboto:400,500" rel="stylesheet">
<link rel="stylesheet" href="./popup.css"> -->
<script src="../pdfjs-3.9.179-dist/build/pdf.js"></script>
<link href='https://fonts.googleapis.com/css?family=Inter' rel='stylesheet'>
<link rel="stylesheet" href="../styles/text_input.css">
Expand All @@ -24,11 +22,10 @@ <h3>Generate QnA</h3>
<button id="back-button">Back</button>
<button id="next-button">Next</button>
</div>
<!-- ******************* -->
<button id="google-form-button">Generate Google Form</button>
<div id="loading-screen" class="loading-screen">
<div class="loading-spinner"></div>
</div>
<!-- ****************** -->
</main>
<script src="../js/text_input.js"></script>
</body>
Expand Down
Loading