서비스 소개
다가온 시험기간. 강의자료만 붙들고 외우고 있는 당신. 당신의 실력이 어느 정도인지 파악하고 싶지 않으신가요?
“Chatster”를 통해 당신이 가지고 있는 PDF로 문제를 만들고 당신의 실력을 테스트해보세요.

🤷서비스 배경
- 공부를 하다 보면, 개념은 알지만 이 개념을 통해서 어떻게 문제가 나올 지 모르기에, 본인이 정확하게 무엇을 모르는지도 모르는 경우가 많습니다. 이에 불편함을 느낀 저희는 PDF를 첨부하면 문제를 만들어주는 서비스를 개발하게 되었습니다.
🤷♀️서비스 대상
- 교수님 혹은 선생님이 주신 강의자료로부터 문제를 만들어서 본인의 실력을 테스트해보고 싶은 학생
🤷♂️서비스 목적
- 본인이 공부한 강의자료를 바탕으로 만들어진 문제를 풀어 봄으로써, 메타 인지 능력을 향상시키고자 하여 이 서비스를 고안하게 되었습니다.
※ 메타 인지란? 자기 자신이 인지하고 있음을 아는 것, 즉 "자신이 알고 있는지 모르고 있는지를 안다"라는 뜻입니다.
서비스 플로우
1. Main Page: PDF를 업로드하고 해당 PDF에서 문제를 출제할 페이지와 출제할 문제 수를 입력하는 페이지

2. Loading Page: GPT가 문제를 생성하는 동안 표시되는 페이지

3. Questions Page: GPT가 출제한 문제를 화면에 제시하여 웹상에서 직접 문제풀이가 가능하도록 함


4. Answers Page: 오답 여부를 파악하고, 풀이를 확인할 수 있는 페이지로, 출제된 문제를 TXT 파일 형태로 다운로드받을 수 있음


서비스 링크
배포 링크: https://port-0-ms-azure-17xqnr2llgujko5k.sel3.cloudtype.app/
git repository: https://github.com/wldnd2/MS_Azure.git
※ 배포 툴 (cloudtype) 의 무료 용량 제한으로 인해, 배포 링크를 통해 실행하게 되면 1페이지당 1문제씩만 문제 생성이 가능합니다. 더욱 자유로운 사용을 위해선 로컬을 통해 테스트해보심을 추천드립니다!🤓
데모 영상
사용된 스택
front-end: html, css
back-end: flask, python
distribute: cloudtype
기대 효과 & 확장 가능성
- 학생들은 이 서비스를 이용하여 본인이 공부하던 강의자료를 바탕으로 만들어진 문제를 통해 자신이 정확하게 알고있는 것과 모르고 있는 것이 무엇인지를 알 수 있을 것입니다.
- 특히, 문제을 출제해 줄 뿐만 아니라 요약 기능을 추가한다면 시험을 대비하여 강의 자료를 단기간에 암기하는 것에도 도움을 줄 것입니다.
- 논문이나 전공 서적 등의 PDF 파일을 이용하여 문제를 추출하여 학습하는 데 사용한다면, 학습 효율을 극대화시킬 것이라고 기대됩니다.
- 학원 선생님 등 문제 제작에 많은 시간을 소모하는 이들에게도 이 서비스는 유용하게 사용될 수 있습니다.
Team INFO
팀 Chatster(ChatGPT + Master) | 경북대학교 컴퓨터학부 소속
전지웅(팀장) jun000628@naver.com
김민주 kimminju77786@gmail.com
김현지 khj011030@gmail.com
이은지 leeej106@knu.ac.kr
최희정 nuly7029@gmail.com
코드 공유 (자세한 사항은 github를 확인해주세요.)
run.py
# -*- coding: utf-8 -*-
"""
pip install flask
pip install openai
pip install PyPDF2
pip install numpy
실행: python run.py
"""
import os
import json
import openai
import secrets
import numpy as np
from PyPDF2 import PdfReader
from pdf import pdf_processing
from generate_txt import generate_txt_file
from werkzeug.utils import secure_filename
from flask import Blueprint, send_file, request, redirect, url_for, render_template, Flask, session
app = Flask(__name__)
app.secret_key = secrets.token_hex(16)
app.jinja_env.add_extension('jinja2.ext.loopcontrols')
UPLOAD_FOLDER = os.getcwd() + '/uploads' # 절대 파일 경로
ALLOWED_EXTENSIONS = set(['pdf'])
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 8 * 1024 * 1024 # 16MB로 업로드 크기 제한, RequestEntityTooLarge : 크기 초과시 이 예외 발생, 처리 필요
GPT_answer = []
User_answer = []
global false_answer
false_answer = 0
def allowed_file(filename):
return '.' in filename and \\
filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
@app.route('/', methods=['GET', 'POST'])
def upload_file():
global false_answer
GPT_answer.clear()
User_answer.clear()
false_answer = 0
if request.method == 'POST':
result = request.form # start_page, end_page, num_of_questions 변수 저장
file = request.files['myfile']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
session['filename'] = filename
session['result'] = result
return redirect(url_for('questions'))
return render_template('fileupload.html') # GET
@app.route('/questions', methods=['GET', 'POST'])
def questions():
if request.method == 'POST':
for key, value in request.form.items():
User_answer.append(int(value))
return redirect(url_for('check'))
else:
GPT_answer.clear()
User_answer.clear()
filename = session.get('filename')
result = session.get('result')
result["filename"] = filename
question = pdf_processing(result["filename"], result["start_page"], result["end_page"], result["num_of_questions"], result["api"])
Qna_result = {}
Qna_number = 1
# print("***********{ PDF RESULT }***********")
# print(question)
print("\\n***********{ Questions PROCESSING }*************")
for key, value in question.items():
try:
if(value[0] == "[" and value[-1] == "]"):
print("***********{ List processing }***********")
value = json.loads(value)
for item in value:
Qna_result[Qna_number] = item
Qna_number += 1
else:
print("***********{ Json processing }***********")
Qna_result[Qna_number] = json.loads(value)
Qna_number += 1
except:
print("***********{ PASS!!!! }*************")
continue
print("\\n***********{ FINAL RESULT }*************")
print(Qna_result)
print("*******************************************")
for key, value in Qna_result.items():
GPT_answer.append(int(value["정답"]))
print(Qna_result)
session["GPT_QUESTIONS"] = json.dumps(Qna_result)
return render_template('questions.html', result=Qna_result)
@app.route('/check', methods=['GET', 'POST'])
def check():
if request.method == 'POST':
GPT_response = json.loads(session.get('GPT_QUESTIONS', '{}'))
print(GPT_response)
generate_txt_file(GPT_response)
# 다운로드할 파일 경로 설정
filepath = os.path.join(os.getcwd(), 'GPT_questions.txt')
# 파일 다운로드 함수 호출
return send_file(filepath, as_attachment=True)
else:
print("********** CHECK ***********")
print(GPT_answer)
print(User_answer)
false_answer = np.equal(GPT_answer,User_answer)
false_ans_num = len(false_answer) - sum(false_answer)
print(false_answer)
print(false_ans_num)
GPT_response = json.loads(session.get('GPT_QUESTIONS', '{}'))
return render_template('check.html', check_result=GPT_response, false_num=false_ans_num, false_answer=false_answer)
if __name__ == '__main__':
app.run()
pdf.py
import os
from werkzeug.utils import secure_filename
from flask import Blueprint, send_file, request, redirect, url_for, render_template, Flask
from PyPDF2 import PdfReader
import openai, json
def pdf_processing(filename:str, start_page, end_page, num_of_questions_per_page, api):
""" PDF 추출 Setting """
reader = PdfReader("./uploads/" + filename)
pages = reader.pages
# txt = open("./downloads/" + filename + "_questions.txt", 'w', encoding='utf-8')
questions = {}
questions_number = 1
cur_page = 0 # 현재 페이지
""" ChatGPT Setting """
OPEN_AI_API_KEY = api # 각자 키 입력 (<https://platform.openai.com/account/api-keys> 확인 ㄱ)
openai.api_key = OPEN_AI_API_KEY
model = "gpt-3.5-turbo"
messages = [ # system content 손 볼 필요 있음
{"role": "system", "content": "사용자가 전송하는 내용을 토대로 문제를 정확히 1개만 출제해. { 문제 : 질문, 1 : 첫 번째 선택지, 2 : 두 번째 선택지, 3: 세 번째 선택지, 4: 네 번째 선택지, 정답: 정답번호, 해설: 해설 } 이러한 json형태로 출력해."}
]
""" JSON Setting """
json_file_path = "./downloads/questions.json"
json_data = {}
json_data['questions'] = []
for page in pages: # 페이지별 문제 추출
cur_page += 1 # 현재 페이지 수
if cur_page < int(start_page) or cur_page > int(end_page): # start_page ~ end_page 까지만 작동
continue
query = page.extract_text() # 각 페이지에서 text 추출하여 query에 저장
print(f"-- {cur_page} 페이지 문제 추출 중 --")
messages.append({"role": "user", "content": query})
for i in range(int(num_of_questions_per_page)):
# ChatGPT API 호출하기
response = openai.ChatCompletion.create(
model=model,
messages=messages
)
answer = response['choices'][0]['message']['content']
print('answer: ',answer)
questions[questions_number] = answer
questions_number += 1
# 다음 페이지를 위해 messages에서 현재 페이지의 text로 작성된 user content 삭제
messages.pop()
# txt.close()
return questions
generate_txt.py
def generate_txt_file(GPT_questions):
with open('GPT_questions.txt', 'w', encoding='utf-8') as f:
for key, value in GPT_questions.items():
f.write(f"문제 {key}: {value['문제']}\\n")
question_num = 1
while True:
print("ddd")
try:
f.write(f"{question_num}. {value[str(question_num)]}\\n")
question_num += 1
except:
break
f.write(f"정답: {value['정답']}\\n")
f.write(f"해설: {value['해설']}\\n\\n")