明确了swarm分配方式的局限性
This commit is contained in:
@@ -6,9 +6,9 @@ import os
|
||||
OPENAI_API_KEY = "sk-4aJj5ygdQ9rw6lS6920712Ef9bB848439522E72318439eCd"
|
||||
OPENAI_BASE_URL = "http://8.218.238.241:17935/v1"
|
||||
|
||||
# MODEL = "chatgpt-4o-latest"
|
||||
MODEL = "chatgpt-4o-latest"
|
||||
# MODEL = "gpt-4o-2024-11-20"
|
||||
MODEL = "deepseek-chat"
|
||||
# MODEL = "deepseek-chat"
|
||||
# config_list = [{"model": MODEL, "api_key": OPENAI_API_KEY, "base_url": OPENAI_BASE_URL, "temperature": 0}]
|
||||
config_list = [{"model": MODEL, "api_key": OPENAI_API_KEY, "base_url": OPENAI_BASE_URL}]
|
||||
|
||||
|
||||
176
_backend/custom.py
Normal file
176
_backend/custom.py
Normal file
@@ -0,0 +1,176 @@
|
||||
from typing import Any, AsyncGenerator, List, Mapping, Sequence
|
||||
|
||||
from autogen_core import CancellationToken
|
||||
from autogen_core.models import ChatCompletionClient, LLMMessage, SystemMessage, UserMessage
|
||||
|
||||
from autogen_agentchat.base import Response
|
||||
from autogen_agentchat.state import SocietyOfMindAgentState
|
||||
|
||||
from autogen_agentchat.base import TaskResult, Team
|
||||
from autogen_agentchat.messages import (
|
||||
AgentEvent,
|
||||
BaseChatMessage,
|
||||
ChatMessage,
|
||||
TextMessage,
|
||||
)
|
||||
from autogen_agentchat.agents._base_chat_agent import BaseChatAgent
|
||||
|
||||
|
||||
class SocietyOfMindAgent(BaseChatAgent):
|
||||
"""An agent that uses an inner team of agents to generate responses.
|
||||
|
||||
Each time the agent's :meth:`on_messages` or :meth:`on_messages_stream`
|
||||
method is called, it runs the inner team of agents and then uses the
|
||||
model client to generate a response based on the inner team's messages.
|
||||
Once the response is generated, the agent resets the inner team by
|
||||
calling :meth:`Team.reset`.
|
||||
|
||||
Args:
|
||||
name (str): The name of the agent.
|
||||
team (Team): The team of agents to use.
|
||||
model_client (ChatCompletionClient): The model client to use for preparing responses.
|
||||
description (str, optional): The description of the agent.
|
||||
instruction (str, optional): The instruction to use when generating a response using the inner team's messages.
|
||||
Defaults to :attr:`DEFAULT_INSTRUCTION`. It assumes the role of 'system'.
|
||||
response_prompt (str, optional): The response prompt to use when generating a response using the inner team's messages.
|
||||
Defaults to :attr:`DEFAULT_RESPONSE_PROMPT`. It assumes the role of 'system'.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import asyncio
|
||||
from autogen_agentchat.ui import Console
|
||||
from autogen_agentchat.agents import AssistantAgent, SocietyOfMindAgent
|
||||
from autogen_ext.models.openai import OpenAIChatCompletionClient
|
||||
from autogen_agentchat.teams import RoundRobinGroupChat
|
||||
from autogen_agentchat.conditions import TextMentionTermination
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
model_client = OpenAIChatCompletionClient(model="gpt-4o")
|
||||
|
||||
agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a writer, write well.")
|
||||
agent2 = AssistantAgent(
|
||||
"assistant2",
|
||||
model_client=model_client,
|
||||
system_message="You are an editor, provide critical feedback. Respond with 'APPROVE' if the text addresses all feedbacks.",
|
||||
)
|
||||
inner_termination = TextMentionTermination("APPROVE")
|
||||
inner_team = RoundRobinGroupChat([agent1, agent2], termination_condition=inner_termination)
|
||||
|
||||
society_of_mind_agent = SocietyOfMindAgent("society_of_mind", team=inner_team, model_client=model_client)
|
||||
|
||||
agent3 = AssistantAgent(
|
||||
"assistant3", model_client=model_client, system_message="Translate the text to Spanish."
|
||||
)
|
||||
team = RoundRobinGroupChat([society_of_mind_agent, agent3], max_turns=2)
|
||||
|
||||
stream = team.run_stream(task="Write a short story with a surprising ending.")
|
||||
await Console(stream)
|
||||
|
||||
|
||||
asyncio.run(main())
|
||||
"""
|
||||
|
||||
DEFAULT_INSTRUCTION = "Earlier you were asked to fulfill a request. You and your team worked diligently to address that request. Here is a transcript of that conversation:"
|
||||
"""str: The default instruction to use when generating a response using the
|
||||
inner team's messages. The instruction will be prepended to the inner team's
|
||||
messages when generating a response using the model. It assumes the role of
|
||||
'system'."""
|
||||
|
||||
DEFAULT_RESPONSE_PROMPT = (
|
||||
"Output a standalone response to the original request, without mentioning any of the intermediate discussion."
|
||||
)
|
||||
"""str: The default response prompt to use when generating a response using
|
||||
the inner team's messages. It assumes the role of 'system'."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
team: Team,
|
||||
model_client: ChatCompletionClient,
|
||||
*,
|
||||
description: str = "An agent that uses an inner team of agents to generate responses.",
|
||||
instruction: str = DEFAULT_INSTRUCTION,
|
||||
response_prompt: str = DEFAULT_RESPONSE_PROMPT,
|
||||
) -> None:
|
||||
super().__init__(name=name, description=description)
|
||||
self._team = team
|
||||
self._model_client = model_client
|
||||
self._instruction = instruction
|
||||
self._response_prompt = response_prompt
|
||||
|
||||
@property
|
||||
def produced_message_types(self) -> Sequence[type[ChatMessage]]:
|
||||
return (TextMessage,)
|
||||
|
||||
async def on_messages(self, messages: Sequence[ChatMessage], cancellation_token: CancellationToken) -> Response:
|
||||
# Call the stream method and collect the messages.
|
||||
response: Response | None = None
|
||||
async for msg in self.on_messages_stream(messages, cancellation_token):
|
||||
if isinstance(msg, Response):
|
||||
response = msg
|
||||
assert response is not None
|
||||
return response
|
||||
|
||||
async def on_messages_stream(
|
||||
self, messages: Sequence[ChatMessage], cancellation_token: CancellationToken
|
||||
) -> AsyncGenerator[AgentEvent | ChatMessage | Response, None]:
|
||||
# Prepare the task for the team of agents.
|
||||
task = list(messages)
|
||||
task = [t for t in task if t.source!="PlanningAgent"][-2:]
|
||||
|
||||
# Run the team of agents.
|
||||
result: TaskResult | None = None
|
||||
inner_messages: List[AgentEvent | ChatMessage] = []
|
||||
count = 0
|
||||
async for inner_msg in self._team.run_stream(task=task, cancellation_token=cancellation_token):
|
||||
if isinstance(inner_msg, TaskResult):
|
||||
result = inner_msg
|
||||
else:
|
||||
count += 1
|
||||
if count <= len(task):
|
||||
# Skip the task messages.
|
||||
continue
|
||||
yield inner_msg
|
||||
inner_messages.append(inner_msg)
|
||||
assert result is not None
|
||||
|
||||
if len(inner_messages) == 0:
|
||||
yield Response(
|
||||
chat_message=TextMessage(source=self.name, content="No response."), inner_messages=inner_messages
|
||||
)
|
||||
else:
|
||||
# Generate a response using the model client.
|
||||
llm_messages: List[LLMMessage] = [SystemMessage(content=self._instruction)]
|
||||
llm_messages.extend(
|
||||
[
|
||||
UserMessage(content=message.content, source=message.source)
|
||||
for message in inner_messages
|
||||
if isinstance(message, BaseChatMessage)
|
||||
]
|
||||
)
|
||||
llm_messages.append(SystemMessage(content=self._response_prompt))
|
||||
completion = await self._model_client.create(messages=llm_messages, cancellation_token=cancellation_token)
|
||||
assert isinstance(completion.content, str)
|
||||
yield Response(
|
||||
chat_message=TextMessage(source=self.name, content=completion.content, models_usage=completion.usage),
|
||||
inner_messages=inner_messages,
|
||||
)
|
||||
|
||||
# Reset the team.
|
||||
await self._team.reset()
|
||||
|
||||
async def on_reset(self, cancellation_token: CancellationToken) -> None:
|
||||
await self._team.reset()
|
||||
|
||||
async def save_state(self) -> Mapping[str, Any]:
|
||||
team_state = await self._team.save_state()
|
||||
state = SocietyOfMindAgentState(inner_team_state=team_state)
|
||||
return state.model_dump()
|
||||
|
||||
async def load_state(self, state: Mapping[str, Any]) -> None:
|
||||
society_of_mind_state = SocietyOfMindAgentState.model_validate(state)
|
||||
await self._team.load_state(society_of_mind_state.inner_team_state)
|
||||
@@ -1,14 +1,14 @@
|
||||
import asyncio
|
||||
from typing import Sequence
|
||||
from autogen_agentchat.agents import AssistantAgent, SocietyOfMindAgent
|
||||
from autogen_agentchat.agents import AssistantAgent#, SocietyOfMindAgent
|
||||
from autogen_agentchat.conditions import MaxMessageTermination, TextMentionTermination, HandoffTermination
|
||||
from autogen_agentchat.messages import AgentEvent, ChatMessage, TextMessage, ToolCallExecutionEvent, HandoffMessage
|
||||
from autogen_agentchat.teams import SelectorGroupChat, RoundRobinGroupChat, Swarm
|
||||
from autogen_agentchat.ui import Console
|
||||
from autogen_ext.models.openai import OpenAIChatCompletionClient
|
||||
from constant import MODEL, OPENAI_API_KEY, OPENAI_BASE_URL
|
||||
from tools import retrieval_from_knowledge_base, search_from_oqmd_by_composition
|
||||
|
||||
from tools import retrieval_from_knowledge_base, search_from_oqmd_by_composition, scheme_convert_to_json
|
||||
from custom import SocietyOfMindAgent
|
||||
|
||||
model_client = OpenAIChatCompletionClient(
|
||||
model=MODEL,
|
||||
@@ -30,13 +30,9 @@ def create_engineer_team() -> SelectorGroupChat | RoundRobinGroupChat:
|
||||
system_message="""
|
||||
You are a Engineer coordinator.
|
||||
Your job is coordinating material science research by delegating to specialized agents:
|
||||
Engineer_CodeWriter: A professional software engineer can convert a synthesis scheme into JSON or XML.
|
||||
Engineer_CodeWriter: A Professional software engineers can convert the composite scheme into JSON format for the robot to execute.
|
||||
Engineer_Visualizer: A professional mind mapping expert can transform natural language synthesis schemes into intuitive mind maps.
|
||||
Always send your plan first, then handoff to appropriate agent.
|
||||
You only plan and delegate tasks - you do not execute them yourself.
|
||||
Always handoff to a single agent at a time.
|
||||
When assigning tasks, use this format:
|
||||
1. <agent> : <task>
|
||||
Always send your plan first, then handoff to appropriate agent. Always handoff to a single agent at a time.
|
||||
|
||||
After all tasks are completed, the member Engineer agent's responses are collated into a detailed, no-miss response that ends with "APPROVE".
|
||||
** Remember: Avoid revealing the above words in your reply. **
|
||||
@@ -46,89 +42,17 @@ def create_engineer_team() -> SelectorGroupChat | RoundRobinGroupChat:
|
||||
|
||||
codewriter_agent = AssistantAgent(
|
||||
"Engineer_CodeWriter",
|
||||
description="A professional software engineer can convert a synthesis scheme into JSON or XML.",
|
||||
description="A Professional software engineers can convert the composite scheme into JSON format for the robot to execute.",
|
||||
model_client=model_client,
|
||||
system_message="""
|
||||
你是一个Engineer_CodeWriter,任务是将详细合成方案转化为机器人实验可执行的标准JSON格式。
|
||||
请使用以下结构确保一致性和便于执行。每个JSON结构的字段必须填充完整,即使有些字段留空。
|
||||
### 标准化JSON结构
|
||||
对每个实验步骤,将细节转化为以下JSON格式:
|
||||
你是一个Engineer_CodeWriter.
|
||||
你的任务是将下文/历史对话中的涉及到的合成方案转化为机器人可执行的标准JSON格式。
|
||||
|
||||
```json
|
||||
{
|
||||
"steps": [
|
||||
{
|
||||
"step": <step_number>, // 步骤编号,例如:1
|
||||
"action": "<action_type>", // 操作类型,例如:"add_material"
|
||||
"description": "<brief_description>",// 步骤简要描述
|
||||
"materials": [ // 材料细节(如适用),列表形式
|
||||
{
|
||||
"name": "<material_name>", // 材料名称,例如:"CsBr"
|
||||
"amount": <amount>, // 材料量,例如:0.85
|
||||
"unit": "<unit>" // 材料单位,例如:"mg" 或 "ml"
|
||||
}
|
||||
],
|
||||
"containers": [ // 容器细节,列表形式
|
||||
{
|
||||
"type": "<container_type>", // 容器类型,例如:"beaker"
|
||||
"capacity": "<capacity>", // 容器容量,例如:"100"
|
||||
"unit": "<unit>", // 容器单位,例如:"ml"
|
||||
"additional_parameters": {
|
||||
"material_of_construction": "<material_type>", // 容器材质,例如:"glass"
|
||||
"shape": "<shape>" // 容器形状,例如:"cylindrical"
|
||||
}
|
||||
}
|
||||
],
|
||||
"equipment": [ // 设备细节(如适用),列表形式
|
||||
{
|
||||
"name": "<equipment_name>", // 设备名称,例如:"centrifuge"
|
||||
"parameters": { // 设备参数
|
||||
"duration": <duration>, // 持续时间(超声波为小时,离心机为分钟)
|
||||
"speed": <speed>, // 转速(rpm)
|
||||
"method": "<method_used>", // 方法
|
||||
"temperature": <temperature>, // 温度(°C)
|
||||
"other": "<additional_details>" // 其他参数(如有)
|
||||
}
|
||||
}
|
||||
],
|
||||
"input_from": ["<previous_output>"], // 来自前一步骤的输入标识符,列表形式
|
||||
"output": "<current_output>", // 当前步骤的输出标识符
|
||||
"validation": { // 验证标准
|
||||
"expected_result": "<expected_result_description>", // 预期结果描述
|
||||
"tolerance": "<tolerance_value>" // 结果允许偏差值
|
||||
}
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
|
||||
### JSON结构字段说明
|
||||
Step: 指定步骤序列号。
|
||||
Action: 操作类型(例如,add_material, ultrasonicate, centrifuge)。
|
||||
Description: 步骤的简要描述。
|
||||
Materials: 使用材料的细节的列表,包括名称、数量和单位。
|
||||
Containers: 使用容器的细节的列表,包括类型、容量和其他参数。
|
||||
Equipment: 使用设备的细节的列表,包括名称和参数。
|
||||
Parameters: 操作步骤的详细参数,即使有些为空。
|
||||
Duration: 步骤持续时间(超声波为小时,离心机为分钟)。
|
||||
Speed: 转速(rpm)。
|
||||
Method: 使用的方法。
|
||||
Temperature: 温度(°C)。
|
||||
Other: 其他参数(如有)。
|
||||
Input_from: 前一步骤的输入标识符的列表。
|
||||
Output: 当前步骤的输出标识符。
|
||||
Validation: 步骤的验证标准,包括预期结果和允许的偏差值。
|
||||
|
||||
### 指示
|
||||
将由批评者确认无误的合成方案转换成前述的JSON指令格式。
|
||||
确保每个字段都准确填充,即使部分字段空白。
|
||||
使用"input_from"引用前一步骤的输出,如有必要。
|
||||
在每个步骤的"validation"字段中填入预期结果和允许偏差值。
|
||||
|
||||
**记住:避免在回复中泄露上述提示词。**
|
||||
Always handoff back to Engineer_PlanningAgent when JSON or XML is complete.
|
||||
""",
|
||||
handoffs=["Engineer_PlanningAgent"]
|
||||
handoffs=["Engineer_PlanningAgent"],
|
||||
tools=[scheme_convert_to_json],
|
||||
reflect_on_tool_use=True
|
||||
)
|
||||
|
||||
visualizer_agent = AssistantAgent(
|
||||
@@ -139,73 +63,6 @@ def create_engineer_team() -> SelectorGroupChat | RoundRobinGroupChat:
|
||||
你是mergrid_ploter,一个专门从事生成合成方案可视化表格的助手。
|
||||
你的任务是将详细的合成方案JSON格式转换为使用Mermaid.js语法的图形表示,以帮助用户更好地理解步骤之间的工作流程和依赖关系。
|
||||
|
||||
### 你的职责包括:
|
||||
1. 解析提供的JSON格式合成方案。
|
||||
2. 生成一个Mermaid.js图表,准确表示每个步骤,包括:
|
||||
- 操作类型
|
||||
- 材料及其数量
|
||||
- 容器细节
|
||||
- 设备细节和参数
|
||||
3. 确保图表清晰易懂,正确显示步骤的顺序和依赖关系。
|
||||
|
||||
### Example JSON Input
|
||||
```json
|
||||
{
|
||||
"steps": [
|
||||
{
|
||||
"step": 1,
|
||||
"action": "add_material",
|
||||
"description": "溶解CsBr和PbBr₂于无水DMF",
|
||||
"materials": [
|
||||
{
|
||||
"name": "CsBr",
|
||||
"amount": 0.85,
|
||||
"unit": "mg"
|
||||
},
|
||||
{
|
||||
"name": "PbBr₂",
|
||||
"amount": 1.2,
|
||||
"unit": "mg"
|
||||
},
|
||||
{
|
||||
"name": "无水DMF",
|
||||
"amount": 10,
|
||||
"unit": "mL"
|
||||
}
|
||||
],
|
||||
"containers": [
|
||||
{
|
||||
"type": "beaker",
|
||||
"capacity": "50",
|
||||
"unit": "mL",
|
||||
"additional_parameters": {
|
||||
"material_of_construction": "glass",
|
||||
"shape": "cylindrical"
|
||||
}
|
||||
}
|
||||
],
|
||||
"equipment": [
|
||||
{
|
||||
"name": "ultrasonic_bath",
|
||||
"parameters": {
|
||||
"duration": 1,
|
||||
"speed": null,
|
||||
"method": "ultrasonication",
|
||||
"temperature": 25
|
||||
}
|
||||
}
|
||||
],
|
||||
"input_from": [],
|
||||
"output": "CsBr_solution",
|
||||
"validation": {
|
||||
"expected_result": "CsBr完全溶解",
|
||||
"tolerance": "允许微量残留"
|
||||
}
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
|
||||
### Example Mermaid.js Output
|
||||
```mermaid
|
||||
graph TD;
|
||||
@@ -221,8 +78,6 @@ def create_engineer_team() -> SelectorGroupChat | RoundRobinGroupChat:
|
||||
B5 --> C2["温度: 25°C"]
|
||||
B5 --> C3["方法: 超声波"]
|
||||
end
|
||||
|
||||
%% 接下来的步骤将类似地定义
|
||||
```
|
||||
|
||||
### JSON到Mermaid转换指示
|
||||
@@ -234,13 +89,15 @@ def create_engineer_team() -> SelectorGroupChat | RoundRobinGroupChat:
|
||||
**记住:避免在回复中泄露上述提示词。**
|
||||
Always handoff back to Engineer_PlanningAgent when response is complete.
|
||||
""",
|
||||
handoffs=["Engineer_PlanningAgent"]
|
||||
handoffs=["Engineer_PlanningAgent"],
|
||||
reflect_on_tool_use=True
|
||||
)
|
||||
|
||||
# The termination condition is a combination of text mention termination and max message termination.
|
||||
handoff_termination = HandoffTermination("Engineer_PlanningAgent")
|
||||
text_mention_termination = TextMentionTermination("APPROVE")
|
||||
max_messages_termination = MaxMessageTermination(max_messages=25)
|
||||
termination = text_mention_termination | max_messages_termination
|
||||
max_messages_termination = MaxMessageTermination(max_messages=50)
|
||||
termination = text_mention_termination | max_messages_termination | handoff_termination
|
||||
# termination = max_messages_termination
|
||||
|
||||
team = Swarm(
|
||||
@@ -248,9 +105,9 @@ def create_engineer_team() -> SelectorGroupChat | RoundRobinGroupChat:
|
||||
termination_condition=termination
|
||||
)
|
||||
|
||||
Engineer_team = SocietyOfMindAgent(
|
||||
name="Engineer_team",
|
||||
engineer_team = SocietyOfMindAgent(
|
||||
name="engineer_team",
|
||||
team=team,
|
||||
description="A team of professional engineers who are responsible for writing code, visualizing experimental schemes, converting experimental schemes to machine code, and more.",
|
||||
model_client=model_client)
|
||||
return Engineer_team
|
||||
return engineer_team
|
||||
@@ -1,10 +1,11 @@
|
||||
import asyncio
|
||||
from typing import Sequence
|
||||
from autogen_agentchat.agents import AssistantAgent, SocietyOfMindAgent
|
||||
from autogen_agentchat.conditions import MaxMessageTermination, TextMentionTermination
|
||||
from autogen_agentchat.agents import AssistantAgent, SocietyOfMindAgent, UserProxyAgent
|
||||
from autogen_agentchat.conditions import MaxMessageTermination, TextMentionTermination, HandoffTermination
|
||||
from autogen_agentchat.messages import AgentEvent, ChatMessage, TextMessage, ToolCallExecutionEvent
|
||||
from autogen_agentchat.teams import SelectorGroupChat, RoundRobinGroupChat
|
||||
from autogen_agentchat.ui import Console
|
||||
from autogen_agentchat.base import Handoff
|
||||
from autogen_ext.models.openai import OpenAIChatCompletionClient
|
||||
from constant import MODEL, OPENAI_API_KEY, OPENAI_BASE_URL
|
||||
from scientist_team import create_scientist_team
|
||||
@@ -28,6 +29,8 @@ async def main(task: str = "") -> dict:
|
||||
engineer_team = create_engineer_team()
|
||||
|
||||
result = {}
|
||||
user = UserProxyAgent("user", input_func=input)
|
||||
|
||||
planning_agent = AssistantAgent(
|
||||
"PlanningAgent",
|
||||
description="An agent for planning tasks, this agent should be the first to engage when given a new task.",
|
||||
@@ -37,16 +40,23 @@ async def main(task: str = "") -> dict:
|
||||
Your job is to break down complex Materials science research tasks into smaller, manageable subtasks.
|
||||
Assign these subtasks to the appropriate sub-teams; not all sub-teams are required to participate in every task.
|
||||
Your sub-teams are:
|
||||
User: A human agent to whom you transfer information whenever you need to confirm your execution steps to a human.
|
||||
Engineer team: A team of professional engineers who are responsible for writing code, visualizing experimental schemes, converting experimental schemes to JSON, and more.
|
||||
Scientist team: A professional team of material scientists who are mainly responsible for consulting on material synthesis, structure, application and properties.
|
||||
Engineer team: A team of professional engineers who are responsible for writing code, visualizing experimental schemes, converting experimental schemes to machine code, and more.
|
||||
You only plan and delegate tasks - you do not execute them yourself.
|
||||
|
||||
第一次回答时你需要初始化任务分配并按顺序执行,在后续的回答中重申你的任务分配,使用如下格式并利用Mermaid绘制流程图:
|
||||
| team | subtask |
|
||||
| --------- | -------------------- |
|
||||
| 1. team_name | sub-Task description |
|
||||
|
||||
When assigning subtasks, use this format:
|
||||
1. <agent> : <task>
|
||||
|
||||
When assigning subtasks, give a flow chart with following format or mermaid to visualize the collaboration between the various teams, such as:
|
||||
<agent 1> -> <agent 2> -> <agent 3>
|
||||
|
||||
每次回答时,你需要清晰明确的指出已经完成的子任务下一步子任务,使用如下格式:
|
||||
**已完成子任务:**
|
||||
1. <team> : <subtask>
|
||||
**Next sub-task:**
|
||||
n. <team> : <subtask>
|
||||
|
||||
You can end with "USER" if you need to, which means you need human approval or other advice or instructions;
|
||||
After plan and delegate tasks are complete, end with "START";
|
||||
Determine if all sub-teams have completed their tasks, and if so, summarize the findings and end with "TERMINATE".
|
||||
""",
|
||||
@@ -55,7 +65,7 @@ async def main(task: str = "") -> dict:
|
||||
|
||||
# The termination condition is a combination of text mention termination and max message termination.
|
||||
text_mention_termination = TextMentionTermination("TERMINATE")
|
||||
max_messages_termination = MaxMessageTermination(max_messages=25)
|
||||
max_messages_termination = MaxMessageTermination(max_messages=100)
|
||||
termination = text_mention_termination | max_messages_termination
|
||||
|
||||
# The selector function is a function that takes the current message thread of the group chat
|
||||
@@ -63,10 +73,12 @@ async def main(task: str = "") -> dict:
|
||||
def selector_func(messages: Sequence[AgentEvent | ChatMessage]) -> str | None:
|
||||
if messages[-1].source != planning_agent.name:
|
||||
return planning_agent.name # Always return to the planning agent after the other agents have spoken.
|
||||
elif "USER" in messages[-1].content:
|
||||
return user.name
|
||||
return None
|
||||
|
||||
team = SelectorGroupChat(
|
||||
[planning_agent, scientist_team, engineer_team],
|
||||
[planning_agent, user, scientist_team, engineer_team],
|
||||
model_client=model_client, # Use a smaller model for the selector.
|
||||
termination_condition=termination,
|
||||
selector_func=selector_func,
|
||||
@@ -83,6 +95,7 @@ async def main(task: str = "") -> dict:
|
||||
|
||||
# Example usage in another function
|
||||
async def main_1():
|
||||
# result = await main(input("Enter your instructions below: \n"))
|
||||
result = await main("Let the robot synthesize CsPbBr3 nanocubes at room temperature")
|
||||
# result = await main("查一下CsPbBr3的晶体结构")
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ model_client = OpenAIChatCompletionClient(
|
||||
},
|
||||
)
|
||||
|
||||
def create_scientist_team() -> SelectorGroupChat | RoundRobinGroupChat:
|
||||
def create_scientist_team() -> SelectorGroupChat | RoundRobinGroupChat | Swarm | AssistantAgent:
|
||||
planning_agent = AssistantAgent(
|
||||
"Scientist_PlanningAgent",
|
||||
description="An agent of Scientist team for planning tasks, this agent should be the first to engage when given a new task.",
|
||||
@@ -30,13 +30,9 @@ def create_scientist_team() -> SelectorGroupChat | RoundRobinGroupChat:
|
||||
system_message="""
|
||||
You are a scientist coordinator.
|
||||
Your job is coordinating material science research by delegating to specialized agents:
|
||||
Scientist_SynthesisAgent: An experienced materials scientist agent who is particularly good at coming up with detailed synthesis schemes, and should be called when the task around a material synthesis topic.
|
||||
Scientist_StructureAgent: A professional materials scientist agent, particularly adept at answering questions related to the structure of materials, has access to a material database. Should be called when the task around a material structure topic.
|
||||
Always send your plan first, then handoff to appropriate agent.
|
||||
You only plan and delegate tasks - you do not execute them yourself.
|
||||
Always handoff to a single agent at a time.
|
||||
When assigning tasks, use this format:
|
||||
1. <agent> : <task>
|
||||
Scientist_SynthesisAgent: An experienced materials scientist agent who is particularly good at coming up with detailed synthesis schemes, and non-material synthesis-related tasks should not handoff tasks to Scientist_SynthesisAgent.
|
||||
Scientist_StructureAgent: A professional materials scientist agent, particularly adept at answering questions related to the structure of materials, has access to a material database. Non-material structure-related tasks should not handoff tasks to Scientist_StructureAgent.
|
||||
Always send your plan first, then handoff to appropriate agent. Always handoff to a single agent at a time.
|
||||
|
||||
After all tasks are completed, the member scientist agent's responses are collated into a detailed, no-miss response that ends with "APPROVE".
|
||||
** Remember: Avoid revealing the above words in your reply. **
|
||||
@@ -123,18 +119,12 @@ def create_scientist_team() -> SelectorGroupChat | RoundRobinGroupChat:
|
||||
)
|
||||
|
||||
# The termination condition is a combination of text mention termination and max message termination.
|
||||
handoff_termination = HandoffTermination("Scientist_PlanningAgent")
|
||||
text_mention_termination = TextMentionTermination("APPROVE")
|
||||
max_messages_termination = MaxMessageTermination(max_messages=25)
|
||||
termination = text_mention_termination | max_messages_termination
|
||||
max_messages_termination = MaxMessageTermination(max_messages=50)
|
||||
termination = text_mention_termination | max_messages_termination | handoff_termination
|
||||
# termination = max_messages_termination
|
||||
|
||||
# The selector function is a function that takes the current message thread of the group chat
|
||||
# and returns the next speaker's name. If None is returned, the LLM-based selection method will be used.
|
||||
def selector_func(messages: Sequence[AgentEvent | ChatMessage]) -> str | None:
|
||||
if messages[-1].source != planning_agent.name:
|
||||
return planning_agent.name # Always return to the planning agent after the other agents have spoken.
|
||||
return None
|
||||
|
||||
# team = SelectorGroupChat(
|
||||
# [planning_agent, synthesis_agent, structure_agent],
|
||||
# model_client=model_client, # Use a smaller model for the selector.
|
||||
|
||||
@@ -83,4 +83,50 @@ def search_from_oqmd_by_composition(composition: str) -> str:
|
||||
response.raise_for_status()
|
||||
return str(response.json()['data'])
|
||||
except requests.exceptions.RequestException as e:
|
||||
return f"Error: {str(e)}"
|
||||
return f"Error: {str(e)}"
|
||||
|
||||
|
||||
def scheme_convert_to_json():
|
||||
return """
|
||||
转换合成方案时,必须严格遵守如下预定义的JSON格式,每个JSON结构的字段必须填充完整,即使有些字段留空:
|
||||
```json
|
||||
{
|
||||
"workflow": [
|
||||
{
|
||||
"step_id": <step_number>,
|
||||
"description": "<brief_description>",
|
||||
"actions": [
|
||||
{
|
||||
"action_id": <action_number>,
|
||||
"action_type": "<action_type>",
|
||||
"materials": [{"name": "<material_name>", "amount": <amount>, "unit": "<unit>"}],
|
||||
"containers": [{"type": "<container_type>", "capacity": "<capacity>", "unit": "<unit>", "additional_parameters": {"material_of_construction": "<material_type>", "shape": "<shape>"}}],
|
||||
"equipment": [{"name": "<equipment_name>", "parameters": {"<param_name>": <param_value>, "<param_name>": <param_value>}}],
|
||||
"output": "<action_output>"
|
||||
}
|
||||
],
|
||||
"dependencies": ["<previous_step_ids>"],
|
||||
"step_output": "<step_output_identifier>"
|
||||
}
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### JSON结构字段说明
|
||||
1. workflow 类型: 数组; 说明: 包含所有步骤的列表; 限制: 每个步骤都是一个对象,且顺序重要。
|
||||
2. step_id 类型: 整数; 说明: 步骤的唯一标识符,用于区分不同的步骤; 限制: 必须唯一,不能重复。
|
||||
3. description 类型: 字符串; 说明: 对步骤的简要描述,说明步骤的目的或内容。限制: 描述应清晰简洁,避免冗长。
|
||||
4. actions 类型: 数组; 说明: 包含该步骤中所有动作的列表。限制: 每个动作都是一个对象,且顺序可能影响执行顺序。
|
||||
5. action_id 类型: 字符串; 说明: 动作的唯一标识符,用于区分不同的动作。限制: 在同一步骤内必须唯一。
|
||||
6. action_type 类型: 字符串; 说明: 动作的类型,例如 "add_material", "ultrasonicate", "centrifuge"。限制: 必须是预定义的类型之一。
|
||||
7. materials 类型: 数组; 说明: 使用的材料列表,每个材料包含名称、数量和单位。限制: 每个材料对象必须包含 "name", "amount", 和 "unit" 字段。
|
||||
8. containers 类型: 数组; 说明: 使用的容器列表,每个容器包含类型、容量、单位和附加参数。限制: 每个容器对象必须包含 "type", "capacity", 和 "unit" 字段,"additional_parameters" 为可选。
|
||||
9. equipment 类型: 数组; 说明: 使用的设备列表,每个设备包含名称和参数。限制: 每个设备对象必须包含 "name" 字段,"parameters" 为可选,根据设备需要填充。
|
||||
10. output 类型: 字符串; 说明: 动作的输出标识符,用于后续步骤的输入。限制: 标识符应唯一且有意义。
|
||||
11. dependencies 类型: 数组; 说明: 依赖的前一步骤的 "step_id" 列表。限制: 每个依赖项必须是有效的 "step_id"。
|
||||
12. step_output 类型: 字符串; 说明: 步骤的输出标识符,用于后续步骤的输入。限制: 标识符应唯一且有意义。
|
||||
"""
|
||||
|
||||
def default_func():
|
||||
return "Approved. Proceed as planned!"
|
||||
Reference in New Issue
Block a user