LukaVidakovic commited on
Commit
c9ba277
·
verified ·
1 Parent(s): bb24b42

Upload 4 files

Browse files
Files changed (4) hide show
  1. app.py +77 -0
  2. llm_functions.py +79 -0
  3. prompts.py +35 -0
  4. requirements.txt +8 -0
app.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from llm_functions import load_data, split_text, initialize_llm, generate_questions, create_retrieval_qa_chain
3
+
4
+ # Initialization of session states
5
+ # Since Streamlit always reruns the script when a widget changes, we need to initialize the session states
6
+ if 'questions' not in st.session_state:
7
+ st.session_state['questions'] = 'empty'
8
+ st.session_state['seperated_question_list'] = 'empty'
9
+ st.session_state['questions_to_answers'] = 'empty'
10
+ st.session_state['submitted'] = 'empty'
11
+
12
+ with st.container():
13
+ st.markdown("""# Smart Study Buddy""")
14
+
15
+ # Get user's OpenAI API Key
16
+ openai_api_key = st.text_input(label="OpenAI API Key ", placeholder="Ex: sk-2twmA8tfCb8un4...", key="openai_api_key_input", help="How to get an OpenAI API Key: https://www.howtogeek.com/885918/how-to-get-an-openai-api-key/")
17
+
18
+ # Container for markdown text
19
+ with st.container():
20
+ st.markdown("""Make sure you've entered your OpenAI API Key.
21
+ Don't have an API key yet?
22
+ Read [this](https://medium.com/@joristechtalk/how-to-get-an-openai-api-key-for-chatgpt-fd2cf6a436c5) article on how to get an API key.""")
23
+
24
+ # Let user upload a file
25
+ uploaded_file = st.file_uploader("Upload your study material", type=['pdf'])
26
+
27
+ if uploaded_file is not None:
28
+ # Check whether user entered an API key
29
+ if not openai_api_key:
30
+ st.error("Please enter your OpenAI API Key")
31
+ else:
32
+ # Load data from PDF
33
+ text_from_pdf = load_data(uploaded_file)
34
+
35
+ # Split text for question generation
36
+ documents_for_question_gen = split_text(text_from_pdf, chunk_size=10000, chunk_overlap=200)
37
+
38
+ # Split text for question answering
39
+ documents_for_question_answering = split_text(text_from_pdf, chunk_size=500, chunk_overlap=200)
40
+
41
+ # Initialize large language model for question generation
42
+ llm_question_gen = initialize_llm(openai_api_key=openai_api_key, model="gpt-3.5-turbo-16k", temperature=0.4)
43
+
44
+ # Initialize large language model for question answering
45
+ llm_question_answering = initialize_llm(openai_api_key=openai_api_key, model="gpt-3.5-turbo", temperature=0.1)
46
+
47
+ # Create questions if they have not yet been generated
48
+ if st.session_state['questions'] == 'empty':
49
+ with st.spinner("Generating questions..."):
50
+ # Assign the generated questions to the session state. This way, the questions are only generated once.
51
+ st.session_state['questions'] = generate_questions(llm=llm_question_gen, chain_type="refine", documents=documents_for_question_gen)
52
+
53
+ if st.session_state['questions'] != 'empty':
54
+ # Show questions on screen. You could use st.code for easy copy-pasting.
55
+ st.info(st.session_state['questions'])
56
+
57
+ # Split questions into a list
58
+ st.session_state['questions_list'] = st.session_state['questions'].split('\n')
59
+
60
+ with st.form(key='my_form'):
61
+ # Create a list of questions that have to be answered
62
+ st.session_state['questions_to_answers'] = st.multiselect(label="Select questions to answer", options=st.session_state['questions_list'])
63
+ submitted = st.form_submit_button('Generate answers')
64
+ if submitted:
65
+ st.session_state['submitted'] = True
66
+
67
+ if st.session_state['submitted']:
68
+ # Initialize the Retrieval QA Chain
69
+ with st.spinner("Generating answers..."):
70
+ generate_answer_chain = create_retrieval_qa_chain(openai_api_key=openai_api_key, documents=documents_for_question_answering, llm=llm_question_answering)
71
+ # For each question, generate an answer
72
+ for question in st.session_state['questions_to_answers']:
73
+ # Generate answer
74
+ answer = generate_answer_chain.run(question)
75
+ # Show answer on screen
76
+ st.write(f"Question: {question}")
77
+ st.info(f"Answer: {answer}")
llm_functions.py ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain.text_splitter import TokenTextSplitter
2
+ from langchain.docstore.document import Document
3
+ from langchain_community.chat_models import ChatOpenAI
4
+ from langchain.chains.summarize import load_summarize_chain
5
+ from prompts import PROMPT_QUESTIONS, REFINE_PROMPT_QUESTIONS
6
+ from langchain.chains import RetrievalQA
7
+ from langchain_community.embeddings import OpenAIEmbeddings
8
+ from langchain_community.vectorstores import Chroma
9
+ from PyPDF2 import PdfReader
10
+
11
+
12
+ # Function to load data from PDF
13
+ def load_data(uploaded_file):
14
+ # Load data from PDF
15
+ pdf_reader = PdfReader(uploaded_file)
16
+ # Combine text from Document into one string
17
+ text = ""
18
+ for page in pdf_reader.pages:
19
+ text += page.extract_text()
20
+
21
+ return text
22
+
23
+
24
+ # Function to split text into chunks
25
+ def split_text(text, chunk_size, chunk_overlap):
26
+ # Initialize text splitter
27
+ text_splitter = TokenTextSplitter(
28
+ model_name="gpt-3.5-turbo", chunk_size=chunk_size, chunk_overlap=chunk_overlap
29
+ )
30
+
31
+ # Split text into chunks
32
+ text_chunks = text_splitter.split_text(text)
33
+
34
+ # Convert chunks to documents
35
+ documents = [Document(page_content=t) for t in text_chunks]
36
+
37
+ return documents
38
+
39
+
40
+ # Function to initialize large language model
41
+ def initialize_llm(openai_api_key, model, temperature):
42
+ # Initialize large language model
43
+ llm = ChatOpenAI(
44
+ openai_api_key=openai_api_key, model=model, temperature=temperature
45
+ )
46
+
47
+ return llm
48
+
49
+
50
+ # Function to generate questions
51
+ def generate_questions(llm, chain_type, documents):
52
+ # Initialize question chain
53
+ question_chain = load_summarize_chain(
54
+ llm=llm,
55
+ chain_type=chain_type,
56
+ question_prompt=PROMPT_QUESTIONS,
57
+ refine_prompt=REFINE_PROMPT_QUESTIONS,
58
+ )
59
+
60
+ # Generate questions
61
+ questions = question_chain.run(documents)
62
+
63
+ return questions
64
+
65
+
66
+ # Function to create Retrieval QA Chain
67
+ def create_retrieval_qa_chain(openai_api_key, documents, llm):
68
+ # Set embeddings
69
+ embeddings = OpenAIEmbeddings(openai_api_key=openai_api_key)
70
+
71
+ # Create vector database
72
+ vector_database = Chroma.from_documents(documents=documents, embedding=embeddings)
73
+
74
+ # Create Retrieval QA Chain
75
+ retrieval_qa_chain = RetrievalQA.from_chain_type(
76
+ llm=llm, chain_type="stuff", retriever=vector_database.as_retriever()
77
+ )
78
+
79
+ return retrieval_qa_chain
prompts.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain.prompts import PromptTemplate
2
+
3
+ prompt_template_questions = """
4
+ You are an expert in creating practice questions based on study material.
5
+ Your goal is to prepare a student for their an exam. You do this by asking questions about the text below:
6
+
7
+ ------------
8
+ {text}
9
+ ------------
10
+
11
+ Create questions that will prepare the student for their exam. Make sure not to lose any important information.
12
+
13
+ QUESTIONS:
14
+ """
15
+ PROMPT_QUESTIONS = PromptTemplate(template=prompt_template_questions, input_variables=["text"])
16
+
17
+ refine_template_questions = ("""
18
+ You are an expert in creating practice questions based on study material.
19
+ Your goal is to help a student prepare for an exam.
20
+ We have received some practice questions to a certain extent: {existing_answer}.
21
+ We have the option to refine the existing questions or add new ones.
22
+ (only if necessary) with some more context below.
23
+ ------------
24
+ {text}
25
+ ------------
26
+
27
+ Given the new context, refine the original questions in English.
28
+ If the context is not helpful, please provide the original questions.
29
+ QUESTIONS:
30
+ """
31
+ )
32
+ REFINE_PROMPT_QUESTIONS = PromptTemplate(
33
+ input_variables=["existing_answer", "text"],
34
+ template=refine_template_questions,
35
+ )
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ langchain
2
+ streamlit
3
+ openai
4
+ pypdf2
5
+ tiktoken
6
+ chromadb
7
+ langchain_community
8
+ langchain-community