| import gradio as gr |
| import chromadb |
| import os |
| import tempfile |
| from langchain.embeddings import HuggingFaceEmbeddings |
| from langchain.vectorstores import Chroma |
| from langchain.text_splitter import CharacterTextSplitter |
| from langchain.document_loaders import PyPDFLoader |
|
|
| def process_pdf(file_binary): |
| log = [] |
| status_message = "" |
|
|
| if not file_binary: |
| return "No file uploaded.", "Error: No file was provided." |
|
|
| try: |
| log.append("Starting PDF upload and processing...") |
|
|
| |
| with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as temp_file: |
| temp_file.write(file_binary) |
| temp_path = temp_file.name |
| log.append(f"Temporary PDF path: {temp_path}") |
|
|
| |
| try: |
| loader = PyPDFLoader(temp_path) |
| documents = loader.load() |
| log.append(f"Loaded {len(documents)} page(s) from PDF.") |
| except Exception as e: |
| raise RuntimeError(f"Error loading PDF: {e}") |
|
|
| |
| try: |
| text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=50) |
| splits = text_splitter.split_documents(documents) |
| log.append(f"Text split into {len(splits)} chunk(s).") |
| except Exception as e: |
| raise RuntimeError(f"Error splitting text: {e}") |
|
|
| |
| try: |
| log.append("Initializing in-memory ChromaDB...") |
| chroma_client = chromadb.Client() |
| embeddings = HuggingFaceEmbeddings( |
| model_name="sentence-transformers/all-MiniLM-L6-v2" |
| ) |
| Chroma.from_documents( |
| splits, |
| embeddings, |
| client=chroma_client |
| ) |
| log.append("Successfully stored PDF chunks in ChromaDB.") |
| except Exception as e: |
| raise RuntimeError(f"Error creating ChromaDB vector store: {e}") |
|
|
| status_message = "PDF processed and stored in (ephemeral) ChromaDB successfully!" |
| log.append(status_message) |
|
|
| except Exception as e: |
| status_message = "Error" |
| log.append(f"Exception occurred: {str(e)}") |
|
|
| return status_message, "\n".join(log) |
|
|
|
|
| def retrieve_context(query): |
| log = [] |
| if not query: |
| return "Error: No query provided." |
|
|
| try: |
| log.append("Retrieving context from in-memory ChromaDB...") |
|
|
| |
| chroma_client = chromadb.Client() |
| embeddings = HuggingFaceEmbeddings( |
| model_name="sentence-transformers/all-MiniLM-L6-v2" |
| ) |
| vectorstore = Chroma(embedding_function=embeddings, client=chroma_client) |
|
|
| |
| results = vectorstore.similarity_search(query, k=3) |
| if results: |
| log.append(f"Found {len(results)} matching chunk(s).") |
| return "\n\n".join([doc.page_content for doc in results]) |
| else: |
| log.append("No matching context found in the current in-memory DB.") |
| return "No relevant context found. Have you processed a PDF yet?" |
|
|
| except Exception as e: |
| log.append(f"Error retrieving context: {str(e)}") |
| return "\n".join(log) |
|
|
|
|
| with gr.Blocks() as demo: |
| gr.Markdown("## PDF Context Retriever with ChromaDB (In-Memory)") |
|
|
| with gr.Row(): |
| |
| pdf_upload = gr.File(label="Upload PDF", type="binary") |
| process_button = gr.Button("Process PDF") |
|
|
| output_text = gr.Textbox(label="Processing Status") |
| log_output = gr.Textbox(label="Log Output", interactive=False) |
|
|
| |
| process_button.click( |
| fn=process_pdf, |
| inputs=pdf_upload, |
| outputs=[output_text, log_output] |
| ) |
|
|
| query_input = gr.Textbox(label="Enter your query") |
| retrieve_button = gr.Button("Retrieve Context") |
| context_output = gr.Textbox(label="Retrieved Context") |
|
|
| retrieve_button.click( |
| fn=retrieve_context, |
| inputs=query_input, |
| outputs=context_output |
| ) |
|
|
| demo.launch() |
|
|