QuickLearnerAI commited on
Commit
2b086bc
Β·
verified Β·
1 Parent(s): 32164f4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +56 -160
app.py CHANGED
@@ -1,249 +1,148 @@
1
  import gradio as gr
2
  import PyPDF2
3
  import io
4
- import time
5
  import os
6
  from together import Together
7
- import textwrap
8
- import tempfile
9
 
10
  def extract_text_from_pdf(pdf_file):
11
- """Extract text from a PDF file"""
12
  text = ""
13
  try:
14
- # Check if the pdf_file is already in bytes format or needs conversion
15
  if hasattr(pdf_file, 'read'):
16
- # If it's a file-like object (from gradio upload)
17
  pdf_content = pdf_file.read()
18
- # Reset the file pointer for potential future reads
19
  if hasattr(pdf_file, 'seek'):
20
  pdf_file.seek(0)
21
  else:
22
- # If it's already bytes
23
  pdf_content = pdf_file
24
 
25
- # Read the PDF file
26
  pdf_reader = PyPDF2.PdfReader(io.BytesIO(pdf_content))
27
-
28
- # Extract text from each page
29
  for page_num in range(len(pdf_reader.pages)):
30
  page_text = pdf_reader.pages[page_num].extract_text()
31
- if page_text: # Check if text extraction worked
32
  text += page_text + "\n\n"
33
  else:
34
  text += f"[Page {page_num+1} - No extractable text found]\n\n"
35
 
36
  if not text.strip():
37
  return "No text could be extracted from the PDF. The document may be scanned or image-based."
38
-
39
  return text
40
  except Exception as e:
41
  return f"Error extracting text from PDF: {str(e)}"
42
 
43
- def format_chat_history(history):
44
- """Format the chat history for display"""
45
- formatted_history = []
46
- for user_msg, bot_msg in history:
47
- formatted_history.append((user_msg, bot_msg))
48
- return formatted_history
49
-
50
  def chat_with_pdf(api_key, pdf_text, user_question, history):
51
- """Chat with the PDF using Together API"""
52
  if not api_key.strip():
53
- return history + [(user_question, "Error: Please enter your Together API key.")], history
54
-
55
  if not pdf_text.strip() or pdf_text.startswith("Error") or pdf_text.startswith("No text"):
56
- return history + [(user_question, "Error: Please upload a valid PDF file with extractable text first.")], history
57
-
58
  if not user_question.strip():
59
- return history + [(user_question, "Error: Please enter a question.")], history
60
-
61
  try:
62
- # Initialize Together client with the API key
63
  client = Together(api_key=api_key)
64
-
65
- # Create the system message with PDF context
66
- # Truncate the PDF text if it's too long (model context limit handling)
67
- max_context_length = 10000 #10000
68
-
69
  if len(pdf_text) > max_context_length:
70
- # More sophisticated truncation that preserves beginning and end
71
  half_length = max_context_length // 2
72
  pdf_context = pdf_text[:half_length] + "\n\n[...Content truncated due to length...]\n\n" + pdf_text[-half_length:]
73
  else:
74
  pdf_context = pdf_text
75
-
76
  system_message = f"""You are an intelligent assistant designed to read, understand, and extract information from PDF documents.
77
  Based on any question or query the user asksβ€”whether it's about content, summaries, data extraction, definitions, insights, or interpretationβ€”you will
78
  analyze the following PDF content and provide an accurate, helpful response grounded in the document. Always respond with clear, concise, and context-aware information.
79
  PDF CONTENT:
80
  {pdf_context}
81
  Answer the user's questions only based on the PDF content above. If the answer cannot be found in the PDF, politely state that the information is not available in the provided document."""
82
-
83
- # Prepare message history for Together API
84
- messages = [
85
- {"role": "system", "content": system_message},
86
- ]
87
-
88
- # Add chat history
89
- for h_user, h_bot in history:
90
- messages.append({"role": "user", "content": h_user})
91
- messages.append({"role": "assistant", "content": h_bot})
92
-
93
- # Add the current user question
94
  messages.append({"role": "user", "content": user_question})
95
-
96
- # Call the Together API
97
  response = client.chat.completions.create(
98
  model="meta-llama/Llama-3.3-70B-Instruct-Turbo-Free",
99
  messages=messages,
100
- max_tokens=5000, #5000
101
  temperature=0.7,
102
  )
103
-
104
- # Extract the assistant's response
105
  assistant_response = response.choices[0].message.content
106
-
107
- # Update the chat history
108
- new_history = history + [(user_question, assistant_response)]
109
-
 
110
  return new_history, new_history
111
-
112
  except Exception as e:
113
- error_message = f"Error: {str(e)}"
114
- return history + [(user_question, error_message)], history
115
 
116
  def process_pdf(pdf_file, api_key_input):
117
- """Process the uploaded PDF file"""
118
  if pdf_file is None:
119
  return "Please upload a PDF file.", "", []
120
-
121
  try:
122
- # Get the file name
123
  file_name = os.path.basename(pdf_file.name) if hasattr(pdf_file, 'name') else "Uploaded PDF"
124
-
125
- # Extract text from the PDF
126
  pdf_text = extract_text_from_pdf(pdf_file)
127
-
128
- # Check if there was an error in extraction
129
  if pdf_text.startswith("Error extracting text from PDF"):
130
  return f"❌ {pdf_text}", "", []
131
-
132
  if not pdf_text.strip() or pdf_text.startswith("No text could be extracted"):
133
  return f"⚠️ {pdf_text}", "", []
134
-
135
- # Count words for information
136
  word_count = len(pdf_text.split())
137
-
138
- # Return a message with the file name and text content
139
  status_message = f"βœ… Successfully processed PDF: {file_name} ({word_count} words extracted)"
140
-
141
- # Also return an empty history
142
  return status_message, pdf_text, []
143
  except Exception as e:
144
  return f"❌ Error processing PDF: {str(e)}", "", []
145
 
146
  def validate_api_key(api_key):
147
- """Simple validation for API key format"""
148
  if not api_key or not api_key.strip():
149
  return "❌ API Key is required"
150
-
151
  if len(api_key.strip()) < 10:
152
  return "❌ API Key appears to be too short"
153
-
154
  return "βœ“ API Key format looks valid (not verified with server)"
155
- # βœ… Clear function
 
 
 
 
 
 
 
 
156
  def clear_all():
157
  return "", "", "", "", [], "", ""
158
 
159
-
160
- # Create the Gradio interface
161
  with gr.Blocks(title="ChatPDF with Together AI", theme=gr.themes.Ocean()) as app:
162
  gr.Markdown("# πŸ“„ ChatPDF with Together AI")
163
  gr.Markdown("Upload a PDF and chat with it using the Llama-3.3-70B model.")
164
-
165
  with gr.Row():
166
  with gr.Column(scale=1):
167
- # API Key input
168
- api_key_input = gr.Textbox(
169
- label="Together API Key",
170
- placeholder="Enter your Together API key here...",
171
- type="password"
172
- )
173
-
174
- # API key validation
175
- api_key_status = gr.Textbox(
176
- label="API Key Status",
177
- interactive=False
178
- )
179
-
180
- # PDF upload
181
- pdf_file = gr.File(
182
- label="Upload PDF",
183
- file_types=[".pdf"],
184
- type="binary" # Ensure we get binary data
185
- )
186
-
187
- # Process PDF button
188
  process_button = gr.Button("Process PDF")
189
-
190
- # Status message
191
- status_message = gr.Textbox(
192
- label="Status",
193
- interactive=False
194
- )
195
-
196
- # Hidden field to store the PDF text
197
  pdf_text = gr.Textbox(visible=False)
198
-
199
- # Optional: Show PDF preview
200
  with gr.Accordion("PDF Content Preview", open=False):
201
- pdf_preview = gr.Textbox(
202
- label="Extracted Text Preview",
203
- interactive=False,
204
- max_lines=10,
205
- show_copy_button=True
206
- )
207
-
208
  with gr.Column(scale=2):
209
- # Chat interface
210
- chatbot = gr.Chatbot(
211
- label="Chat with PDF",
212
- height=500,
213
- show_copy_button=True
214
- )
215
-
216
- # Question input
217
- question = gr.Textbox(
218
- label="Ask a question about the PDF",
219
- placeholder="What is the main topic of this document?",
220
- lines=2
221
- )
222
-
223
- # Submit button
224
  submit_button = gr.Button("Submit Question")
225
- # clear button
226
-
227
-
228
- # Event handlers
229
- def update_preview(text):
230
- """Update the preview with the first few lines of the PDF text"""
231
- if not text or text.startswith("Error") or text.startswith("No text"):
232
- return text
233
-
234
- # Get the first ~500 characters for preview
235
- preview = text[:500]
236
- if len(text) > 500:
237
- preview += "...\n[Text truncated for preview. Full text will be used for chat.]"
238
- return preview
239
-
240
- # API key validation event
241
- api_key_input.change(
242
- fn=validate_api_key,
243
- inputs=[api_key_input],
244
- outputs=[api_key_status]
245
- )
246
-
247
  process_button.click(
248
  fn=process_pdf,
249
  inputs=[pdf_file, api_key_input],
@@ -253,7 +152,7 @@ with gr.Blocks(title="ChatPDF with Together AI", theme=gr.themes.Ocean()) as app
253
  inputs=[pdf_text],
254
  outputs=[pdf_preview]
255
  )
256
-
257
  submit_button.click(
258
  fn=chat_with_pdf,
259
  inputs=[api_key_input, pdf_text, question, chatbot],
@@ -262,7 +161,7 @@ with gr.Blocks(title="ChatPDF with Together AI", theme=gr.themes.Ocean()) as app
262
  fn=lambda: "",
263
  outputs=question
264
  )
265
-
266
  question.submit(
267
  fn=chat_with_pdf,
268
  inputs=[api_key_input, pdf_text, question, chatbot],
@@ -272,7 +171,6 @@ with gr.Blocks(title="ChatPDF with Together AI", theme=gr.themes.Ocean()) as app
272
  outputs=question
273
  )
274
 
275
- # βœ… Clear Button Handler
276
  clear_button.click(
277
  fn=clear_all,
278
  outputs=[
@@ -286,7 +184,5 @@ with gr.Blocks(title="ChatPDF with Together AI", theme=gr.themes.Ocean()) as app
286
  ]
287
  )
288
 
289
- # Launch the app
290
  if __name__ == "__main__":
291
  app.launch(share=True)
292
-
 
1
  import gradio as gr
2
  import PyPDF2
3
  import io
 
4
  import os
5
  from together import Together
 
 
6
 
7
  def extract_text_from_pdf(pdf_file):
 
8
  text = ""
9
  try:
 
10
  if hasattr(pdf_file, 'read'):
 
11
  pdf_content = pdf_file.read()
 
12
  if hasattr(pdf_file, 'seek'):
13
  pdf_file.seek(0)
14
  else:
 
15
  pdf_content = pdf_file
16
 
 
17
  pdf_reader = PyPDF2.PdfReader(io.BytesIO(pdf_content))
 
 
18
  for page_num in range(len(pdf_reader.pages)):
19
  page_text = pdf_reader.pages[page_num].extract_text()
20
+ if page_text:
21
  text += page_text + "\n\n"
22
  else:
23
  text += f"[Page {page_num+1} - No extractable text found]\n\n"
24
 
25
  if not text.strip():
26
  return "No text could be extracted from the PDF. The document may be scanned or image-based."
 
27
  return text
28
  except Exception as e:
29
  return f"Error extracting text from PDF: {str(e)}"
30
 
 
 
 
 
 
 
 
31
  def chat_with_pdf(api_key, pdf_text, user_question, history):
 
32
  if not api_key.strip():
33
+ return history + [{"role": "user", "content": user_question}, {"role": "assistant", "content": "Error: Please enter your Together API key."}], history
34
+
35
  if not pdf_text.strip() or pdf_text.startswith("Error") or pdf_text.startswith("No text"):
36
+ return history + [{"role": "user", "content": user_question}, {"role": "assistant", "content": "Error: Please upload a valid PDF file with extractable text first."}], history
37
+
38
  if not user_question.strip():
39
+ return history + [{"role": "user", "content": user_question}, {"role": "assistant", "content": "Error: Please enter a question."}], history
40
+
41
  try:
 
42
  client = Together(api_key=api_key)
43
+
44
+ max_context_length = 10000
 
 
 
45
  if len(pdf_text) > max_context_length:
 
46
  half_length = max_context_length // 2
47
  pdf_context = pdf_text[:half_length] + "\n\n[...Content truncated due to length...]\n\n" + pdf_text[-half_length:]
48
  else:
49
  pdf_context = pdf_text
50
+
51
  system_message = f"""You are an intelligent assistant designed to read, understand, and extract information from PDF documents.
52
  Based on any question or query the user asksβ€”whether it's about content, summaries, data extraction, definitions, insights, or interpretationβ€”you will
53
  analyze the following PDF content and provide an accurate, helpful response grounded in the document. Always respond with clear, concise, and context-aware information.
54
  PDF CONTENT:
55
  {pdf_context}
56
  Answer the user's questions only based on the PDF content above. If the answer cannot be found in the PDF, politely state that the information is not available in the provided document."""
57
+
58
+ messages = [{"role": "system", "content": system_message}]
59
+ for msg in history:
60
+ messages.append(msg)
61
+
 
 
 
 
 
 
 
62
  messages.append({"role": "user", "content": user_question})
63
+
 
64
  response = client.chat.completions.create(
65
  model="meta-llama/Llama-3.3-70B-Instruct-Turbo-Free",
66
  messages=messages,
67
+ max_tokens=5000,
68
  temperature=0.7,
69
  )
70
+
 
71
  assistant_response = response.choices[0].message.content
72
+ new_history = history + [
73
+ {"role": "user", "content": user_question},
74
+ {"role": "assistant", "content": assistant_response}
75
+ ]
76
+
77
  return new_history, new_history
78
+
79
  except Exception as e:
80
+ return history + [{"role": "user", "content": user_question}, {"role": "assistant", "content": f"Error: {str(e)}"}], history
 
81
 
82
  def process_pdf(pdf_file, api_key_input):
 
83
  if pdf_file is None:
84
  return "Please upload a PDF file.", "", []
85
+
86
  try:
 
87
  file_name = os.path.basename(pdf_file.name) if hasattr(pdf_file, 'name') else "Uploaded PDF"
 
 
88
  pdf_text = extract_text_from_pdf(pdf_file)
89
+
 
90
  if pdf_text.startswith("Error extracting text from PDF"):
91
  return f"❌ {pdf_text}", "", []
92
+
93
  if not pdf_text.strip() or pdf_text.startswith("No text could be extracted"):
94
  return f"⚠️ {pdf_text}", "", []
95
+
 
96
  word_count = len(pdf_text.split())
 
 
97
  status_message = f"βœ… Successfully processed PDF: {file_name} ({word_count} words extracted)"
 
 
98
  return status_message, pdf_text, []
99
  except Exception as e:
100
  return f"❌ Error processing PDF: {str(e)}", "", []
101
 
102
  def validate_api_key(api_key):
 
103
  if not api_key or not api_key.strip():
104
  return "❌ API Key is required"
 
105
  if len(api_key.strip()) < 10:
106
  return "❌ API Key appears to be too short"
 
107
  return "βœ“ API Key format looks valid (not verified with server)"
108
+
109
+ def update_preview(text):
110
+ if not text or text.startswith("Error") or text.startswith("No text"):
111
+ return text
112
+ preview = text[:500]
113
+ if len(text) > 500:
114
+ preview += "...\n[Text truncated for preview. Full text will be used for chat.]"
115
+ return preview
116
+
117
  def clear_all():
118
  return "", "", "", "", [], "", ""
119
 
120
+ # πŸš€ Gradio Interface
 
121
  with gr.Blocks(title="ChatPDF with Together AI", theme=gr.themes.Ocean()) as app:
122
  gr.Markdown("# πŸ“„ ChatPDF with Together AI")
123
  gr.Markdown("Upload a PDF and chat with it using the Llama-3.3-70B model.")
124
+
125
  with gr.Row():
126
  with gr.Column(scale=1):
127
+ api_key_input = gr.Textbox(label="Together API Key", placeholder="Enter your Together API key here...", type="password")
128
+ api_key_status = gr.Textbox(label="API Key Status", interactive=False)
129
+ pdf_file = gr.File(label="Upload PDF", file_types=[".pdf"], type="binary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  process_button = gr.Button("Process PDF")
131
+ status_message = gr.Textbox(label="Status", interactive=False)
 
 
 
 
 
 
 
132
  pdf_text = gr.Textbox(visible=False)
133
+
 
134
  with gr.Accordion("PDF Content Preview", open=False):
135
+ pdf_preview = gr.Textbox(label="Extracted Text Preview", interactive=False, max_lines=10, show_copy_button=True)
136
+
 
 
 
 
 
137
  with gr.Column(scale=2):
138
+ chatbot = gr.Chatbot(label="Chat with PDF", height=500, show_copy_button=True, type="messages")
139
+ question = gr.Textbox(label="Ask a question about the PDF", placeholder="What is the main topic of this document?", lines=2)
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  submit_button = gr.Button("Submit Question")
141
+ clear_button = gr.Button("Clear Chat & Reset", variant="stop") # βœ… CLEAR BUTTON
142
+
143
+ # πŸ”„ Events
144
+ api_key_input.change(fn=validate_api_key, inputs=[api_key_input], outputs=[api_key_status])
145
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  process_button.click(
147
  fn=process_pdf,
148
  inputs=[pdf_file, api_key_input],
 
152
  inputs=[pdf_text],
153
  outputs=[pdf_preview]
154
  )
155
+
156
  submit_button.click(
157
  fn=chat_with_pdf,
158
  inputs=[api_key_input, pdf_text, question, chatbot],
 
161
  fn=lambda: "",
162
  outputs=question
163
  )
164
+
165
  question.submit(
166
  fn=chat_with_pdf,
167
  inputs=[api_key_input, pdf_text, question, chatbot],
 
171
  outputs=question
172
  )
173
 
 
174
  clear_button.click(
175
  fn=clear_all,
176
  outputs=[
 
184
  ]
185
  )
186
 
 
187
  if __name__ == "__main__":
188
  app.launch(share=True)