refactor(agent): Agent modular refactoring (#1487)

This commit is contained in:
Fangyin Cheng
2024-05-07 09:45:26 +08:00
committed by GitHub
parent 2a418f91e8
commit 863b5404dd
86 changed files with 4513 additions and 967 deletions

View File

@@ -1,9 +1,10 @@
"""Indicator Assistant Agent."""
import logging
from typing import List
from ..actions.indicator_action import IndicatorAction
import logging
from ..core.base_agent import ConversableAgent
from ..core.profile import DynConfig, ProfileConfig
from .actions.indicator_action import IndicatorAction
logger = logging.getLogger(__name__)
@@ -11,29 +12,48 @@ logger = logging.getLogger(__name__)
class IndicatorAssistantAgent(ConversableAgent):
"""Indicator Assistant Agent."""
name = "Indicator"
profile: str = "Indicator"
goal: str = (
"Summarize answer summaries based on user questions from provided "
"resource information or from historical conversation memories."
)
constraints: List[str] = [
"Prioritize the summary of answers to user questions from the improved resource"
" text. If no relevant information is found, summarize it from the historical"
" dialogue memory given. It is forbidden to make up your own.",
"You need to first detect user's question that you need to answer with your "
"summarization.",
"Extract the provided text content used for summarization.",
"Then you need to summarize the extracted text content.",
"Output the content of summarization ONLY related to user's question. The "
"output language must be the same to user's question language.",
"If you think the provided text content is not related to user questions at "
"all, ONLY output 'Did not find the information you want.'!!.",
]
desc: str = (
"You can summarize provided text content according to user's questions "
"and output the summarization."
profile: ProfileConfig = ProfileConfig(
name=DynConfig(
"Indicator",
category="agent",
key="dbgpt_agent_expand_indicator_assistant_agent_profile_name",
),
role=DynConfig(
"Indicator",
category="agent",
key="dbgpt_agent_expand_indicator_assistant_agent_profile_role",
),
goal=DynConfig(
"Summarize answer summaries based on user questions from provided "
"resource information or from historical conversation memories.",
category="agent",
key="dbgpt_agent_expand_indicator_assistant_agent_profile_goal",
),
constraints=DynConfig(
[
"Prioritize the summary of answers to user questions from the "
"improved resource text. If no relevant information is found, "
"summarize it from the historical dialogue memory given. It is "
"forbidden to make up your own.",
"You need to first detect user's question that you need to answer "
"with your summarization.",
"Extract the provided text content used for summarization.",
"Then you need to summarize the extracted text content.",
"Output the content of summarization ONLY related to user's question. "
"The output language must be the same to user's question language.",
"If you think the provided text content is not related to user "
"questions at all, ONLY output 'Did not find the information you "
"want.'!!.",
],
category="agent",
key="dbgpt_agent_expand_indicator_assistant_agent_profile_constraints",
),
desc=DynConfig(
"You can summarize provided text content according to user's questions "
"and output the summarization.",
category="agent",
key="dbgpt_agent_expand_indicator_assistant_agent_profile_desc",
),
)
def __init__(self, **kwargs):

View File

@@ -0,0 +1 @@
"""Actions of expand Agents."""

View File

@@ -0,0 +1,106 @@
"""Chart Action for SQL execution and rendering."""
import json
import logging
from typing import Optional
from dbgpt._private.pydantic import BaseModel, Field, model_to_json
from dbgpt.vis.tags.vis_chart import Vis, VisChart
from ...core.action.base import Action, ActionOutput
from ...resource.resource_api import AgentResource, ResourceType
from ...resource.resource_db_api import ResourceDbClient
logger = logging.getLogger(__name__)
class SqlInput(BaseModel):
"""SQL input model."""
display_type: str = Field(
...,
description="The chart rendering method selected for SQL. If you dont know "
"what to output, just output 'response_table' uniformly.",
)
sql: str = Field(
..., description="Executable sql generated for the current target/problem"
)
thought: str = Field(..., description="Summary of thoughts to the user")
class ChartAction(Action[SqlInput]):
"""Chart action class."""
def __init__(self):
"""Create a chart action."""
super().__init__()
self._render_protocol = VisChart()
@property
def resource_need(self) -> Optional[ResourceType]:
"""Return the resource type needed for the action."""
return ResourceType.DB
@property
def render_protocol(self) -> Optional[Vis]:
"""Return the render protocol."""
return self._render_protocol
@property
def out_model_type(self):
"""Return the output model type."""
return SqlInput
async def run(
self,
ai_message: str,
resource: Optional[AgentResource] = None,
rely_action_out: Optional[ActionOutput] = None,
need_vis_render: bool = True,
**kwargs,
) -> ActionOutput:
"""Perform the action."""
try:
param: SqlInput = self._input_convert(ai_message, SqlInput)
except Exception as e:
logger.exception(f"{str(e)}! \n {ai_message}")
return ActionOutput(
is_exe_success=False,
content="The requested correctly structured answer could not be found.",
)
try:
if not self.resource_loader:
raise ValueError("ResourceLoader is not initialized")
resource_db_client: Optional[
ResourceDbClient
] = self.resource_loader.get_resource_api(
self.resource_need, ResourceDbClient
)
if not resource_db_client:
raise ValueError(
"There is no implementation class bound to database resource "
"execution"
)
if not resource:
raise ValueError("The data resource is not found")
data_df = await resource_db_client.query_to_df(resource.value, param.sql)
if not self.render_protocol:
raise ValueError("The rendering protocol is not initialized")
view = await self.render_protocol.display(
chart=json.loads(model_to_json(param)), data_df=data_df
)
if not self.resource_need:
raise ValueError("The resource type is not found")
return ActionOutput(
is_exe_success=True,
content=model_to_json(param),
view=view,
resource_type=self.resource_need.value,
resource_value=resource.value,
)
except Exception as e:
logger.exception("Check your answers, the sql run failed")
return ActionOutput(
is_exe_success=False,
content=f"Check your answers, the sql run failed!Reason:{str(e)}",
)

View File

@@ -0,0 +1,148 @@
"""Code Action Module."""
import logging
from typing import Optional, Union
from dbgpt.util.code_utils import UNKNOWN, execute_code, extract_code, infer_lang
from dbgpt.util.utils import colored
from dbgpt.vis.tags.vis_code import Vis, VisCode
from ...core.action.base import Action, ActionOutput
from ...resource.resource_api import AgentResource
logger = logging.getLogger(__name__)
class CodeAction(Action[None]):
"""Code Action Module."""
def __init__(self):
"""Create a code action."""
super().__init__()
self._render_protocol = VisCode()
self._code_execution_config = {}
@property
def render_protocol(self) -> Optional[Vis]:
"""Return the render protocol."""
return self._render_protocol
async def run(
self,
ai_message: str,
resource: Optional[AgentResource] = None,
rely_action_out: Optional[ActionOutput] = None,
need_vis_render: bool = True,
**kwargs,
) -> ActionOutput:
"""Perform the action."""
try:
code_blocks = extract_code(ai_message)
if len(code_blocks) < 1:
logger.info(
f"No executable code found in answer,{ai_message}",
)
return ActionOutput(
is_exe_success=False, content="No executable code found in answer."
)
elif len(code_blocks) > 1 and code_blocks[0][0] == UNKNOWN:
# found code blocks, execute code and push "last_n_messages" back
logger.info(
f"Missing available code block type, unable to execute code,"
f"{ai_message}",
)
return ActionOutput(
is_exe_success=False,
content="Missing available code block type, "
"unable to execute code.",
)
exitcode, logs = self.execute_code_blocks(code_blocks)
exit_success = exitcode == 0
content = (
logs
if exit_success
else f"exitcode: {exitcode} (execution failed)\n {logs}"
)
param = {
"exit_success": exit_success,
"language": code_blocks[0][0],
"code": code_blocks,
"log": logs,
}
if not self.render_protocol:
raise NotImplementedError("The render_protocol should be implemented.")
view = await self.render_protocol.display(content=param)
return ActionOutput(
is_exe_success=exit_success,
content=content,
view=view,
thoughts=ai_message,
observations=content,
)
except Exception as e:
logger.exception("Code Action Run Failed")
return ActionOutput(
is_exe_success=False, content="Code execution exception" + str(e)
)
def execute_code_blocks(self, code_blocks):
"""Execute the code blocks and return the result."""
logs_all = ""
exitcode = -1
for i, code_block in enumerate(code_blocks):
lang, code = code_block
if not lang:
lang = infer_lang(code)
print(
colored(
f"\n>>>>>>>> EXECUTING CODE BLOCK {i} "
f"(inferred language is {lang})...",
"red",
),
flush=True,
)
if lang in ["bash", "shell", "sh"]:
exitcode, logs, image = execute_code(
code, lang=lang, **self._code_execution_config
)
elif lang in ["python", "Python"]:
if code.startswith("# filename: "):
filename = code[11 : code.find("\n")].strip()
else:
filename = None
exitcode, logs, image = execute_code(
code,
lang="python",
filename=filename,
**self._code_execution_config,
)
else:
# In case the language is not supported, we return an error message.
exitcode, logs, image = (
1,
f"unknown language {lang}",
None,
)
# raise NotImplementedError
if image is not None:
self._code_execution_config["use_docker"] = image
logs_all += "\n" + logs
if exitcode != 0:
return exitcode, logs_all
return exitcode, logs_all
@property
def use_docker(self) -> Union[bool, str, None]:
"""Whether to use docker to execute the code.
Bool value of whether to use docker to execute the code,
or str value of the docker image name to use, or None when code execution is
disabled.
"""
return (
None
if self._code_execution_config is False
else self._code_execution_config.get("use_docker")
)

View File

@@ -0,0 +1,130 @@
"""Dashboard Action Module."""
import json
import logging
from typing import List, Optional
from dbgpt._private.pydantic import BaseModel, Field, model_to_dict
from dbgpt.vis.tags.vis_dashboard import Vis, VisDashboard
from ...core.action.base import Action, ActionOutput
from ...resource.resource_api import AgentResource, ResourceType
from ...resource.resource_db_api import ResourceDbClient
logger = logging.getLogger(__name__)
class ChartItem(BaseModel):
"""Chart item model."""
title: str = Field(
...,
description="The title of the current analysis chart.",
)
display_type: str = Field(
...,
description="The chart rendering method selected for SQL. If you dont know "
"what to output, just output 'response_table' uniformly.",
)
sql: str = Field(
..., description="Executable sql generated for the current target/problem"
)
thought: str = Field(..., description="Summary of thoughts to the user")
def to_dict(self):
"""Convert to dict."""
return model_to_dict(self)
class DashboardAction(Action[List[ChartItem]]):
"""Dashboard action class."""
def __init__(self):
"""Create a dashboard action."""
super().__init__()
self._render_protocol = VisDashboard()
@property
def resource_need(self) -> Optional[ResourceType]:
"""Return the resource type needed for the action."""
return ResourceType.DB
@property
def render_protocol(self) -> Optional[Vis]:
"""Return the render protocol."""
return self._render_protocol
@property
def out_model_type(self):
"""Return the output model type."""
return List[ChartItem]
async def run(
self,
ai_message: str,
resource: Optional[AgentResource] = None,
rely_action_out: Optional[ActionOutput] = None,
need_vis_render: bool = True,
**kwargs,
) -> ActionOutput:
"""Perform the action."""
try:
input_param = self._input_convert(ai_message, List[ChartItem])
except Exception as e:
logger.exception(str(e))
return ActionOutput(
is_exe_success=False,
content="The requested correctly structured answer could not be found.",
)
if not isinstance(input_param, list):
return ActionOutput(
is_exe_success=False,
content="The requested correctly structured answer could not be found.",
)
chart_items: List[ChartItem] = input_param
try:
if not self.resource_loader:
raise ValueError("Resource loader is not initialized!")
resource_db_client: Optional[
ResourceDbClient
] = self.resource_loader.get_resource_api(
self.resource_need, ResourceDbClient
)
if not resource_db_client:
raise ValueError(
"There is no implementation class bound to database resource "
"execution"
)
if not resource:
raise ValueError("Resource is not initialized!")
chart_params = []
for chart_item in chart_items:
chart_dict = {}
try:
sql_df = await resource_db_client.query_to_df(
resource.value, chart_item.sql
)
chart_dict = chart_item.to_dict()
chart_dict["data"] = sql_df
except Exception as e:
logger.warning(f"Sql execute failed{str(e)}")
chart_dict["err_msg"] = str(e)
chart_params.append(chart_dict)
if not self.render_protocol:
raise ValueError("The render protocol is not initialized!")
view = await self.render_protocol.display(charts=chart_params)
return ActionOutput(
is_exe_success=True,
content=json.dumps(
[chart_item.to_dict() for chart_item in chart_items]
),
view=view,
)
except Exception as e:
logger.exception("Dashboard generate Failed")
return ActionOutput(
is_exe_success=False, content=f"Dashboard action run failed!{str(e)}"
)

View File

@@ -0,0 +1,157 @@
"""Indicator Action."""
import json
import logging
from typing import Optional
from dbgpt._private.pydantic import BaseModel, Field
from dbgpt.vis.tags.vis_plugin import Vis, VisPlugin
from ...core.action.base import Action, ActionOutput
from ...core.schema import Status
from ...resource.resource_api import AgentResource, ResourceType
logger = logging.getLogger(__name__)
class IndicatorInput(BaseModel):
"""Indicator input model."""
indicator_name: str = Field(
...,
description="The name of a indicator.",
)
api: str = Field(
...,
description="The api of a indicator.",
)
method: str = Field(
...,
description="The api of a indicator request method.",
)
args: dict = Field(
default={"arg name1": "", "arg name2": ""},
description="The tool selected for the current target, the parameter "
"information required for execution",
)
thought: str = Field(..., description="Summary of thoughts to the user")
class IndicatorAction(Action[IndicatorInput]):
"""Indicator action class."""
def __init__(self):
"""Create a indicator action."""
super().__init__()
self._render_protocol = VisPlugin()
@property
def resource_need(self) -> Optional[ResourceType]:
"""Return the resource type needed for the action."""
return ResourceType.Knowledge
@property
def render_protocol(self) -> Optional[Vis]:
"""Return the render protocol."""
return self._render_protocol
@property
def out_model_type(self):
"""Return the output model type."""
return IndicatorInput
@property
def ai_out_schema(self) -> Optional[str]:
"""Return the AI output schema."""
out_put_schema = {
"indicator_name": "The name of a tool that can be used to answer the "
"current question or solve the current task.",
"api": "",
"method": "",
"args": {
"arg name1": "Parameters in api definition",
"arg name2": "Parameters in api definition",
},
"thought": "Summary of thoughts to the user",
}
return f"""Please response in the following json format:
{json.dumps(out_put_schema, indent=2, ensure_ascii=False)}
Make sure the response is correct json and can be parsed by Python json.loads.
"""
async def run(
self,
ai_message: str,
resource: Optional[AgentResource] = None,
rely_action_out: Optional[ActionOutput] = None,
need_vis_render: bool = True,
**kwargs,
) -> ActionOutput:
"""Perform the action."""
import requests
from requests.exceptions import HTTPError
try:
input_param = self._input_convert(ai_message, IndicatorInput)
except Exception as e:
logger.exception((str(e)))
return ActionOutput(
is_exe_success=False,
content="The requested correctly structured answer could not be found.",
)
if isinstance(input_param, list):
return ActionOutput(
is_exe_success=False,
content="The requested correctly structured answer could not be found.",
)
param: IndicatorInput = input_param
response_success = True
result: Optional[str] = None
try:
status = Status.COMPLETE.value
err_msg = None
try:
status = Status.RUNNING.value
if param.method.lower() == "get":
response = requests.get(param.api, params=param.args)
elif param.method.lower() == "post":
response = requests.post(param.api, data=param.args)
else:
response = requests.request(
param.method.lower(), param.api, data=param.args
)
# Raise an HTTPError if the HTTP request returned an unsuccessful
# status code
response.raise_for_status()
result = response.text
except HTTPError as http_err:
response_success = False
print(f"HTTP error occurred: {http_err}")
except Exception as e:
response_success = False
logger.exception(f"API [{param.indicator_name}] excute Failed!")
status = Status.FAILED.value
err_msg = f"API [{param.api}] request Failed!{str(e)}"
plugin_param = {
"name": param.indicator_name,
"args": param.args,
"status": status,
"logo": None,
"result": result,
"err_msg": err_msg,
}
if not self.render_protocol:
raise NotImplementedError("The render_protocol should be implemented.")
view = await self.render_protocol.display(content=plugin_param)
return ActionOutput(
is_exe_success=response_success, content=result, view=view
)
except Exception as e:
logger.exception("Indicator Action Run Failed")
return ActionOutput(
is_exe_success=False, content=f"Indicator action run failed!{str(e)}"
)

View File

@@ -0,0 +1,157 @@
"""Plugin Action Module."""
import json
import logging
from typing import Optional
from dbgpt._private.pydantic import BaseModel, Field
from dbgpt.vis.tags.vis_plugin import Vis, VisPlugin
from ...core.action.base import Action, ActionOutput
from ...core.schema import Status
from ...plugin.generator import PluginPromptGenerator
from ...resource.resource_api import AgentResource, ResourceType
from ...resource.resource_plugin_api import ResourcePluginClient
logger = logging.getLogger(__name__)
class PluginInput(BaseModel):
"""Plugin input model."""
tool_name: str = Field(
...,
description="The name of a tool that can be used to answer the current question"
" or solve the current task.",
)
args: dict = Field(
default={"arg name1": "", "arg name2": ""},
description="The tool selected for the current target, the parameter "
"information required for execution",
)
thought: str = Field(..., description="Summary of thoughts to the user")
class PluginAction(Action[PluginInput]):
"""Plugin action class."""
def __init__(self):
"""Create a plugin action."""
super().__init__()
self._render_protocol = VisPlugin()
@property
def resource_need(self) -> Optional[ResourceType]:
"""Return the resource type needed for the action."""
return ResourceType.Plugin
@property
def render_protocol(self) -> Optional[Vis]:
"""Return the render protocol."""
return self._render_protocol
@property
def out_model_type(self):
"""Return the output model type."""
return PluginInput
@property
def ai_out_schema(self) -> Optional[str]:
"""Return the AI output schema."""
out_put_schema = {
"tool_name": "The name of a tool that can be used to answer the current "
"question or solve the current task.",
"args": {
"arg name1": "arg value1",
"arg name2": "arg value2",
},
"thought": "Summary of thoughts to the user",
}
return f"""Please response in the following json format:
{json.dumps(out_put_schema, indent=2, ensure_ascii=False)}
Make sure the response is correct json and can be parsed by Python json.loads.
"""
async def run(
self,
ai_message: str,
resource: Optional[AgentResource] = None,
rely_action_out: Optional[ActionOutput] = None,
need_vis_render: bool = True,
**kwargs,
) -> ActionOutput:
"""Perform the plugin action.
Args:
ai_message (str): The AI message.
resource (Optional[AgentResource], optional): The resource. Defaults to
None.
rely_action_out (Optional[ActionOutput], optional): The rely action output.
Defaults to None.
need_vis_render (bool, optional): Whether need visualization rendering.
Defaults to True.
"""
plugin_generator: Optional[PluginPromptGenerator] = kwargs.get(
"plugin_generator", None
)
if not plugin_generator:
raise ValueError("No plugin generator found!")
try:
param: PluginInput = self._input_convert(ai_message, PluginInput)
except Exception as e:
logger.exception((str(e)))
return ActionOutput(
is_exe_success=False,
content="The requested correctly structured answer could not be found.",
)
try:
if not self.resource_loader:
raise ValueError("No resource_loader found!")
resource_plugin_client: Optional[
ResourcePluginClient
] = self.resource_loader.get_resource_api(
self.resource_need, ResourcePluginClient
)
if not resource_plugin_client:
raise ValueError("No implementation of the use of plug-in resources")
response_success = True
status = Status.RUNNING.value
err_msg = None
try:
tool_result = await resource_plugin_client.execute_command(
param.tool_name, param.args, plugin_generator
)
status = Status.COMPLETE.value
except Exception as e:
response_success = False
logger.exception(f"Tool [{param.tool_name}] execute failed!")
status = Status.FAILED.value
err_msg = f"Tool [{param.tool_name}] execute failed! {str(e)}"
tool_result = err_msg
plugin_param = {
"name": param.tool_name,
"args": param.args,
"status": status,
"logo": None,
"result": tool_result,
"err_msg": err_msg,
}
if not self.render_protocol:
raise NotImplementedError("The render_protocol should be implemented.")
view = await self.render_protocol.display(content=plugin_param)
return ActionOutput(
is_exe_success=response_success,
content=tool_result,
view=view,
observations=tool_result,
)
except Exception as e:
logger.exception("Tool Action Run Failed")
return ActionOutput(
is_exe_success=False, content=f"Tool action run failed!{str(e)}"
)

View File

@@ -1,12 +1,14 @@
"""Code Assistant Agent."""
from typing import List, Optional, Tuple
from typing import Optional, Tuple
from dbgpt.core import ModelMessageRoleType
from dbgpt.util.string_utils import str_to_bool
from ..actions.code_action import CodeAction
from ..core.agent import AgentMessage
from ..core.base_agent import ConversableAgent
from ..core.profile import DynConfig, ProfileConfig
from .actions.code_action import CodeAction
CHECK_RESULT_SYSTEM_MESSAGE = (
"You are an expert in analyzing the results of task execution. Your responsibility "
@@ -42,54 +44,75 @@ CHECK_RESULT_SYSTEM_MESSAGE = (
class CodeAssistantAgent(ConversableAgent):
"""Code Assistant Agent."""
name: str = "Turing"
profile: str = "CodeEngineer"
goal: str = (
"Solve tasks using your coding and language skills.\n"
"In the following cases, suggest python code (in a python coding block) or "
"shell script (in a sh coding block) for the user to execute.\n"
" 1. When you need to collect info, use the code to output the info you "
"need, for example, browse or search the web, download/read a file, print the "
"content of a webpage or a file, get the current date/time, check the "
"operating system. After sufficient info is printed and the task is ready to be"
" solved based on your language skill, you can solve the task by yourself.\n"
" 2. When you need to perform some task with code, use the code to perform "
"the task and output the result. Finish the task smartly."
)
constraints: List[str] = [
"The user cannot provide any other feedback or perform any other action beyond"
" executing the code you suggest. The user can't modify your code. So do not "
"suggest incomplete code which requires users to modify. Don't use a code block"
" if it's not intended to be executed by the user.Don't ask users to copy and "
"paste results. Instead, the 'Print' function must be used for output when "
"relevant.",
"When using code, you must indicate the script type in the code block. Please "
"don't include multiple code blocks in one response.",
"If you want the user to save the code in a file before executing it, put "
"# filename: <filename> inside the code block as the first line.",
"If you receive user input that indicates an error in the code execution, fix "
"the error and output the complete code again. It is recommended to use the "
"complete code rather than partial code or code changes. If the error cannot be"
" fixed, or the task is not resolved even after the code executes successfully,"
" analyze the problem, revisit your assumptions, gather additional information"
" you need from historical conversation records, and consider trying a "
"different approach.",
"Unless necessary, give priority to solving problems with python code. If it "
"involves downloading files or storing data locally, please use 'Print' to "
"output the full file path of the stored data and a brief introduction to the "
"data.",
"The output content of the 'print' function will be passed to other LLM agents "
"as dependent data. Please control the length of the output content of the "
"'print' function. The 'print' function only outputs part of the key data "
"information that is relied on, and is as concise as possible.",
"The code is executed without user participation. It is forbidden to use "
"methods that will block the process or need to be shut down, such as the "
"plt.show() method of matplotlib.pyplot as plt.",
"It is prohibited to fabricate non-existent data to achieve goals.",
]
desc: str = (
"Can independently write and execute python/shell code to solve various"
" problems"
profile: ProfileConfig = ProfileConfig(
name=DynConfig(
"Turing",
category="agent",
key="dbgpt_agent_expand_code_assistant_agent_profile_name",
),
role=DynConfig(
"CodeEngineer",
category="agent",
key="dbgpt_agent_expand_code_assistant_agent_profile_role",
),
goal=DynConfig(
"Solve tasks using your coding and language skills.\n"
"In the following cases, suggest python code (in a python coding block) or "
"shell script (in a sh coding block) for the user to execute.\n"
" 1. When you need to collect info, use the code to output the info you "
"need, for example, browse or search the web, download/read a file, print "
"the content of a webpage or a file, get the current date/time, check the "
"operating system. After sufficient info is printed and the task is ready "
"to be solved based on your language skill, you can solve the task by "
"yourself.\n"
" 2. When you need to perform some task with code, use the code to "
"perform the task and output the result. Finish the task smartly.",
category="agent",
key="dbgpt_agent_expand_code_assistant_agent_profile_goal",
),
constraints=DynConfig(
[
"The user cannot provide any other feedback or perform any other "
"action beyond executing the code you suggest. The user can't modify "
"your code. So do not suggest incomplete code which requires users to "
"modify. Don't use a code block if it's not intended to be executed "
"by the user.Don't ask users to copy and paste results. Instead, "
"the 'Print' function must be used for output when relevant.",
"When using code, you must indicate the script type in the code block. "
"Please don't include multiple code blocks in one response.",
"If you want the user to save the code in a file before executing it, "
"put # filename: <filename> inside the code block as the first line.",
"If you receive user input that indicates an error in the code "
"execution, fix the error and output the complete code again. It is "
"recommended to use the complete code rather than partial code or "
"code changes. If the error cannot be fixed, or the task is not "
"resolved even after the code executes successfully, analyze the "
"problem, revisit your assumptions, gather additional information you "
"need from historical conversation records, and consider trying a "
"different approach.",
"Unless necessary, give priority to solving problems with python "
"code. If it involves downloading files or storing data locally, "
"please use 'Print' to output the full file path of the stored data "
"and a brief introduction to the data.",
"The output content of the 'print' function will be passed to other "
"LLM agents as dependent data. Please control the length of the "
"output content of the 'print' function. The 'print' function only "
"outputs part of the key data information that is relied on, "
"and is as concise as possible.",
"The code is executed without user participation. It is forbidden to "
"use methods that will block the process or need to be shut down, "
"such as the plt.show() method of matplotlib.pyplot as plt.",
"It is prohibited to fabricate non-existent data to achieve goals.",
],
category="agent",
key="dbgpt_agent_expand_code_assistant_agent_profile_constraints",
),
desc=DynConfig(
"Can independently write and execute python/shell code to solve various"
" problems",
category="agent",
key="dbgpt_agent_expand_code_assistant_agent_profile_desc",
),
)
def __init__(self, **kwargs):

View File

@@ -1,37 +1,54 @@
"""Dashboard Assistant Agent."""
from typing import List
from ..actions.dashboard_action import DashboardAction
from ..core.agent import AgentMessage
from ..core.base_agent import ConversableAgent
from ..core.profile import DynConfig, ProfileConfig
from ..resource.resource_db_api import ResourceDbClient
from .actions.dashboard_action import DashboardAction
class DashboardAssistantAgent(ConversableAgent):
"""Dashboard Assistant Agent."""
name: str = "Visionary"
profile: str = "Reporter"
goal: str = (
"Read the provided historical messages, collect various analysis SQLs "
"from them, and assemble them into professional reports."
)
constraints: List[str] = [
"You are only responsible for collecting and sorting out the analysis SQL that"
" already exists in historical messages, and do not generate any analysis sql "
"yourself.",
"In order to build a report with rich display types, you can appropriately "
"adjust the display type of the charts you collect so that you can build a "
"better report. Of course, you can choose from the following available "
"display types: {display_type}",
"Please read and completely collect all analysis sql in the historical "
"conversation, and do not omit or modify the content of the analysis sql.",
]
desc: str = (
"Observe and organize various analysis results and construct "
"professional reports"
profile: ProfileConfig = ProfileConfig(
name=DynConfig(
"Visionary",
category="agent",
key="dbgpt_agent_expand_dashboard_assistant_agent_profile_name",
),
role=DynConfig(
"Reporter",
category="agent",
key="dbgpt_agent_expand_dashboard_assistant_agent_profile_role",
),
goal=DynConfig(
"Read the provided historical messages, collect various analysis SQLs "
"from them, and assemble them into professional reports.",
category="agent",
key="dbgpt_agent_expand_dashboard_assistant_agent_profile_goal",
),
constraints=DynConfig(
[
"You are only responsible for collecting and sorting out the analysis "
"SQL that already exists in historical messages, and do not generate "
"any analysis sql yourself.",
"In order to build a report with rich display types, you can "
"appropriately adjust the display type of the charts you collect so "
"that you can build a better report. Of course, you can choose from "
"the following available display types: {{ display_type }}",
"Please read and completely collect all analysis sql in the "
"historical conversation, and do not omit or modify the content of "
"the analysis sql.",
],
category="agent",
key="dbgpt_agent_expand_dashboard_assistant_agent_profile_constraints",
),
desc=DynConfig(
"Observe and organize various analysis results and construct "
"professional reports",
category="agent",
key="dbgpt_agent_expand_dashboard_assistant_agent_profile_desc",
),
)
def __init__(self, **kwargs):

View File

@@ -2,14 +2,15 @@
import json
import logging
from typing import List, Optional, Tuple, cast
from typing import Optional, Tuple, cast
from ..actions.action import ActionOutput
from ..actions.chart_action import ChartAction
from ..core.action.base import ActionOutput
from ..core.agent import AgentMessage
from ..core.base_agent import ConversableAgent
from ..core.profile import DynConfig, ProfileConfig
from ..resource.resource_api import ResourceType
from ..resource.resource_db_api import ResourceDbClient
from .actions.chart_action import ChartAction
logger = logging.getLogger(__name__)
@@ -17,31 +18,53 @@ logger = logging.getLogger(__name__)
class DataScientistAgent(ConversableAgent):
"""Data Scientist Agent."""
name: str = "Edgar"
profile: str = "DataScientist"
goal: str = (
"Use correct {dialect} SQL to analyze and solve tasks based on the data"
" structure information of the database given in the resource."
)
constraints: List[str] = [
"Please check the generated SQL carefully. Please strictly abide by the data "
"structure definition given. It is prohibited to use non-existent fields and "
"data values. Do not use fields from table A to table B. You can perform "
"multi-table related queries.",
"If the data and fields that need to be analyzed in the target are in different"
" tables, it is recommended to use multi-table correlation queries first, and "
"pay attention to the correlation between multiple table structures.",
"It is forbidden to construct data by yourself as a query condition. If you "
"want to query a specific field, if the value of the field is provided, then "
"you can perform a group statistical query on the field.",
"Please select an appropriate one from the supported display methods for data "
"display. If no suitable display type is found, table display is used by "
"default. Supported display types: \n {display_type}",
]
desc: str = (
"Use database resources to conduct data analysis, analyze SQL, and "
"provide recommended rendering methods."
profile: ProfileConfig = ProfileConfig(
name=DynConfig(
"Edgar",
category="agent",
key="dbgpt_agent_expand_dashboard_assistant_agent_profile_name",
),
role=DynConfig(
"DataScientist",
category="agent",
key="dbgpt_agent_expand_dashboard_assistant_agent_profile_role",
),
goal=DynConfig(
"Use correct {{ dialect }} SQL to analyze and solve tasks based on the data"
" structure information of the database given in the resource.",
category="agent",
key="dbgpt_agent_expand_dashboard_assistant_agent_profile_goal",
),
constraints=DynConfig(
[
"Please check the generated SQL carefully. Please strictly abide by "
"the data structure definition given. It is prohibited to use "
"non-existent fields and data values. Do not use fields from table A "
"to table B. You can perform multi-table related queries.",
"If the data and fields that need to be analyzed in the target are in "
"different tables, it is recommended to use multi-table correlation "
"queries first, and pay attention to the correlation between multiple "
"table structures.",
"It is forbidden to construct data by yourself as a query condition. "
"If you want to query a specific field, if the value of the field is "
"provided, then you can perform a group statistical query on the "
"field.",
"Please select an appropriate one from the supported display methods "
"for data display. If no suitable display type is found, "
"table display is used by default. Supported display types: \n"
"{{ display_type }}",
],
category="agent",
key="dbgpt_agent_expand_dashboard_assistant_agent_profile_constraints",
),
desc=DynConfig(
"Use database resources to conduct data analysis, analyze SQL, and provide "
"recommended rendering methods.",
category="agent",
key="dbgpt_agent_expand_dashboard_assistant_agent_profile_desc",
),
)
max_retry_count: int = 5
def __init__(self, **kwargs):

View File

@@ -1,12 +1,14 @@
"""Plugin Assistant Agent."""
import logging
from typing import Any, Dict, List, Optional
from ..actions.plugin_action import PluginAction
import logging
from typing import Any, Dict, Optional
from ..core.base_agent import ConversableAgent
from ..core.profile import DynConfig, ProfileConfig
from ..plugin.generator import PluginPromptGenerator
from ..resource.resource_api import ResourceType
from ..resource.resource_plugin_api import ResourcePluginClient
from .actions.plugin_action import PluginAction
logger = logging.getLogger(__name__)
@@ -16,23 +18,42 @@ class PluginAssistantAgent(ConversableAgent):
plugin_generator: Optional[PluginPromptGenerator] = None
name: str = "LuBan"
profile: str = "ToolExpert"
goal: str = (
"Read and understand the tool information given in the resources below to "
"understand their capabilities and how to use them,and choosing the right tools"
" to achieve the user's goals."
)
constraints: List[str] = [
"Please read the parameter definition of the tool carefully and extract the "
"specific parameters required to execute the tool from the user goal.",
"Please output the selected tool name and specific parameter information in "
"json format according to the following required format. If there is an "
"example, please refer to the sample format output.",
]
desc: str = (
"You can use the following tools to complete the task objectives, tool "
"information: {tool_infos}"
profile: ProfileConfig = ProfileConfig(
name=DynConfig(
"LuBan",
category="agent",
key="dbgpt_agent_expand_plugin_assistant_agent_name",
),
role=DynConfig(
"ToolExpert",
category="agent",
key="dbgpt_agent_expand_plugin_assistant_agent_role",
),
goal=DynConfig(
"Read and understand the tool information given in the resources "
"below to understand their capabilities and how to use them,and choosing "
"the right tools to achieve the user's goals.",
category="agent",
key="dbgpt_agent_expand_plugin_assistant_agent_goal",
),
constraints=DynConfig(
[
"Please read the parameter definition of the tool carefully and extract"
" the specific parameters required to execute the tool from the user "
"goal.",
"Please output the selected tool name and specific parameter "
"information in json format according to the following required format."
" If there is an example, please refer to the sample format output.",
],
category="agent",
key="dbgpt_agent_expand_plugin_assistant_agent_constraints",
),
desc=DynConfig(
"You can use the following tools to complete the task objectives, "
"tool information: {tool_infos}",
category="agent",
key="dbgpt_agent_expand_plugin_assistant_agent_desc",
),
)
def __init__(self, **kwargs):
@@ -40,14 +61,14 @@ class PluginAssistantAgent(ConversableAgent):
super().__init__(**kwargs)
self._init_actions([PluginAction])
@property
def introduce(self, **kwargs) -> str:
"""Introduce the agent."""
if not self.plugin_generator:
raise ValueError("PluginGenerator is not loaded.")
return self.desc.format(
tool_infos=self.plugin_generator.generate_commands_string()
)
# @property
# def introduce(self, **kwargs) -> str:
# """Introduce the agent."""
# if not self.plugin_generator:
# raise ValueError("PluginGenerator is not loaded.")
# return self.desc.format(
# tool_infos=self.plugin_generator.generate_commands_string()
# )
async def preload_resource(self):
"""Preload the resource."""

View File

@@ -1,4 +1,5 @@
"""Retrieve Summary Assistant Agent."""
import glob
import json
import logging
@@ -9,9 +10,10 @@ from urllib.parse import urlparse
from dbgpt.configs.model_config import PILOT_PATH
from dbgpt.core import ModelMessageRoleType
from ..actions.action import Action, ActionOutput
from ..core.action.base import Action, ActionOutput
from ..core.agent import Agent, AgentMessage, AgentReviewInfo
from ..core.base_agent import ConversableAgent
from ..core.profile import ProfileConfig
from ..resource.resource_api import AgentResource
from ..util.cmp import cmp_string_equal
@@ -86,18 +88,7 @@ class RetrieveSummaryAssistantAgent(ConversableAgent):
including suggesting python code blocks and debugging.
"""
goal = (
"You're an extraction expert. You need to extract Please complete this task "
"step by step following instructions below:\n"
" 1. You need to first ONLY extract user's question that you need to answer "
"without ANY file paths and URLs. \n"
" 2. Extract the provided file paths and URLs.\n"
" 3. Construct the extracted file paths and URLs as a list of strings.\n"
" 4. ONLY output the extracted results with the following json format: "
"{response}."
)
PROMPT_QA = (
PROMPT_QA: str = (
"You are a great summary writer to summarize the provided text content "
"according to user questions.\n"
"User's Question is: {input_question}\n\n"
@@ -118,7 +109,7 @@ class RetrieveSummaryAssistantAgent(ConversableAgent):
"If the provided text content CAN NOT ANSWER user's question, ONLY output "
"'NO RELATIONSHIP.UPDATE TEXT CONTENT.'!!."
)
CHECK_RESULT_SYSTEM_MESSAGE = (
CHECK_RESULT_SYSTEM_MESSAGE: str = (
"You are an expert in analyzing the results of a summary task."
"Your responsibility is to check whether the summary results can summarize the "
"input provided by the user, and then make a judgment. You need to answer "
@@ -131,20 +122,30 @@ class RetrieveSummaryAssistantAgent(ConversableAgent):
"not summarized. TERMINATE"
)
DEFAULT_DESCRIBE = (
DEFAULT_DESCRIBE: str = (
"Summarize provided content according to user's questions and "
"the provided file paths."
)
name = "RetrieveSummarizer"
desc = DEFAULT_DESCRIBE
profile: ProfileConfig = ProfileConfig(
name="RetrieveSummarizer",
role="Assistant",
goal="You're an extraction expert. You need to extract Please complete this "
"task step by step following instructions below:\n"
" 1. You need to first ONLY extract user's question that you need to answer "
"without ANY file paths and URLs. \n"
" 2. Extract the provided file paths and URLs.\n"
" 3. Construct the extracted file paths and URLs as a list of strings.\n"
" 4. ONLY output the extracted results with the following json format: "
"{{ response }}.",
desc=DEFAULT_DESCRIBE,
)
chunk_token_size: int = 4000
chunk_mode: str = "multi_lines"
_model = "gpt-3.5-turbo-16k"
_max_tokens = _get_max_tokens(_model)
context_max_tokens = _max_tokens * 0.8
_model: str = "gpt-3.5-turbo-16k"
_max_tokens: int = _get_max_tokens(_model)
context_max_tokens: int = int(_max_tokens * 0.8)
def __init__(
self,
@@ -174,12 +175,14 @@ class RetrieveSummaryAssistantAgent(ConversableAgent):
reply_message: AgentMessage = self._init_reply_message(
received_message=received_message
)
await self._system_message_assembly(
received_message.content, reply_message.context
)
# 1.Think about how to do things
llm_reply, model_name = await self.thinking(
self._load_thinking_messages(received_message, sender, rely_messages)
await self._load_thinking_messages(
received_message,
sender,
rely_messages,
context=reply_message.get_dict_context(),
)
)
if not llm_reply:
@@ -454,16 +457,16 @@ class RetrieveSummaryAssistantAgent(ConversableAgent):
" set to False."
)
must_break_at_empty_line = False
chunks.append(prev) if len(
prev
) > 10 else None # don't add chunks less than 10 characters
(
chunks.append(prev) if len(prev) > 10 else None
) # don't add chunks less than 10 characters
lines = lines[cnt:]
lines_tokens = lines_tokens[cnt:]
sum_tokens = sum(lines_tokens)
text_to_chunk = "\n".join(lines)
chunks.append(text_to_chunk) if len(
text_to_chunk
) > 10 else None # don't add chunks less than 10 characters
(
chunks.append(text_to_chunk) if len(text_to_chunk) > 10 else None
) # don't add chunks less than 10 characters
return chunks
def _extract_text_from_pdf(self, file: str) -> str:

View File

@@ -1,9 +1,10 @@
"""Summary Assistant Agent."""
import logging
from typing import List
from ..actions.blank_action import BlankAction
import logging
from ..core.action.blank_action import BlankAction
from ..core.base_agent import ConversableAgent
from ..core.profile import DynConfig, ProfileConfig
logger = logging.getLogger(__name__)
@@ -11,29 +12,48 @@ logger = logging.getLogger(__name__)
class SummaryAssistantAgent(ConversableAgent):
"""Summary Assistant Agent."""
name: str = "Aristotle"
profile: str = "Summarizer"
goal: str = (
"Summarize answer summaries based on user questions from provided "
"resource information or from historical conversation memories."
)
constraints: List[str] = [
"Prioritize the summary of answers to user questions from the improved resource"
" text. If no relevant information is found, summarize it from the historical "
"dialogue memory given. It is forbidden to make up your own.",
"You need to first detect user's question that you need to answer with your"
" summarization.",
"Extract the provided text content used for summarization.",
"Then you need to summarize the extracted text content.",
"Output the content of summarization ONLY related to user's question. The "
"output language must be the same to user's question language.",
"If you think the provided text content is not related to user questions at "
"all, ONLY output 'Did not find the information you want.'!!.",
]
desc: str = (
"You can summarize provided text content according to user's questions"
" and output the summarization."
profile: ProfileConfig = ProfileConfig(
name=DynConfig(
"Aristotle",
category="agent",
key="dbgpt_agent_expand_summary_assistant_agent_profile_name",
),
role=DynConfig(
"Summarizer",
category="agent",
key="dbgpt_agent_expand_summary_assistant_agent_profile_role",
),
goal=DynConfig(
"Summarize answer summaries based on user questions from provided "
"resource information or from historical conversation memories.",
category="agent",
key="dbgpt_agent_expand_summary_assistant_agent_profile_goal",
),
constraints=DynConfig(
[
"Prioritize the summary of answers to user questions from the improved "
"resource text. If no relevant information is found, summarize it from "
"the historical dialogue memory given. It is forbidden to make up your "
"own.",
"You need to first detect user's question that you need to answer with "
"your summarization.",
"Extract the provided text content used for summarization.",
"Then you need to summarize the extracted text content.",
"Output the content of summarization ONLY related to user's question. "
"The output language must be the same to user's question language.",
"If you think the provided text content is not related to user "
"questions at all, ONLY output 'Did not find the information you "
"want.'!!.",
],
category="agent",
key="dbgpt_agent_expand_summary_assistant_agent_profile_constraints",
),
desc=DynConfig(
"You can summarize provided text content according to user's questions"
" and output the summarization.",
category="agent",
key="dbgpt_agent_expand_summary_assistant_agent_profile_desc",
),
)
def __init__(self, **kwargs):