24Arys11 commited on
Commit
f49023b
·
1 Parent(s): 98ada6c

minor refactoring

Browse files
Files changed (6) hide show
  1. agents.py +8 -17
  2. alfred.py +14 -19
  3. app.py +19 -16
  4. args.py +86 -1
  5. itf_agent.py +2 -2
  6. llm_factory.py +1 -68
agents.py CHANGED
@@ -1,23 +1,14 @@
1
  from args import Args
2
  from itf_agent import IAgent
3
- from llm_factory import AgentPreset
4
  from toolbox import Toolbox
5
 
6
 
7
- PRIMARY_AGENT_PRESET = AgentPreset(Args.primary_llm_interface, Args.primary_model,
8
- temperature = None, max_tokens = 2048, repeat_penalty = None)
9
- SECONDARY_AGENT_PRESET = AgentPreset(Args.primary_llm_interface, Args.secondary_model,
10
- temperature = None, max_tokens = 2048, repeat_penalty = None)
11
- VISION_AGENT_PRESET = AgentPreset(Args.vlm_interface, Args.vision_model,
12
- temperature = None, max_tokens = 2048, repeat_penalty = None)
13
-
14
-
15
  class Manager(IAgent):
16
  """
17
  Orchestrates the workflow by delegating tasks to specialized nodes and integrating their outputs
18
  """
19
  def __init__(self):
20
- super().__init__("01_manager.txt", PRIMARY_AGENT_PRESET)
21
 
22
 
23
  class Auditor(IAgent):
@@ -25,7 +16,7 @@ class Auditor(IAgent):
25
  Reviews manager's outputs for accuracy, safety, and quality
26
  """
27
  def __init__(self):
28
- super().__init__("02_auditor.txt", PRIMARY_AGENT_PRESET)
29
 
30
 
31
  class Summarizer(IAgent):
@@ -33,7 +24,7 @@ class Summarizer(IAgent):
33
  Generates concise summaries of conversations or passages.
34
  """
35
  def __init__(self):
36
- super().__init__("03_summarizer.txt", PRIMARY_AGENT_PRESET)
37
 
38
 
39
  class Solver(IAgent):
@@ -41,7 +32,7 @@ class Solver(IAgent):
41
  Central problem-solving node that coordinates with specialized experts based on task requirements
42
  """
43
  def __init__(self):
44
- super().__init__("04_solver.txt", PRIMARY_AGENT_PRESET)
45
 
46
 
47
  class Researcher(IAgent):
@@ -55,7 +46,7 @@ class Researcher(IAgent):
55
  toolbox.duckduckgo_images_search,
56
  toolbox.duckduckgo_videos_search
57
  ]
58
- super().__init__("05_researcher.txt", PRIMARY_AGENT_PRESET, tools)
59
 
60
 
61
  class Reasoner(IAgent):
@@ -77,7 +68,7 @@ class Reasoner(IAgent):
77
  encryption_toolbox.caesar_cipher_brute_force,
78
  encryption_toolbox.reverse_string
79
  ]
80
- super().__init__("06_reasoner.txt", PRIMARY_AGENT_PRESET, tools)
81
 
82
 
83
  class Viewer(IAgent):
@@ -85,7 +76,7 @@ class Viewer(IAgent):
85
  Processes, analyzes, and generates information related to images
86
  """
87
  def __init__(self):
88
- super().__init__("07_viewer.txt", VISION_AGENT_PRESET)
89
 
90
 
91
  class OutputGuard(IAgent):
@@ -93,4 +84,4 @@ class OutputGuard(IAgent):
93
  Performs logical reasoning, inference, and step-by-step problem-solving
94
  """
95
  def __init__(self):
96
- super().__init__("08_output_guard.txt", SECONDARY_AGENT_PRESET)
 
1
  from args import Args
2
  from itf_agent import IAgent
 
3
  from toolbox import Toolbox
4
 
5
 
 
 
 
 
 
 
 
 
6
  class Manager(IAgent):
7
  """
8
  Orchestrates the workflow by delegating tasks to specialized nodes and integrating their outputs
9
  """
10
  def __init__(self):
11
+ super().__init__("01_manager.txt", Args.PRIMARY_AGENT_PRESET)
12
 
13
 
14
  class Auditor(IAgent):
 
16
  Reviews manager's outputs for accuracy, safety, and quality
17
  """
18
  def __init__(self):
19
+ super().__init__("02_auditor.txt", Args.PRIMARY_AGENT_PRESET)
20
 
21
 
22
  class Summarizer(IAgent):
 
24
  Generates concise summaries of conversations or passages.
25
  """
26
  def __init__(self):
27
+ super().__init__("03_summarizer.txt", Args.PRIMARY_AGENT_PRESET)
28
 
29
 
30
  class Solver(IAgent):
 
32
  Central problem-solving node that coordinates with specialized experts based on task requirements
33
  """
34
  def __init__(self):
35
+ super().__init__("04_solver.txt", Args.PRIMARY_AGENT_PRESET)
36
 
37
 
38
  class Researcher(IAgent):
 
46
  toolbox.duckduckgo_images_search,
47
  toolbox.duckduckgo_videos_search
48
  ]
49
+ super().__init__("05_researcher.txt", Args.PRIMARY_AGENT_PRESET, tools)
50
 
51
 
52
  class Reasoner(IAgent):
 
68
  encryption_toolbox.caesar_cipher_brute_force,
69
  encryption_toolbox.reverse_string
70
  ]
71
+ super().__init__("06_reasoner.txt", Args.PRIMARY_AGENT_PRESET, tools)
72
 
73
 
74
  class Viewer(IAgent):
 
76
  Processes, analyzes, and generates information related to images
77
  """
78
  def __init__(self):
79
+ super().__init__("07_viewer.txt", Args.VISION_AGENT_PRESET)
80
 
81
 
82
  class OutputGuard(IAgent):
 
84
  Performs logical reasoning, inference, and step-by-step problem-solving
85
  """
86
  def __init__(self):
87
+ super().__init__("08_output_guard.txt", Args.SECONDARY_AGENT_PRESET)
alfred.py CHANGED
@@ -1,22 +1,12 @@
1
- from typing import Dict, Any
 
 
2
 
3
  from args import Args
4
  from graph import State
5
  from graph_builder import GraphBuilder
6
 
7
 
8
- # Maximum number of interactions between Assistant and Manager
9
- MAX_INTERACTIONS = 6
10
- # Verification happening every few messages to check whether the manager agent
11
- # is making progress or it got stuck (in a repetitive loop or similar pitfalls)
12
- AUDIT_INTERVAL = 3
13
- # Maximum depth of recursion for Manager
14
- MAX_DEPTH = 2
15
- # For both Assistant and Manager:
16
- TEMPERATURE = 0.7
17
- MAX_TOKENS = 2000
18
-
19
-
20
  class Alfred:
21
 
22
  def __init__(self):
@@ -25,15 +15,15 @@ class Alfred:
25
  self.graph_builder = GraphBuilder()
26
  self.agent_graph = self.graph_builder.build_agent_graph()
27
 
28
- async def __call__(self, question: str) -> str:
29
  print(f"Agent received question (first 50 chars): {question[:50]}...")
30
- result = await self.process_query(question)
31
  response = result["final_response"]
32
  print(f"Agent processed the response: {response}")
33
 
34
  return response
35
 
36
- async def process_query(self, query: str) -> Dict[str, Any]:
37
  """
38
  Process a query through the agent graph.
39
 
@@ -45,10 +35,15 @@ class Alfred:
45
  """
46
  initial_state: State = {
47
  "initial_query": query,
48
- "messages": [],
49
- "nr_interactions": 0,
 
 
 
 
 
50
  "final_response": None
51
  }
52
 
53
- result = await self.agent_graph.ainvoke(initial_state)
54
  return result
 
1
+ from langchain_core.messages import BaseMessage
2
+
3
+ from typing import Any, Dict
4
 
5
  from args import Args
6
  from graph import State
7
  from graph_builder import GraphBuilder
8
 
9
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  class Alfred:
11
 
12
  def __init__(self):
 
15
  self.graph_builder = GraphBuilder()
16
  self.agent_graph = self.graph_builder.build_agent_graph()
17
 
18
+ def __call__(self, question: str) -> str:
19
  print(f"Agent received question (first 50 chars): {question[:50]}...")
20
+ result = self.process_query(question)
21
  response = result["final_response"]
22
  print(f"Agent processed the response: {response}")
23
 
24
  return response
25
 
26
+ def process_query(self, query: str) -> Dict[str, Any]:
27
  """
28
  Process a query through the agent graph.
29
 
 
35
  """
36
  initial_state: State = {
37
  "initial_query": query,
38
+ "messages": [BaseMessage(query)], # Manager's context
39
+ "task_progress": [], # Solver's context
40
+ "audit_interval": Args.AlfredParams.AUDIT_INTERVAL,
41
+ "manager_queries": 0,
42
+ "solver_queries": 0,
43
+ "max_interactions": Args.AlfredParams.MAX_INTERACTIONS,
44
+ "max_solving_effort": Args.AlfredParams.MAX_SOLVING_EFFORT,
45
  "final_response": None
46
  }
47
 
48
+ result = self.agent_graph.invoke(initial_state)
49
  return result
app.py CHANGED
@@ -52,6 +52,7 @@ class Application:
52
  """
53
 
54
  print(f"Fetching questions from: {self.questions_url}")
 
55
  try:
56
  response = requests.get(self.questions_url, timeout=15)
57
  response.raise_for_status()
@@ -62,7 +63,8 @@ class Application:
62
  print(f"Fetched {len(questions_data)} questions.")
63
  except requests.exceptions.JSONDecodeError as e:
64
  print(f"Error decoding JSON response from questions endpoint: {e}")
65
- print(f"Response text: {response.text[:500]}")
 
66
  return f"Error decoding server response for questions: {e}", None
67
  except requests.exceptions.RequestException as e:
68
  print(f"Error fetching questions: {e}")
@@ -73,7 +75,7 @@ class Application:
73
  return questions_data
74
 
75
  @staticmethod
76
- async def _run_agent(questions_data, agent):
77
  """
78
  Runs the agent on a list of questions and collects results.
79
 
@@ -99,7 +101,7 @@ class Application:
99
  print(f"Skipping item with missing task_id or question: {item}")
100
  continue
101
  try:
102
- submitted_answer = await agent(question_text)
103
  print(f"SUBMITED_ANSWER: {submitted_answer}")
104
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
105
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
@@ -127,17 +129,18 @@ class Application:
127
  print(f"Submitting {len(answers_payload)} answers to: {self.submit_url}")
128
  try:
129
  if MOCK_SUBMISSION:
130
- mock_response = type('MockResponse', (), {
131
- 'status_code': 200,
132
- 'json': lambda *args: {
133
- "username": self.username,
134
- "score": 100,
135
- "correct_count": len(answers_payload),
136
- "total_attempted": len(answers_payload),
137
- "message": "Mock submission successful."
138
- }
139
- })
140
- response = mock_response()
 
141
  else:
142
  response = requests.post(self.submit_url, json=submission_data, timeout=60)
143
  response.raise_for_status()
@@ -179,7 +182,7 @@ class Application:
179
  results_df = pd.DataFrame(results_log)
180
  return status_message, results_df
181
 
182
- async def eval_and_submit_all(self, profile: gr.OAuthProfile | None):
183
  """
184
  Fetches all questions, runs the agent on them, submits all answers,
185
  and displays the results.
@@ -202,7 +205,7 @@ class Application:
202
  questions_data = self._fetch_questions()
203
 
204
  # 3. Run your Agent
205
- results_log, answers_payload = await self._run_agent(questions_data, agent)
206
 
207
  if not answers_payload:
208
  print("Agent did not produce any answers to submit.")
 
52
  """
53
 
54
  print(f"Fetching questions from: {self.questions_url}")
55
+ response = None
56
  try:
57
  response = requests.get(self.questions_url, timeout=15)
58
  response.raise_for_status()
 
63
  print(f"Fetched {len(questions_data)} questions.")
64
  except requests.exceptions.JSONDecodeError as e:
65
  print(f"Error decoding JSON response from questions endpoint: {e}")
66
+ if response:
67
+ print(f"Response text: {response.text[:500]}")
68
  return f"Error decoding server response for questions: {e}", None
69
  except requests.exceptions.RequestException as e:
70
  print(f"Error fetching questions: {e}")
 
75
  return questions_data
76
 
77
  @staticmethod
78
+ def _run_agent(questions_data, agent):
79
  """
80
  Runs the agent on a list of questions and collects results.
81
 
 
101
  print(f"Skipping item with missing task_id or question: {item}")
102
  continue
103
  try:
104
+ submitted_answer = agent(question_text)
105
  print(f"SUBMITED_ANSWER: {submitted_answer}")
106
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
107
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
 
129
  print(f"Submitting {len(answers_payload)} answers to: {self.submit_url}")
130
  try:
131
  if MOCK_SUBMISSION:
132
+ app_username = self.username
133
+ class MockResponse:
134
+ status_code = 200
135
+ def json(self):
136
+ return {
137
+ "username": app_username,
138
+ "score": 100,
139
+ "correct_count": len(answers_payload),
140
+ "total_attempted": len(answers_payload),
141
+ "message": "Mock submission successful."
142
+ }
143
+ response = MockResponse()
144
  else:
145
  response = requests.post(self.submit_url, json=submission_data, timeout=60)
146
  response.raise_for_status()
 
182
  results_df = pd.DataFrame(results_log)
183
  return status_message, results_df
184
 
185
+ def eval_and_submit_all(self, profile: gr.OAuthProfile | None):
186
  """
187
  Fetches all questions, runs the agent on them, submits all answers,
188
  and displays the results.
 
205
  questions_data = self._fetch_questions()
206
 
207
  # 3. Run your Agent
208
+ results_log, answers_payload = self._run_agent(questions_data, agent)
209
 
210
  if not answers_payload:
211
  print("Agent did not produce any answers to submit.")
args.py CHANGED
@@ -1,5 +1,5 @@
1
-
2
  from enum import Enum
 
3
 
4
  from logger import Logger
5
 
@@ -10,6 +10,71 @@ class LLMInterface(Enum):
10
  # Add your own if you like (then adjust the LLMFactory)
11
 
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  class Args:
14
  LOGGER = Logger.set_logger()
15
  primary_llm_interface=LLMInterface.OPENAI
@@ -21,3 +86,23 @@ class Args:
21
  api_base="http://127.0.0.1:1234/v1" # LM Studio local endpoint
22
  api_key=None
23
  token = "" # Not needed when using OpenAILike API
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from enum import Enum
2
+ from typing import Optional
3
 
4
  from logger import Logger
5
 
 
10
  # Add your own if you like (then adjust the LLMFactory)
11
 
12
 
13
+ class AgentPreset:
14
+ def __init__(self, interface: LLMInterface, model_name: str, temperature: Optional[float] = None,
15
+ max_tokens: Optional[int] = None, repeat_penalty: Optional[float] = None):
16
+ """
17
+ Initialize an AgentPreset with LLM configuration parameters.
18
+
19
+ Args:
20
+ interface: The model interface to use (e.g., OPENAI, HUGGINGFACE)
21
+ model_name: Name of the model to use
22
+ temperature: Controls randomness in responses (0.0-1.0)
23
+ max_tokens: Maximum number of tokens to generate in response
24
+ repeat_penalty: Penalty for token repetition
25
+ """
26
+ self.interface = interface
27
+ self.model_name = model_name
28
+ self.temperature = temperature
29
+ self.max_tokens = max_tokens
30
+ self.repeat_penalty = repeat_penalty
31
+
32
+ def get_interface(self) -> LLMInterface:
33
+ """
34
+ Get the model interface.
35
+
36
+ Returns:
37
+ LLMInterface: The interface used for this agent.
38
+ """
39
+ return self.interface
40
+
41
+ def get_model_name(self) -> str:
42
+ """
43
+ Get the model name.
44
+
45
+ Returns:
46
+ str: The name of the model.
47
+ """
48
+ return self.model_name
49
+
50
+ def get_temperature(self) -> float | None:
51
+ """
52
+ Get the temperature setting.
53
+
54
+ Returns:
55
+ float: The temperature value controlling randomness.
56
+ """
57
+ return self.temperature
58
+
59
+ def get_max_tokens(self) -> int | None:
60
+ """
61
+ Get the maximum tokens setting.
62
+
63
+ Returns:
64
+ int: The maximum number of tokens for generation.
65
+ """
66
+ return self.max_tokens
67
+
68
+ def get_repeat_penalty(self) -> float | None:
69
+ """
70
+ Get the repeat penalty setting.
71
+
72
+ Returns:
73
+ float: The penalty value for token repetition.
74
+ """
75
+ return self.repeat_penalty
76
+
77
+
78
  class Args:
79
  LOGGER = Logger.set_logger()
80
  primary_llm_interface=LLMInterface.OPENAI
 
86
  api_base="http://127.0.0.1:1234/v1" # LM Studio local endpoint
87
  api_key=None
88
  token = "" # Not needed when using OpenAILike API
89
+ # Agent presets
90
+ PRIMARY_AGENT_PRESET = AgentPreset(
91
+ primary_llm_interface, primary_model,
92
+ temperature = None, max_tokens = 2048, repeat_penalty = None
93
+ )
94
+ SECONDARY_AGENT_PRESET = AgentPreset(
95
+ primary_llm_interface, secondary_model,
96
+ temperature = None, max_tokens = 2048, repeat_penalty = None
97
+ )
98
+ VISION_AGENT_PRESET = AgentPreset(
99
+ vlm_interface, vision_model,
100
+ temperature = None, max_tokens = 2048, repeat_penalty = None
101
+ )
102
+ class AlfredParams:
103
+ # Maximum number of interactions between Manager and Solver
104
+ MAX_INTERACTIONS = 6
105
+ # Maximum number of interactions between Solver and it's assistants
106
+ MAX_SOLVING_EFFORT = 6
107
+ # Verification happening every few messages to see whether the manager agent got stuck
108
+ AUDIT_INTERVAL = 3
itf_agent.py CHANGED
@@ -5,8 +5,8 @@ import os
5
  import re
6
  from typing import List
7
 
8
- from args import Args
9
- from llm_factory import LLMFactory, AgentPreset
10
 
11
 
12
  class IAgent():
 
5
  import re
6
  from typing import List
7
 
8
+ from args import Args, AgentPreset
9
+ from llm_factory import LLMFactory
10
 
11
 
12
  class IAgent():
llm_factory.py CHANGED
@@ -1,74 +1,7 @@
1
  from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpoint
2
  from langchain_openai import ChatOpenAI
3
 
4
- from typing import Optional
5
-
6
- from args import LLMInterface, Args
7
-
8
-
9
- class AgentPreset:
10
- def __init__(self, interface: LLMInterface, model_name: str, temperature: Optional[float] = None,
11
- max_tokens: Optional[int] = None, repeat_penalty: Optional[float] = None):
12
- """
13
- Initialize an AgentPreset with LLM configuration parameters.
14
-
15
- Args:
16
- interface: The model interface to use (e.g., OPENAI, HUGGINGFACE)
17
- model_name: Name of the model to use
18
- temperature: Controls randomness in responses (0.0-1.0)
19
- max_tokens: Maximum number of tokens to generate in response
20
- repeat_penalty: Penalty for token repetition
21
- """
22
- self.interface = interface
23
- self.model_name = model_name
24
- self.temperature = temperature
25
- self.max_tokens = max_tokens
26
- self.repeat_penalty = repeat_penalty
27
-
28
- def get_interface(self) -> LLMInterface:
29
- """
30
- Get the model interface.
31
-
32
- Returns:
33
- LLMInterface: The interface used for this agent.
34
- """
35
- return self.interface
36
-
37
- def get_model_name(self) -> str:
38
- """
39
- Get the model name.
40
-
41
- Returns:
42
- str: The name of the model.
43
- """
44
- return self.model_name
45
-
46
- def get_temperature(self) -> float:
47
- """
48
- Get the temperature setting.
49
-
50
- Returns:
51
- float: The temperature value controlling randomness.
52
- """
53
- return self.temperature
54
-
55
- def get_max_tokens(self) -> int:
56
- """
57
- Get the maximum tokens setting.
58
-
59
- Returns:
60
- int: The maximum number of tokens for generation.
61
- """
62
- return self.max_tokens
63
-
64
- def get_repeat_penalty(self) -> float:
65
- """
66
- Get the repeat penalty setting.
67
-
68
- Returns:
69
- float: The penalty value for token repetition.
70
- """
71
- return self.repeat_penalty
72
 
73
 
74
  class LLMFactory():
 
1
  from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpoint
2
  from langchain_openai import ChatOpenAI
3
 
4
+ from args import LLMInterface, Args, AgentPreset
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
 
7
  class LLMFactory():