Skip to content

Commit

Permalink
feat(agent): add app starter role in mutli agent (#2265)
Browse files Browse the repository at this point in the history
Co-authored-by: cinjospeh <[email protected]>
  • Loading branch information
cinjoseph and cinjospeh authored Jan 3, 2025
1 parent ad1e8e2 commit 0e3b2dc
Show file tree
Hide file tree
Showing 6 changed files with 671 additions and 0 deletions.
166 changes: 166 additions & 0 deletions dbgpt/agent/resource/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import dataclasses
import uuid
from typing import Optional, Tuple, Dict, Type, Any, List, cast

from dbgpt.agent import ConversableAgent, AgentMessage, AgentContext
from dbgpt.serve.agent.agents.app_agent_manage import get_app_manager
from dbgpt.util import ParameterDescription
from .base import Resource, ResourceParameters, ResourceType


def get_app_list():
apps = get_app_manager().get_dbgpts()
results = [
{
"label": f"{app.app_name}({app.app_code})",
"key": app.app_code,
"description": app.app_describe
}
for app in apps
]
return results


@dataclasses.dataclass
class AppResourceParameters(ResourceParameters):
app_code: str = dataclasses.field(
default=None,
metadata={
"help": "app code",
"valid_values": get_app_list(),
},
)

@classmethod
def to_configurations(
cls,
parameters: Type["AppResourceParameters"],
version: Optional[str] = None,
**kwargs,
) -> Any:
"""Convert the parameters to configurations."""
conf: List[ParameterDescription] = cast(
List[ParameterDescription], super().to_configurations(parameters)
)
version = version or cls._resource_version()
if version != "v1":
return conf
# Compatible with old version
for param in conf:
if param.param_name == "app_code":
return param.valid_values or []
return []

@classmethod
def from_dict(
cls, data: dict, ignore_extra_fields: bool = True
) -> ResourceParameters:
"""Create a new instance from a dictionary."""
copied_data = data.copy()
if "app_code" not in copied_data and "value" in copied_data:
copied_data["app_code"] = copied_data.pop("value")
return super().from_dict(copied_data, ignore_extra_fields=ignore_extra_fields)


class AppResource(Resource[AppResourceParameters]):
"""AppResource resource class."""

def __init__(self, name: str, app_code: str, **kwargs):
self._resource_name = name
self._app_code = app_code

app = get_app_manager().get_app(self._app_code)
self._app_name = app.app_name
self._app_desc = app.app_describe

@classmethod
def type(cls) -> ResourceType:
return ResourceType.App

@property
def name(self) -> str:
return self._resource_name

@classmethod
def resource_parameters_class(cls, **kwargs) -> Type[ResourceParameters]:
"""Return the resource parameters class."""
return AppResourceParameters

async def get_prompt(self, *, lang: str = "en", prompt_type: str = "default", question: Optional[str] = None,
resource_name: Optional[str] = None, **kwargs) -> Tuple[str, Optional[Dict]]:
"""Get the prompt."""

prompt_template_zh = (
"{name}:调用此资源与应用 {app_name} 进行交互。"
"应用 {app_name} 有什么用?{description}"
)
prompt_template_en = (
"{name}:Call this resource to interact with the application {app_name} ."
"What is the application {app_name} useful for? {description} "
)
template = prompt_template_en if lang == "en" else prompt_template_zh

return (
template.format(
name=self.name,
app_name=self._app_name,
description=self._app_desc
),
None,
)

@property
def is_async(self) -> bool:
"""Return whether the tool is asynchronous."""
return True

async def execute(self, *args, resource_name: Optional[str] = None, **kwargs) -> Any:
if self.is_async:
raise RuntimeError("Async execution is not supported")

async def async_execute(
self,
*args,
resource_name: Optional[str] = None,
**kwargs,
) -> Any:
"""Execute the tool asynchronously.
Args:
*args: The positional arguments.
resource_name (str, optional): The tool name to be executed(not used for
specific tool).
**kwargs: The keyword arguments.
"""

user_input = kwargs.get("user_input")
parent_agent = kwargs.get("parent_agent")

reply_message = await self.chat_2_app_once(self._app_code, user_input=user_input, sender=parent_agent)
return reply_message.content

async def chat_2_app_once(self,
app_code: str,
user_input: str,
conv_uid: str = None,
sender: ConversableAgent = None) -> AgentMessage:
# create a new conv_uid
conv_uid = str(uuid.uuid4()) if conv_uid is None else conv_uid

gpts_app = get_app_manager().get_app(app_code)

app_agent = await get_app_manager().create_agent_by_app_code(gpts_app, conv_uid=conv_uid)

agent_message = AgentMessage(
content=user_input,
current_goal=user_input,
context={
"conv_uid": conv_uid,
},
rounds=0,
)

reply_message: AgentMessage = await app_agent.generate_reply(received_message=agent_message,
sender=sender)

return reply_message
1 change: 1 addition & 0 deletions dbgpt/agent/resource/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class ResourceType(str, Enum):
ExcelFile = "excel_file"
ImageFile = "image_file"
AWELFlow = "awel_flow"
App = "app"
# Resource type for resource pack
Pack = "pack"

Expand Down
2 changes: 2 additions & 0 deletions dbgpt/app/component_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,14 @@ def _initialize_resource_manager(system_app: SystemApp):
from dbgpt.serve.agent.resource.datasource import DatasourceResource
from dbgpt.serve.agent.resource.knowledge import KnowledgeSpaceRetrieverResource
from dbgpt.serve.agent.resource.plugin import PluginToolPack
from dbgpt.agent.resource.app import AppResource

initialize_resource(system_app)
rm = get_resource_manager(system_app)
rm.register_resource(DatasourceResource)
rm.register_resource(KnowledgeSpaceRetrieverResource)
rm.register_resource(PluginToolPack, resource_type=ResourceType.Tool)
rm.register_resource(AppResource)
# Register a search tool
rm.register_resource(resource_instance=baidu_search)
rm.register_resource(resource_instance=list_dbgpt_support_models)
Expand Down
Loading

0 comments on commit 0e3b2dc

Please sign in to comment.