massgen 0.0.3__py3-none-any.whl → 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of massgen might be problematic. Click here for more details.
- massgen/__init__.py +142 -8
- massgen/adapters/__init__.py +29 -0
- massgen/adapters/ag2_adapter.py +483 -0
- massgen/adapters/base.py +183 -0
- massgen/adapters/tests/__init__.py +0 -0
- massgen/adapters/tests/test_ag2_adapter.py +439 -0
- massgen/adapters/tests/test_agent_adapter.py +128 -0
- massgen/adapters/utils/__init__.py +2 -0
- massgen/adapters/utils/ag2_utils.py +236 -0
- massgen/adapters/utils/tests/__init__.py +0 -0
- massgen/adapters/utils/tests/test_ag2_utils.py +138 -0
- massgen/agent_config.py +329 -55
- massgen/api_params_handler/__init__.py +10 -0
- massgen/api_params_handler/_api_params_handler_base.py +99 -0
- massgen/api_params_handler/_chat_completions_api_params_handler.py +176 -0
- massgen/api_params_handler/_claude_api_params_handler.py +113 -0
- massgen/api_params_handler/_response_api_params_handler.py +130 -0
- massgen/backend/__init__.py +39 -4
- massgen/backend/azure_openai.py +385 -0
- massgen/backend/base.py +341 -69
- massgen/backend/base_with_mcp.py +1102 -0
- massgen/backend/capabilities.py +386 -0
- massgen/backend/chat_completions.py +577 -130
- massgen/backend/claude.py +1033 -537
- massgen/backend/claude_code.py +1203 -0
- massgen/backend/cli_base.py +209 -0
- massgen/backend/docs/BACKEND_ARCHITECTURE.md +126 -0
- massgen/backend/{CLAUDE_API_RESEARCH.md → docs/CLAUDE_API_RESEARCH.md} +18 -18
- massgen/backend/{GEMINI_API_DOCUMENTATION.md → docs/GEMINI_API_DOCUMENTATION.md} +9 -9
- massgen/backend/docs/Gemini MCP Integration Analysis.md +1050 -0
- massgen/backend/docs/MCP_IMPLEMENTATION_CLAUDE_BACKEND.md +177 -0
- massgen/backend/docs/MCP_INTEGRATION_RESPONSE_BACKEND.md +352 -0
- massgen/backend/docs/OPENAI_GPT5_MODELS.md +211 -0
- massgen/backend/{OPENAI_RESPONSES_API_FORMAT.md → docs/OPENAI_RESPONSE_API_TOOL_CALLS.md} +3 -3
- massgen/backend/docs/OPENAI_response_streaming.md +20654 -0
- massgen/backend/docs/inference_backend.md +257 -0
- massgen/backend/docs/permissions_and_context_files.md +1085 -0
- massgen/backend/external.py +126 -0
- massgen/backend/gemini.py +1850 -241
- massgen/backend/grok.py +40 -156
- massgen/backend/inference.py +156 -0
- massgen/backend/lmstudio.py +171 -0
- massgen/backend/response.py +1095 -322
- massgen/chat_agent.py +131 -113
- massgen/cli.py +1560 -275
- massgen/config_builder.py +2396 -0
- massgen/configs/BACKEND_CONFIGURATION.md +458 -0
- massgen/configs/README.md +559 -216
- massgen/configs/ag2/ag2_case_study.yaml +27 -0
- massgen/configs/ag2/ag2_coder.yaml +34 -0
- massgen/configs/ag2/ag2_coder_case_study.yaml +36 -0
- massgen/configs/ag2/ag2_gemini.yaml +27 -0
- massgen/configs/ag2/ag2_groupchat.yaml +108 -0
- massgen/configs/ag2/ag2_groupchat_gpt.yaml +118 -0
- massgen/configs/ag2/ag2_single_agent.yaml +21 -0
- massgen/configs/basic/multi/fast_timeout_example.yaml +37 -0
- massgen/configs/basic/multi/gemini_4o_claude.yaml +31 -0
- massgen/configs/basic/multi/gemini_gpt5nano_claude.yaml +36 -0
- massgen/configs/{gemini_4o_claude.yaml → basic/multi/geminicode_4o_claude.yaml} +3 -3
- massgen/configs/basic/multi/geminicode_gpt5nano_claude.yaml +36 -0
- massgen/configs/basic/multi/glm_gemini_claude.yaml +25 -0
- massgen/configs/basic/multi/gpt4o_audio_generation.yaml +30 -0
- massgen/configs/basic/multi/gpt4o_image_generation.yaml +31 -0
- massgen/configs/basic/multi/gpt5nano_glm_qwen.yaml +26 -0
- massgen/configs/basic/multi/gpt5nano_image_understanding.yaml +26 -0
- massgen/configs/{three_agents_default.yaml → basic/multi/three_agents_default.yaml} +8 -4
- massgen/configs/basic/multi/three_agents_opensource.yaml +27 -0
- massgen/configs/basic/multi/three_agents_vllm.yaml +20 -0
- massgen/configs/basic/multi/two_agents_gemini.yaml +19 -0
- massgen/configs/{two_agents.yaml → basic/multi/two_agents_gpt5.yaml} +14 -6
- massgen/configs/basic/multi/two_agents_opensource_lmstudio.yaml +31 -0
- massgen/configs/basic/multi/two_qwen_vllm_sglang.yaml +28 -0
- massgen/configs/{single_agent.yaml → basic/single/single_agent.yaml} +1 -1
- massgen/configs/{single_flash2.5.yaml → basic/single/single_flash2.5.yaml} +1 -2
- massgen/configs/basic/single/single_gemini2.5pro.yaml +16 -0
- massgen/configs/basic/single/single_gpt4o_audio_generation.yaml +22 -0
- massgen/configs/basic/single/single_gpt4o_image_generation.yaml +22 -0
- massgen/configs/basic/single/single_gpt4o_video_generation.yaml +24 -0
- massgen/configs/basic/single/single_gpt5nano.yaml +20 -0
- massgen/configs/basic/single/single_gpt5nano_file_search.yaml +18 -0
- massgen/configs/basic/single/single_gpt5nano_image_understanding.yaml +17 -0
- massgen/configs/basic/single/single_gptoss120b.yaml +15 -0
- massgen/configs/basic/single/single_openrouter_audio_understanding.yaml +15 -0
- massgen/configs/basic/single/single_qwen_video_understanding.yaml +15 -0
- massgen/configs/debug/code_execution/command_filtering_blacklist.yaml +29 -0
- massgen/configs/debug/code_execution/command_filtering_whitelist.yaml +28 -0
- massgen/configs/debug/code_execution/docker_verification.yaml +29 -0
- massgen/configs/debug/skip_coordination_test.yaml +27 -0
- massgen/configs/debug/test_sdk_migration.yaml +17 -0
- massgen/configs/docs/DISCORD_MCP_SETUP.md +208 -0
- massgen/configs/docs/TWITTER_MCP_ENESCINAR_SETUP.md +82 -0
- massgen/configs/providers/azure/azure_openai_multi.yaml +21 -0
- massgen/configs/providers/azure/azure_openai_single.yaml +19 -0
- massgen/configs/providers/claude/claude.yaml +14 -0
- massgen/configs/providers/gemini/gemini_gpt5nano.yaml +28 -0
- massgen/configs/providers/local/lmstudio.yaml +11 -0
- massgen/configs/providers/openai/gpt5.yaml +46 -0
- massgen/configs/providers/openai/gpt5_nano.yaml +46 -0
- massgen/configs/providers/others/grok_single_agent.yaml +19 -0
- massgen/configs/providers/others/zai_coding_team.yaml +108 -0
- massgen/configs/providers/others/zai_glm45.yaml +12 -0
- massgen/configs/{creative_team.yaml → teams/creative/creative_team.yaml} +16 -6
- massgen/configs/{travel_planning.yaml → teams/creative/travel_planning.yaml} +16 -6
- massgen/configs/{news_analysis.yaml → teams/research/news_analysis.yaml} +16 -6
- massgen/configs/{research_team.yaml → teams/research/research_team.yaml} +15 -7
- massgen/configs/{technical_analysis.yaml → teams/research/technical_analysis.yaml} +16 -6
- massgen/configs/tools/code-execution/basic_command_execution.yaml +25 -0
- massgen/configs/tools/code-execution/code_execution_use_case_simple.yaml +41 -0
- massgen/configs/tools/code-execution/docker_claude_code.yaml +32 -0
- massgen/configs/tools/code-execution/docker_multi_agent.yaml +32 -0
- massgen/configs/tools/code-execution/docker_simple.yaml +29 -0
- massgen/configs/tools/code-execution/docker_with_resource_limits.yaml +32 -0
- massgen/configs/tools/code-execution/multi_agent_playwright_automation.yaml +57 -0
- massgen/configs/tools/filesystem/cc_gpt5_gemini_filesystem.yaml +34 -0
- massgen/configs/tools/filesystem/claude_code_context_sharing.yaml +68 -0
- massgen/configs/tools/filesystem/claude_code_flash2.5.yaml +43 -0
- massgen/configs/tools/filesystem/claude_code_flash2.5_gptoss.yaml +49 -0
- massgen/configs/tools/filesystem/claude_code_gpt5nano.yaml +31 -0
- massgen/configs/tools/filesystem/claude_code_single.yaml +40 -0
- massgen/configs/tools/filesystem/fs_permissions_test.yaml +87 -0
- massgen/configs/tools/filesystem/gemini_gemini_workspace_cleanup.yaml +54 -0
- massgen/configs/tools/filesystem/gemini_gpt5_filesystem_casestudy.yaml +30 -0
- massgen/configs/tools/filesystem/gemini_gpt5nano_file_context_path.yaml +43 -0
- massgen/configs/tools/filesystem/gemini_gpt5nano_protected_paths.yaml +45 -0
- massgen/configs/tools/filesystem/gpt5mini_cc_fs_context_path.yaml +31 -0
- massgen/configs/tools/filesystem/grok4_gpt5_gemini_filesystem.yaml +32 -0
- massgen/configs/tools/filesystem/multiturn/grok4_gpt5_claude_code_filesystem_multiturn.yaml +58 -0
- massgen/configs/tools/filesystem/multiturn/grok4_gpt5_gemini_filesystem_multiturn.yaml +58 -0
- massgen/configs/tools/filesystem/multiturn/two_claude_code_filesystem_multiturn.yaml +47 -0
- massgen/configs/tools/filesystem/multiturn/two_gemini_flash_filesystem_multiturn.yaml +48 -0
- massgen/configs/tools/mcp/claude_code_discord_mcp_example.yaml +27 -0
- massgen/configs/tools/mcp/claude_code_simple_mcp.yaml +35 -0
- massgen/configs/tools/mcp/claude_code_twitter_mcp_example.yaml +32 -0
- massgen/configs/tools/mcp/claude_mcp_example.yaml +24 -0
- massgen/configs/tools/mcp/claude_mcp_test.yaml +27 -0
- massgen/configs/tools/mcp/five_agents_travel_mcp_test.yaml +157 -0
- massgen/configs/tools/mcp/five_agents_weather_mcp_test.yaml +103 -0
- massgen/configs/tools/mcp/gemini_mcp_example.yaml +24 -0
- massgen/configs/tools/mcp/gemini_mcp_filesystem_test.yaml +23 -0
- massgen/configs/tools/mcp/gemini_mcp_filesystem_test_sharing.yaml +23 -0
- massgen/configs/tools/mcp/gemini_mcp_filesystem_test_single_agent.yaml +17 -0
- massgen/configs/tools/mcp/gemini_mcp_filesystem_test_with_claude_code.yaml +24 -0
- massgen/configs/tools/mcp/gemini_mcp_test.yaml +27 -0
- massgen/configs/tools/mcp/gemini_notion_mcp.yaml +52 -0
- massgen/configs/tools/mcp/gpt5_nano_mcp_example.yaml +24 -0
- massgen/configs/tools/mcp/gpt5_nano_mcp_test.yaml +27 -0
- massgen/configs/tools/mcp/gpt5mini_claude_code_discord_mcp_example.yaml +38 -0
- massgen/configs/tools/mcp/gpt_oss_mcp_example.yaml +25 -0
- massgen/configs/tools/mcp/gpt_oss_mcp_test.yaml +28 -0
- massgen/configs/tools/mcp/grok3_mini_mcp_example.yaml +24 -0
- massgen/configs/tools/mcp/grok3_mini_mcp_test.yaml +27 -0
- massgen/configs/tools/mcp/multimcp_gemini.yaml +111 -0
- massgen/configs/tools/mcp/qwen_api_mcp_example.yaml +25 -0
- massgen/configs/tools/mcp/qwen_api_mcp_test.yaml +28 -0
- massgen/configs/tools/mcp/qwen_local_mcp_example.yaml +24 -0
- massgen/configs/tools/mcp/qwen_local_mcp_test.yaml +27 -0
- massgen/configs/tools/planning/five_agents_discord_mcp_planning_mode.yaml +140 -0
- massgen/configs/tools/planning/five_agents_filesystem_mcp_planning_mode.yaml +151 -0
- massgen/configs/tools/planning/five_agents_notion_mcp_planning_mode.yaml +151 -0
- massgen/configs/tools/planning/five_agents_twitter_mcp_planning_mode.yaml +155 -0
- massgen/configs/tools/planning/gpt5_mini_case_study_mcp_planning_mode.yaml +73 -0
- massgen/configs/tools/web-search/claude_streamable_http_test.yaml +43 -0
- massgen/configs/tools/web-search/gemini_streamable_http_test.yaml +43 -0
- massgen/configs/tools/web-search/gpt5_mini_streamable_http_test.yaml +43 -0
- massgen/configs/tools/web-search/gpt_oss_streamable_http_test.yaml +44 -0
- massgen/configs/tools/web-search/grok3_mini_streamable_http_test.yaml +43 -0
- massgen/configs/tools/web-search/qwen_api_streamable_http_test.yaml +44 -0
- massgen/configs/tools/web-search/qwen_local_streamable_http_test.yaml +43 -0
- massgen/coordination_tracker.py +708 -0
- massgen/docker/README.md +462 -0
- massgen/filesystem_manager/__init__.py +21 -0
- massgen/filesystem_manager/_base.py +9 -0
- massgen/filesystem_manager/_code_execution_server.py +545 -0
- massgen/filesystem_manager/_docker_manager.py +477 -0
- massgen/filesystem_manager/_file_operation_tracker.py +248 -0
- massgen/filesystem_manager/_filesystem_manager.py +813 -0
- massgen/filesystem_manager/_path_permission_manager.py +1261 -0
- massgen/filesystem_manager/_workspace_tools_server.py +1815 -0
- massgen/formatter/__init__.py +10 -0
- massgen/formatter/_chat_completions_formatter.py +284 -0
- massgen/formatter/_claude_formatter.py +235 -0
- massgen/formatter/_formatter_base.py +156 -0
- massgen/formatter/_response_formatter.py +263 -0
- massgen/frontend/__init__.py +1 -2
- massgen/frontend/coordination_ui.py +471 -286
- massgen/frontend/displays/base_display.py +56 -11
- massgen/frontend/displays/create_coordination_table.py +1956 -0
- massgen/frontend/displays/rich_terminal_display.py +1259 -619
- massgen/frontend/displays/simple_display.py +9 -4
- massgen/frontend/displays/terminal_display.py +27 -68
- massgen/logger_config.py +681 -0
- massgen/mcp_tools/README.md +232 -0
- massgen/mcp_tools/__init__.py +105 -0
- massgen/mcp_tools/backend_utils.py +1035 -0
- massgen/mcp_tools/circuit_breaker.py +195 -0
- massgen/mcp_tools/client.py +894 -0
- massgen/mcp_tools/config_validator.py +138 -0
- massgen/mcp_tools/docs/circuit_breaker.md +646 -0
- massgen/mcp_tools/docs/client.md +950 -0
- massgen/mcp_tools/docs/config_validator.md +478 -0
- massgen/mcp_tools/docs/exceptions.md +1165 -0
- massgen/mcp_tools/docs/security.md +854 -0
- massgen/mcp_tools/exceptions.py +338 -0
- massgen/mcp_tools/hooks.py +212 -0
- massgen/mcp_tools/security.py +780 -0
- massgen/message_templates.py +342 -64
- massgen/orchestrator.py +1515 -241
- massgen/stream_chunk/__init__.py +35 -0
- massgen/stream_chunk/base.py +92 -0
- massgen/stream_chunk/multimodal.py +237 -0
- massgen/stream_chunk/text.py +162 -0
- massgen/tests/mcp_test_server.py +150 -0
- massgen/tests/multi_turn_conversation_design.md +0 -8
- massgen/tests/test_azure_openai_backend.py +156 -0
- massgen/tests/test_backend_capabilities.py +262 -0
- massgen/tests/test_backend_event_loop_all.py +179 -0
- massgen/tests/test_chat_completions_refactor.py +142 -0
- massgen/tests/test_claude_backend.py +15 -28
- massgen/tests/test_claude_code.py +268 -0
- massgen/tests/test_claude_code_context_sharing.py +233 -0
- massgen/tests/test_claude_code_orchestrator.py +175 -0
- massgen/tests/test_cli_backends.py +180 -0
- massgen/tests/test_code_execution.py +679 -0
- massgen/tests/test_external_agent_backend.py +134 -0
- massgen/tests/test_final_presentation_fallback.py +237 -0
- massgen/tests/test_gemini_planning_mode.py +351 -0
- massgen/tests/test_grok_backend.py +7 -10
- massgen/tests/test_http_mcp_server.py +42 -0
- massgen/tests/test_integration_simple.py +198 -0
- massgen/tests/test_mcp_blocking.py +125 -0
- massgen/tests/test_message_context_building.py +29 -47
- massgen/tests/test_orchestrator_final_presentation.py +48 -0
- massgen/tests/test_path_permission_manager.py +2087 -0
- massgen/tests/test_rich_terminal_display.py +14 -13
- massgen/tests/test_timeout.py +133 -0
- massgen/tests/test_v3_3agents.py +11 -12
- massgen/tests/test_v3_simple.py +8 -13
- massgen/tests/test_v3_three_agents.py +11 -18
- massgen/tests/test_v3_two_agents.py +8 -13
- massgen/token_manager/__init__.py +7 -0
- massgen/token_manager/token_manager.py +400 -0
- massgen/utils.py +52 -16
- massgen/v1/agent.py +45 -91
- massgen/v1/agents.py +18 -53
- massgen/v1/backends/gemini.py +50 -153
- massgen/v1/backends/grok.py +21 -54
- massgen/v1/backends/oai.py +39 -111
- massgen/v1/cli.py +36 -93
- massgen/v1/config.py +8 -12
- massgen/v1/logging.py +43 -127
- massgen/v1/main.py +18 -32
- massgen/v1/orchestrator.py +68 -209
- massgen/v1/streaming_display.py +62 -163
- massgen/v1/tools.py +8 -12
- massgen/v1/types.py +9 -23
- massgen/v1/utils.py +5 -23
- massgen-0.1.0.dist-info/METADATA +1245 -0
- massgen-0.1.0.dist-info/RECORD +273 -0
- massgen-0.1.0.dist-info/entry_points.txt +2 -0
- massgen/frontend/logging/__init__.py +0 -9
- massgen/frontend/logging/realtime_logger.py +0 -197
- massgen-0.0.3.dist-info/METADATA +0 -568
- massgen-0.0.3.dist-info/RECORD +0 -76
- massgen-0.0.3.dist-info/entry_points.txt +0 -2
- /massgen/backend/{Function calling openai responses.md → docs/Function calling openai responses.md} +0 -0
- {massgen-0.0.3.dist-info → massgen-0.1.0.dist-info}/WHEEL +0 -0
- {massgen-0.0.3.dist-info → massgen-0.1.0.dist-info}/licenses/LICENSE +0 -0
- {massgen-0.0.3.dist-info → massgen-0.1.0.dist-info}/top_level.txt +0 -0
massgen/v1/agent.py
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
import sys
|
|
3
|
-
import time
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
4
2
|
import json
|
|
5
|
-
|
|
6
|
-
from
|
|
3
|
+
import time
|
|
4
|
+
from abc import ABC
|
|
5
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
6
|
+
from concurrent.futures import TimeoutError as FutureTimeoutError
|
|
7
|
+
from typing import Any, Callable, Dict, List, Optional
|
|
7
8
|
|
|
8
9
|
from dotenv import load_dotenv
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
from .backends import gemini, grok, oai
|
|
12
|
+
from .types import AgentResponse, AgentState, ModelConfig, TaskInput
|
|
13
|
+
from .utils import function_to_json, get_agent_type_from_model
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
from .utils import get_agent_type_from_model, function_to_json
|
|
14
|
-
from abc import ABC, abstractmethod
|
|
15
|
-
from typing import Any, Callable, Union, Optional, List, Dict
|
|
16
|
-
from .backends import oai, gemini, grok
|
|
15
|
+
load_dotenv()
|
|
17
16
|
|
|
18
17
|
# TASK_INSTRUCTION = """
|
|
19
18
|
# Please use your expertise and tools (if available) to fully verify if the best CURRENT ANSWER addresses the ORIGINAL MESSAGE.
|
|
@@ -24,7 +23,7 @@ from .backends import oai, gemini, grok
|
|
|
24
23
|
# """
|
|
25
24
|
|
|
26
25
|
SYSTEM_INSTRUCTION = f"""
|
|
27
|
-
You are evaluating answers from multiple agents for final response to a message.
|
|
26
|
+
You are evaluating answers from multiple agents for final response to a message.
|
|
28
27
|
|
|
29
28
|
For every aspect, claim, reasoning steps in the CURRENT ANSWERS, verify correctness, factual accuracy, and completeness using your expertise, reasoning, and available tools.
|
|
30
29
|
|
|
@@ -111,9 +110,7 @@ class MassAgent(ABC):
|
|
|
111
110
|
"grok": grok.process_message,
|
|
112
111
|
}
|
|
113
112
|
if self.agent_type not in process_message_impl_map:
|
|
114
|
-
raise ValueError(
|
|
115
|
-
f"Unknown agent type: {self.agent_type}. Available types: {list(process_message_impl_map.keys())}"
|
|
116
|
-
)
|
|
113
|
+
raise ValueError(f"Unknown agent type: {self.agent_type}. Available types: {list(process_message_impl_map.keys())}")
|
|
117
114
|
|
|
118
115
|
# Get the appropriate process_message implementation based on the agent type
|
|
119
116
|
self.process_message_impl = process_message_impl_map[self.agent_type]
|
|
@@ -130,9 +127,7 @@ class MassAgent(ABC):
|
|
|
130
127
|
self.stream_callback = stream_callback
|
|
131
128
|
self.kwargs = kwargs
|
|
132
129
|
|
|
133
|
-
def process_message(
|
|
134
|
-
self, messages: List[Dict[str, str]], tools: List[str] = None
|
|
135
|
-
) -> AgentResponse:
|
|
130
|
+
def process_message(self, messages: List[Dict[str, str]], tools: List[str] = None) -> AgentResponse:
|
|
136
131
|
"""
|
|
137
132
|
Core LLM inference function for task processing.
|
|
138
133
|
|
|
@@ -164,9 +159,7 @@ class MassAgent(ABC):
|
|
|
164
159
|
try:
|
|
165
160
|
# Use ThreadPoolExecutor to implement timeout
|
|
166
161
|
with ThreadPoolExecutor(max_workers=1) as executor:
|
|
167
|
-
future = executor.submit(
|
|
168
|
-
self.process_message_impl, messages=messages, tools=tools, **config
|
|
169
|
-
)
|
|
162
|
+
future = executor.submit(self.process_message_impl, messages=messages, tools=tools, **config)
|
|
170
163
|
|
|
171
164
|
try:
|
|
172
165
|
# Wait for result with timeout
|
|
@@ -202,11 +195,9 @@ class MassAgent(ABC):
|
|
|
202
195
|
"""
|
|
203
196
|
# Use the orchestrator to update the answer and notify other agents to restart
|
|
204
197
|
self.orchestrator.notify_answer_update(self.agent_id, new_answer)
|
|
205
|
-
return
|
|
198
|
+
return "The new answer has been added."
|
|
206
199
|
|
|
207
|
-
def vote(
|
|
208
|
-
self, agent_id: int, reason: str = "", invalid_vote_options: List[int] = []
|
|
209
|
-
):
|
|
200
|
+
def vote(self, agent_id: int, reason: str = "", invalid_vote_options: List[int] = []):
|
|
210
201
|
"""
|
|
211
202
|
Vote for the representative agent, who you believe has found the correct solution.
|
|
212
203
|
|
|
@@ -255,9 +246,7 @@ class MassAgent(ABC):
|
|
|
255
246
|
deduplicated_function_calls.append(func_call)
|
|
256
247
|
return deduplicated_function_calls
|
|
257
248
|
|
|
258
|
-
def _execute_function_calls(
|
|
259
|
-
self, function_calls: List[Dict], invalid_vote_options: List[int] = []
|
|
260
|
-
):
|
|
249
|
+
def _execute_function_calls(self, function_calls: List[Dict], invalid_vote_options: List[int] = []):
|
|
261
250
|
"""Execute function calls and return function outputs."""
|
|
262
251
|
from .tools import register_tool
|
|
263
252
|
|
|
@@ -311,9 +300,7 @@ class MassAgent(ABC):
|
|
|
311
300
|
|
|
312
301
|
# DEBUGGING
|
|
313
302
|
with open("function_calls.txt", "a") as f:
|
|
314
|
-
f.write(
|
|
315
|
-
f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Agent {self.agent_id} ({self.model}):\n"
|
|
316
|
-
)
|
|
303
|
+
f.write(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Agent {self.agent_id} ({self.model}):\n")
|
|
317
304
|
f.write(f"{json.dumps(error_output, indent=2)}\n")
|
|
318
305
|
f.write(f"Successful called: {False}\n")
|
|
319
306
|
|
|
@@ -335,7 +322,7 @@ class MassAgent(ABC):
|
|
|
335
322
|
"new_answer": {
|
|
336
323
|
"type": "string",
|
|
337
324
|
"description": "Your new answer, which should be self-contained, complete, and ready to serve as the definitive final response.",
|
|
338
|
-
}
|
|
325
|
+
},
|
|
339
326
|
},
|
|
340
327
|
"required": ["new_answer"],
|
|
341
328
|
},
|
|
@@ -360,16 +347,8 @@ class MassAgent(ABC):
|
|
|
360
347
|
},
|
|
361
348
|
}
|
|
362
349
|
# Check if there are any available options to vote for. If not, only return the add_answer schema.
|
|
363
|
-
available_options = [
|
|
364
|
-
|
|
365
|
-
for agent_id, agent_state in self.orchestrator.agent_states.items()
|
|
366
|
-
if agent_state.curr_answer
|
|
367
|
-
]
|
|
368
|
-
return (
|
|
369
|
-
[add_answer_schema, vote_schema]
|
|
370
|
-
if available_options
|
|
371
|
-
else [add_answer_schema]
|
|
372
|
-
)
|
|
350
|
+
available_options = [agent_id for agent_id, agent_state in self.orchestrator.agent_states.items() if agent_state.curr_answer]
|
|
351
|
+
return [add_answer_schema, vote_schema] if available_options else [add_answer_schema]
|
|
373
352
|
|
|
374
353
|
def _get_registered_tools(self) -> List[Dict[str, Any]]:
|
|
375
354
|
"""Return the tool schema for the tools that are available to this agent."""
|
|
@@ -420,9 +399,7 @@ class MassAgent(ABC):
|
|
|
420
399
|
agent_votes = []
|
|
421
400
|
for agent_id, agent_state in self.orchestrator.agent_states.items():
|
|
422
401
|
if agent_state.curr_vote:
|
|
423
|
-
agent_votes.append(
|
|
424
|
-
f"**Vote for Agent {agent_state.curr_vote.target_id}**: {agent_state.curr_vote.reason}"
|
|
425
|
-
)
|
|
402
|
+
agent_votes.append(f"**Vote for Agent {agent_state.curr_vote.target_id}**: {agent_state.curr_vote.reason}")
|
|
426
403
|
return agent_votes
|
|
427
404
|
|
|
428
405
|
def _get_task_input(self, task: TaskInput) -> str:
|
|
@@ -440,11 +417,7 @@ class MassAgent(ABC):
|
|
|
440
417
|
all_agent_answers = self._get_all_answers()
|
|
441
418
|
all_agent_answers_str = "\n\n".join(all_agent_answers)
|
|
442
419
|
# Check if in debate mode or not
|
|
443
|
-
voted_agents = [
|
|
444
|
-
agent_id
|
|
445
|
-
for agent_id, agent_state in self.orchestrator.agent_states.items()
|
|
446
|
-
if agent_state.curr_vote is not None
|
|
447
|
-
]
|
|
420
|
+
voted_agents = [agent_id for agent_id, agent_state in self.orchestrator.agent_states.items() if agent_state.curr_vote is not None]
|
|
448
421
|
if len(voted_agents) == len(self.orchestrator.agent_states):
|
|
449
422
|
# Case 2: All agents have voted and are debating. Can not use agent status to check as they have been updated to 'working/debate'
|
|
450
423
|
all_agent_votes = self._get_all_votes()
|
|
@@ -458,9 +431,7 @@ class MassAgent(ABC):
|
|
|
458
431
|
else:
|
|
459
432
|
# Case 3: All agents are working and not in debating
|
|
460
433
|
status = "working"
|
|
461
|
-
task_input = AGENT_ANSWER_MESSAGE.format(
|
|
462
|
-
task=task.question, agent_answers=all_agent_answers_str
|
|
463
|
-
)
|
|
434
|
+
task_input = AGENT_ANSWER_MESSAGE.format(task=task.question, agent_answers=all_agent_answers_str)
|
|
464
435
|
|
|
465
436
|
return status, task_input
|
|
466
437
|
|
|
@@ -500,17 +471,13 @@ class MassAgent(ABC):
|
|
|
500
471
|
|
|
501
472
|
# Initialize working messages
|
|
502
473
|
curr_round = 0
|
|
503
|
-
working_status, working_messages, all_tools = self._get_curr_messages_and_tools(
|
|
504
|
-
task
|
|
505
|
-
)
|
|
474
|
+
working_status, working_messages, all_tools = self._get_curr_messages_and_tools(task)
|
|
506
475
|
|
|
507
476
|
# Start the task solving loop
|
|
508
477
|
while curr_round < self.max_rounds and self.state.status == "working":
|
|
509
478
|
try:
|
|
510
479
|
# Call LLM with current conversation
|
|
511
|
-
result = self.process_message(
|
|
512
|
-
messages=working_messages, tools=all_tools
|
|
513
|
-
)
|
|
480
|
+
result = self.process_message(messages=working_messages, tools=all_tools)
|
|
514
481
|
|
|
515
482
|
# Before Making the new result into effect, check if there is any update from other agents that are unseen by this agent
|
|
516
483
|
agents_with_update = self.check_update()
|
|
@@ -521,30 +488,19 @@ class MassAgent(ABC):
|
|
|
521
488
|
|
|
522
489
|
# Add assistant response
|
|
523
490
|
if result.text:
|
|
524
|
-
working_messages.append(
|
|
525
|
-
{"role": "assistant", "content": result.text}
|
|
526
|
-
)
|
|
491
|
+
working_messages.append({"role": "assistant", "content": result.text})
|
|
527
492
|
|
|
528
493
|
# Execute function calls if any
|
|
529
494
|
if result.function_calls:
|
|
530
495
|
# Deduplicate function calls by their name
|
|
531
|
-
result.function_calls = self.deduplicate_function_calls(
|
|
532
|
-
result.function_calls
|
|
533
|
-
)
|
|
496
|
+
result.function_calls = self.deduplicate_function_calls(result.function_calls)
|
|
534
497
|
# Not voting if there is any update
|
|
535
|
-
function_outputs, successful_called = self._execute_function_calls(
|
|
536
|
-
result.function_calls, invalid_vote_options=agents_with_update
|
|
537
|
-
)
|
|
498
|
+
function_outputs, successful_called = self._execute_function_calls(result.function_calls, invalid_vote_options=agents_with_update)
|
|
538
499
|
|
|
539
500
|
renew_conversation = False
|
|
540
|
-
for function_call, function_output, successful_called in zip(
|
|
541
|
-
result.function_calls, function_outputs, successful_called
|
|
542
|
-
):
|
|
501
|
+
for function_call, function_output, successful_called in zip(result.function_calls, function_outputs, successful_called):
|
|
543
502
|
# If call `add_answer`, we need to rebuild the conversation history with new answers
|
|
544
|
-
if (
|
|
545
|
-
function_call.get("name") == "add_answer"
|
|
546
|
-
and successful_called
|
|
547
|
-
):
|
|
503
|
+
if function_call.get("name") == "add_answer" and successful_called:
|
|
548
504
|
renew_conversation = True
|
|
549
505
|
break
|
|
550
506
|
|
|
@@ -553,17 +509,15 @@ class MassAgent(ABC):
|
|
|
553
509
|
renew_conversation = True
|
|
554
510
|
break
|
|
555
511
|
|
|
556
|
-
if
|
|
557
|
-
|
|
558
|
-
): # Add all function call results to the current conversation and continue the loop
|
|
559
|
-
for function_call, function_output in zip(
|
|
560
|
-
result.function_calls, function_outputs
|
|
561
|
-
):
|
|
512
|
+
if not renew_conversation: # Add all function call results to the current conversation and continue the loop
|
|
513
|
+
for function_call, function_output in zip(result.function_calls, function_outputs):
|
|
562
514
|
working_messages.extend([function_call, function_output])
|
|
563
515
|
else: # Renew the conversation
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
516
|
+
(
|
|
517
|
+
working_status,
|
|
518
|
+
working_messages,
|
|
519
|
+
all_tools,
|
|
520
|
+
) = self._get_curr_messages_and_tools(task)
|
|
567
521
|
else:
|
|
568
522
|
# No function calls - check if we should continue or stop
|
|
569
523
|
if self.state.status == "voted":
|
|
@@ -573,15 +527,17 @@ class MassAgent(ABC):
|
|
|
573
527
|
# Check if there is any update from other agents that are unseen by this agent
|
|
574
528
|
if has_update and working_status != "initial":
|
|
575
529
|
# The vote option has changed, thus we need to renew the conversation within the loop
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
530
|
+
(
|
|
531
|
+
working_status,
|
|
532
|
+
working_messages,
|
|
533
|
+
all_tools,
|
|
534
|
+
) = self._get_curr_messages_and_tools(task)
|
|
579
535
|
else: # Continue the current conversation and prompting checkin
|
|
580
536
|
working_messages.append(
|
|
581
537
|
{
|
|
582
538
|
"role": "user",
|
|
583
539
|
"content": "Finish your work above by making a tool call of `vote` or `add_answer`. Make sure you actually call the tool.",
|
|
584
|
-
}
|
|
540
|
+
},
|
|
585
541
|
)
|
|
586
542
|
|
|
587
543
|
curr_round += 1
|
|
@@ -592,9 +548,7 @@ class MassAgent(ABC):
|
|
|
592
548
|
break
|
|
593
549
|
|
|
594
550
|
except Exception as e:
|
|
595
|
-
print(
|
|
596
|
-
f"❌ Agent {self.agent_id} error in round {self.state.chat_round}: {e}"
|
|
597
|
-
)
|
|
551
|
+
print(f"❌ Agent {self.agent_id} error in round {self.state.chat_round}: {e}")
|
|
598
552
|
if self.orchestrator:
|
|
599
553
|
self.orchestrator.mark_agent_failed(self.agent_id, str(e))
|
|
600
554
|
|
massgen/v1/agents.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
1
2
|
"""
|
|
2
3
|
MassAgent implementations that wrap the existing agent backends.
|
|
3
4
|
|
|
@@ -5,20 +6,14 @@ This module provides MassAgent-compatible wrappers for the existing
|
|
|
5
6
|
OpenAI, Gemini, and Grok agent implementations.
|
|
6
7
|
"""
|
|
7
8
|
|
|
8
|
-
import
|
|
9
|
-
import sys
|
|
10
|
-
import copy
|
|
11
|
-
import time
|
|
12
|
-
import traceback
|
|
13
|
-
from typing import Callable, Union, Optional, List, Dict, Any
|
|
9
|
+
from typing import Callable, Dict, List, Optional
|
|
14
10
|
|
|
15
11
|
from dotenv import load_dotenv
|
|
16
12
|
|
|
17
|
-
load_dotenv()
|
|
18
|
-
|
|
19
13
|
from .agent import MassAgent
|
|
20
14
|
from .types import ModelConfig, TaskInput
|
|
21
|
-
|
|
15
|
+
|
|
16
|
+
load_dotenv()
|
|
22
17
|
|
|
23
18
|
|
|
24
19
|
class OpenAIMassAgent(MassAgent):
|
|
@@ -32,7 +27,6 @@ class OpenAIMassAgent(MassAgent):
|
|
|
32
27
|
stream_callback: Optional[Callable] = None,
|
|
33
28
|
**kwargs,
|
|
34
29
|
):
|
|
35
|
-
|
|
36
30
|
# Pass all configuration to parent, including agent_type
|
|
37
31
|
super().__init__(
|
|
38
32
|
agent_id=agent_id,
|
|
@@ -54,7 +48,6 @@ class GrokMassAgent(OpenAIMassAgent):
|
|
|
54
48
|
stream_callback: Optional[Callable] = None,
|
|
55
49
|
**kwargs,
|
|
56
50
|
):
|
|
57
|
-
|
|
58
51
|
# Pass all configuration to parent, including agent_type
|
|
59
52
|
super().__init__(
|
|
60
53
|
agent_id=agent_id,
|
|
@@ -76,7 +69,6 @@ class GeminiMassAgent(OpenAIMassAgent):
|
|
|
76
69
|
stream_callback: Optional[Callable] = None,
|
|
77
70
|
**kwargs,
|
|
78
71
|
):
|
|
79
|
-
|
|
80
72
|
# Pass all configuration to parent, including agent_type
|
|
81
73
|
super().__init__(
|
|
82
74
|
agent_id=agent_id,
|
|
@@ -157,19 +149,13 @@ class GeminiMassAgent(OpenAIMassAgent):
|
|
|
157
149
|
if working_messages[-1].get("role", "") == "user":
|
|
158
150
|
if not function_call_enabled:
|
|
159
151
|
working_messages[-1]["content"] += (
|
|
160
|
-
"\n\n"
|
|
161
|
-
+ "Note that the `add_answer` and `vote` tools are not enabled now. Please prioritize using the built-in tools to analyze the task first."
|
|
152
|
+
"\n\n" + "Note that the `add_answer` and `vote` tools are not enabled now. Please prioritize using the built-in tools to analyze the task first."
|
|
162
153
|
)
|
|
163
154
|
else:
|
|
164
|
-
working_messages[-1]["content"] +=
|
|
165
|
-
"\n\n"
|
|
166
|
-
+ "Note that the `add_answer` and `vote` tools are enabled now."
|
|
167
|
-
)
|
|
155
|
+
working_messages[-1]["content"] += "\n\n" + "Note that the `add_answer` and `vote` tools are enabled now."
|
|
168
156
|
|
|
169
157
|
# Call LLM with current conversation
|
|
170
|
-
result = self.process_message(
|
|
171
|
-
messages=working_messages, tools=available_tools
|
|
172
|
-
)
|
|
158
|
+
result = self.process_message(messages=working_messages, tools=available_tools)
|
|
173
159
|
|
|
174
160
|
# Before Making the new result into effect, check if there is any update from other agents that are unseen by this agent
|
|
175
161
|
agents_with_update = self.check_update()
|
|
@@ -180,29 +166,18 @@ class GeminiMassAgent(OpenAIMassAgent):
|
|
|
180
166
|
|
|
181
167
|
# Add assistant response
|
|
182
168
|
if result.text:
|
|
183
|
-
working_messages.append(
|
|
184
|
-
{"role": "assistant", "content": result.text}
|
|
185
|
-
)
|
|
169
|
+
working_messages.append({"role": "assistant", "content": result.text})
|
|
186
170
|
|
|
187
171
|
# Execute function calls if any
|
|
188
172
|
if result.function_calls:
|
|
189
173
|
# Deduplicate function calls by their name
|
|
190
|
-
result.function_calls = self.deduplicate_function_calls(
|
|
191
|
-
|
|
192
|
-
)
|
|
193
|
-
function_outputs, successful_called = self._execute_function_calls(
|
|
194
|
-
result.function_calls, invalid_vote_options=agents_with_update
|
|
195
|
-
)
|
|
174
|
+
result.function_calls = self.deduplicate_function_calls(result.function_calls)
|
|
175
|
+
function_outputs, successful_called = self._execute_function_calls(result.function_calls, invalid_vote_options=agents_with_update)
|
|
196
176
|
|
|
197
177
|
renew_conversation = False
|
|
198
|
-
for function_call, function_output, successful_called in zip(
|
|
199
|
-
result.function_calls, function_outputs, successful_called
|
|
200
|
-
):
|
|
178
|
+
for function_call, function_output, successful_called in zip(result.function_calls, function_outputs, successful_called):
|
|
201
179
|
# If call `add_answer`, we need to rebuild the conversation history with new answers
|
|
202
|
-
if (
|
|
203
|
-
function_call.get("name") == "add_answer"
|
|
204
|
-
and successful_called
|
|
205
|
-
):
|
|
180
|
+
if function_call.get("name") == "add_answer" and successful_called:
|
|
206
181
|
renew_conversation = True
|
|
207
182
|
break
|
|
208
183
|
|
|
@@ -213,17 +188,13 @@ class GeminiMassAgent(OpenAIMassAgent):
|
|
|
213
188
|
|
|
214
189
|
if not renew_conversation:
|
|
215
190
|
# Add all function call results to the current conversation
|
|
216
|
-
for function_call, function_output in zip(
|
|
217
|
-
result.function_calls, function_outputs
|
|
218
|
-
):
|
|
191
|
+
for function_call, function_output in zip(result.function_calls, function_outputs):
|
|
219
192
|
working_messages.extend([function_call, function_output])
|
|
220
193
|
# If we have used custom tools, switch to built-in tools in the next round
|
|
221
194
|
if tool_switch:
|
|
222
195
|
available_tools = built_in_tools
|
|
223
196
|
function_call_enabled = False
|
|
224
|
-
print(
|
|
225
|
-
f"🔄 Agent {self.agent_id} (Gemini) switching to built-in tools in the next round"
|
|
226
|
-
)
|
|
197
|
+
print(f"🔄 Agent {self.agent_id} (Gemini) switching to built-in tools in the next round")
|
|
227
198
|
else: # Renew the conversation
|
|
228
199
|
(
|
|
229
200
|
working_status,
|
|
@@ -259,16 +230,14 @@ class GeminiMassAgent(OpenAIMassAgent):
|
|
|
259
230
|
{
|
|
260
231
|
"role": "user",
|
|
261
232
|
"content": "Finish your work above by making a tool call of `vote` or `add_answer`. Make sure you actually call the tool.",
|
|
262
|
-
}
|
|
233
|
+
},
|
|
263
234
|
)
|
|
264
235
|
|
|
265
236
|
# Switch to custom tools in the next round
|
|
266
237
|
if tool_switch:
|
|
267
238
|
available_tools = system_tools + custom_tools
|
|
268
239
|
function_call_enabled = True
|
|
269
|
-
print(
|
|
270
|
-
f"🔄 Agent {self.agent_id} (Gemini) switching to custom tools in the next round"
|
|
271
|
-
)
|
|
240
|
+
print(f"🔄 Agent {self.agent_id} (Gemini) switching to custom tools in the next round")
|
|
272
241
|
|
|
273
242
|
curr_round += 1
|
|
274
243
|
self.state.chat_round += 1
|
|
@@ -278,9 +247,7 @@ class GeminiMassAgent(OpenAIMassAgent):
|
|
|
278
247
|
break
|
|
279
248
|
|
|
280
249
|
except Exception as e:
|
|
281
|
-
print(
|
|
282
|
-
f"❌ Agent {self.agent_id} error in round {self.state.chat_round}: {e}"
|
|
283
|
-
)
|
|
250
|
+
print(f"❌ Agent {self.agent_id} error in round {self.state.chat_round}: {e}")
|
|
284
251
|
if self.orchestrator:
|
|
285
252
|
self.orchestrator.mark_agent_failed(self.agent_id, str(e))
|
|
286
253
|
|
|
@@ -318,9 +285,7 @@ def create_agent(
|
|
|
318
285
|
}
|
|
319
286
|
|
|
320
287
|
if agent_type not in agent_classes:
|
|
321
|
-
raise ValueError(
|
|
322
|
-
f"Unknown agent type: {agent_type}. Available types: {list(agent_classes.keys())}"
|
|
323
|
-
)
|
|
288
|
+
raise ValueError(f"Unknown agent type: {agent_type}. Available types: {list(agent_classes.keys())}")
|
|
324
289
|
|
|
325
290
|
return agent_classes[agent_type](
|
|
326
291
|
agent_id=agent_id,
|