koler commited on
Commit
4536b92
·
verified ·
1 Parent(s): 954170a

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +145 -38
src/streamlit_app.py CHANGED
@@ -1,40 +1,147 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
 
 
4
  import streamlit as st
 
 
 
 
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import tempfile
3
+ import os
4
+ import fitz # PyMuPDF
5
+ import io
6
  import streamlit as st
7
+ from PIL import Image
8
+ from langchain_community.document_loaders import PyPDFLoader
9
+ from langchain_text_splitters import RecursiveCharacterTextSplitter
10
+ from langchain_community.embeddings import HuggingFaceEmbeddings
11
+ from langchain_community.vectorstores import FAISS
12
+ from langchain.chains import RetrievalQA
13
+ from langchain_community.llms import HuggingFacePipeline
14
+ from transformers import AutoTokenizer, pipeline, AutoModelForSeq2SeqLM
15
 
16
+ # Fix for event loop issues
17
+ if os.name == 'nt':
18
+ asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
19
+
20
+ MODEL_NAME = "google/flan-t5-base"
21
+ EMBEDDING_MODEL = "sentence-transformers/all-MiniLM-L6-v2"
22
+ CHUNK_SIZE = 500
23
+ CHUNK_OVERLAP = 50
24
+
25
+ def initialize_general_model():
26
+ """Initialize the model for general knowledge questions"""
27
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
28
+ model = AutoModelForSeq2SeqLM.from_pretrained(MODEL_NAME)
29
+
30
+ return pipeline(
31
+ "text2text-generation",
32
+ model=model,
33
+ tokenizer=tokenizer,
34
+ max_length=256,
35
+ temperature=0,
36
+ repetition_penalty=1.2
37
+ )
38
+
39
+ def create_vector_store(pdf_path):
40
+ """Process PDF and create FAISS vector store"""
41
+ loader = PyPDFLoader(pdf_path)
42
+ pages = loader.load_and_split()
43
+
44
+ text_splitter = RecursiveCharacterTextSplitter(
45
+ chunk_size=CHUNK_SIZE,
46
+ chunk_overlap=CHUNK_OVERLAP
47
+ )
48
+ texts = text_splitter.split_documents(pages)
49
+
50
+ embeddings = HuggingFaceEmbeddings(model_name=EMBEDDING_MODEL)
51
+ return FAISS.from_documents(texts, embeddings)
52
+
53
+ def create_qa_chain(vectorstore):
54
+ """Create the Retrieval QA chain for PDF content"""
55
+ pipe = initialize_general_model()
56
+ llm = HuggingFacePipeline(pipeline=pipe)
57
+
58
+ return RetrievalQA.from_chain_type(
59
+ llm=llm,
60
+ chain_type="stuff",
61
+ retriever=vectorstore.as_retriever(),
62
+ return_source_documents=True
63
+ )
64
+
65
+ def render_pdf_page(pdf_bytes, page_number):
66
+ """Render specific PDF page as image"""
67
+ doc = fitz.open(stream=pdf_bytes, filetype="pdf")
68
+ page = doc.load_page(page_number)
69
+ pix = page.get_pixmap()
70
+ img_bytes = pix.tobytes()
71
+ return Image.open(io.BytesIO(img_bytes))
72
+
73
+ def main():
74
+ st.title("VectorAsk")
75
+ st.write("Get answers with source page images!")
76
+
77
+ # Initialize session states
78
+ if 'pdf_bytes' not in st.session_state:
79
+ st.session_state.pdf_bytes = None
80
+
81
+ mode = st.radio("Select answer source:",
82
+ ("PDF Content", "Text input"),
83
+ horizontal=True)
84
+
85
+ if mode == "PDF Content":
86
+ uploaded_file = st.file_uploader("Upload PDF", type="pdf")
87
+ if uploaded_file is not None:
88
+ st.session_state.pdf_bytes = uploaded_file.getvalue()
89
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp_file:
90
+ tmp_file.write(st.session_state.pdf_bytes)
91
+ tmp_path = tmp_file.name
92
+
93
+ with st.spinner("Processing PDF..."):
94
+ vectorstore = create_vector_store(tmp_path)
95
+ os.remove(tmp_path)
96
+ st.session_state['qa_chain'] = create_qa_chain(vectorstore)
97
+
98
+ question = st.text_input("Enter your question:")
99
+
100
+ if question:
101
+ with st.spinner("Generating answer..."):
102
+ if mode == "General Knowledge":
103
+ if 'general_pipe' not in st.session_state:
104
+ st.session_state.general_pipe = initialize_general_model()
105
+
106
+ result = st.session_state.general_pipe(
107
+ question,
108
+ max_length=256,
109
+ temperature=0
110
+ )[0]['generated_text']
111
+
112
+ st.subheader("Answer:")
113
+ st.write(result)
114
+ st.info("This answer is generated from the model's general knowledge")
115
+
116
+ elif mode == "PDF Content":
117
+ if 'qa_chain' not in st.session_state:
118
+ st.warning("Please upload a PDF file first!")
119
+ return
120
+
121
+ result = st.session_state['qa_chain']({"query": question})
122
+
123
+ # Display answer
124
+ st.subheader("Answer:")
125
+ st.write(result["result"])
126
+
127
+ # Display source documents with images
128
+ st.subheader("Source Evidence:")
129
+ for doc in result["source_documents"]:
130
+ page_num = doc.metadata['page']
131
+
132
+ col1, col2 = st.columns([2, 3])
133
+ with col1:
134
+ try:
135
+ img = render_pdf_page(st.session_state.pdf_bytes, page_num)
136
+ st.image(img, caption=f"Page {page_num + 1}", use_column_width=True)
137
+ except Exception as e:
138
+ st.error(f"Error rendering page: {str(e)}")
139
+
140
+ with col2:
141
+ st.write(f"**Page {page_num + 1} Content:**")
142
+ st.write(doc.page_content)
143
+
144
+ st.write("---")
145
+
146
+ if __name__ == "__main__":
147
+ main()