Spaces:
Sleeping
Sleeping
File size: 5,332 Bytes
4a5279c 63f5111 4a5279c 63f5111 4a5279c 63f5111 4a5279c 63f5111 4a5279c 63f5111 4a5279c 63f5111 4a5279c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
import os
import streamlit as st
import PyPDF2
import numpy as np
import faiss
from sentence_transformers import SentenceTransformer
from transformers import AutoTokenizer, AutoModelForCausalLM
from langchain.chains import ConversationalRetrievalChain
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import FAISS
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.llms import HuggingFacePipeline
from langchain.prompts import PromptTemplate
from transformers import pipeline
# Load embedding model
@st.cache_resource
def load_embedding_model():
return SentenceTransformer("all-MiniLM-L6-v2")
# Parse PDF file
def parse_pdf(file):
pdf_reader = PyPDF2.PdfReader(file)
text = ""
for page in pdf_reader.pages:
text += page.extract_text()
return text
# Split text into chunks
def split_text(text, chunk_size=500, chunk_overlap=100):
text_splitter = RecursiveCharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=chunk_overlap)
return text_splitter.split_text(text)
# Create FAISS index
def create_faiss_index(texts, embedding_model):
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
vectorstore = FAISS.from_texts(texts, embeddings)
return vectorstore
# Generate response from the model
def generate_response(prompt, model, tokenizer):
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
outputs = model.generate(**inputs, max_length=512, num_return_sequences=1)
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
return response
# Main Streamlit app
def main():
st.title("Advanced Chat with Your Document")
# Initialize session state for conversation history and documents
if "conversation_history" not in st.session_state:
st.session_state.conversation_history = []
if "vectorstore" not in st.session_state:
st.session_state.vectorstore = None
# Step 1: Upload multiple PDF files
uploaded_files = st.file_uploader("Upload PDF files", type=["pdf"], accept_multiple_files=True)
if uploaded_files:
st.write(f"{len(uploaded_files)} file(s) uploaded successfully!")
# Process PDFs
with st.spinner("Processing PDFs..."):
all_texts = []
for uploaded_file in uploaded_files:
pdf_text = parse_pdf(uploaded_file)
chunks = split_text(pdf_text)
all_texts.extend(chunks)
# Create a unified vector database
embedding_model = load_embedding_model()
st.session_state.vectorstore = create_faiss_index(all_texts, embedding_model)
st.success("PDFs processed! You can now ask questions.")
# Step 2: Chat interface
user_input = st.text_input("Ask a question about the document(s):")
if user_input:
if st.session_state.vectorstore is None:
st.error("Please upload and process documents first.")
return
with st.spinner("Generating response..."):
# Load the LLM
model_name = "meta-llama/Llama-2-7b-chat-hf" # Replace with your local path
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name, device_map="auto", torch_dtype=torch.float16)
# Set up LangChain components
retriever = st.session_state.vectorstore.as_retriever()
llm = HuggingFacePipeline(pipeline=pipeline("text-generation", model=model, tokenizer=tokenizer))
# Define a custom prompt template for Chain-of-Thought reasoning
prompt_template = """
Answer the following question based ONLY on the provided context.
If the question requires multi-step reasoning, break it down step by step.
Context: {context}
Question: {question}
Answer:
"""
prompt = PromptTemplate(template=prompt_template, input_variables=["context", "question"])
# Create a conversational retrieval chain
qa_chain = ConversationalRetrievalChain.from_llm(
llm=llm,
retriever=retriever,
combine_docs_chain_kwargs={"prompt": prompt},
return_source_documents=True
)
# Add conversation history
chat_history = st.session_state.conversation_history[-3:] # Last 3 interactions
result = qa_chain({"question": user_input, "chat_history": chat_history})
# Extract response and update conversation history
response = result["answer"]
st.session_state.conversation_history.append(f"User: {user_input}")
st.session_state.conversation_history.append(f"Bot: {response}")
st.write(f"**Response:** {response}")
# Display source documents (optional)
if "source_documents" in result:
st.subheader("Source Documents")
for doc in result["source_documents"]:
st.write(doc.page_content)
# Display conversation history
st.subheader("Conversation History")
for line in st.session_state.conversation_history:
st.write(line)
if __name__ == "__main__":
main() |