submit-project / src /streamlit_app.py
koler's picture
Update src/streamlit_app.py
4536b92 verified
Raw
History Blame Contribute Delete
5.31 kB
import asyncio
import tempfile
import os
import fitz # PyMuPDF
import io
import streamlit as st
from PIL import Image
from langchain_community.document_loaders import PyPDFLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.chains import RetrievalQA
from langchain_community.llms import HuggingFacePipeline
from transformers import AutoTokenizer, pipeline, AutoModelForSeq2SeqLM
# Fix for event loop issues
if os.name == 'nt':
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
MODEL_NAME = "google/flan-t5-base"
EMBEDDING_MODEL = "sentence-transformers/all-MiniLM-L6-v2"
CHUNK_SIZE = 500
CHUNK_OVERLAP = 50
def initialize_general_model():
"""Initialize the model for general knowledge questions"""
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
model = AutoModelForSeq2SeqLM.from_pretrained(MODEL_NAME)
return pipeline(
"text2text-generation",
model=model,
tokenizer=tokenizer,
max_length=256,
temperature=0,
repetition_penalty=1.2
)
def create_vector_store(pdf_path):
"""Process PDF and create FAISS vector store"""
loader = PyPDFLoader(pdf_path)
pages = loader.load_and_split()
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=CHUNK_SIZE,
chunk_overlap=CHUNK_OVERLAP
)
texts = text_splitter.split_documents(pages)
embeddings = HuggingFaceEmbeddings(model_name=EMBEDDING_MODEL)
return FAISS.from_documents(texts, embeddings)
def create_qa_chain(vectorstore):
"""Create the Retrieval QA chain for PDF content"""
pipe = initialize_general_model()
llm = HuggingFacePipeline(pipeline=pipe)
return RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=vectorstore.as_retriever(),
return_source_documents=True
)
def render_pdf_page(pdf_bytes, page_number):
"""Render specific PDF page as image"""
doc = fitz.open(stream=pdf_bytes, filetype="pdf")
page = doc.load_page(page_number)
pix = page.get_pixmap()
img_bytes = pix.tobytes()
return Image.open(io.BytesIO(img_bytes))
def main():
st.title("VectorAsk")
st.write("Get answers with source page images!")
# Initialize session states
if 'pdf_bytes' not in st.session_state:
st.session_state.pdf_bytes = None
mode = st.radio("Select answer source:",
("PDF Content", "Text input"),
horizontal=True)
if mode == "PDF Content":
uploaded_file = st.file_uploader("Upload PDF", type="pdf")
if uploaded_file is not None:
st.session_state.pdf_bytes = uploaded_file.getvalue()
with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp_file:
tmp_file.write(st.session_state.pdf_bytes)
tmp_path = tmp_file.name
with st.spinner("Processing PDF..."):
vectorstore = create_vector_store(tmp_path)
os.remove(tmp_path)
st.session_state['qa_chain'] = create_qa_chain(vectorstore)
question = st.text_input("Enter your question:")
if question:
with st.spinner("Generating answer..."):
if mode == "General Knowledge":
if 'general_pipe' not in st.session_state:
st.session_state.general_pipe = initialize_general_model()
result = st.session_state.general_pipe(
question,
max_length=256,
temperature=0
)[0]['generated_text']
st.subheader("Answer:")
st.write(result)
st.info("This answer is generated from the model's general knowledge")
elif mode == "PDF Content":
if 'qa_chain' not in st.session_state:
st.warning("Please upload a PDF file first!")
return
result = st.session_state['qa_chain']({"query": question})
# Display answer
st.subheader("Answer:")
st.write(result["result"])
# Display source documents with images
st.subheader("Source Evidence:")
for doc in result["source_documents"]:
page_num = doc.metadata['page']
col1, col2 = st.columns([2, 3])
with col1:
try:
img = render_pdf_page(st.session_state.pdf_bytes, page_num)
st.image(img, caption=f"Page {page_num + 1}", use_column_width=True)
except Exception as e:
st.error(f"Error rendering page: {str(e)}")
with col2:
st.write(f"**Page {page_num + 1} Content:**")
st.write(doc.page_content)
st.write("---")
if __name__ == "__main__":
main()