Skip to content

Commit

Permalink
Refactor the AgentScope Studio and open source AgentScope Workstation (
Browse files Browse the repository at this point in the history
…#238)

---------

Co-authored-by: DavdGao <[email protected]>
Co-authored-by: rayrayraykk <[email protected]>
Co-authored-by: qbc <[email protected]>
Co-authored-by: zhijianma <[email protected]>
  • Loading branch information
5 people authored Jun 9, 2024
1 parent 62bb5d8 commit 3560d8e
Show file tree
Hide file tree
Showing 130 changed files with 19,253 additions and 15,883 deletions.
4 changes: 3 additions & 1 deletion examples/distributed_debate/distributed_debate.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@

from user_proxy_agent import UserProxyAgent

from loguru import logger

import agentscope
from agentscope.agents import DialogAgent
from agentscope.msghub import msghub
from agentscope.server import RpcAgentServerLauncher
from agentscope.message import Msg
from agentscope.utils.logging_utils import logger


FIRST_ROUND = """
Welcome to the debate on whether Artificial General Intelligence (AGI) can be achieved using the GPT model framework. This debate will consist of three rounds. In each round, the affirmative side will present their argument first, followed by the negative side. After both sides have presented, the adjudicator will summarize the key points and analyze the strengths of the arguments.
Expand Down
9 changes: 8 additions & 1 deletion examples/distributed_search/searcher_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ def reply(self, x: dict = None) -> dict:
),
)
query = self.model(prompt).text
self.speak(query)
results = self.search(
question=query,
num_results=self.result_num,
Expand All @@ -85,4 +84,12 @@ def reply(self, x: dict = None) -> dict:
for result in results
],
)
self.speak(
Msg(
name=self.name,
role="assistant",
content="Search results:\n"
f"{[result['link'] for result in results]}",
),
)
return msg
8 changes: 7 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
"black",
]

studio_requires = []

# released requires
minimal_requires = [
"docstring_parser",
Expand All @@ -66,6 +68,7 @@
"Flask==3.0.0",
"Flask-Cors==4.0.0",
"Flask-SocketIO==5.3.6",
"flask_sqlalchemy",
"flake8",
# TODO: move into other requires
"dashscope==1.14.1",
Expand All @@ -74,6 +77,7 @@
"google-generativeai>=0.4.0",
"zhipuai",
"litellm",
"psutil",
]

distribute_requires = minimal_requires + rpc_requires
Expand All @@ -87,6 +91,7 @@
+ doc_requires
+ test_requires
+ gradio_requires
+ studio_requires
)

with open("README.md", "r", encoding="UTF-8") as fh:
Expand Down Expand Up @@ -123,7 +128,8 @@
python_requires=">=3.9",
entry_points={
"console_scripts": [
"as_studio=agentscope.web.studio.studio:run_app",
"as_studio=agentscope.studio:init",
"as_gradio=agentscope.web.gradio.studio:run_app",
"as_workflow=agentscope.web.workstation.workflow:main",
"as_server=agentscope.server.launcher:as_server",
],
Expand Down
30 changes: 27 additions & 3 deletions src/agentscope/_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
from .agents import AgentBase
from ._runtime import _runtime
from .file_manager import file_manager
from .utils.logging_utils import LOG_LEVEL, setup_logger
from .logging import LOG_LEVEL, setup_logger
from .utils.monitor import MonitorFactory
from .models import read_model_configs
from .constants import _DEFAULT_DIR
from .constants import _DEFAULT_LOG_LEVEL
from .studio._client import _studio_client

# init setting
_INIT_SETTINGS = {}
Expand All @@ -30,6 +31,7 @@ def init(
logger_level: LOG_LEVEL = _DEFAULT_LOG_LEVEL,
runtime_id: Optional[str] = None,
agent_configs: Optional[Union[str, list, dict]] = None,
studio_url: Optional[str] = None,
) -> Sequence[AgentBase]:
"""A unified entry to initialize the package, including model configs,
runtime names, saving directories and logging settings.
Expand Down Expand Up @@ -65,6 +67,8 @@ def init(
which can be loaded by json.loads(). One agent config should
cover the required arguments to initialize a specific agent
object, otherwise the default values will be used.
studio_url (`Optional[str]`, defaults to `None`):
The url of the agentscope studio.
"""
init_process(
model_configs=model_configs,
Expand All @@ -76,17 +80,19 @@ def init(
save_log=save_log,
use_monitor=use_monitor,
logger_level=logger_level,
studio_url=studio_url,
)

# save init settings for subprocess
_INIT_SETTINGS["model_configs"] = model_configs
_INIT_SETTINGS["project"] = project
_INIT_SETTINGS["name"] = name
_INIT_SETTINGS["project"] = _runtime.project
_INIT_SETTINGS["name"] = _runtime.name
_INIT_SETTINGS["runtime_id"] = _runtime.runtime_id
_INIT_SETTINGS["save_dir"] = save_dir
_INIT_SETTINGS["save_api_invoke"] = save_api_invoke
_INIT_SETTINGS["save_log"] = save_log
_INIT_SETTINGS["logger_level"] = logger_level
_INIT_SETTINGS["use_monitor"] = use_monitor

# Save code if needed
if save_code:
Expand Down Expand Up @@ -128,6 +134,7 @@ def init_process(
save_log: bool = False,
use_monitor: bool = True,
logger_level: LOG_LEVEL = _DEFAULT_LOG_LEVEL,
studio_url: Optional[str] = None,
) -> None:
"""An entry to initialize the package in a process.
Expand All @@ -153,12 +160,16 @@ def init_process(
Whether to activate the monitor.
logger_level (`LOG_LEVEL`, defaults to `"INFO"`):
The logging level of logger.
studio_url (`Optional[str]`, defaults to `None`):
The url of the agentscope studio.
"""
# Init the runtime
if project is not None:
_runtime.project = project

if name is not None:
_runtime.name = name

if runtime_id is not None:
_runtime.runtime_id = runtime_id

Expand All @@ -178,3 +189,16 @@ def init_process(
db_path=file_manager.path_db,
impl_type="sqlite" if use_monitor else "dummy",
)

# Init studio client, which will push messages to web ui and fetch user
# inputs from web ui
if studio_url is not None:
_studio_client.initialize(_runtime.runtime_id, studio_url)
# Register in AgentScope Studio
_studio_client.register_running_instance(
project=_runtime.project,
name=_runtime.name,
timestamp=_runtime.timestamp,
run_dir=file_manager.dir_root,
pid=os.getpid(),
)
22 changes: 18 additions & 4 deletions src/agentscope/_runtime.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# -*- coding: utf-8 -*-
"""Manage the id for each runtime"""
import os
from datetime import datetime
from typing import Any

from agentscope.utils.tools import _get_timestamp
from agentscope.utils.tools import _get_process_creation_time
from agentscope.utils.tools import _generate_random_code

_RUNTIME_ID_FORMAT = "run_%Y%m%d-%H%M%S_{}"
Expand All @@ -14,17 +16,20 @@ class _Runtime:
"""A singleton class used to record the runtime information, which will
be initialized when the package is imported."""

project: str = None
project: str
"""The project name, which is used to identify the project."""

name: str = None
name: str
"""The name for runtime, which is used to identify this runtime."""

runtime_id: str = None
runtime_id: str
"""The id for runtime, which is used to identify the this runtime and
name the saving directory."""

_timestamp: datetime = datetime.now()
pid: int
"""The process id of the runtime."""

_timestamp: datetime
"""The timestamp of when the runtime is initialized."""

_instance = None
Expand All @@ -48,13 +53,22 @@ def __init__(self) -> None:
self.project = _generate_random_code()
self.name = _generate_random_code(uppercase=False)

self.pid = os.getpid()
self._timestamp = _get_process_creation_time()

# Obtain time from timestamp in string format, and then turn it into
# runtime ID format
self.runtime_id = _get_timestamp(
_RUNTIME_ID_FORMAT,
self._timestamp,
).format(self.name)

def generate_new_runtime_id(self) -> str:
"""Generate a new random runtime id."""
return _get_timestamp(_RUNTIME_ID_FORMAT).format(
_generate_random_code(uppercase=False),
)

@property
def timestamp(self) -> str:
"""Get the current timestamp in specific format."""
Expand Down
30 changes: 27 additions & 3 deletions src/agentscope/agents/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from loguru import logger

from agentscope.agents.operator import Operator
from agentscope.message import Msg
from agentscope.models import load_model_by_config_name
from agentscope.memory import TemporaryMemory

Expand Down Expand Up @@ -301,10 +302,33 @@ def __call__(self, *args: Any, **kwargs: Any) -> dict:

def speak(
self,
content: Union[str, dict],
content: Union[str, Msg],
) -> None:
"""Speak out the content generated by the agent."""
logger.chat(content)
"""
Speak out the message generated by the agent. If a string is given,
a Msg object will be created with the string as the content.
Args:
content (`Union[str, Msg]`):
The content of the message to be spoken out. If a string is
given, a Msg object will be created with the agent's name, role
as "assistant", and the given string as the content.
"""
if isinstance(content, str):
msg = Msg(
name=self.name,
content=content,
role="assistant",
)
elif isinstance(content, Msg):
msg = content
else:
raise TypeError(
"From version 0.0.5, the speak method only accepts str or Msg "
f"object, got {type(content)} instead.",
)

logger.chat(msg)

def observe(self, x: Union[dict, Sequence[dict]]) -> None:
"""Observe the input, store it in memory without response to it.
Expand Down
5 changes: 5 additions & 0 deletions src/agentscope/agents/rpc_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
)
from agentscope.rpc import RpcAgentClient
from agentscope.server.launcher import RpcAgentServerLauncher
from agentscope.studio._client import _studio_client


class RpcAgent(AgentBase):
Expand Down Expand Up @@ -70,13 +71,17 @@ def __init__(
launch_server = port is None
if launch_server:
self.host = "localhost"
studio_url = None
if _studio_client.active:
studio_url = _studio_client.studio_url
self.server_launcher = RpcAgentServerLauncher(
host=self.host,
port=port,
max_pool_size=max_pool_size,
max_timeout_seconds=max_timeout_seconds,
local_mode=local_mode,
custom_agents=[agent_class],
studio_url=studio_url,
)
if not lazy_launch:
self._launch_server()
Expand Down
Loading

0 comments on commit 3560d8e

Please sign in to comment.