Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor monitor #13

Merged
merged 26 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 17 additions & 14 deletions .github/workflows/sphinx_docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,36 @@ on:

jobs:
pages:
runs-on: ubuntu-latest
timeout-minutes: 20
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
python-version: ['3.9']
env:
OS: ${{ matrix.os }}
PYTHON: '3.9'
steps:
- name: Checkout repository
uses: actions/checkout@master
- uses: actions/checkout@master
- name: Setup Python ${{ matrix.python-version }}
uses: actions/setup-python@master
with:
python_version: ${{ matrix.python-version }}
- id: deployment
python-version: ${{ matrix.python-version }}
- name: Install Dependencies
run: |
pip install -q -e .[full]
- id: build
name: Build Documentation
uses: sphinx-notes/pages@v3
with:
documentation_path: ./docs/sphinx_doc/source
python_version: ${{ matrix.python-version }}
publish: false
requirements_path: ./docs/sphinx_doc/requirements.txt
run: |
cd docs/sphinx_doc
make clean html
- name: Upload Documentation
uses: actions/upload-artifact@v3
with:
name: SphinxDoc
path: ${{ steps.deployment.outputs.artifact }}
path: 'docs/sphinx_doc/build'
- uses: peaceiris/actions-gh-pages@v3
if: github.event_name == 'push' && github_ref == 'refs/heads/main'
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ${{ steps.deployment.outputs.artifact }}
publish_dir: 'docs/sphinx_doc/build/html'
40 changes: 40 additions & 0 deletions docs/sphinx_doc/source/agentscope.agents.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Agents package
==========================

operator module
-------------------------------

.. automodule:: agentscope.agents.operator
:members:
:undoc-members:
:show-inheritance:

agent module
-------------------------------

Expand All @@ -13,6 +21,38 @@ rpc_agent module
-------------------------------

.. automodule:: agentscope.agents.rpc_agent
:members:
:undoc-members:
:show-inheritance:

user_agent module
-------------------------------

.. automodule:: agentscope.agents.user_agent
:members:
:undoc-members:
:show-inheritance:

dialog_agent module
-------------------------------

.. automodule:: agentscope.agents.dialog_agent
:members:
:undoc-members:
:show-inheritance:

dict_dialog_agent module
-------------------------------

.. automodule:: agentscope.agents.dict_dialog_agent
:members:
:undoc-members:
:show-inheritance:

rpc_dialog_agent module
-------------------------------

.. automodule:: agentscope.agents.dict_dialog_agent
:members:
:undoc-members:
:show-inheritance:
9 changes: 7 additions & 2 deletions src/agentscope/_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@
from ._runtime import Runtime
from .file_manager import file_manager
from .utils.logging_utils 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


_DEFAULT_DIR = "./runs"
_DEFAULT_LOG_LEVEL = "INFO"
_INIT_SETTINGS = {}


Expand Down Expand Up @@ -85,6 +87,9 @@ def init(
dir_log = str(file_manager.dir_log) if save_log else None
setup_logger(dir_log, logger_level)

# Set monitor
_ = MonitorFactory.get_monitor(db_path=file_manager.path_db)

# Load config and init agent by configs
if agent_configs is not None:
if isinstance(agent_configs, str):
Expand Down
7 changes: 7 additions & 0 deletions src/agentscope/configs/model_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import Any
from ..constants import _DEFAULT_MAX_RETRIES
from ..constants import _DEFAULT_MESSAGES_KEY
from ..constants import _DEFAULT_API_BUDGET


class CfgBase(dict):
Expand Down Expand Up @@ -57,6 +58,9 @@ class OpenAICfg(CfgBase):
"""The arguments used in openai api generation, e.g. `temperature`,
`seed`."""

budget: float = _DEFAULT_API_BUDGET
"""The total budget using this model. Set to `None` means no limit."""


class PostApiCfg(CfgBase):
"""The config for Post API. The final request post will be
Expand Down Expand Up @@ -113,3 +117,6 @@ class PostApiCfg(CfgBase):
"""The key of the prompt messages in `requests.post()`,
e.g. `request.post(json={${messages_key}: messages, **json_args})`. For
huggingface and modelscope inference API, the key is `inputs`"""

budget: float = _DEFAULT_API_BUDGET
pan-x-c marked this conversation as resolved.
Show resolved Hide resolved
"""The total budget using this model. Set to `None` means no limit."""
4 changes: 4 additions & 0 deletions src/agentscope/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@
_DEFAULT_SUBDIR_FILE = "file"
_DEFAULT_SUBDIR_INVOKE = "invoke"
_DEFAULT_IMAGE_NAME = "image_{}_{}.png"
_DEFAULT_SQLITE_DB_PATH = "agentscope.db"
# for model wrapper
_DEFAULT_MAX_RETRIES = 3
_DEFAULT_MESSAGES_KEY = "inputs"
_DEFAULT_RETRY_INTERVAL = 1
_DEFAULT_API_BUDGET = None
# for execute python
_DEFAULT_PYPI_MIRROR = "http://mirrors.aliyun.com/pypi/simple/"
_DEFAULT_TRUSTED_HOST = "mirrors.aliyun.com"
# for monitor
_DEFAULT_MONITOR_TABLE_NAME = "monitor_metrics"
# for summarization
_DEFAULT_SUMMARIZATION_PROMPT = """
TEXT: {}
Expand Down
15 changes: 13 additions & 2 deletions src/agentscope/file_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
_DEFAULT_SUBDIR_CODE,
_DEFAULT_SUBDIR_FILE,
_DEFAULT_SUBDIR_INVOKE,
_DEFAULT_SQLITE_DB_PATH,
_DEFAULT_IMAGE_NAME,
)

Expand Down Expand Up @@ -48,6 +49,10 @@ def _get_and_create_subdir(self, subdir: str) -> str:
os.makedirs(path)
return path

def _get_file_path(self, file_name: str) -> str:
"""Get the path of the file."""
return os.path.join(self.dir, Runtime.runtime_id, file_name)

@property
def dir_log(self) -> str:
"""The directory for saving logs."""
Expand All @@ -69,11 +74,17 @@ def dir_invoke(self) -> str:
"""The directory for saving api invocations."""
return self._get_and_create_subdir(_DEFAULT_SUBDIR_INVOKE)

@property
def path_db(self) -> str:
"""The path to the sqlite db file."""
return self._get_file_path(_DEFAULT_SQLITE_DB_PATH)

def init(self, save_dir: str, save_api_invoke: bool = False) -> None:
"""Set the directory for saving files."""
self.dir = save_dir
if not os.path.exists(save_dir):
os.makedirs(save_dir)
runtime_dir = os.path.join(save_dir, Runtime.runtime_id)
if not os.path.exists(runtime_dir):
os.makedirs(runtime_dir)

self.save_api_invoke = save_api_invoke

Expand Down
24 changes: 21 additions & 3 deletions src/agentscope/models/openai_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
except ImportError:
openai = None

from ..utils import MonitorFactory
from ..utils.monitor import MonitorFactory
from ..utils.monitor import get_full_name
from ..utils import QuotaExceededError
from ..utils.token_utils import get_openai_max_length

Expand All @@ -28,6 +29,7 @@ def __init__(
organization: str = None,
client_args: dict = None,
generate_args: dict = None,
budget: float = None,
) -> None:
"""Initialize the openai client.

Expand All @@ -49,6 +51,9 @@ def __init__(
generate_args (`dict`, default `None`):
The extra keyword arguments used in openai api generation,
e.g. `temperature`, `seed`.
budget (`float`, default `None`):
The total budget using this model. Set to `None` means no
limit.
"""
super().__init__(name)

Expand Down Expand Up @@ -77,8 +82,18 @@ def __init__(

# Set monitor accordingly
self.monitor = None
self.budget = budget
self._register_budget()
self._register_default_metrics()

def _register_budget(self) -> None:
self.monitor = MonitorFactory.get_monitor()
self.monitor.register_budget(
model_name=self.model_name,
value=self.budget,
prefix=self.model_name,
)

def _register_default_metrics(self) -> None:
"""Register metrics to the monitor."""
raise NotImplementedError(
Expand All @@ -95,7 +110,7 @@ def _metric(self, metric_name: str) -> str:
Returns:
`str`: Metric name of this wrapper.
"""
return f"{self.__class__.__name__}.{self.model_name}.{metric_name}"
return get_full_name(name=metric_name, prefix=self.model_name)


class OpenAIChatWrapper(OpenAIWrapper):
Expand Down Expand Up @@ -193,7 +208,10 @@ def __call__(

# step5: update monitor accordingly
try:
self.monitor.update(**response.usage.model_dump())
self.monitor.update(
response.usage.model_dump(),
prefix=self.model_name,
)
except QuotaExceededError as e:
# TODO: optimize quota exceeded error handling process
logger.error(e.message)
Expand Down
Loading