Synchronize Instances from AgentScope (#29)

This commit is contained in:
Lamont Huffman
2025-11-07 10:00:43 +08:00
committed by GitHub
parent 30d86efbb3
commit 1558fb86f9
9 changed files with 69 additions and 73 deletions

View File

@@ -21,8 +21,7 @@ from agentscope.token import TokenCounterBase, OpenAITokenCounter
_BROWSER_AGENT_DEFAULT_SYS_PROMPT = ( _BROWSER_AGENT_DEFAULT_SYS_PROMPT = (
"You are a helpful browser automation assistant. " "You are a helpful browser automation assistant. "
"You can navigate websites, take screenshots, and interact with web pages." "You can navigate websites, take screenshots, and interact with web pages."
"Always describe what you see and meta_planner_agent" "Always describe what you see and plan your next steps clearly. "
" your next steps clearly. "
"When taking actions, explain what you're doing and why." "When taking actions, explain what you're doing and why."
) )
_BROWSER_AGENT_REASONING_PROMPT = ( _BROWSER_AGENT_REASONING_PROMPT = (
@@ -30,7 +29,7 @@ _BROWSER_AGENT_REASONING_PROMPT = (
"The snapshot (and screenshot) of the current webpage is (are) given " "The snapshot (and screenshot) of the current webpage is (are) given "
"below. Since you can only view the latest webpage, " "below. Since you can only view the latest webpage, "
"you must promptly summarize current status, record required data, " "you must promptly summarize current status, record required data, "
"and meta_planner_agent your next steps." "and plan your next steps."
) )

View File

@@ -3,12 +3,12 @@
import asyncio import asyncio
import os import os
from agentscope.agent import UserAgent
from agentscope.formatter import DashScopeChatFormatter from agentscope.formatter import DashScopeChatFormatter
from agentscope.mcp import StdIOStatefulClient
from agentscope.memory import InMemoryMemory from agentscope.memory import InMemoryMemory
from agentscope.model import DashScopeChatModel from agentscope.model import DashScopeChatModel
from agentscope.tool import Toolkit from agentscope.tool import Toolkit
from agentscope.mcp import StdIOStatefulClient
from agentscope.agent import UserAgent
from browser_agent import BrowserAgent # pylint: disable=C0411 from browser_agent import BrowserAgent # pylint: disable=C0411
@@ -69,7 +69,7 @@ if __name__ == "__main__":
print( print(
"The browser agent will use " "The browser agent will use "
"playwright-mcp (https://github.com/microsoft/playwright-mcp)." "playwright-mcp (https://github.com/microsoft/playwright-mcp)."
"Make sure the MCP server can be installed " "Make sure the MCP server is can be install "
"by `npx @playwright/mcp@latest`", "by `npx @playwright/mcp@latest`",
) )

View File

@@ -20,7 +20,7 @@ class SubtasksDecomposition(BaseModel):
working_plan: str = Field( working_plan: str = Field(
description=( description=(
"A logically ordered step-by-step working " "A logically ordered step-by-step working "
"meta_planner_agent (3-5 steps), each step starting with " "plan (3-5 steps), each step starting with "
"its number (1., 2., etc), including both " "its number (1., 2., etc), including both "
"core and expansion steps. Expanded steps " "core and expansion steps. Expanded steps "
"should be clearly marked with (EXPANSION) " "should be clearly marked with (EXPANSION) "
@@ -85,7 +85,7 @@ class ReflectFailure(BaseModel):
"subtask needs to be rephrased due " "subtask needs to be rephrased due "
"to a design flaw or misunderstanding. " "to a design flaw or misunderstanding. "
"If rephrasing is needed, provide the " "If rephrasing is needed, provide the "
"modified working meta_planner_agent with only the " "modified working plan with only the "
"inappropriate subtask replaced by its " "inappropriate subtask replaced by its "
"improved version." "improved version."
), ),
@@ -95,14 +95,14 @@ class ReflectFailure(BaseModel):
"properties": { "properties": {
"need_rephrase": { "need_rephrase": {
"type": "boolean", "type": "boolean",
"description": "Set to 'true' if the failed" "description": "Set to 'true' if the failed subtask "
" subtask needs to be rephrased due to a design " "needs to be rephrased due to a design "
"flaw or misunderstanding; otherwise, 'false'.", "flaw or misunderstanding; otherwise, 'false'.",
}, },
"rephrased_plan": { "rephrased_plan": {
"type": "string", "type": "string",
"description": "The modified working " "description": "The modified working plan "
"meta_planner_agent with only the inappropriate " "with only the inappropriate "
"subtask replaced by its improved version. If no " "subtask replaced by its improved version. If no "
"rephrasing is needed, provide an empty string.", "rephrasing is needed, provide an empty string.",
}, },

View File

@@ -8,9 +8,7 @@ import asyncio
from typing import Type, Optional, Any, Tuple from typing import Type, Optional, Any, Tuple
from datetime import datetime from datetime import datetime
from copy import deepcopy from copy import deepcopy
import shortuuid import shortuuid
from pydantic import BaseModel from pydantic import BaseModel
from built_in_prompt.promptmodule import ( from built_in_prompt.promptmodule import (
@@ -25,6 +23,7 @@ from utils import (
get_dynamic_tool_call_json, get_dynamic_tool_call_json,
get_structure_output, get_structure_output,
) )
from agentscope import logger, setup_logger from agentscope import logger, setup_logger
from agentscope.mcp import StatefulClientBase from agentscope.mcp import StatefulClientBase
from agentscope.agent import ReActAgent from agentscope.agent import ReActAgent
@@ -43,6 +42,7 @@ from agentscope.message import (
ToolResultBlock, ToolResultBlock,
) )
_DEEP_RESEARCH_AGENT_DEFAULT_SYS_PROMPT = "You're a helpful assistant." _DEEP_RESEARCH_AGENT_DEFAULT_SYS_PROMPT = "You're a helpful assistant."
_LOG_DIR = os.path.join(os.path.dirname(__file__), "log") _LOG_DIR = os.path.join(os.path.dirname(__file__), "log")
@@ -196,7 +196,7 @@ class DeepResearchAgent(ReActAgent):
SubTaskItem(objective=self.user_query), SubTaskItem(objective=self.user_query),
) )
# Identify the expected output and generate a meta_planner_agent # Identify the expected output and generate a plan
await self.decompose_and_expand_subtask() await self.decompose_and_expand_subtask()
msg.content += ( msg.content += (
f"\nExpected Output:\n{self.current_subtask[0].knowledge_gaps}" f"\nExpected Output:\n{self.current_subtask[0].knowledge_gaps}"
@@ -214,7 +214,7 @@ class DeepResearchAgent(ReActAgent):
) )
for _ in range(self.max_iters): for _ in range(self.max_iters):
# Generate the working meta_planner_agent first # Generate the working plan first
if not self.current_subtask[-1].working_plan: if not self.current_subtask[-1].working_plan:
await self.decompose_and_expand_subtask() await self.decompose_and_expand_subtask()
@@ -497,23 +497,20 @@ class DeepResearchAgent(ReActAgent):
async def decompose_and_expand_subtask(self) -> ToolResponse: async def decompose_and_expand_subtask(self) -> ToolResponse:
"""Identify the knowledge gaps of the current subtask and generate a """Identify the knowledge gaps of the current subtask and generate a
working meta_planner_agent by subtask decomposition. working plan by subtask decomposition. The working plan includes
The working meta_planner_agent includes
necessary steps for task completion and expanded steps. necessary steps for task completion and expanded steps.
Returns: Returns:
ToolResponse: ToolResponse:
The knowledge gaps and working meta_planner_agent The knowledge gaps and working plan of the current subtask
of the current subtask in JSON format. in JSON format.
""" """
if len(self.current_subtask) <= self.max_depth: if len(self.current_subtask) <= self.max_depth:
decompose_sys_prompt = self.prompt_dict["decompose_sys_prompt"] decompose_sys_prompt = self.prompt_dict["decompose_sys_prompt"]
previous_plan = "" previous_plan = ""
for i, subtask in enumerate(self.current_subtask): for i, subtask in enumerate(self.current_subtask):
previous_plan += ( previous_plan += f"The {i}-th plan: {subtask.working_plan}\n"
f"The {i}-th meta_planner_agent: {subtask.working_plan}\n"
)
previous_plan_inst = self.prompt_dict[ previous_plan_inst = self.prompt_dict[
"previous_plan_inst" "previous_plan_inst"
].format_map( ].format_map(
@@ -716,7 +713,7 @@ class DeepResearchAgent(ReActAgent):
async def summarize_intermediate_results(self) -> ToolResponse: async def summarize_intermediate_results(self) -> ToolResponse:
"""Summarize the intermediate results into a report when a step """Summarize the intermediate results into a report when a step
in working meta_planner_agent is completed. in working plan is completed.
Returns: Returns:
ToolResponse: ToolResponse:
@@ -740,9 +737,7 @@ class DeepResearchAgent(ReActAgent):
"user", "user",
self.prompt_dict["summarize_hint"].format_map( self.prompt_dict["summarize_hint"].format_map(
{ {
"meta_planner_agent": self.current_subtask[ "plan": self.current_subtask[-1].working_plan,
-1
].working_plan,
}, },
), ),
role="user", role="user",
@@ -953,12 +948,11 @@ class DeepResearchAgent(ReActAgent):
async def reflect_failure(self) -> ToolResponse: async def reflect_failure(self) -> ToolResponse:
"""Reflect on the failure of the action and determine to rephrase """Reflect on the failure of the action and determine to rephrase
the meta_planner_agent or deeper decompose the current step. the plan or deeper decompose the current step.
Returns: Returns:
ToolResponse: ToolResponse:
The reflection about meta_planner_agent The reflection about plan rephrasing and subtask decomposition.
rephrasing and subtask decomposition.
""" """
reflect_sys_prompt = self.prompt_dict["reflect_sys_prompt"] reflect_sys_prompt = self.prompt_dict["reflect_sys_prompt"]
conversation_history = "" conversation_history = ""
@@ -974,7 +968,7 @@ class DeepResearchAgent(ReActAgent):
reflect_inst = self.prompt_dict["reflect_instruction"].format_map( reflect_inst = self.prompt_dict["reflect_instruction"].format_map(
{ {
"conversation_history": conversation_history, "conversation_history": conversation_history,
"meta_planner_agent": self.current_subtask[-1].working_plan, "plan": self.current_subtask[-1].working_plan,
}, },
) )
try: try:

View File

@@ -3,14 +3,14 @@
import asyncio import asyncio
import os import os
from deep_research_agent import DeepResearchAgent
from agentscope import logger from agentscope import logger
from agentscope.formatter import DashScopeChatFormatter from agentscope.formatter import DashScopeChatFormatter
from agentscope.mcp import StdIOStatefulClient
from agentscope.memory import InMemoryMemory from agentscope.memory import InMemoryMemory
from agentscope.message import Msg
from agentscope.model import DashScopeChatModel from agentscope.model import DashScopeChatModel
from agentscope.message import Msg
from deep_research_agent import DeepResearchAgent from agentscope.mcp import StdIOStatefulClient
async def main(user_query: str) -> None: async def main(user_query: str) -> None:

View File

@@ -8,6 +8,7 @@ from pydantic import BaseModel
from agentscope.tool import Toolkit, ToolResponse from agentscope.tool import Toolkit, ToolResponse
TOOL_RESULTS_MAX_WORDS = 5000 TOOL_RESULTS_MAX_WORDS = 5000
@@ -219,7 +220,7 @@ def load_prompt_dict() -> dict:
prompt_dict["reasoning_prompt"] = ( prompt_dict["reasoning_prompt"] = (
"## Current Subtask:\n{objective}\n" "## Current Subtask:\n{objective}\n"
"## Working Plan:\n{meta_planner_agent}\n" "## Working Plan:\n{plan}\n"
"{knowledge_gap}\n" "{knowledge_gap}\n"
"## Research Depth:\n{depth}" "## Research Depth:\n{depth}"
) )
@@ -281,17 +282,14 @@ def load_prompt_dict() -> dict:
prompt_dict["summarize_hint"] = ( prompt_dict["summarize_hint"] = (
"Based on your work history above, examine which step in the " "Based on your work history above, examine which step in the "
"following working meta_planner_agent has been " "following working plan has been completed. Mark the completed "
"completed. Mark the completed "
"step with [DONE] at the end of its line (e.g., k. step k [DONE]) " "step with [DONE] at the end of its line (e.g., k. step k [DONE]) "
"and leave the uncompleted steps unchanged. You MUST return only " "and leave the uncompleted steps unchanged. You MUST return only "
"the updated meta_planner_agent, preserving exactly " "the updated plan, preserving exactly the same format as the "
"the same format as the " "original plan. Do not include any explanations, reasoning, "
"original meta_planner_agent. Do not include any "
"explanations, reasoning, "
"or section headers such as '## Working Plan:', just output the" "or section headers such as '## Working Plan:', just output the"
"updated meta_planner_agent itself." "updated plan itself."
"\n\n## Working Plan:\n{meta_planner_agent}" "\n\n## Working Plan:\n{plan}"
) )
prompt_dict["summarize_inst"] = ( prompt_dict["summarize_inst"] = (
@@ -307,19 +305,17 @@ def load_prompt_dict() -> dict:
"following report that consolidates and summarizes the essential " "following report that consolidates and summarizes the essential "
"findings:\n {intermediate_report}\n\n" "findings:\n {intermediate_report}\n\n"
"Such report has been saved to the {report_path}. " "Such report has been saved to the {report_path}. "
"I will now **proceed to the next item** " "I will now **proceed to the next item** in the working plan."
"in the working meta_planner_agent."
) )
prompt_dict["save_report_hint"] = ( prompt_dict["save_report_hint"] = (
"The milestone results of the current " "The milestone results of the current item in working plan "
"item in working meta_planner_agent "
"are summarized into the following report:\n{intermediate_report}" "are summarized into the following report:\n{intermediate_report}"
) )
prompt_dict["reflect_instruction"] = ( prompt_dict["reflect_instruction"] = (
"## Work History:\n{conversation_history}\n" "## Work History:\n{conversation_history}\n"
"## Working Plan:\n{meta_planner_agent}\n" "## Working Plan:\n{plan}\n"
) )
prompt_dict["subtask_complete_hint"] = ( prompt_dict["subtask_complete_hint"] = (

View File

@@ -2,31 +2,37 @@
# pylint: disable=too-many-branches, too-many-statements, no-name-in-module # pylint: disable=too-many-branches, too-many-statements, no-name-in-module
"""A werewolf game implemented by agentscope.""" """A werewolf game implemented by agentscope."""
import numpy as np import numpy as np
from agentscope.agent import ReActAgent
from agentscope.pipeline import MsgHub, fanout_pipeline, sequential_pipeline
from prompt import EnglishPrompts as Prompts
from utils import ( from utils import (
MAX_DISCUSSION_ROUND,
MAX_GAME_ROUND,
EchoAgent,
Players,
majority_vote, majority_vote,
names_to_str, names_to_str,
EchoAgent,
MAX_GAME_ROUND,
MAX_DISCUSSION_ROUND,
Players,
) )
from structured_model import ( from structured_model import (
DiscussionModel, DiscussionModel,
WitchResurrectModel,
get_hunter_model,
get_poison_model,
get_seer_model,
get_vote_model, get_vote_model,
get_poison_model,
WitchResurrectModel,
get_seer_model,
get_hunter_model,
) )
from prompt import EnglishPrompts as Prompts
# Uncomment the following line to use Chinese prompts # Uncomment the following line to use Chinese prompts
# from prompt import ChinesePrompts as Prompts # from prompt import ChinesePrompts as Prompts
from agentscope.agent import ReActAgent
from agentscope.pipeline import (
MsgHub,
sequential_pipeline,
fanout_pipeline,
)
moderator = EchoAgent() moderator = EchoAgent()
@@ -113,7 +119,7 @@ async def werewolves_game(agents: list[ReActAgent]) -> None:
names_to_str(players.current_alive), names_to_str(players.current_alive),
), ),
), ),
name="game_werewolves", name="werewolves",
) as werewolves_hub: ) as werewolves_hub:
# Discussion # Discussion
n_werewolves = len(players.werewolves) n_werewolves = len(players.werewolves)

View File

@@ -4,15 +4,16 @@
import asyncio import asyncio
import os import os
from game import werewolves_game
from agentscope.agent import ReActAgent from agentscope.agent import ReActAgent
from agentscope.formatter import DashScopeMultiAgentFormatter from agentscope.formatter import DashScopeMultiAgentFormatter
from agentscope.model import DashScopeChatModel from agentscope.model import DashScopeChatModel
from agentscope.session import JSONSession from agentscope.session import JSONSession
from game import werewolves_game
def get_official_agents(name: str) -> ReActAgent: def get_official_agents(name: str) -> ReActAgent:
"""Get the official game_werewolves game agents.""" """Get the official werewolves game agents."""
agent = ReActAgent( agent = ReActAgent(
name=name, name=name,
sys_prompt=f"""You're a werewolf game player named {name}. sys_prompt=f"""You're a werewolf game player named {name}.
@@ -21,9 +22,9 @@ def get_official_agents(name: str) -> ReActAgent:
Your target is to win the game with your teammates as much as possible. Your target is to win the game with your teammates as much as possible.
# GAME RULES # GAME RULES
- In werewolf game, players are divided into three game_werewolves, three villagers, one seer, one hunter and one witch. - In werewolf game, players are divided into three werewolves, three villagers, one seer, one hunter and one witch.
- Werewolves: kill one player each night, and must hide identity during the day. - Werewolves: kill one player each night, and must hide identity during the day.
- Villagers: ordinary players without special abilities, try to identify and eliminate game_werewolves. - Villagers: ordinary players without special abilities, try to identify and eliminate werewolves.
- Seer: A special villager who can check one player's identity each night. - Seer: A special villager who can check one player's identity each night.
- Witch: A special villager with two one-time-use potions: a healing potion to save a player from being killed at night, and a poison to eliminate one player at night. - Witch: A special villager with two one-time-use potions: a healing potion to save a player from being killed at night, and a poison to eliminate one player at night.
- Hunter: A special villager who can take one player down with them when they are eliminated. - Hunter: A special villager who can take one player down with them when they are eliminated.
@@ -39,18 +40,18 @@ Your target is to win the game with your teammates as much as possible.
# GAME GUIDANCE # GAME GUIDANCE
- Try your best to win the game with your teammates, tricks, lies, and deception are all allowed, e.g. pretending to be a different role. - Try your best to win the game with your teammates, tricks, lies, and deception are all allowed, e.g. pretending to be a different role.
- During discussion, don't be political, be direct and to the point. - During discussion, don't be political, be direct and to the point.
- The day phase voting provides important clues. For example, the game_werewolves may vote together, attack the seer, etc. - The day phase voting provides important clues. For example, the werewolves may vote together, attack the seer, etc.
## GAME GUIDANCE FOR WEREWOLF ## GAME GUIDANCE FOR WEREWOLF
- Seer is your greatest threat, who can check one player's identity each night. Analyze players' speeches, find out the seer and eliminate him/her will greatly increase your chances of winning. - Seer is your greatest threat, who can check one player's identity each night. Analyze players' speeches, find out the seer and eliminate him/her will greatly increase your chances of winning.
- In the first night, making random choices is common for game_werewolves since no information is available. - In the first night, making random choices is common for werewolves since no information is available.
- Pretending to be other roles (seer, witch or villager) is a common strategy to hide your identity and mislead other villagers in the day phase. - Pretending to be other roles (seer, witch or villager) is a common strategy to hide your identity and mislead other villagers in the day phase.
- The outcome of the night phase provides important clues. For example, if witch uses the healing or poison potion, if the dead player is hunter, etc. Use this information to adjust your strategy. - The outcome of the night phase provides important clues. For example, if witch uses the healing or poison potion, if the dead player is hunter, etc. Use this information to adjust your strategy.
## GAME GUIDANCE FOR SEER ## GAME GUIDANCE FOR SEER
- Seer is very important to villagers, exposing yourself too early may lead to being targeted by game_werewolves. - Seer is very important to villagers, exposing yourself too early may lead to being targeted by werewolves.
- Your ability to check one player's identity is crucial. - Your ability to check one player's identity is crucial.
- The outcome of the night phase provides important clues. For example, if witch uses the healing or poison potion, if the dead player is hunter, etc. Use this information to adjust your strategy. - The outcome of the night phase provides important clues. For example, if witch uses the healing or poison potion, if the dead player is hunter, etc. Use this information to adjust your strategy.
## GAME GUIDANCE FOR WITCH ## GAME GUIDANCE FOR WITCH
- Witch has two powerful potions, use them wisely to protect key villagers or eliminate suspected game_werewolves. - Witch has two powerful potions, use them wisely to protect key villagers or eliminate suspected werewolves.
- The outcome of the night phase provides important clues. For example, if the dead player is hunter, etc. Use this information to adjust your strategy. - The outcome of the night phase provides important clues. For example, if the dead player is hunter, etc. Use this information to adjust your strategy.
## GAME GUIDANCE FOR HUNTER ## GAME GUIDANCE FOR HUNTER
- Using your ability in day phase will expose your role (since only hunter can take one player down) - Using your ability in day phase will expose your role (since only hunter can take one player down)

View File

@@ -108,13 +108,13 @@ class EnglishPrompts:
to_all_wolf_win = ( to_all_wolf_win = (
"There are {n_alive} players alive, and {n_werewolves} of them are " "There are {n_alive} players alive, and {n_werewolves} of them are "
"game_werewolves. " "werewolves. "
"The game is over and game_werewolves win🐺🎉!" "The game is over and werewolves win🐺🎉!"
"In this game, the true roles of all players are: {true_roles}" "In this game, the true roles of all players are: {true_roles}"
) )
to_all_village_win = ( to_all_village_win = (
"All the game_werewolves have been eliminated." "All the werewolves have been eliminated."
"The game is over and villagers win🏘🎉!" "The game is over and villagers win🏘🎉!"
"In this game, the true roles of all players are: {true_roles}" "In this game, the true roles of all players are: {true_roles}"
) )