josondev commited on
Commit
86c8869
·
verified ·
1 Parent(s): 807a857

Update veryfinal.py

Browse files
Files changed (1) hide show
  1. veryfinal.py +110 -254
veryfinal.py CHANGED
@@ -1,13 +1,13 @@
1
  """
2
- Enhanced Multi-LLM Agent System with Question-Answering Capabilities
3
- Supports Groq (Llama-3 8B/70B, DeepSeek), Google Gemini, NVIDIA NIM, and Agno-style agents
4
  """
5
 
6
  import os
7
  import time
8
  import random
9
  import operator
10
- from typing import List, Dict, Any, TypedDict, Annotated, Optional
11
  from dotenv import load_dotenv
12
 
13
  from langchain_core.tools import tool
@@ -18,106 +18,57 @@ from langgraph.checkpoint.memory import MemorySaver
18
  from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
19
  from langchain_groq import ChatGroq
20
 
21
- # Load environment variables
22
  load_dotenv()
23
 
24
- # Enhanced system prompt for question-answering tasks
25
  ENHANCED_SYSTEM_PROMPT = (
26
- '''You are a helpful assistant tasked with answering questions using a set of tools.
27
- You must provide accurate, comprehensive answers based on available information.
28
- When answering questions, follow these guidelines:\n
29
- 1)You are a helpful assistant tasked with answering questions using a set of tools.
30
- 2)Now, I will ask you a question. Report your thoughts, and finish your answer with the following template: FINAL ANSWER: [YOUR FINAL ANSWER].
31
- 3)YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of numbers and/or strings. If you are asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the digits in plain text unless specified otherwise. If you are asked for a comma separated list, apply the above rules depending of whether the element to be put in the list is a number or a string.
32
- 4)Your answer should only start with "FINAL ANSWER: ", then follows with the answer.'''
 
 
 
33
  )
34
 
35
- # ---- Tool Definitions with Enhanced Docstrings ----
36
  @tool
37
- def multiply(a: int | float, b: int | float) -> int | float:
38
- """Multiply two numbers.
39
-
40
- Args:
41
- a: first int | float
42
- b: second int | float
43
- """
44
  return a * b
45
 
46
  @tool
47
- def add(a: int | float, b: int | float) -> int | float:
48
- """
49
- Adds two integers and returns the sum.
50
-
51
- Args:
52
- a (int): First integer
53
- b (int): Second integer
54
-
55
- Returns:
56
- int: Sum of a and b
57
- """
58
  return a + b
59
 
60
  @tool
61
- def subtract(a: int | float, b: int | float) -> int | float:
62
- """
63
- Subtracts the second integer from the first and returns the difference.
64
-
65
- Args:
66
- a (int): First integer (minuend)
67
- b (int): Second integer (subtrahend)
68
-
69
- Returns:
70
- int: Difference of a and b
71
- """
72
  return a - b
73
 
74
  @tool
75
- def divide(a: int | float, b: int | float) -> int | float:
76
- """
77
- Divides the first integer by the second and returns the quotient.
78
-
79
- Args:
80
- a (int): Dividend
81
- b (int): Divisor
82
-
83
- Returns:
84
- float: Quotient of a divided by b
85
-
86
- Raises:
87
- ValueError: If b is zero
88
- """
89
- if b == 0 or b==0.0:
90
  raise ValueError("Cannot divide by zero.")
91
  return a / b
92
 
93
  @tool
94
- def modulus(a: int | float, b: int | float) -> int | float:
95
- """
96
- Returns the remainder when dividing the first integer by the second.
97
-
98
- Args:
99
- a (int): Dividend
100
- b (int): Divisor
101
-
102
- Returns:
103
- int: Remainder of a divided by b
104
- """
105
  return a % b
106
 
107
  @tool
108
  def optimized_web_search(query: str) -> str:
109
- """
110
- Performs an optimized web search using TavilySearchResults.
111
-
112
- Args:
113
- query (str): Search query string
114
-
115
- Returns:
116
- str: Concatenated search results with URLs and content snippets
117
- """
118
  try:
119
  time.sleep(random.uniform(0.7, 1.5))
120
- docs = TavilySearchResults(max_results=3).invoke(query=query)
 
121
  return "\n\n---\n\n".join(
122
  f"<Doc url='{d.get('url','')}'>{d.get('content','')[:800]}</Doc>"
123
  for d in docs
@@ -127,15 +78,7 @@ def optimized_web_search(query: str) -> str:
127
 
128
  @tool
129
  def optimized_wiki_search(query: str) -> str:
130
- """
131
- Performs an optimized Wikipedia search and returns content snippets.
132
-
133
- Args:
134
- query (str): Wikipedia search query
135
-
136
- Returns:
137
- str: Wikipedia content with source attribution
138
- """
139
  try:
140
  time.sleep(random.uniform(0.3, 1))
141
  docs = WikipediaLoader(query=query, load_max_docs=2).load()
@@ -146,59 +89,22 @@ def optimized_wiki_search(query: str) -> str:
146
  except Exception as e:
147
  return f"Wikipedia search failed: {e}"
148
 
149
- # ---- LLM Provider Integrations ----
150
- try:
151
- from langchain_nvidia_ai_endpoints import ChatNVIDIA
152
- NVIDIA_AVAILABLE = True
153
- except ImportError:
154
- NVIDIA_AVAILABLE = False
155
-
156
- try:
157
- import google.generativeai as genai
158
- from langchain_google_genai import ChatGoogleGenerativeAI
159
- GOOGLE_AVAILABLE = True
160
- except ImportError:
161
- GOOGLE_AVAILABLE = False
162
-
163
  # ---- Enhanced Agent State ----
164
  class EnhancedAgentState(TypedDict):
165
- """
166
- State structure for the enhanced multi-LLM agent system.
167
-
168
- Attributes:
169
- messages: List of conversation messages
170
- query: Current query string
171
- agent_type: Selected agent/LLM type
172
- final_answer: Generated response
173
- perf: Performance metrics
174
- agno_resp: Agno-style response metadata
175
- tools_used: List of tools used in processing
176
- reasoning: Step-by-step reasoning process
177
- """
178
  messages: Annotated[List[HumanMessage | AIMessage], operator.add]
179
  query: str
180
  agent_type: str
181
  final_answer: str
182
  perf: Dict[str, Any]
183
  agno_resp: str
184
- tools_used: List[str]
185
- reasoning: str
186
 
187
  # ---- Enhanced Multi-LLM System ----
188
- class EnhancedQuestionAnsweringSystem:
189
- """
190
- Advanced question-answering system that routes queries to appropriate LLM providers
191
- and uses tools to gather information for comprehensive answers.
192
-
193
- Features:
194
- - Multi-LLM routing (Groq, Google, NVIDIA)
195
- - Tool integration for web search and calculations
196
- - Structured reasoning and answer formatting
197
- - Performance monitoring
198
- """
199
 
200
  def __init__(self):
201
- """Initialize the enhanced question-answering system."""
202
  self.tools = [
203
  multiply, add, subtract, divide, modulus,
204
  optimized_web_search, optimized_wiki_search
@@ -206,15 +112,7 @@ class EnhancedQuestionAnsweringSystem:
206
  self.graph = self._build_graph()
207
 
208
  def _llm(self, model_name: str) -> ChatGroq:
209
- """
210
- Create a Groq LLM instance.
211
-
212
- Args:
213
- model_name (str): Model identifier
214
-
215
- Returns:
216
- ChatGroq: Configured Groq LLM instance
217
- """
218
  return ChatGroq(
219
  model=model_name,
220
  temperature=0,
@@ -222,55 +120,53 @@ class EnhancedQuestionAnsweringSystem:
222
  )
223
 
224
  def _build_graph(self) -> StateGraph:
225
- """
226
- Build the LangGraph state machine with enhanced question-answering capabilities.
227
-
228
- Returns:
229
- StateGraph: Compiled graph with routing logic
230
- """
231
  # Initialize LLMs
232
  llama8_llm = self._llm("llama3-8b-8192")
233
  llama70_llm = self._llm("llama3-70b-8192")
234
  deepseek_llm = self._llm("deepseek-chat")
235
 
236
  def router(st: EnhancedAgentState) -> EnhancedAgentState:
237
- """
238
- Route queries to appropriate LLM based on complexity and content.
239
-
240
- Args:
241
- st (EnhancedAgentState): Current state
242
-
243
- Returns:
244
- EnhancedAgentState: Updated state with agent selection
245
- """
246
  q = st["query"].lower()
247
 
248
- # Route based on query characteristics
249
- if any(keyword in q for keyword in ["calculate", "compute", "math", "number"]):
250
  t = "llama70" # Use more powerful model for calculations
251
- elif any(keyword in q for keyword in ["search", "find", "lookup", "wikipedia"]):
252
  t = "search_enhanced" # Use search-enhanced processing
253
  elif "deepseek" in q or any(keyword in q for keyword in ["analyze", "reasoning", "complex"]):
254
  t = "deepseek"
 
 
255
  elif len(q.split()) > 20: # Complex queries
256
  t = "llama70"
257
  else:
258
  t = "llama8" # Default for simple queries
259
 
260
- return {**st, "agent_type": t, "tools_used": [], "reasoning": ""}
261
 
262
  def llama8_node(st: EnhancedAgentState) -> EnhancedAgentState:
263
  """Process query with Llama-3 8B model."""
264
  t0 = time.time()
265
  try:
 
 
 
 
 
 
 
266
  sys = SystemMessage(content=ENHANCED_SYSTEM_PROMPT)
267
- res = llama8_llm.invoke([sys, HumanMessage(content=st["query"])])
268
 
269
- reasoning = "Used Llama-3 8B for efficient processing of straightforward query."
 
 
 
270
 
271
  return {**st,
272
- "final_answer": res.content,
273
- "reasoning": reasoning,
274
  "perf": {"time": time.time() - t0, "prov": "Groq-Llama3-8B"}}
275
  except Exception as e:
276
  return {**st, "final_answer": f"Error: {e}", "perf": {"error": str(e)}}
@@ -279,14 +175,23 @@ class EnhancedQuestionAnsweringSystem:
279
  """Process query with Llama-3 70B model."""
280
  t0 = time.time()
281
  try:
 
 
 
 
 
 
 
282
  sys = SystemMessage(content=ENHANCED_SYSTEM_PROMPT)
283
- res = llama70_llm.invoke([sys, HumanMessage(content=st["query"])])
284
 
285
- reasoning = "Used Llama-3 70B for complex reasoning and detailed analysis."
 
 
 
286
 
287
  return {**st,
288
- "final_answer": res.content,
289
- "reasoning": reasoning,
290
  "perf": {"time": time.time() - t0, "prov": "Groq-Llama3-70B"}}
291
  except Exception as e:
292
  return {**st, "final_answer": f"Error: {e}", "perf": {"error": str(e)}}
@@ -295,14 +200,23 @@ class EnhancedQuestionAnsweringSystem:
295
  """Process query with DeepSeek model."""
296
  t0 = time.time()
297
  try:
 
 
 
 
 
 
 
298
  sys = SystemMessage(content=ENHANCED_SYSTEM_PROMPT)
299
- res = deepseek_llm.invoke([sys, HumanMessage(content=st["query"])])
300
 
301
- reasoning = "Used DeepSeek for advanced reasoning and analytical tasks."
 
 
 
302
 
303
  return {**st,
304
- "final_answer": res.content,
305
- "reasoning": reasoning,
306
  "perf": {"time": time.time() - t0, "prov": "Groq-DeepSeek"}}
307
  except Exception as e:
308
  return {**st, "final_answer": f"Error: {e}", "perf": {"error": str(e)}}
@@ -310,43 +224,38 @@ class EnhancedQuestionAnsweringSystem:
310
  def search_enhanced_node(st: EnhancedAgentState) -> EnhancedAgentState:
311
  """Process query with search enhancement."""
312
  t0 = time.time()
313
- tools_used = []
314
- reasoning_steps = []
315
 
316
  try:
317
- # Determine if we need web search or Wikipedia
318
  query = st["query"]
319
  search_results = ""
320
 
321
  if any(keyword in query.lower() for keyword in ["wikipedia", "wiki"]):
322
  search_results = optimized_wiki_search.invoke({"query": query})
323
- tools_used.append("wikipedia_search")
324
- reasoning_steps.append("Searched Wikipedia for relevant information")
325
  else:
326
  search_results = optimized_web_search.invoke({"query": query})
327
- tools_used.append("web_search")
328
- reasoning_steps.append("Performed web search for current information")
329
 
330
- # Enhance query with search results
331
  enhanced_query = f"""
332
- Original Query: {query}
333
 
334
  Search Results:
335
  {search_results}
336
 
337
- Based on the search results above, please provide a comprehensive answer to the original query.
 
338
  """
339
 
340
  sys = SystemMessage(content=ENHANCED_SYSTEM_PROMPT)
341
  res = llama70_llm.invoke([sys, HumanMessage(content=enhanced_query)])
342
 
343
- reasoning_steps.append("Used Llama-3 70B to analyze search results and generate comprehensive answer")
344
- reasoning = " -> ".join(reasoning_steps)
 
 
345
 
346
  return {**st,
347
- "final_answer": res.content,
348
- "tools_used": tools_used,
349
- "reasoning": reasoning,
350
  "perf": {"time": time.time() - t0, "prov": "Search-Enhanced-Llama70"}}
351
  except Exception as e:
352
  return {**st, "final_answer": f"Error: {e}", "perf": {"error": str(e)}}
@@ -373,24 +282,14 @@ class EnhancedQuestionAnsweringSystem:
373
  return g.compile(checkpointer=MemorySaver())
374
 
375
  def process_query(self, q: str) -> str:
376
- """
377
- Process a query through the enhanced question-answering system.
378
-
379
- Args:
380
- q (str): Input query
381
-
382
- Returns:
383
- str: Generated response with proper formatting
384
- """
385
  state = {
386
  "messages": [HumanMessage(content=q)],
387
  "query": q,
388
  "agent_type": "",
389
  "final_answer": "",
390
  "perf": {},
391
- "agno_resp": "",
392
- "tools_used": [],
393
- "reasoning": ""
394
  }
395
  cfg = {"configurable": {"thread_id": f"qa_{hash(q)}"}}
396
 
@@ -398,73 +297,30 @@ class EnhancedQuestionAnsweringSystem:
398
  out = self.graph.invoke(state, cfg)
399
  answer = out.get("final_answer", "").strip()
400
 
401
- # Ensure proper formatting
402
- if not answer.startswith("FINAL ANSWER:"):
403
- # Extract the actual answer if it's buried in explanation
404
- if "FINAL ANSWER:" in answer:
405
- answer = answer.split("FINAL ANSWER:")[-1].strip()
406
- answer = f"FINAL ANSWER: {answer}"
407
- else:
408
- # Add FINAL ANSWER prefix if missing
409
- answer = f"FINAL ANSWER: {answer}"
410
 
411
- return answer
412
  except Exception as e:
413
- return f"FINAL ANSWER: Error processing query: {e}"
414
 
415
  def build_graph(provider: str | None = None) -> StateGraph:
416
- """
417
- Build and return the graph for the enhanced question-answering system.
418
-
419
- Args:
420
- provider (str | None): Provider preference (optional)
421
-
422
- Returns:
423
- StateGraph: Compiled graph instance
424
- """
425
- return EnhancedQuestionAnsweringSystem().graph
426
-
427
- # ---- Main Question-Answering Interface ----
428
- class QuestionAnsweringAgent:
429
- """
430
- Main interface for the question-answering agent system.
431
- """
432
-
433
- def __init__(self):
434
- """Initialize the question-answering agent."""
435
- self.system = EnhancedQuestionAnsweringSystem()
436
-
437
- def answer_question(self, question: str) -> str:
438
- """
439
- Answer a question using the enhanced multi-LLM system.
440
-
441
- Args:
442
- question (str): The question to answer
443
-
444
- Returns:
445
- str: Formatted answer with FINAL ANSWER prefix
446
- """
447
- return self.system.process_query(question)
448
 
449
  if __name__ == "__main__":
450
- # Initialize the question-answering system
451
- qa_agent = QuestionAnsweringAgent()
452
 
453
- # Test with sample questions
454
  test_questions = [
455
- "How many studio albums were published by Mercedes Sosa between 2000 and 2009?",
456
  "What is 25 multiplied by 17?",
457
- "Find information about the capital of France on Wikipedia",
458
- "What is the population of Tokyo according to recent data?"
459
  ]
460
 
461
- print("=" * 80)
462
- print("Enhanced Question-Answering Agent System")
463
- print("=" * 80)
464
-
465
- for i, question in enumerate(test_questions, 1):
466
- print(f"\nQuestion {i}: {question}")
467
- print("-" * 60)
468
- answer = qa_agent.answer_question(question)
469
- print(answer)
470
- print()
 
1
  """
2
+ Enhanced Multi-LLM Agent System - CORRECTED VERSION
3
+ Fixes the issue where questions are returned as answers
4
  """
5
 
6
  import os
7
  import time
8
  import random
9
  import operator
10
+ from typing import List, Dict, Any, TypedDict, Annotated
11
  from dotenv import load_dotenv
12
 
13
  from langchain_core.tools import tool
 
18
  from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
19
  from langchain_groq import ChatGroq
20
 
 
21
  load_dotenv()
22
 
23
+ # Enhanced system prompt for proper question-answering
24
  ENHANCED_SYSTEM_PROMPT = (
25
+ "You are a helpful assistant tasked with answering questions using available tools. "
26
+ "Follow these guidelines:\n"
27
+ "1. Read the question carefully and understand what is being asked\n"
28
+ "2. Use available tools when you need external information\n"
29
+ "3. Provide accurate, specific answers based on the information you find\n"
30
+ "4. For numbers: don't use commas or units unless specified\n"
31
+ "5. For strings: don't use articles or abbreviations, write digits in plain text\n"
32
+ "6. Always end with 'FINAL ANSWER: [YOUR ANSWER]' where [YOUR ANSWER] is concise\n"
33
+ "7. Never repeat the question as your answer\n"
34
+ "8. If you cannot find the answer, state 'Information not available'\n"
35
  )
36
 
37
+ # ---- Tool Definitions ----
38
  @tool
39
+ def multiply(a: int, b: int) -> int:
40
+ """Multiply two integers and return the product."""
 
 
 
 
 
41
  return a * b
42
 
43
  @tool
44
+ def add(a: int, b: int) -> int:
45
+ """Add two integers and return the sum."""
 
 
 
 
 
 
 
 
 
46
  return a + b
47
 
48
  @tool
49
+ def subtract(a: int, b: int) -> int:
50
+ """Subtract the second integer from the first and return the difference."""
 
 
 
 
 
 
 
 
 
51
  return a - b
52
 
53
  @tool
54
+ def divide(a: int, b: int) -> float:
55
+ """Divide the first integer by the second and return the quotient."""
56
+ if b == 0:
 
 
 
 
 
 
 
 
 
 
 
 
57
  raise ValueError("Cannot divide by zero.")
58
  return a / b
59
 
60
  @tool
61
+ def modulus(a: int, b: int) -> int:
62
+ """Return the remainder when dividing the first integer by the second."""
 
 
 
 
 
 
 
 
 
63
  return a % b
64
 
65
  @tool
66
  def optimized_web_search(query: str) -> str:
67
+ """Perform web search using TavilySearchResults."""
 
 
 
 
 
 
 
 
68
  try:
69
  time.sleep(random.uniform(0.7, 1.5))
70
+ search_tool = TavilySearchResults(max_results=3)
71
+ docs = search_tool.invoke({"query": query})
72
  return "\n\n---\n\n".join(
73
  f"<Doc url='{d.get('url','')}'>{d.get('content','')[:800]}</Doc>"
74
  for d in docs
 
78
 
79
  @tool
80
  def optimized_wiki_search(query: str) -> str:
81
+ """Perform Wikipedia search and return content."""
 
 
 
 
 
 
 
 
82
  try:
83
  time.sleep(random.uniform(0.3, 1))
84
  docs = WikipediaLoader(query=query, load_max_docs=2).load()
 
89
  except Exception as e:
90
  return f"Wikipedia search failed: {e}"
91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  # ---- Enhanced Agent State ----
93
  class EnhancedAgentState(TypedDict):
94
+ """State structure for the enhanced agent system."""
 
 
 
 
 
 
 
 
 
 
 
 
95
  messages: Annotated[List[HumanMessage | AIMessage], operator.add]
96
  query: str
97
  agent_type: str
98
  final_answer: str
99
  perf: Dict[str, Any]
100
  agno_resp: str
 
 
101
 
102
  # ---- Enhanced Multi-LLM System ----
103
+ class HybridLangGraphMultiLLMSystem:
104
+ """Enhanced question-answering system with proper response handling."""
 
 
 
 
 
 
 
 
 
105
 
106
  def __init__(self):
107
+ """Initialize the enhanced multi-LLM system."""
108
  self.tools = [
109
  multiply, add, subtract, divide, modulus,
110
  optimized_web_search, optimized_wiki_search
 
112
  self.graph = self._build_graph()
113
 
114
  def _llm(self, model_name: str) -> ChatGroq:
115
+ """Create a Groq LLM instance."""
 
 
 
 
 
 
 
 
116
  return ChatGroq(
117
  model=model_name,
118
  temperature=0,
 
120
  )
121
 
122
  def _build_graph(self) -> StateGraph:
123
+ """Build the LangGraph state machine with proper response handling."""
 
 
 
 
 
124
  # Initialize LLMs
125
  llama8_llm = self._llm("llama3-8b-8192")
126
  llama70_llm = self._llm("llama3-70b-8192")
127
  deepseek_llm = self._llm("deepseek-chat")
128
 
129
  def router(st: EnhancedAgentState) -> EnhancedAgentState:
130
+ """Route queries to appropriate LLM based on content analysis."""
 
 
 
 
 
 
 
 
131
  q = st["query"].lower()
132
 
133
+ # Enhanced routing logic
134
+ if any(keyword in q for keyword in ["calculate", "compute", "math", "multiply", "add", "subtract", "divide"]):
135
  t = "llama70" # Use more powerful model for calculations
136
+ elif any(keyword in q for keyword in ["search", "find", "lookup", "wikipedia", "information about"]):
137
  t = "search_enhanced" # Use search-enhanced processing
138
  elif "deepseek" in q or any(keyword in q for keyword in ["analyze", "reasoning", "complex"]):
139
  t = "deepseek"
140
+ elif "llama-8" in q:
141
+ t = "llama8"
142
  elif len(q.split()) > 20: # Complex queries
143
  t = "llama70"
144
  else:
145
  t = "llama8" # Default for simple queries
146
 
147
+ return {**st, "agent_type": t}
148
 
149
  def llama8_node(st: EnhancedAgentState) -> EnhancedAgentState:
150
  """Process query with Llama-3 8B model."""
151
  t0 = time.time()
152
  try:
153
+ # Create enhanced prompt with context
154
+ enhanced_query = f"""
155
+ Question: {st["query"]}
156
+
157
+ Please provide a direct, accurate answer to this question. Do not repeat the question.
158
+ """
159
+
160
  sys = SystemMessage(content=ENHANCED_SYSTEM_PROMPT)
161
+ res = llama8_llm.invoke([sys, HumanMessage(content=enhanced_query)])
162
 
163
+ # Extract and clean the answer
164
+ answer = res.content.strip()
165
+ if "FINAL ANSWER:" in answer:
166
+ answer = answer.split("FINAL ANSWER:")[-1].strip()
167
 
168
  return {**st,
169
+ "final_answer": answer,
 
170
  "perf": {"time": time.time() - t0, "prov": "Groq-Llama3-8B"}}
171
  except Exception as e:
172
  return {**st, "final_answer": f"Error: {e}", "perf": {"error": str(e)}}
 
175
  """Process query with Llama-3 70B model."""
176
  t0 = time.time()
177
  try:
178
+ # Create enhanced prompt with context
179
+ enhanced_query = f"""
180
+ Question: {st["query"]}
181
+
182
+ Please provide a direct, accurate answer to this question. Do not repeat the question.
183
+ """
184
+
185
  sys = SystemMessage(content=ENHANCED_SYSTEM_PROMPT)
186
+ res = llama70_llm.invoke([sys, HumanMessage(content=enhanced_query)])
187
 
188
+ # Extract and clean the answer
189
+ answer = res.content.strip()
190
+ if "FINAL ANSWER:" in answer:
191
+ answer = answer.split("FINAL ANSWER:")[-1].strip()
192
 
193
  return {**st,
194
+ "final_answer": answer,
 
195
  "perf": {"time": time.time() - t0, "prov": "Groq-Llama3-70B"}}
196
  except Exception as e:
197
  return {**st, "final_answer": f"Error: {e}", "perf": {"error": str(e)}}
 
200
  """Process query with DeepSeek model."""
201
  t0 = time.time()
202
  try:
203
+ # Create enhanced prompt with context
204
+ enhanced_query = f"""
205
+ Question: {st["query"]}
206
+
207
+ Please provide a direct, accurate answer to this question. Do not repeat the question.
208
+ """
209
+
210
  sys = SystemMessage(content=ENHANCED_SYSTEM_PROMPT)
211
+ res = deepseek_llm.invoke([sys, HumanMessage(content=enhanced_query)])
212
 
213
+ # Extract and clean the answer
214
+ answer = res.content.strip()
215
+ if "FINAL ANSWER:" in answer:
216
+ answer = answer.split("FINAL ANSWER:")[-1].strip()
217
 
218
  return {**st,
219
+ "final_answer": answer,
 
220
  "perf": {"time": time.time() - t0, "prov": "Groq-DeepSeek"}}
221
  except Exception as e:
222
  return {**st, "final_answer": f"Error: {e}", "perf": {"error": str(e)}}
 
224
  def search_enhanced_node(st: EnhancedAgentState) -> EnhancedAgentState:
225
  """Process query with search enhancement."""
226
  t0 = time.time()
 
 
227
 
228
  try:
229
+ # Determine search strategy
230
  query = st["query"]
231
  search_results = ""
232
 
233
  if any(keyword in query.lower() for keyword in ["wikipedia", "wiki"]):
234
  search_results = optimized_wiki_search.invoke({"query": query})
 
 
235
  else:
236
  search_results = optimized_web_search.invoke({"query": query})
 
 
237
 
238
+ # Create comprehensive prompt with search results
239
  enhanced_query = f"""
240
+ Original Question: {query}
241
 
242
  Search Results:
243
  {search_results}
244
 
245
+ Based on the search results above, provide a direct answer to the original question.
246
+ Extract the specific information requested. Do not repeat the question.
247
  """
248
 
249
  sys = SystemMessage(content=ENHANCED_SYSTEM_PROMPT)
250
  res = llama70_llm.invoke([sys, HumanMessage(content=enhanced_query)])
251
 
252
+ # Extract and clean the answer
253
+ answer = res.content.strip()
254
+ if "FINAL ANSWER:" in answer:
255
+ answer = answer.split("FINAL ANSWER:")[-1].strip()
256
 
257
  return {**st,
258
+ "final_answer": answer,
 
 
259
  "perf": {"time": time.time() - t0, "prov": "Search-Enhanced-Llama70"}}
260
  except Exception as e:
261
  return {**st, "final_answer": f"Error: {e}", "perf": {"error": str(e)}}
 
282
  return g.compile(checkpointer=MemorySaver())
283
 
284
  def process_query(self, q: str) -> str:
285
+ """Process a query and return the final answer."""
 
 
 
 
 
 
 
 
286
  state = {
287
  "messages": [HumanMessage(content=q)],
288
  "query": q,
289
  "agent_type": "",
290
  "final_answer": "",
291
  "perf": {},
292
+ "agno_resp": ""
 
 
293
  }
294
  cfg = {"configurable": {"thread_id": f"qa_{hash(q)}"}}
295
 
 
297
  out = self.graph.invoke(state, cfg)
298
  answer = out.get("final_answer", "").strip()
299
 
300
+ # Ensure we don't return the question as the answer
301
+ if answer == q or answer.startswith(q):
302
+ return "Information not available"
 
 
 
 
 
 
303
 
304
+ return answer if answer else "No answer generated"
305
  except Exception as e:
306
+ return f"Error processing query: {e}"
307
 
308
  def build_graph(provider: str | None = None) -> StateGraph:
309
+ """Build and return the graph for the enhanced agent system."""
310
+ return HybridLangGraphMultiLLMSystem().graph
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311
 
312
  if __name__ == "__main__":
313
+ # Test the system
314
+ qa_system = HybridLangGraphMultiLLMSystem()
315
 
 
316
  test_questions = [
 
317
  "What is 25 multiplied by 17?",
318
+ "Who was the first president of the United States?",
319
+ "Find information about artificial intelligence on Wikipedia"
320
  ]
321
 
322
+ for question in test_questions:
323
+ print(f"Question: {question}")
324
+ answer = qa_system.process_query(question)
325
+ print(f"Answer: {answer}")
326
+ print("-" * 50)