AbdulHadiDev/PDF_Query_bot_using_Pinecone_and_Langchain
0
1# import os2# import pinecone3# from langchain.document_loaders import PyPDFDirectoryLoader4# from langchain.text_splitter import RecursiveCharacterTextSplitter5# from langchain_google_genai import GoogleGenerativeAIEmbeddings6# from langchain_google_genai import ChatGoogleGenerativeAI7# from langchain.vectorstores import Pinecone8# from langchain.chains import RetrievalQA9# from dotenv import load_dotenv10# import streamlit as st11 12 13# load_dotenv()14 15 16# pinecone_client = pinecone.Pinecone(17# api_key=os.getenv("PINECONE_API_KEY"), 18# environment="us-east-1" 19# )20 21# index_name = "langchainvector"22 23# embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001")24 25# def read_doc(directory):26# file_loader = PyPDFDirectoryLoader(directory)27# documents = file_loader.load()28# return documents29 30 31# doc = read_doc('documents/')32# print(f"Loaded {len(doc)} documents")33 34 35# index=Pinecone.from_documents(doc,embeddings,index_name=index_name)36 37# llm = ChatGoogleGenerativeAI(model='gemini-1.5-pro', temperature=0.9)38 39# chain = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=index.as_retriever())40 41 42# def retrieve_answers(query):43# response = chain.run(query)44# return response45 46# # Streamlit app47# st.set_page_config(page_title="Budget Bot", page_icon=":robot_face:")48# st.header("Sindh Budget Quiz bot(PDF questioning bot using Pinecone and Langchain)")49 50# user_input = st.text_input("Input:", key="input")51# submit = st.button("Ask the question")52 53 54# if submit:55# if not user_input:56# st.warning("Please enter a question.")57# else:58# try:59# answer = retrieve_answers(user_input)60# st.subheader("The Response is")61# st.write(answer)62# except Exception as e:63# st.error(f"An error occurred: {e}")64 65# Deployment on hugging face66 67import os68import time69import streamlit as st70import pinecone71from dotenv import load_dotenv72 73from langchain.document_loaders import PyPDFDirectoryLoader74from langchain.text_splitter import RecursiveCharacterTextSplitter75from langchain_google_genai import GoogleGenerativeAIEmbeddings, ChatGoogleGenerativeAI76from langchain_community.vectorstores import Pinecone as PineconeVectorStore77from langchain.chains import RetrievalQA78 79 80# =========================81# Setup & Config82# =========================83 84load_dotenv()85 86st.set_page_config(87 page_title="Sindh Budget Quiz Bot (PDF Q&A with Pinecone + LangChain)",88 page_icon=":robot_face:",89)90st.title("Sindh Budget Quiz Bot")91 92PINECONE_API_KEY = os.getenv("PINECONE_API_KEY")93GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")94 95if not PINECONE_API_KEY or not GOOGLE_API_KEY:96 st.error("❌ Missing API keys. Set PINECONE_API_KEY and GOOGLE_API_KEY in your .env or Space Secrets.")97 st.stop()98 99# Your Pinecone index details (from your dashboard screenshot)100INDEX_NAME = "langchainvector"101PINECONE_ENV = "us-east-1" # AWS us-east-1 (matches your console)102EMBED_DIM = 768 # Google "models/embedding-001" returns 768-d vectors103NAMESPACE = "__default__" # leave default unless you need multi-tenant104 105 106# =========================107# Utilities108# =========================109 110@st.cache_data(show_spinner=False)111def load_documents(directory: str):112 """Load PDFs from a directory."""113 loader = PyPDFDirectoryLoader(directory)114 docs = loader.load()115 return docs116 117@st.cache_resource(show_spinner=False)118def build_embeddings():119 """Create (and cache) the embeddings model."""120 return GoogleGenerativeAIEmbeddings(121 model="models/embedding-001",122 api_key=GOOGLE_API_KEY123 )124 125def ensure_pinecone_ready():126 """Init Pinecone and ensure index exists (v2 client)."""127 try:128 pinecone.init(api_key=PINECONE_API_KEY, environment=PINECONE_ENV)129 except Exception as e:130 st.error(f"❌ Failed to initialize Pinecone: {e}\n"131 f"- Make sure your Space can reach external services.\n"132 f"- If on HF free CPU, networking to Pinecone can be blocked.")133 st.stop()134 135 # Create the index if it doesn't exist136 try:137 existing = pinecone.list_indexes()138 if INDEX_NAME not in existing:139 pinecone.create_index(140 name=INDEX_NAME,141 dimension=EMBED_DIM,142 metric="cosine"143 )144 # Wait briefly for serverless index to be ready145 time.sleep(5)146 except Exception as e:147 st.error(f"❌ Could not verify/create Pinecone index '{INDEX_NAME}': {e}")148 st.stop()149 150def get_index_stats():151 """Describe index stats (to avoid re-embedding if already populated)."""152 try:153 idx = pinecone.Index(INDEX_NAME)154 return idx.describe_index_stats()155 except Exception:156 return None157 158@st.cache_resource(show_spinner=False)159def make_vectorstore(docs):160 """Create or connect to the Pinecone vectorstore, embedding docs only if needed."""161 # Split docs before embedding162 splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=150)163 chunks = splitter.split_documents(docs)164 165 # Check if the index already has vectors; if it does, just connect without re-upserting166 stats = get_index_stats()167 has_vectors = False168 if stats and "namespaces" in stats and NAMESPACE in stats["namespaces"]:169 ns_stats = stats["namespaces"][NAMESPACE]170 has_vectors = ns_stats.get("vector_count", 0) > 0171 172 embeddings = build_embeddings()173 174 if has_vectors:175 # Just connect to existing index176 vs = PineconeVectorStore(177 index=pinecone.Index(INDEX_NAME),178 embedding=embeddings,179 text_key="text",180 namespace=NAMESPACE181 )182 return vs183 184 # Otherwise, (first run) embed & upsert185 vs = PineconeVectorStore.from_documents(186 documents=chunks,187 embedding=embeddings,188 index_name=INDEX_NAME,189 namespace=NAMESPACE190 )191 return vs192 193@st.cache_resource(show_spinner=False)194def make_chain(vectorstore):195 """Build the RetrievalQA chain once."""196 llm = ChatGoogleGenerativeAI(model="gemini-1.5-pro", temperature=0.2, api_key=GOOGLE_API_KEY)197 retriever = vectorstore.as_retriever(search_kwargs={"k": 4})198 chain = RetrievalQA.from_chain_type(199 llm=llm,200 chain_type="stuff",201 retriever=retriever202 )203 return chain204 205 206# =========================207# Pipeline Bootstrap208# =========================209 210st.caption("Loading documents from `documents/`…")211docs = load_documents("documents/")212st.success(f"✅ Loaded {len(docs)} PDF pages")213 214st.caption("Connecting to Pinecone…")215ensure_pinecone_ready()216 217st.caption("Preparing vector store…")218vectorstore = make_vectorstore(docs)219st.success("✅ Vector store ready")220 221chain = make_chain(vectorstore)222 223 224# =========================225# UI226# =========================227 228prompt = st.text_input("Ask a question about the Sindh Budget PDFs:")229if st.button("Ask"):230 if not prompt.strip():231 st.warning("Please enter a question.")232 else:233 with st.spinner("Thinking…"):234 try:235 answer = chain.run(prompt)236 st.subheader("Answer")237 st.write(answer)238 except Exception as e:239 st.error(f"❌ Error while answering: {e}")240 241 