ragunath-ravi commited on
Commit
d4655d0
·
verified ·
1 Parent(s): 34bde9a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +19 -46
app.py CHANGED
@@ -8,7 +8,7 @@ import json
8
  import asyncio
9
  from dataclasses import dataclass, asdict
10
  import logging
11
- import sys # Import sys for exiting if token is missing
12
 
13
  # Document processing imports
14
  import PyPDF2
@@ -29,7 +29,7 @@ logging.basicConfig(level=logging.INFO)
29
  logger = logging.getLogger(__name__)
30
 
31
  # --- Get HF token from environment and perform a crucial check ---
32
- HF_TOKEN = os.getenv('hf_token')
33
 
34
  if HF_TOKEN is None:
35
  logger.error("FATAL ERROR: HuggingFace token (HF_TOKEN) environment variable is not set.")
@@ -70,7 +70,7 @@ class MCPCommunicator:
70
  if message.receiver == agent_name:
71
  return message
72
  # Re-queue if not for this agent
73
- await self.message_queue.put(message)
74
 
75
  # Global MCP instance
76
  mcp = MCPCommunicator()
@@ -171,7 +171,7 @@ class IngestionAgent(BaseAgent):
171
  """Process uploaded documents and return chunked documents"""
172
  all_documents = []
173
 
174
- for file_path in files:
175
  file_ext = os.path.splitext(file_path)[1].lower()
176
  filename = os.path.basename(file_path)
177
 
@@ -256,10 +256,9 @@ class RetrievalAgent(BaseAgent):
256
  class LLMResponseAgent(BaseAgent):
257
  def __init__(self):
258
  super().__init__("LLMResponseAgent")
259
- # Use the global HF_TOKEN which is validated at script start
260
  self.client = InferenceClient(
261
  model="meta-llama/Llama-3.1-8B-Instruct",
262
- token=HF_TOKEN # Pass the token here
263
  )
264
 
265
  def format_prompt_for_conversational(self, query: str, context_chunks: List[Dict]) -> str:
@@ -272,8 +271,6 @@ class LLMResponseAgent(BaseAgent):
272
  for chunk in context_chunks
273
  ])
274
 
275
- # We are putting the RAG prompt into the 'user' input for the conversational model.
276
- # This is a common way to use a conversational model for RAG if text_generation isn't available.
277
  prompt_as_user_input = f"""Based on the following context from uploaded documents, please answer the user's question.
278
 
279
  Context:
@@ -283,32 +280,22 @@ Question: {query}
283
 
284
  Please provide a comprehensive answer based on the context above. If the context doesn't contain enough information to fully answer the question, please mention what information is available and what might be missing.
285
 
286
- Answer:""" # Keeping "Answer:" to guide the model to start generating the answer directly.
287
  return prompt_as_user_input
288
 
289
  async def generate_response(self, query: str, context_chunks: List[Dict], trace_id: str) -> str:
290
  """Generate response using LLM via the conversational task."""
291
  try:
292
- # Format the RAG prompt as the user's input for the conversational model
293
  formatted_input = self.format_prompt_for_conversational(query, context_chunks)
294
 
295
- # Use the conversational task
296
  response = self.client.conversational(
297
- inputs=formatted_input, # This is the current user turn
298
- # No past_user_inputs or generated_responses are provided initially
299
- # to keep it stateless per query, akin to text_generation.
300
  parameters={
301
  "temperature": 0.7,
302
  "max_new_tokens": 512,
303
- # Add other parameters if needed, e.g., do_sample, top_p, top_k
304
- # "do_sample": True,
305
- # "top_p": 0.95,
306
- # "top_k": 50,
307
  }
308
  )
309
 
310
- # The conversational response has a list of generated responses.
311
- # We assume the first one is the primary answer.
312
  if response.generated_responses:
313
  return response.generated_responses[0]
314
  else:
@@ -325,7 +312,7 @@ class CoordinatorAgent(BaseAgent):
325
  super().__init__("CoordinatorAgent")
326
  self.ingestion_agent = IngestionAgent()
327
  self.retrieval_agent = RetrievalAgent()
328
- self.llm_agent = LLMResponseAgent() # LLMResponseAgent will use the global HF_TOKEN
329
  self.documents_processed = False
330
 
331
  async def process_documents(self, files: List[str]) -> str:
@@ -333,7 +320,6 @@ class CoordinatorAgent(BaseAgent):
333
  trace_id = str(uuid.uuid4())
334
 
335
  try:
336
- # Step 1: Ingestion
337
  await self.send_mcp_message(
338
  "IngestionAgent",
339
  "DOCUMENT_INGESTION_REQUEST",
@@ -350,7 +336,6 @@ class CoordinatorAgent(BaseAgent):
350
  trace_id
351
  )
352
 
353
- # Step 2: Create vector store
354
  await self.retrieval_agent.create_vector_store(documents, trace_id)
355
 
356
  self.documents_processed = True
@@ -369,7 +354,6 @@ class CoordinatorAgent(BaseAgent):
369
  trace_id = str(uuid.uuid4())
370
 
371
  try:
372
- # Step 1: Retrieval
373
  await self.send_mcp_message(
374
  "RetrievalAgent",
375
  "RETRIEVAL_REQUEST",
@@ -377,9 +361,8 @@ class CoordinatorAgent(BaseAgent):
377
  trace_id
378
  )
379
 
380
- context_chunks = await self.retrieval_agent.retrieve_relevant_chunks(query, k=5, trace_id=trace_id)
381
 
382
- # Step 2: LLM Response
383
  await self.send_mcp_message(
384
  "LLMResponseAgent",
385
  "LLM_GENERATION_REQUEST",
@@ -399,31 +382,19 @@ class CoordinatorAgent(BaseAgent):
399
  coordinator = CoordinatorAgent()
400
 
401
  async def process_files(files):
402
- """Process uploaded files"""
403
  if not files:
404
  return "❌ Please upload at least one file."
405
 
406
- file_paths = []
407
- for file in files:
408
- temp_dir = tempfile.gettempdir()
409
- unique_filename = f"{uuid.uuid4()}_{os.path.basename(file.name)}"
410
- temp_path = os.path.join(temp_dir, unique_filename)
411
- try:
412
- file_content = file.read()
413
- with open(temp_path, 'wb') as f:
414
- f.write(file_content)
415
- file_paths.append(temp_path)
416
- except Exception as e:
417
- logger.error(f"Error saving uploaded file {file.name}: {e}")
418
- return f"❌ Error saving uploaded file {file.name}: {e}"
419
 
420
- result = await coordinator.process_documents(file_paths)
421
 
422
- for path in file_paths:
423
- try:
424
- os.remove(path)
425
- except Exception as e:
426
- logger.warning(f"Could not remove temporary file {path}: {e}")
427
 
428
  return result
429
 
@@ -629,6 +600,8 @@ def create_interface():
629
  label="Choose Files",
630
  file_count="multiple",
631
  file_types=[".pdf", ".docx", ".pptx", ".csv", ".txt", ".md"],
 
 
632
  elem_classes=["file-upload"]
633
  )
634
 
 
8
  import asyncio
9
  from dataclasses import dataclass, asdict
10
  import logging
11
+ import sys
12
 
13
  # Document processing imports
14
  import PyPDF2
 
29
  logger = logging.getLogger(__name__)
30
 
31
  # --- Get HF token from environment and perform a crucial check ---
32
+ HF_TOKEN = os.getenv('HF_TOKEN')
33
 
34
  if HF_TOKEN is None:
35
  logger.error("FATAL ERROR: HuggingFace token (HF_TOKEN) environment variable is not set.")
 
70
  if message.receiver == agent_name:
71
  return message
72
  # Re-queue if not for this agent
73
+ await self.mcp.put(message) # Corrected: Use mcp.put instead of message_queue.put directly
74
 
75
  # Global MCP instance
76
  mcp = MCPCommunicator()
 
171
  """Process uploaded documents and return chunked documents"""
172
  all_documents = []
173
 
174
+ for file_path in files: # file_path is already the path to the temporary file
175
  file_ext = os.path.splitext(file_path)[1].lower()
176
  filename = os.path.basename(file_path)
177
 
 
256
  class LLMResponseAgent(BaseAgent):
257
  def __init__(self):
258
  super().__init__("LLMResponseAgent")
 
259
  self.client = InferenceClient(
260
  model="meta-llama/Llama-3.1-8B-Instruct",
261
+ token=HF_TOKEN
262
  )
263
 
264
  def format_prompt_for_conversational(self, query: str, context_chunks: List[Dict]) -> str:
 
271
  for chunk in context_chunks
272
  ])
273
 
 
 
274
  prompt_as_user_input = f"""Based on the following context from uploaded documents, please answer the user's question.
275
 
276
  Context:
 
280
 
281
  Please provide a comprehensive answer based on the context above. If the context doesn't contain enough information to fully answer the question, please mention what information is available and what might be missing.
282
 
283
+ Answer:"""
284
  return prompt_as_user_input
285
 
286
  async def generate_response(self, query: str, context_chunks: List[Dict], trace_id: str) -> str:
287
  """Generate response using LLM via the conversational task."""
288
  try:
 
289
  formatted_input = self.format_prompt_for_conversational(query, context_chunks)
290
 
 
291
  response = self.client.conversational(
292
+ inputs=formatted_input,
 
 
293
  parameters={
294
  "temperature": 0.7,
295
  "max_new_tokens": 512,
 
 
 
 
296
  }
297
  )
298
 
 
 
299
  if response.generated_responses:
300
  return response.generated_responses[0]
301
  else:
 
312
  super().__init__("CoordinatorAgent")
313
  self.ingestion_agent = IngestionAgent()
314
  self.retrieval_agent = RetrievalAgent()
315
+ self.llm_agent = LLMResponseAgent()
316
  self.documents_processed = False
317
 
318
  async def process_documents(self, files: List[str]) -> str:
 
320
  trace_id = str(uuid.uuid4())
321
 
322
  try:
 
323
  await self.send_mcp_message(
324
  "IngestionAgent",
325
  "DOCUMENT_INGESTION_REQUEST",
 
336
  trace_id
337
  )
338
 
 
339
  await self.retrieval_agent.create_vector_store(documents, trace_id)
340
 
341
  self.documents_processed = True
 
354
  trace_id = str(uuid.uuid4())
355
 
356
  try:
 
357
  await self.send_mcp_message(
358
  "RetrievalAgent",
359
  "RETRIEVAL_REQUEST",
 
361
  trace_id
362
  )
363
 
364
+ context_chunks = await self.retrierieval_agent.retrieve_relevant_chunks(query, k=5, trace_id=trace_id)
365
 
 
366
  await self.send_mcp_message(
367
  "LLMResponseAgent",
368
  "LLM_GENERATION_REQUEST",
 
382
  coordinator = CoordinatorAgent()
383
 
384
  async def process_files(files):
385
+ """Process uploaded files (already temporary file paths from Gradio)"""
386
  if not files:
387
  return "❌ Please upload at least one file."
388
 
389
+ # Gradio's gr.File component with default type="filepath" already provides
390
+ # the temporary file paths. We just need to pass them to the ingestion agent.
391
+ # The 'files' variable here is already a list of strings (filepaths).
392
+ file_paths_for_ingestion = [file.name for file in files] # Extract the actual path string
 
 
 
 
 
 
 
 
 
393
 
394
+ result = await coordinator.process_documents(file_paths_for_ingestion)
395
 
396
+ # Cleanup is handled by Gradio's tmp directory cleanup, but explicit removal is also fine.
397
+ # No need to manually create temp files or read content.
 
 
 
398
 
399
  return result
400
 
 
600
  label="Choose Files",
601
  file_count="multiple",
602
  file_types=[".pdf", ".docx", ".pptx", ".csv", ".txt", ".md"],
603
+ # type="filepath" is the default, but explicitly setting it helps clarify
604
+ type="filepath",
605
  elem_classes=["file-upload"]
606
  )
607