Spaces:
Runtime error
Runtime error
| import os | |
| import faiss | |
| import numpy as np | |
| import gradio as gr | |
| from pypdf import PdfReader | |
| from sentence_transformers import SentenceTransformer | |
| from groq import Groq | |
| # ----------------------------- | |
| # Initialize Models | |
| # ----------------------------- | |
| embedder = SentenceTransformer("all-MiniLM-L6-v2") | |
| # Safely load API key | |
| GROQ_API_KEY = os.getenv("Rag") | |
| client = Groq(api_key=GROQ_API_KEY) if GROQ_API_KEY else None | |
| # ----------------------------- | |
| # Global Storage | |
| # ----------------------------- | |
| index = None | |
| documents = [] | |
| # ----------------------------- | |
| # PDF Processing | |
| # ----------------------------- | |
| def read_pdf(file): | |
| try: | |
| reader = PdfReader(file.name) # FIX for Hugging Face | |
| text = "" | |
| for page in reader.pages: | |
| if page.extract_text(): | |
| text += page.extract_text() | |
| return text | |
| except Exception as e: | |
| return f"Error reading PDF: {str(e)}" | |
| def chunk_text(text, chunk_size=500, overlap=100): | |
| chunks = [] | |
| start = 0 | |
| while start < len(text): | |
| end = start + chunk_size | |
| chunks.append(text[start:end]) | |
| start += chunk_size - overlap | |
| return chunks | |
| # ----------------------------- | |
| # Create FAISS Index | |
| # ----------------------------- | |
| def create_index(chunks): | |
| global index, documents | |
| documents = chunks | |
| embeddings = embedder.encode(chunks) | |
| embeddings = np.array(embeddings).astype("float32") | |
| dimension = embeddings.shape[1] | |
| index = faiss.IndexFlatL2(dimension) | |
| index.add(embeddings) | |
| # ----------------------------- | |
| # Retrieval | |
| # ----------------------------- | |
| def retrieve(query, k=3, threshold=1.2): | |
| global index | |
| if index is None: | |
| return [], None | |
| query_embedding = embedder.encode([query]) | |
| query_embedding = np.array(query_embedding).astype("float32") | |
| distances, indices = index.search(query_embedding, k) | |
| relevant_chunks = [] | |
| valid_distances = [] | |
| for i, dist in zip(indices[0], distances[0]): | |
| if i < len(documents) and dist < threshold: | |
| relevant_chunks.append(documents[i]) | |
| valid_distances.append(dist) | |
| # Confidence | |
| confidence = None | |
| if valid_distances: | |
| avg = np.mean(valid_distances) | |
| if avg < 0.5: | |
| confidence = "High" | |
| elif avg < 1.0: | |
| confidence = "Medium" | |
| else: | |
| confidence = "Low" | |
| return relevant_chunks, confidence | |
| # ----------------------------- | |
| # LLM (Groq) | |
| # ----------------------------- | |
| def ask_groq(context_chunks, question): | |
| if client is None: | |
| return "Error: GROQ_API_KEY not set in Hugging Face Secrets." | |
| context = "\n".join(context_chunks) | |
| prompt = f""" | |
| You are an intelligent assistant. | |
| Rules: | |
| 1. If answer is clearly in context β answer normally. | |
| 2. If related but not exact β say: | |
| "This is not explicitly mentioned in the document, but based on related context..." | |
| 3. If irrelevant β say: | |
| "The document does not contain information related to this question." | |
| Context: | |
| {context} | |
| Question: | |
| {question} | |
| """ | |
| try: | |
| response = client.chat.completions.create( | |
| messages=[{"role": "user", "content": prompt}], | |
| model="llama-3.3-70b-versatile", | |
| ) | |
| return response.choices[0].message.content | |
| except Exception as e: | |
| return f"Groq API Error: {str(e)}" | |
| # ----------------------------- | |
| # Main Functions | |
| # ----------------------------- | |
| def process_pdf(file): | |
| if file is None: | |
| return "Please upload a PDF." | |
| text = read_pdf(file) | |
| if not text or "Error" in text: | |
| return text | |
| chunks = chunk_text(text) | |
| create_index(chunks) | |
| return f"β PDF processed! Chunks: {len(chunks)}" | |
| def answer_question(question): | |
| if index is None: | |
| return "Please upload and process a PDF first." | |
| context_chunks, confidence = retrieve(question) | |
| if not context_chunks: | |
| return "The document does not contain information related to this question." | |
| answer = ask_groq(context_chunks, question) | |
| if confidence: | |
| answer = f"(Confidence: {confidence})\n\n{answer}" | |
| return answer | |
| # ----------------------------- | |
| # Gradio UI | |
| # ----------------------------- | |
| with gr.Blocks() as demo: | |
| gr.Markdown("## π RAG PDF Q&A (Groq + FAISS)") | |
| file_input = gr.File(label="Upload PDF") | |
| upload_btn = gr.Button("Process PDF") | |
| status = gr.Textbox(label="Status") | |
| question = gr.Textbox(label="Ask a question") | |
| answer = gr.Textbox(label="Answer") | |
| upload_btn.click(process_pdf, inputs=file_input, outputs=status) | |
| question.submit(answer_question, inputs=question, outputs=answer) | |
| # ----------------------------- | |
| # Launch | |
| # ----------------------------- | |
| if __name__ == "__main__": | |
| demo.launch(server_name="0.0.0.0", server_port=7860) |