SakibAhmed commited on
Commit
b955403
·
verified ·
1 Parent(s): 9ce91fe

Upload 2 files

Browse files
Files changed (2) hide show
  1. chunker.py +23 -14
  2. llm_handling.py +23 -32
chunker.py CHANGED
@@ -6,6 +6,8 @@ from typing import List, Dict, Optional
6
 
7
  from pypdf import PdfReader
8
  import docx as python_docx
 
 
9
  from langchain.text_splitter import RecursiveCharacterTextSplitter
10
 
11
  # --- Logging Setup ---
@@ -18,8 +20,7 @@ logging.basicConfig(
18
  )
19
  logger = logging.getLogger(__name__)
20
 
21
- # --- Text Extraction Helper Functions ---
22
- # Note: These are duplicated from llm_handling.py to make this a standalone script.
23
  def extract_text_from_file(file_path: str, file_type: str) -> Optional[str]:
24
  logger.info(f"Extracting text from {file_type.upper()} file: {os.path.basename(file_path)}")
25
  text_content = None
@@ -33,6 +34,18 @@ def extract_text_from_file(file_path: str, file_type: str) -> Optional[str]:
33
  elif file_type == 'txt':
34
  with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
35
  text_content = f.read()
 
 
 
 
 
 
 
 
 
 
 
 
36
  else:
37
  logger.warning(f"Unsupported file type for text extraction: {file_type} for file {os.path.basename(file_path)}")
38
  return None
@@ -45,18 +58,16 @@ def extract_text_from_file(file_path: str, file_type: str) -> Optional[str]:
45
  logger.error(f"Error extracting text from {os.path.basename(file_path)} ({file_type.upper()}): {e}", exc_info=True)
46
  return None
47
 
48
- SUPPORTED_EXTENSIONS = {
49
- 'pdf': lambda path: extract_text_from_file(path, 'pdf'),
50
- 'docx': lambda path: extract_text_from_file(path, 'docx'),
51
- 'txt': lambda path: extract_text_from_file(path, 'txt'),
52
- }
53
 
54
  def process_sources_and_create_chunks(
55
  sources_dir: str,
56
  output_file: str,
57
  chunk_size: int = 1000,
58
  chunk_overlap: int = 150,
59
- text_output_dir: Optional[str] = None # MODIFIED: Added optional parameter
60
  ) -> None:
61
  """
62
  Scans a directory for source files, extracts text, splits it into chunks,
@@ -69,7 +80,6 @@ def process_sources_and_create_chunks(
69
 
70
  logger.info(f"Starting chunking process. Sources: '{sources_dir}', Output: '{output_file}'")
71
 
72
- # MODIFIED: Create text output directory if provided
73
  if text_output_dir:
74
  os.makedirs(text_output_dir, exist_ok=True)
75
  logger.info(f"Will save raw extracted text to: '{text_output_dir}'")
@@ -90,10 +100,10 @@ def process_sources_and_create_chunks(
90
  continue
91
 
92
  logger.info(f"Processing source file: {filename}")
93
- text_content = SUPPORTED_EXTENSIONS[file_ext](file_path)
 
94
 
95
  if text_content:
96
- # MODIFIED: Save the raw text to a file if directory is specified
97
  if text_output_dir:
98
  try:
99
  text_output_path = os.path.join(text_output_dir, f"{filename}.txt")
@@ -143,7 +153,7 @@ def main():
143
  '--sources-dir',
144
  type=str,
145
  required=True,
146
- help="The directory containing source files (PDFs, DOCX, TXT)."
147
  )
148
  parser.add_argument(
149
  '--output-file',
@@ -151,7 +161,6 @@ def main():
151
  required=True,
152
  help="The full path for the output JSON file containing the chunks."
153
  )
154
- # MODIFIED: Added new optional argument
155
  parser.add_argument(
156
  '--text-output-dir',
157
  type=str,
@@ -179,7 +188,7 @@ def main():
179
  output_file=args.output_file,
180
  chunk_size=args.chunk_size,
181
  chunk_overlap=args.chunk_overlap,
182
- text_output_dir=args.text_output_dir # MODIFIED: Pass argument
183
  )
184
  except Exception as e:
185
  logger.critical(f"A critical error occurred during the chunking process: {e}", exc_info=True)
 
6
 
7
  from pypdf import PdfReader
8
  import docx as python_docx
9
+ # ADDED: Import pandas to handle CSV/XLSX files
10
+ import pandas as pd
11
  from langchain.text_splitter import RecursiveCharacterTextSplitter
12
 
13
  # --- Logging Setup ---
 
20
  )
21
  logger = logging.getLogger(__name__)
22
 
23
+ # --- Text Extraction Helper Functions (MODIFIED) ---
 
24
  def extract_text_from_file(file_path: str, file_type: str) -> Optional[str]:
25
  logger.info(f"Extracting text from {file_type.upper()} file: {os.path.basename(file_path)}")
26
  text_content = None
 
34
  elif file_type == 'txt':
35
  with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
36
  text_content = f.read()
37
+ # ADDED: Logic for CSV and XLSX files
38
+ elif file_type in ['csv', 'xlsx']:
39
+ df = pd.read_excel(file_path) if file_type == 'xlsx' else pd.read_csv(file_path)
40
+ if df.empty:
41
+ return ""
42
+ # Convert each row into a descriptive string format
43
+ text_chunks = []
44
+ for index, row in df.iterrows():
45
+ row_text = f"Row {index + 1}: "
46
+ row_text += ", ".join([f"{col}: {val}" for col, val in row.items() if pd.notna(val)])
47
+ text_chunks.append(row_text)
48
+ text_content = "\n".join(text_chunks)
49
  else:
50
  logger.warning(f"Unsupported file type for text extraction: {file_type} for file {os.path.basename(file_path)}")
51
  return None
 
58
  logger.error(f"Error extracting text from {os.path.basename(file_path)} ({file_type.upper()}): {e}", exc_info=True)
59
  return None
60
 
61
+ # MODIFIED: Added 'csv' and 'xlsx' to the list of supported extensions
62
+ SUPPORTED_EXTENSIONS = ['pdf', 'docx', 'txt', 'csv', 'xlsx']
63
+
 
 
64
 
65
  def process_sources_and_create_chunks(
66
  sources_dir: str,
67
  output_file: str,
68
  chunk_size: int = 1000,
69
  chunk_overlap: int = 150,
70
+ text_output_dir: Optional[str] = None
71
  ) -> None:
72
  """
73
  Scans a directory for source files, extracts text, splits it into chunks,
 
80
 
81
  logger.info(f"Starting chunking process. Sources: '{sources_dir}', Output: '{output_file}'")
82
 
 
83
  if text_output_dir:
84
  os.makedirs(text_output_dir, exist_ok=True)
85
  logger.info(f"Will save raw extracted text to: '{text_output_dir}'")
 
100
  continue
101
 
102
  logger.info(f"Processing source file: {filename}")
103
+ # MODIFIED: Simplified the call to the unified extraction function
104
+ text_content = extract_text_from_file(file_path, file_ext)
105
 
106
  if text_content:
 
107
  if text_output_dir:
108
  try:
109
  text_output_path = os.path.join(text_output_dir, f"{filename}.txt")
 
153
  '--sources-dir',
154
  type=str,
155
  required=True,
156
+ help="The directory containing source files (PDFs, DOCX, TXT, CSV, XLSX)."
157
  )
158
  parser.add_argument(
159
  '--output-file',
 
161
  required=True,
162
  help="The full path for the output JSON file containing the chunks."
163
  )
 
164
  parser.add_argument(
165
  '--text-output-dir',
166
  type=str,
 
188
  output_file=args.output_file,
189
  chunk_size=args.chunk_size,
190
  chunk_overlap=args.chunk_overlap,
191
+ text_output_dir=args.text_output_dir
192
  )
193
  except Exception as e:
194
  logger.critical(f"A critical error occurred during the chunking process: {e}", exc_info=True)
llm_handling.py CHANGED
@@ -14,6 +14,8 @@ import torch
14
  from sentence_transformers import SentenceTransformer
15
  from pypdf import PdfReader
16
  import docx as python_docx
 
 
17
 
18
  from llama_index.core.llms import ChatMessage
19
  from llama_index.llms.groq import Groq as LlamaIndexGroqClient
@@ -27,7 +29,6 @@ from langchain.callbacks.manager import CallbackManagerForRetrieverRun
27
  from langchain.schema.runnable import RunnablePassthrough, RunnableParallel
28
  from langchain.schema.output_parser import StrOutputParser
29
  from langchain.text_splitter import RecursiveCharacterTextSplitter
30
- # MODIFIED: Import the new prompt
31
  from system_prompts import RAG_SYSTEM_PROMPT, FALLBACK_SYSTEM_PROMPT, QA_FORMATTER_PROMPT
32
 
33
  logger = logging.getLogger(__name__)
@@ -43,7 +44,6 @@ if not GROQ_API_KEY:
43
  logger.critical("CRITICAL: BOT_API_KEY environment variable not found. Services will fail.")
44
 
45
  FALLBACK_LLM_MODEL_NAME = os.getenv("GROQ_FALLBACK_MODEL", "llama-3.1-70b-versatile")
46
- # ADDED: New constant for the auxiliary model
47
  AUXILIARY_LLM_MODEL_NAME = os.getenv("GROQ_AUXILIARY_MODEL", "llama3-8b-8192")
48
  _MODULE_BASE_DIR = os.path.dirname(os.path.abspath(__file__))
49
  RAG_FAISS_INDEX_SUBDIR_NAME = "faiss_index"
@@ -61,7 +61,8 @@ RAG_DEFAULT_RETRIEVER_K = int(os.getenv("RAG_RETRIEVER_K", 3))
61
  GDRIVE_SOURCES_ENABLED = os.getenv("GDRIVE_SOURCES_ENABLED", "False").lower() == "true"
62
  GDRIVE_FOLDER_ID_OR_URL = os.getenv("GDRIVE_FOLDER_URL")
63
 
64
- # --- Text Extraction Helper Function ---
 
65
  def extract_text_from_file(file_path: str, file_type: str) -> Optional[str]:
66
  logger.info(f"Extracting text from {file_type.upper()} file: {os.path.basename(file_path)}")
67
  try:
@@ -74,13 +75,28 @@ def extract_text_from_file(file_path: str, file_type: str) -> Optional[str]:
74
  elif file_type == 'txt':
75
  with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
76
  return f.read()
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  logger.warning(f"Unsupported file type for text extraction: {file_type}")
78
  return None
79
  except Exception as e:
80
  logger.error(f"Error extracting text from {os.path.basename(file_path)}: {e}", exc_info=True)
81
  return None
82
 
83
- FAISS_RAG_SUPPORTED_EXTENSIONS = {'pdf': 'pdf', 'docx': 'docx', 'txt': 'txt'}
 
 
84
 
85
  # --- FAISS RAG System ---
86
  class FAISSRetrieverWithScore(BaseRetriever):
@@ -180,18 +196,17 @@ class KnowledgeRAG:
180
  processed_files_this_build.append(filename)
181
 
182
  if not all_docs_for_vectorstore:
183
- self.logger.warning(f"No processable PDF/DOCX/TXT documents found in '{source_folder_path}'. RAG index will only contain other sources if available.")
184
 
185
 
186
  self.processed_source_files = processed_files_this_build
187
 
188
- # This print statement is kept for console visibility on startup/rebuild
189
  print("\n--- Document Files Used for RAG Index ---")
190
  if self.processed_source_files:
191
  for filename in self.processed_source_files:
192
  print(f"- {filename}")
193
  else:
194
- print("No PDF/DOCX/TXT source files were processed for the RAG index.")
195
  print("---------------------------------------\n")
196
 
197
  if not all_docs_for_vectorstore:
@@ -242,7 +257,6 @@ class KnowledgeRAG:
242
 
243
  def invoke(self, query: str, top_k: Optional[int] = None) -> Dict[str, Any]:
244
  if not self.rag_chain:
245
- # MODIFIED: Changed severity
246
  self.logger.warning("RAG system not fully initialized. Cannot invoke.")
247
  return {"answer": "The provided bibliography does not contain specific information on this topic.", "source": "system_error", "cited_source_details": []}
248
 
@@ -263,7 +277,6 @@ class KnowledgeRAG:
263
 
264
  context_str = self.format_docs(retrieved_docs)
265
 
266
- # MODIFIED: Added full logging as per user request
267
  print(f"\n--- RAG INVOKE ---")
268
  print(f"QUESTION: {query}")
269
  print(f"CONTEXT:\n{context_str}")
@@ -314,13 +327,11 @@ class KnowledgeRAG:
314
  self.retriever.k = k_to_use
315
 
316
  try:
317
- # Check for docs first to avoid streaming "no info" message
318
  retrieved_docs = self.retriever.get_relevant_documents(query)
319
  if not retrieved_docs:
320
  yield "The provided bibliography does not contain specific information on this topic."
321
  return
322
 
323
- # MODIFIED: Added full logging for streaming as per user request
324
  context_str = self.format_docs(retrieved_docs)
325
  print(f"\n--- RAG STREAM ---")
326
  print(f"QUESTION: {query}")
@@ -368,8 +379,6 @@ class GroqBot:
368
  messages.append(ChatMessage(role="system", content=f"**Potentially Relevant Q&A Information from other sources:**\n{qa_info}"))
369
  messages.append(ChatMessage(role="user", content=f"**Current User Query:**\n{current_query}"))
370
 
371
- # MODIFIED: Added full logging as per user request
372
- # The conversion to dict is necessary because ChatMessage is not directly JSON serializable
373
  messages_for_print = [msg.dict() for msg in messages]
374
  print(f"\n--- FALLBACK STREAM ---")
375
  print(f"MESSAGES SENT TO LLM:\n{json.dumps(messages_for_print, indent=2)}")
@@ -384,14 +393,9 @@ class GroqBot:
384
  self.logger.error(f"Groq API error in get_response (Fallback): {e}", exc_info=True)
385
  yield "I am currently unable to process this request due to a technical issue."
386
 
387
- # ADDED: New function for formatting QA answers
388
  def get_answer_from_context(question: str, context: str, system_prompt: str) -> str:
389
- """
390
- Calls the LLM with a specific question and context from a QA source (CSV/XLSX).
391
- """
392
  logger.info(f"Formatting answer for question '{question[:50]}...' using QA context.")
393
  try:
394
- # Use the auxiliary model for this task for speed and cost-efficiency
395
  formatter_llm = ChatGroq(
396
  temperature=0.1,
397
  groq_api_key=GROQ_API_KEY,
@@ -402,7 +406,6 @@ def get_answer_from_context(question: str, context: str, system_prompt: str) ->
402
 
403
  chain = prompt_template | formatter_llm | StrOutputParser()
404
 
405
- # MODIFIED: Added full logging as per user request
406
  print(f"\n--- QA FORMATTER ---")
407
  print(f"QUESTION: {question}")
408
  print(f"CONTEXT:\n{context}")
@@ -421,14 +424,9 @@ def get_answer_from_context(question: str, context: str, system_prompt: str) ->
421
  logger.error(f"Error in get_answer_from_context: {e}", exc_info=True)
422
  return "Sorry, I was unable to formulate an answer based on the available information."
423
 
424
- # ADDED: New function for streaming QA answers
425
  def stream_answer_from_context(question: str, context: str, system_prompt: str) -> Iterator[str]:
426
- """
427
- Calls the LLM with a specific question and context from a QA source and streams the response.
428
- """
429
  logger.info(f"Streaming formatted answer for question '{question[:50]}...' using QA context.")
430
  try:
431
- # Use the auxiliary model for this task for speed and cost-efficiency
432
  formatter_llm = ChatGroq(
433
  temperature=0.1,
434
  groq_api_key=GROQ_API_KEY,
@@ -439,7 +437,6 @@ def stream_answer_from_context(question: str, context: str, system_prompt: str)
439
 
440
  chain = prompt_template | formatter_llm | StrOutputParser()
441
 
442
- # MODIFIED: Added full logging as per user request
443
  print(f"\n--- QA FORMATTER (STREAM) ---")
444
  print(f"QUESTION: {question}")
445
  print(f"CONTEXT:\n{context}")
@@ -493,7 +490,6 @@ def download_and_unzip_gdrive_folder(folder_id_or_url: str, target_dir: str) ->
493
  logger.info(f"Successfully moved GDrive contents to {target_dir}")
494
  return True
495
  except Exception as e:
496
- # MODIFIED: Corrected self.logger to logger
497
  logger.error(f"Error during GDrive download/processing: {e}", exc_info=True)
498
  return False
499
 
@@ -556,15 +552,10 @@ def initialize_and_get_rag_system(force_rebuild: bool = False) -> Optional[Knowl
556
  groq_bot_instance = GroqBot()
557
 
558
  def get_auxiliary_chat_response(messages: List[Dict]) -> str:
559
- """
560
- Handles requests for auxiliary tasks like generating titles or follow-up questions.
561
- Uses a separate, smaller model for efficiency.
562
- """
563
  logger.info(f"Routing auxiliary request to model: {AUXILIARY_LLM_MODEL_NAME}")
564
  try:
565
- # Initialize a dedicated client for this call to use the specific auxiliary model
566
  aux_client = ChatGroq(
567
- temperature=0.2, # A bit more creative than RAG, but still grounded
568
  groq_api_key=GROQ_API_KEY,
569
  model_name=AUXILIARY_LLM_MODEL_NAME
570
  )
 
14
  from sentence_transformers import SentenceTransformer
15
  from pypdf import PdfReader
16
  import docx as python_docx
17
+ # ADDED: Import pandas to handle CSV/XLSX files
18
+ import pandas as pd
19
 
20
  from llama_index.core.llms import ChatMessage
21
  from llama_index.llms.groq import Groq as LlamaIndexGroqClient
 
29
  from langchain.schema.runnable import RunnablePassthrough, RunnableParallel
30
  from langchain.schema.output_parser import StrOutputParser
31
  from langchain.text_splitter import RecursiveCharacterTextSplitter
 
32
  from system_prompts import RAG_SYSTEM_PROMPT, FALLBACK_SYSTEM_PROMPT, QA_FORMATTER_PROMPT
33
 
34
  logger = logging.getLogger(__name__)
 
44
  logger.critical("CRITICAL: BOT_API_KEY environment variable not found. Services will fail.")
45
 
46
  FALLBACK_LLM_MODEL_NAME = os.getenv("GROQ_FALLBACK_MODEL", "llama-3.1-70b-versatile")
 
47
  AUXILIARY_LLM_MODEL_NAME = os.getenv("GROQ_AUXILIARY_MODEL", "llama3-8b-8192")
48
  _MODULE_BASE_DIR = os.path.dirname(os.path.abspath(__file__))
49
  RAG_FAISS_INDEX_SUBDIR_NAME = "faiss_index"
 
61
  GDRIVE_SOURCES_ENABLED = os.getenv("GDRIVE_SOURCES_ENABLED", "False").lower() == "true"
62
  GDRIVE_FOLDER_ID_OR_URL = os.getenv("GDRIVE_FOLDER_URL")
63
 
64
+
65
+ # --- Text Extraction Helper Function (MODIFIED) ---
66
  def extract_text_from_file(file_path: str, file_type: str) -> Optional[str]:
67
  logger.info(f"Extracting text from {file_type.upper()} file: {os.path.basename(file_path)}")
68
  try:
 
75
  elif file_type == 'txt':
76
  with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
77
  return f.read()
78
+ # ADDED: Logic for CSV and XLSX files
79
+ elif file_type in ['csv', 'xlsx']:
80
+ df = pd.read_excel(file_path) if file_type == 'xlsx' else pd.read_csv(file_path)
81
+ if df.empty:
82
+ return ""
83
+ # Convert each row into a descriptive string format
84
+ text_chunks = []
85
+ for index, row in df.iterrows():
86
+ row_text = f"Row {index + 1}: "
87
+ row_text += ", ".join([f"{col}: {val}" for col, val in row.items() if pd.notna(val)])
88
+ text_chunks.append(row_text)
89
+ return "\n".join(text_chunks)
90
+
91
  logger.warning(f"Unsupported file type for text extraction: {file_type}")
92
  return None
93
  except Exception as e:
94
  logger.error(f"Error extracting text from {os.path.basename(file_path)}: {e}", exc_info=True)
95
  return None
96
 
97
+ # MODIFIED: Added 'csv' and 'xlsx' to the list of supported extensions for RAG
98
+ FAISS_RAG_SUPPORTED_EXTENSIONS = {'pdf': 'pdf', 'docx': 'docx', 'txt': 'txt', 'csv': 'csv', 'xlsx': 'xlsx'}
99
+
100
 
101
  # --- FAISS RAG System ---
102
  class FAISSRetrieverWithScore(BaseRetriever):
 
196
  processed_files_this_build.append(filename)
197
 
198
  if not all_docs_for_vectorstore:
199
+ self.logger.warning(f"No processable PDF/DOCX/TXT/CSV/XLSX documents found in '{source_folder_path}'. RAG index will only contain other sources if available.")
200
 
201
 
202
  self.processed_source_files = processed_files_this_build
203
 
 
204
  print("\n--- Document Files Used for RAG Index ---")
205
  if self.processed_source_files:
206
  for filename in self.processed_source_files:
207
  print(f"- {filename}")
208
  else:
209
+ print("No PDF/DOCX/TXT/CSV/XLSX source files were processed for the RAG index.")
210
  print("---------------------------------------\n")
211
 
212
  if not all_docs_for_vectorstore:
 
257
 
258
  def invoke(self, query: str, top_k: Optional[int] = None) -> Dict[str, Any]:
259
  if not self.rag_chain:
 
260
  self.logger.warning("RAG system not fully initialized. Cannot invoke.")
261
  return {"answer": "The provided bibliography does not contain specific information on this topic.", "source": "system_error", "cited_source_details": []}
262
 
 
277
 
278
  context_str = self.format_docs(retrieved_docs)
279
 
 
280
  print(f"\n--- RAG INVOKE ---")
281
  print(f"QUESTION: {query}")
282
  print(f"CONTEXT:\n{context_str}")
 
327
  self.retriever.k = k_to_use
328
 
329
  try:
 
330
  retrieved_docs = self.retriever.get_relevant_documents(query)
331
  if not retrieved_docs:
332
  yield "The provided bibliography does not contain specific information on this topic."
333
  return
334
 
 
335
  context_str = self.format_docs(retrieved_docs)
336
  print(f"\n--- RAG STREAM ---")
337
  print(f"QUESTION: {query}")
 
379
  messages.append(ChatMessage(role="system", content=f"**Potentially Relevant Q&A Information from other sources:**\n{qa_info}"))
380
  messages.append(ChatMessage(role="user", content=f"**Current User Query:**\n{current_query}"))
381
 
 
 
382
  messages_for_print = [msg.dict() for msg in messages]
383
  print(f"\n--- FALLBACK STREAM ---")
384
  print(f"MESSAGES SENT TO LLM:\n{json.dumps(messages_for_print, indent=2)}")
 
393
  self.logger.error(f"Groq API error in get_response (Fallback): {e}", exc_info=True)
394
  yield "I am currently unable to process this request due to a technical issue."
395
 
 
396
  def get_answer_from_context(question: str, context: str, system_prompt: str) -> str:
 
 
 
397
  logger.info(f"Formatting answer for question '{question[:50]}...' using QA context.")
398
  try:
 
399
  formatter_llm = ChatGroq(
400
  temperature=0.1,
401
  groq_api_key=GROQ_API_KEY,
 
406
 
407
  chain = prompt_template | formatter_llm | StrOutputParser()
408
 
 
409
  print(f"\n--- QA FORMATTER ---")
410
  print(f"QUESTION: {question}")
411
  print(f"CONTEXT:\n{context}")
 
424
  logger.error(f"Error in get_answer_from_context: {e}", exc_info=True)
425
  return "Sorry, I was unable to formulate an answer based on the available information."
426
 
 
427
  def stream_answer_from_context(question: str, context: str, system_prompt: str) -> Iterator[str]:
 
 
 
428
  logger.info(f"Streaming formatted answer for question '{question[:50]}...' using QA context.")
429
  try:
 
430
  formatter_llm = ChatGroq(
431
  temperature=0.1,
432
  groq_api_key=GROQ_API_KEY,
 
437
 
438
  chain = prompt_template | formatter_llm | StrOutputParser()
439
 
 
440
  print(f"\n--- QA FORMATTER (STREAM) ---")
441
  print(f"QUESTION: {question}")
442
  print(f"CONTEXT:\n{context}")
 
490
  logger.info(f"Successfully moved GDrive contents to {target_dir}")
491
  return True
492
  except Exception as e:
 
493
  logger.error(f"Error during GDrive download/processing: {e}", exc_info=True)
494
  return False
495
 
 
552
  groq_bot_instance = GroqBot()
553
 
554
  def get_auxiliary_chat_response(messages: List[Dict]) -> str:
 
 
 
 
555
  logger.info(f"Routing auxiliary request to model: {AUXILIARY_LLM_MODEL_NAME}")
556
  try:
 
557
  aux_client = ChatGroq(
558
+ temperature=0.2,
559
  groq_api_key=GROQ_API_KEY,
560
  model_name=AUXILIARY_LLM_MODEL_NAME
561
  )