tayy786 commited on
Commit
c588395
Β·
verified Β·
1 Parent(s): 2aff52b

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +194 -0
app.py ADDED
@@ -0,0 +1,194 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import numpy as np
3
+ import gradio as gr
4
+ from pypdf import PdfReader
5
+ from sentence_transformers import SentenceTransformer
6
+ from groq import Groq
7
+
8
+ # -----------------------------
9
+ # Initialize Models
10
+ # -----------------------------
11
+ embedder = SentenceTransformer("all-MiniLM-L6-v2")
12
+
13
+ GROQ_API_KEY = os.getenv("Rag")
14
+ client = Groq(api_key=GROQ_API_KEY) if GROQ_API_KEY else None
15
+
16
+ # -----------------------------
17
+ # Global Storage
18
+ # -----------------------------
19
+ documents = []
20
+ embeddings = None
21
+
22
+ # -----------------------------
23
+ # PDF Processing
24
+ # -----------------------------
25
+ def read_pdf(file):
26
+ try:
27
+ reader = PdfReader(file.name)
28
+ text = ""
29
+ for page in reader.pages:
30
+ content = page.extract_text()
31
+ if content:
32
+ text += content
33
+ return text
34
+ except Exception as e:
35
+ return f"Error reading PDF: {str(e)}"
36
+
37
+
38
+ def chunk_text(text, chunk_size=500, overlap=100):
39
+ chunks = []
40
+ start = 0
41
+
42
+ while start < len(text):
43
+ end = start + chunk_size
44
+ chunks.append(text[start:end])
45
+ start += chunk_size - overlap
46
+
47
+ return chunks
48
+
49
+
50
+ # -----------------------------
51
+ # Create Embeddings
52
+ # -----------------------------
53
+ def create_embeddings(chunks):
54
+ global documents, embeddings
55
+
56
+ documents = chunks
57
+ embeddings = embedder.encode(chunks)
58
+ embeddings = np.array(embeddings)
59
+
60
+
61
+ # -----------------------------
62
+ # Cosine Similarity Retrieval
63
+ # -----------------------------
64
+ def cosine_similarity(a, b):
65
+ return np.dot(a, b.T) / (np.linalg.norm(a) * np.linalg.norm(b, axis=1))
66
+
67
+
68
+ def retrieve(query, k=3, threshold=0.3):
69
+ global embeddings
70
+
71
+ if embeddings is None:
72
+ return [], None
73
+
74
+ query_embedding = embedder.encode([query])[0]
75
+
76
+ sims = cosine_similarity(query_embedding, embeddings)
77
+
78
+ top_k_idx = np.argsort(sims)[-k:][::-1]
79
+
80
+ relevant_chunks = []
81
+ scores = []
82
+
83
+ for i in top_k_idx:
84
+ if sims[i] > threshold:
85
+ relevant_chunks.append(documents[i])
86
+ scores.append(sims[i])
87
+
88
+ # Confidence
89
+ confidence = None
90
+ if scores:
91
+ avg = np.mean(scores)
92
+ if avg > 0.7:
93
+ confidence = "High"
94
+ elif avg > 0.5:
95
+ confidence = "Medium"
96
+ else:
97
+ confidence = "Low"
98
+
99
+ return relevant_chunks, confidence
100
+
101
+
102
+ # -----------------------------
103
+ # Groq LLM
104
+ # -----------------------------
105
+ def ask_groq(context_chunks, question):
106
+ if client is None:
107
+ return "Error: Please set GROQ_API_KEY in Hugging Face Secrets."
108
+
109
+ context = "\n".join(context_chunks)
110
+
111
+ prompt = f"""
112
+ You are an intelligent assistant.
113
+
114
+ Rules:
115
+ 1. If answer is clearly in context β†’ answer normally.
116
+ 2. If related but not exact β†’ say:
117
+ "This is not explicitly mentioned in the document, but based on related context..."
118
+ 3. If irrelevant β†’ say:
119
+ "The document does not contain information related to this question."
120
+
121
+ Context:
122
+ {context}
123
+
124
+ Question:
125
+ {question}
126
+ """
127
+
128
+ try:
129
+ response = client.chat.completions.create(
130
+ messages=[{"role": "user", "content": prompt}],
131
+ model="llama-3.3-70b-versatile",
132
+ )
133
+ return response.choices[0].message.content
134
+ except Exception as e:
135
+ return f"Groq API Error: {str(e)}"
136
+
137
+
138
+ # -----------------------------
139
+ # Main Functions
140
+ # -----------------------------
141
+ def process_pdf(file):
142
+ if file is None:
143
+ return "Please upload a PDF."
144
+
145
+ text = read_pdf(file)
146
+
147
+ if not text or "Error" in text:
148
+ return text
149
+
150
+ chunks = chunk_text(text)
151
+ create_embeddings(chunks)
152
+
153
+ return f"βœ… PDF processed successfully! Chunks: {len(chunks)}"
154
+
155
+
156
+ def answer_question(question):
157
+ if embeddings is None:
158
+ return "Please upload and process a PDF first."
159
+
160
+ context_chunks, confidence = retrieve(question)
161
+
162
+ if not context_chunks:
163
+ return "The document does not contain information related to this question."
164
+
165
+ answer = ask_groq(context_chunks, question)
166
+
167
+ if confidence:
168
+ answer = f"(Confidence: {confidence})\n\n{answer}"
169
+
170
+ return answer
171
+
172
+
173
+ # -----------------------------
174
+ # Gradio UI
175
+ # -----------------------------
176
+ with gr.Blocks() as demo:
177
+ gr.Markdown("## πŸ“„ RAG PDF Q&A (Groq + HuggingFace Ready)")
178
+
179
+ file_input = gr.File(label="Upload PDF")
180
+ upload_btn = gr.Button("Process PDF")
181
+ status = gr.Textbox(label="Status")
182
+
183
+ question = gr.Textbox(label="Ask a question")
184
+ answer = gr.Textbox(label="Answer")
185
+
186
+ upload_btn.click(process_pdf, inputs=file_input, outputs=status)
187
+ question.submit(answer_question, inputs=question, outputs=answer)
188
+
189
+
190
+ # -----------------------------
191
+ # Launch
192
+ # -----------------------------
193
+ if __name__ == "__main__":
194
+ demo.launch(server_name="0.0.0.0", server_port=7860)