massgen 0.1.4__py3-none-any.whl → 0.1.6__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 +1 -1
- massgen/backend/base_with_custom_tool_and_mcp.py +453 -23
- massgen/backend/capabilities.py +39 -0
- massgen/backend/chat_completions.py +111 -197
- massgen/backend/claude.py +210 -181
- massgen/backend/gemini.py +1015 -1559
- massgen/backend/grok.py +3 -2
- massgen/backend/response.py +160 -220
- massgen/chat_agent.py +340 -20
- massgen/cli.py +399 -25
- massgen/config_builder.py +20 -54
- massgen/config_validator.py +931 -0
- massgen/configs/README.md +95 -10
- massgen/configs/memory/gpt5mini_gemini_baseline_research_to_implementation.yaml +94 -0
- massgen/configs/memory/gpt5mini_gemini_context_window_management.yaml +187 -0
- massgen/configs/memory/gpt5mini_gemini_research_to_implementation.yaml +127 -0
- massgen/configs/memory/gpt5mini_high_reasoning_gemini.yaml +107 -0
- massgen/configs/memory/single_agent_compression_test.yaml +64 -0
- massgen/configs/tools/custom_tools/claude_code_custom_tool_with_mcp_example.yaml +1 -0
- massgen/configs/tools/custom_tools/claude_custom_tool_example_no_path.yaml +1 -1
- massgen/configs/tools/custom_tools/claude_custom_tool_with_mcp_example.yaml +1 -0
- massgen/configs/tools/custom_tools/computer_use_browser_example.yaml +1 -1
- massgen/configs/tools/custom_tools/computer_use_docker_example.yaml +1 -1
- massgen/configs/tools/custom_tools/gemini_custom_tool_with_mcp_example.yaml +1 -0
- massgen/configs/tools/custom_tools/gpt5_nano_custom_tool_with_mcp_example.yaml +1 -0
- massgen/configs/tools/custom_tools/gpt_oss_custom_tool_with_mcp_example.yaml +1 -0
- massgen/configs/tools/custom_tools/grok3_mini_custom_tool_with_mcp_example.yaml +1 -0
- massgen/configs/tools/custom_tools/interop/ag2_and_langgraph_lesson_planner.yaml +65 -0
- massgen/configs/tools/custom_tools/interop/ag2_and_openai_assistant_lesson_planner.yaml +65 -0
- massgen/configs/tools/custom_tools/interop/ag2_lesson_planner_example.yaml +48 -0
- massgen/configs/tools/custom_tools/interop/agentscope_lesson_planner_example.yaml +48 -0
- massgen/configs/tools/custom_tools/interop/langgraph_lesson_planner_example.yaml +49 -0
- massgen/configs/tools/custom_tools/interop/openai_assistant_lesson_planner_example.yaml +50 -0
- massgen/configs/tools/custom_tools/interop/smolagent_lesson_planner_example.yaml +49 -0
- massgen/configs/tools/custom_tools/qwen_api_custom_tool_with_mcp_example.yaml +1 -0
- massgen/configs/tools/custom_tools/two_models_with_tools_example.yaml +44 -0
- massgen/formatter/_gemini_formatter.py +61 -15
- massgen/memory/README.md +277 -0
- massgen/memory/__init__.py +26 -0
- massgen/memory/_base.py +193 -0
- massgen/memory/_compression.py +237 -0
- massgen/memory/_context_monitor.py +211 -0
- massgen/memory/_conversation.py +255 -0
- massgen/memory/_fact_extraction_prompts.py +333 -0
- massgen/memory/_mem0_adapters.py +257 -0
- massgen/memory/_persistent.py +687 -0
- massgen/memory/docker-compose.qdrant.yml +36 -0
- massgen/memory/docs/DESIGN.md +388 -0
- massgen/memory/docs/QUICKSTART.md +409 -0
- massgen/memory/docs/SUMMARY.md +319 -0
- massgen/memory/docs/agent_use_memory.md +408 -0
- massgen/memory/docs/orchestrator_use_memory.md +586 -0
- massgen/memory/examples.py +237 -0
- massgen/orchestrator.py +207 -7
- massgen/tests/memory/test_agent_compression.py +174 -0
- massgen/tests/memory/test_context_window_management.py +286 -0
- massgen/tests/memory/test_force_compression.py +154 -0
- massgen/tests/memory/test_simple_compression.py +147 -0
- massgen/tests/test_ag2_lesson_planner.py +223 -0
- massgen/tests/test_agent_memory.py +534 -0
- massgen/tests/test_config_validator.py +1156 -0
- massgen/tests/test_conversation_memory.py +382 -0
- massgen/tests/test_langgraph_lesson_planner.py +223 -0
- massgen/tests/test_orchestrator_memory.py +620 -0
- massgen/tests/test_persistent_memory.py +435 -0
- massgen/token_manager/token_manager.py +6 -0
- massgen/tool/__init__.py +2 -9
- massgen/tool/_decorators.py +52 -0
- massgen/tool/_extraframework_agents/ag2_lesson_planner_tool.py +251 -0
- massgen/tool/_extraframework_agents/agentscope_lesson_planner_tool.py +303 -0
- massgen/tool/_extraframework_agents/langgraph_lesson_planner_tool.py +275 -0
- massgen/tool/_extraframework_agents/openai_assistant_lesson_planner_tool.py +247 -0
- massgen/tool/_extraframework_agents/smolagent_lesson_planner_tool.py +180 -0
- massgen/tool/_manager.py +102 -16
- massgen/tool/_registered_tool.py +3 -0
- massgen/tool/_result.py +3 -0
- {massgen-0.1.4.dist-info → massgen-0.1.6.dist-info}/METADATA +138 -77
- {massgen-0.1.4.dist-info → massgen-0.1.6.dist-info}/RECORD +82 -37
- massgen/backend/gemini_mcp_manager.py +0 -545
- massgen/backend/gemini_trackers.py +0 -344
- {massgen-0.1.4.dist-info → massgen-0.1.6.dist-info}/WHEEL +0 -0
- {massgen-0.1.4.dist-info → massgen-0.1.6.dist-info}/entry_points.txt +0 -0
- {massgen-0.1.4.dist-info → massgen-0.1.6.dist-info}/licenses/LICENSE +0 -0
- {massgen-0.1.4.dist-info → massgen-0.1.6.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
AG2 (AutoGen) Nested Chat Lesson Planner Tool
|
|
4
|
+
This tool demonstrates interoperability by wrapping AutoGen's nested chat functionality as a MassGen custom tool.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
from typing import Any, AsyncGenerator, Dict, List
|
|
9
|
+
|
|
10
|
+
from autogen import ConversableAgent, GroupChat, GroupChatManager
|
|
11
|
+
|
|
12
|
+
from massgen.tool import context_params
|
|
13
|
+
from massgen.tool._result import ExecutionResult, TextContent
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def run_ag2_lesson_planner_agent(
|
|
17
|
+
messages: List[Dict[str, Any]],
|
|
18
|
+
api_key: str,
|
|
19
|
+
):
|
|
20
|
+
"""
|
|
21
|
+
Core AG2 lesson planner agent - pure AutoGen implementation.
|
|
22
|
+
|
|
23
|
+
This function contains the pure AG2/AutoGen logic for creating lesson plans
|
|
24
|
+
using nested chats and multiple specialized agents.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
messages: messages for the agent to execute
|
|
28
|
+
api_key: OpenAI API key for the agents
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
The formatted lesson plan as a string
|
|
32
|
+
|
|
33
|
+
Raises:
|
|
34
|
+
Exception: Any errors during agent execution
|
|
35
|
+
"""
|
|
36
|
+
if not messages:
|
|
37
|
+
raise ValueError("No messages provided for lesson planning.")
|
|
38
|
+
# Configure LLM
|
|
39
|
+
llm_config = {
|
|
40
|
+
"config_list": [
|
|
41
|
+
{
|
|
42
|
+
"api_type": "openai",
|
|
43
|
+
"model": "gpt-4o",
|
|
44
|
+
"api_key": api_key,
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
# Curriculum Standards Agent
|
|
50
|
+
curriculum_agent = ConversableAgent(
|
|
51
|
+
name="Curriculum_Agent",
|
|
52
|
+
system_message="""You are a curriculum standards expert for fourth grade education.
|
|
53
|
+
When given a topic, you provide relevant grade-level standards and learning objectives.
|
|
54
|
+
Format every response as:
|
|
55
|
+
STANDARDS:
|
|
56
|
+
- [Standard 1]
|
|
57
|
+
- [Standard 2]
|
|
58
|
+
OBJECTIVES:
|
|
59
|
+
- By the end of this lesson, students will be able to [objective 1]
|
|
60
|
+
- By the end of this lesson, students will be able to [objective 2]""",
|
|
61
|
+
human_input_mode="NEVER",
|
|
62
|
+
llm_config=llm_config,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Lesson Planner Agent
|
|
66
|
+
lesson_planner_agent = ConversableAgent(
|
|
67
|
+
name="Lesson_Planner_Agent",
|
|
68
|
+
system_message="""You are a lesson planning specialist.
|
|
69
|
+
Given standards and objectives, you create detailed lesson plans including:
|
|
70
|
+
- Opening/Hook (5-10 minutes)
|
|
71
|
+
- Main Activity (20-30 minutes)
|
|
72
|
+
- Practice Activity (15-20 minutes)
|
|
73
|
+
- Assessment/Closure (5-10 minutes)
|
|
74
|
+
Format as a structured lesson plan with clear timing and materials needed.""",
|
|
75
|
+
human_input_mode="NEVER",
|
|
76
|
+
llm_config=llm_config,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Lesson Reviewer Agent
|
|
80
|
+
lesson_reviewer_agent = ConversableAgent(
|
|
81
|
+
name="Lesson_Reviewer_Agent",
|
|
82
|
+
system_message="""You are a lesson plan reviewer who ensures:
|
|
83
|
+
1. Age-appropriate content and activities
|
|
84
|
+
2. Alignment with provided standards
|
|
85
|
+
3. Realistic timing
|
|
86
|
+
4. Clear instructions
|
|
87
|
+
5. Differentiation opportunities
|
|
88
|
+
Provide specific feedback in these areas and suggest improvements if needed.""",
|
|
89
|
+
human_input_mode="NEVER",
|
|
90
|
+
llm_config=llm_config,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# Lead Teacher Agent
|
|
94
|
+
lead_teacher_agent = ConversableAgent(
|
|
95
|
+
name="Lead_Teacher_Agent",
|
|
96
|
+
system_message="""You are an experienced fourth grade teacher who oversees the lesson planning process.
|
|
97
|
+
Your role is to:
|
|
98
|
+
1. Initiate the planning process with a clear topic
|
|
99
|
+
2. Review and integrate feedback from other agents
|
|
100
|
+
3. Ensure the final lesson plan is practical and engaging
|
|
101
|
+
4. Make final adjustments based on classroom experience""",
|
|
102
|
+
human_input_mode="NEVER",
|
|
103
|
+
llm_config=llm_config,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
# Create the group chat for collaborative lesson planning
|
|
107
|
+
planning_chat = GroupChat(
|
|
108
|
+
agents=[curriculum_agent, lesson_planner_agent, lesson_reviewer_agent],
|
|
109
|
+
messages=[],
|
|
110
|
+
max_round=2,
|
|
111
|
+
send_introductions=True,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
planning_manager = GroupChatManager(
|
|
115
|
+
groupchat=planning_chat,
|
|
116
|
+
llm_config=llm_config,
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
# Formatter of the final lesson plan to a standard format
|
|
120
|
+
formatter_message = """You are a lesson plan formatter. Format the complete plan as follows:
|
|
121
|
+
<title>Lesson plan title</title>
|
|
122
|
+
<standards>Standards covered</standards>
|
|
123
|
+
<learning_objectives>Key learning objectives</learning_objectives>
|
|
124
|
+
<materials>Materials required</materials>
|
|
125
|
+
<activities>Lesson plan activities</activities>
|
|
126
|
+
<assessment>Assessment details</assessment>
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
lesson_formatter = ConversableAgent(
|
|
130
|
+
name="formatter_agent",
|
|
131
|
+
system_message=formatter_message,
|
|
132
|
+
llm_config=llm_config,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# Create nested chats configuration
|
|
136
|
+
nested_chats = [
|
|
137
|
+
{
|
|
138
|
+
# The first internal chat determines the standards and objectives
|
|
139
|
+
"recipient": curriculum_agent,
|
|
140
|
+
"message": f"Please provide fourth grade standards and objectives for: {messages}",
|
|
141
|
+
"max_turns": 2,
|
|
142
|
+
"summary_method": "last_msg",
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
# A group chat follows, where the lesson plan is created
|
|
146
|
+
"recipient": planning_manager,
|
|
147
|
+
"message": "Based on these standards and objectives, create a detailed lesson plan.",
|
|
148
|
+
"max_turns": 1,
|
|
149
|
+
"summary_method": "last_msg",
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
# Finally, a two-agent chat formats the lesson plan
|
|
153
|
+
"recipient": lesson_formatter,
|
|
154
|
+
"message": "Format the lesson plan.",
|
|
155
|
+
"max_turns": 1,
|
|
156
|
+
"summary_method": "last_msg",
|
|
157
|
+
},
|
|
158
|
+
]
|
|
159
|
+
|
|
160
|
+
# Register nested chats with the lead teacher
|
|
161
|
+
lead_teacher_agent.register_nested_chats(
|
|
162
|
+
chat_queue=nested_chats,
|
|
163
|
+
trigger=lambda sender: sender.name == "Assistant_Agent",
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
# Create a simple assistant agent to trigger the nested chat
|
|
167
|
+
assistant_agent = ConversableAgent(
|
|
168
|
+
name="Assistant_Agent",
|
|
169
|
+
system_message="You are a helpful assistant.",
|
|
170
|
+
human_input_mode="NEVER",
|
|
171
|
+
llm_config=llm_config,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
# Initiate the chat and get the result
|
|
175
|
+
response = assistant_agent.run(
|
|
176
|
+
recipient=lead_teacher_agent,
|
|
177
|
+
message=str(messages),
|
|
178
|
+
max_turns=1,
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# Extract the lesson plan from the result
|
|
182
|
+
|
|
183
|
+
return response
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
@context_params("prompt")
|
|
187
|
+
async def ag2_lesson_planner(
|
|
188
|
+
prompt: List[Dict[str, Any]],
|
|
189
|
+
) -> AsyncGenerator[ExecutionResult, None]:
|
|
190
|
+
"""
|
|
191
|
+
MassGen custom tool wrapper for AG2 lesson planner.
|
|
192
|
+
|
|
193
|
+
This is the interface exposed to MassGen's backend. It handles environment setup,
|
|
194
|
+
error handling, and wraps the core agent logic in ExecutionResult.
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
prompt: processed message list from orchestrator (auto-injected via execution_context)
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
ExecutionResult containing the formatted lesson plan or error message
|
|
201
|
+
"""
|
|
202
|
+
# Get API key from environment
|
|
203
|
+
api_key = os.getenv("OPENAI_API_KEY")
|
|
204
|
+
|
|
205
|
+
if not api_key:
|
|
206
|
+
yield ExecutionResult(
|
|
207
|
+
output_blocks=[
|
|
208
|
+
TextContent(data="Error: OPENAI_API_KEY not found. Please set the environment variable."),
|
|
209
|
+
],
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
try:
|
|
213
|
+
# Call the core agent function with processed messages
|
|
214
|
+
response = run_ag2_lesson_planner_agent(
|
|
215
|
+
messages=prompt,
|
|
216
|
+
api_key=api_key,
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
last_nested_chat_event_msgs = []
|
|
220
|
+
|
|
221
|
+
def process_and_log_event(*args, **kwargs) -> None:
|
|
222
|
+
"""Process and log AG2 event, returning string representation."""
|
|
223
|
+
line = " ".join(str(arg) for arg in args)
|
|
224
|
+
last_nested_chat_event_msgs.append(line)
|
|
225
|
+
|
|
226
|
+
for event in response.events:
|
|
227
|
+
last_nested_chat_event_msgs.clear()
|
|
228
|
+
event.print(f=process_and_log_event)
|
|
229
|
+
formatted_message = "\n".join(last_nested_chat_event_msgs)
|
|
230
|
+
|
|
231
|
+
if event.type == "run_completion":
|
|
232
|
+
# Final output
|
|
233
|
+
yield ExecutionResult(
|
|
234
|
+
output_blocks=[
|
|
235
|
+
TextContent(data=event.content.summary),
|
|
236
|
+
],
|
|
237
|
+
)
|
|
238
|
+
else:
|
|
239
|
+
yield ExecutionResult(
|
|
240
|
+
output_blocks=[
|
|
241
|
+
TextContent(data=formatted_message),
|
|
242
|
+
],
|
|
243
|
+
is_log=True,
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
except Exception as e:
|
|
247
|
+
yield ExecutionResult(
|
|
248
|
+
output_blocks=[
|
|
249
|
+
TextContent(data=f"Error creating lesson plan: {str(e)}"),
|
|
250
|
+
],
|
|
251
|
+
)
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
AgentScope Lesson Planner Tool
|
|
4
|
+
This tool demonstrates interoperability by wrapping AgentScope's multi-agent framework as a MassGen custom tool.
|
|
5
|
+
Compatible with AgentScope 1.0.6+
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
from typing import Any, AsyncGenerator, Dict, List
|
|
10
|
+
|
|
11
|
+
import agentscope
|
|
12
|
+
from agentscope.agent import AgentBase
|
|
13
|
+
from agentscope.formatter import OpenAIChatFormatter
|
|
14
|
+
from agentscope.memory import InMemoryMemory
|
|
15
|
+
from agentscope.message import Msg
|
|
16
|
+
from agentscope.model import OpenAIChatModel
|
|
17
|
+
|
|
18
|
+
from massgen.tool import context_params
|
|
19
|
+
from massgen.tool._result import ExecutionResult, TextContent
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class SimpleDialogAgent(AgentBase):
|
|
23
|
+
"""
|
|
24
|
+
A simple dialog agent for AgentScope 1.0.6+
|
|
25
|
+
This is a lightweight replacement for the deprecated DialogAgent.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
name: str,
|
|
31
|
+
sys_prompt: str,
|
|
32
|
+
model: OpenAIChatModel,
|
|
33
|
+
):
|
|
34
|
+
"""
|
|
35
|
+
Initialize the dialog agent.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
name: Agent name
|
|
39
|
+
sys_prompt: System prompt for the agent
|
|
40
|
+
model: OpenAI chat model instance
|
|
41
|
+
"""
|
|
42
|
+
super().__init__()
|
|
43
|
+
self.name = name
|
|
44
|
+
self.sys_prompt = sys_prompt
|
|
45
|
+
self.model = model
|
|
46
|
+
self.formatter = OpenAIChatFormatter()
|
|
47
|
+
self.memory = InMemoryMemory()
|
|
48
|
+
|
|
49
|
+
# Store system prompt to add later (memory operations are async)
|
|
50
|
+
self.pending_sys_msg = None
|
|
51
|
+
if sys_prompt:
|
|
52
|
+
self.pending_sys_msg = Msg(name="system", content=sys_prompt, role="system")
|
|
53
|
+
|
|
54
|
+
async def reply(self, x: Msg = None) -> Msg:
|
|
55
|
+
"""
|
|
56
|
+
Generate a reply to the input message.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
x: Input message
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
Response message
|
|
63
|
+
"""
|
|
64
|
+
# Add system prompt on first call
|
|
65
|
+
if self.pending_sys_msg is not None:
|
|
66
|
+
await self.memory.add(self.pending_sys_msg)
|
|
67
|
+
self.pending_sys_msg = None
|
|
68
|
+
|
|
69
|
+
# Add user message to memory
|
|
70
|
+
if x is not None:
|
|
71
|
+
await self.memory.add(x)
|
|
72
|
+
|
|
73
|
+
# Get conversation history
|
|
74
|
+
history = await self.memory.get_memory()
|
|
75
|
+
|
|
76
|
+
# Format messages for the model
|
|
77
|
+
formatted_msgs = []
|
|
78
|
+
for msg in history:
|
|
79
|
+
formatted_msgs.append(
|
|
80
|
+
{
|
|
81
|
+
"role": msg.role,
|
|
82
|
+
"content": msg.content if isinstance(msg.content, str) else str(msg.content),
|
|
83
|
+
},
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# Generate response using the model
|
|
87
|
+
response = await self.model(formatted_msgs)
|
|
88
|
+
|
|
89
|
+
# Extract content from ChatResponse
|
|
90
|
+
# response.content is a list like [{'type': 'text', 'text': '...'}]
|
|
91
|
+
content = ""
|
|
92
|
+
if hasattr(response, "content") and isinstance(response.content, list):
|
|
93
|
+
for item in response.content:
|
|
94
|
+
if isinstance(item, dict) and item.get("type") == "text":
|
|
95
|
+
content += item.get("text", "")
|
|
96
|
+
elif hasattr(response, "content"):
|
|
97
|
+
content = str(response.content)
|
|
98
|
+
else:
|
|
99
|
+
content = str(response)
|
|
100
|
+
|
|
101
|
+
# Create response message
|
|
102
|
+
response_msg = Msg(
|
|
103
|
+
name=self.name,
|
|
104
|
+
content=content,
|
|
105
|
+
role="assistant",
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# Add response to memory
|
|
109
|
+
await self.memory.add(response_msg)
|
|
110
|
+
|
|
111
|
+
return response_msg
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
async def run_agentscope_lesson_planner_agent(
|
|
115
|
+
messages: List[Dict[str, Any]],
|
|
116
|
+
api_key: str,
|
|
117
|
+
) -> str:
|
|
118
|
+
"""
|
|
119
|
+
Core AgentScope lesson planner agent - pure AgentScope implementation.
|
|
120
|
+
|
|
121
|
+
This function contains the pure AgentScope logic for creating lesson plans
|
|
122
|
+
using multiple specialized DialogAgents in a sequential pipeline.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
messages: Complete message history from orchestrator
|
|
126
|
+
api_key: OpenAI API key for the agents
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
The formatted lesson plan as a string
|
|
130
|
+
|
|
131
|
+
Raises:
|
|
132
|
+
Exception: Any errors during agent execution
|
|
133
|
+
"""
|
|
134
|
+
if not messages:
|
|
135
|
+
raise ValueError("No messages provided for lesson planning.")
|
|
136
|
+
|
|
137
|
+
# Extract the user's topic/request from messages
|
|
138
|
+
# Messages is typically a list of dicts with 'role' and 'content'
|
|
139
|
+
user_prompt = ""
|
|
140
|
+
for msg in messages:
|
|
141
|
+
if isinstance(msg, dict) and msg.get("role") == "user":
|
|
142
|
+
user_prompt = msg.get("content", "")
|
|
143
|
+
break
|
|
144
|
+
|
|
145
|
+
if not user_prompt:
|
|
146
|
+
# Fallback: use the entire messages as string
|
|
147
|
+
user_prompt = str(messages)
|
|
148
|
+
|
|
149
|
+
# Initialize AgentScope (simplified for 1.0.6)
|
|
150
|
+
agentscope.init(
|
|
151
|
+
project="massgen_lesson_planner",
|
|
152
|
+
name="agentscope_lesson_planner_run",
|
|
153
|
+
logging_level="WARNING",
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
# Create shared model instance
|
|
157
|
+
model = OpenAIChatModel(
|
|
158
|
+
model_name="gpt-4o",
|
|
159
|
+
api_key=api_key,
|
|
160
|
+
stream=False,
|
|
161
|
+
generate_kwargs={
|
|
162
|
+
"temperature": 0.7,
|
|
163
|
+
},
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
# Create specialized agents for each step
|
|
167
|
+
curriculum_agent = SimpleDialogAgent(
|
|
168
|
+
name="Curriculum_Standards_Expert",
|
|
169
|
+
sys_prompt="""You are a curriculum standards expert for fourth grade education.
|
|
170
|
+
When given a topic, you provide relevant grade-level standards and learning objectives.
|
|
171
|
+
Format every response as:
|
|
172
|
+
STANDARDS:
|
|
173
|
+
- [Standard 1]
|
|
174
|
+
- [Standard 2]
|
|
175
|
+
OBJECTIVES:
|
|
176
|
+
- By the end of this lesson, students will be able to [objective 1]
|
|
177
|
+
- By the end of this lesson, students will be able to [objective 2]""",
|
|
178
|
+
model=model,
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
lesson_planner_agent = SimpleDialogAgent(
|
|
182
|
+
name="Lesson_Planning_Specialist",
|
|
183
|
+
sys_prompt="""You are a lesson planning specialist.
|
|
184
|
+
Given standards and objectives, you create detailed lesson plans including:
|
|
185
|
+
- Opening/Hook (5-10 minutes)
|
|
186
|
+
- Main Activity (20-30 minutes)
|
|
187
|
+
- Practice Activity (15-20 minutes)
|
|
188
|
+
- Assessment/Closure (5-10 minutes)
|
|
189
|
+
Format as a structured lesson plan with clear timing and materials needed.""",
|
|
190
|
+
model=model,
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
reviewer_agent = SimpleDialogAgent(
|
|
194
|
+
name="Lesson_Plan_Reviewer",
|
|
195
|
+
sys_prompt="""You are a lesson plan reviewer who ensures:
|
|
196
|
+
1. Age-appropriate content and activities
|
|
197
|
+
2. Alignment with provided standards
|
|
198
|
+
3. Realistic timing
|
|
199
|
+
4. Clear instructions
|
|
200
|
+
5. Differentiation opportunities
|
|
201
|
+
Provide an improved version of the lesson plan incorporating your feedback.""",
|
|
202
|
+
model=model,
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
formatter_agent = SimpleDialogAgent(
|
|
206
|
+
name="Lesson_Plan_Formatter",
|
|
207
|
+
sys_prompt="""You are a lesson plan formatter. Format the complete plan as follows:
|
|
208
|
+
<title>Lesson plan title</title>
|
|
209
|
+
<standards>Standards covered</standards>
|
|
210
|
+
<learning_objectives>Key learning objectives</learning_objectives>
|
|
211
|
+
<materials>Materials required</materials>
|
|
212
|
+
<activities>Detailed lesson plan activities with timing</activities>
|
|
213
|
+
<assessment>Assessment details</assessment>""",
|
|
214
|
+
model=model,
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
# Build the initial message
|
|
218
|
+
initial_message = f"Please provide fourth grade standards and objectives for: {user_prompt}"
|
|
219
|
+
|
|
220
|
+
# Create the sequential pipeline
|
|
221
|
+
# Step 1: Get curriculum standards
|
|
222
|
+
msg = Msg(name="User", content=initial_message, role="user")
|
|
223
|
+
standards_response = await curriculum_agent.reply(msg)
|
|
224
|
+
|
|
225
|
+
# Step 2: Create lesson plan based on standards
|
|
226
|
+
lesson_msg = Msg(
|
|
227
|
+
name="User",
|
|
228
|
+
content=f"Based on these standards and objectives, create a detailed lesson plan:\n\n{standards_response.content}",
|
|
229
|
+
role="user",
|
|
230
|
+
)
|
|
231
|
+
lesson_response = await lesson_planner_agent.reply(lesson_msg)
|
|
232
|
+
|
|
233
|
+
# Step 3: Review and improve the lesson plan
|
|
234
|
+
review_msg = Msg(
|
|
235
|
+
name="User",
|
|
236
|
+
content=f"Please review and improve this lesson plan:\n\n{lesson_response.content}",
|
|
237
|
+
role="user",
|
|
238
|
+
)
|
|
239
|
+
reviewed_response = await reviewer_agent.reply(review_msg)
|
|
240
|
+
|
|
241
|
+
# Step 4: Format the final lesson plan
|
|
242
|
+
format_msg = Msg(
|
|
243
|
+
name="User",
|
|
244
|
+
content=f"Format this reviewed lesson plan:\n\n{reviewed_response.content}",
|
|
245
|
+
role="user",
|
|
246
|
+
)
|
|
247
|
+
final_response = await formatter_agent.reply(format_msg)
|
|
248
|
+
|
|
249
|
+
# Extract the final lesson plan
|
|
250
|
+
lesson_plan = final_response.content if isinstance(final_response.content, str) else str(final_response.content)
|
|
251
|
+
|
|
252
|
+
return lesson_plan
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
@context_params("prompt")
|
|
256
|
+
async def agentscope_lesson_planner(
|
|
257
|
+
prompt: List[Dict[str, Any]],
|
|
258
|
+
) -> AsyncGenerator[ExecutionResult, None]:
|
|
259
|
+
"""
|
|
260
|
+
MassGen custom tool wrapper for AgentScope lesson planner.
|
|
261
|
+
|
|
262
|
+
This is the interface exposed to MassGen's backend. It handles environment setup,
|
|
263
|
+
error handling, and wraps the core agent logic in ExecutionResult.
|
|
264
|
+
|
|
265
|
+
Args:
|
|
266
|
+
prompt: processed message list from orchestrator (auto-injected via execution_context)
|
|
267
|
+
|
|
268
|
+
Returns:
|
|
269
|
+
ExecutionResult containing the formatted lesson plan or error message
|
|
270
|
+
"""
|
|
271
|
+
# Get API key from environment
|
|
272
|
+
api_key = os.getenv("OPENAI_API_KEY")
|
|
273
|
+
|
|
274
|
+
if not api_key:
|
|
275
|
+
yield ExecutionResult(
|
|
276
|
+
output_blocks=[
|
|
277
|
+
TextContent(data="Error: OPENAI_API_KEY not found. Please set the environment variable."),
|
|
278
|
+
],
|
|
279
|
+
)
|
|
280
|
+
return
|
|
281
|
+
|
|
282
|
+
try:
|
|
283
|
+
# Call the core agent function with processed messages
|
|
284
|
+
lesson_plan = await run_agentscope_lesson_planner_agent(
|
|
285
|
+
messages=prompt,
|
|
286
|
+
api_key=api_key,
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
yield ExecutionResult(
|
|
290
|
+
output_blocks=[
|
|
291
|
+
TextContent(data=f"AgentScope Lesson Planner Result:\n\n{lesson_plan}"),
|
|
292
|
+
],
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
except Exception as e:
|
|
296
|
+
import traceback
|
|
297
|
+
|
|
298
|
+
error_details = traceback.format_exc()
|
|
299
|
+
yield ExecutionResult(
|
|
300
|
+
output_blocks=[
|
|
301
|
+
TextContent(data=f"Error creating lesson plan: {str(e)}\n\nDetails:\n{error_details}"),
|
|
302
|
+
],
|
|
303
|
+
)
|