forked from eosphoros-ai/DB-GPT
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Native data AI application framework based on AWEL+AGENT (eosphoros-a…
…i#1152) Co-authored-by: Fangyin Cheng <[email protected]> Co-authored-by: lcx01800250 <[email protected]> Co-authored-by: licunxing <[email protected]> Co-authored-by: Aralhi <[email protected]> Co-authored-by: xuyuan23 <[email protected]> Co-authored-by: aries_ckt <[email protected]> Co-authored-by: hzh97 <[email protected]>
- Loading branch information
1 parent
dbb9ac8
commit d5afa6e
Showing
328 changed files
with
22,613 additions
and
3,289 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
import json | ||
from abc import ABC | ||
from typing import ( | ||
Any, | ||
Dict, | ||
Generic, | ||
List, | ||
Optional, | ||
Tuple, | ||
Type, | ||
TypeVar, | ||
Union, | ||
get_args, | ||
get_origin, | ||
) | ||
|
||
from pydantic import BaseModel | ||
|
||
from dbgpt.agent.resource.resource_api import AgentResource, ResourceType | ||
from dbgpt.agent.resource.resource_loader import ResourceLoader | ||
from dbgpt.util.json_utils import find_json_objects | ||
|
||
T = TypeVar("T", None, BaseModel, List[BaseModel]) | ||
|
||
|
||
class ActionOutput(BaseModel): | ||
content: str | ||
is_exe_success: bool = True | ||
view: str = None | ||
resource_type: Optional[str] = None | ||
resource_value: Optional[Any] = None | ||
|
||
@staticmethod | ||
def from_dict(param: Optional[Dict]): | ||
if not param: | ||
return None | ||
return ActionOutput.parse_obj(param) | ||
|
||
|
||
class Action(ABC, Generic[T]): | ||
def __init__(self): | ||
self.resource_loader: ResourceLoader = None | ||
|
||
def init_resource_loader(self, resource_loader: ResourceLoader): | ||
self.resource_loader = resource_loader | ||
|
||
@property | ||
def resource_need(self) -> Optional[ResourceType]: | ||
return None | ||
|
||
@property | ||
def render_protocal(self): | ||
raise NotImplementedError("The run method should be implemented in a subclass.") | ||
|
||
def render_prompt(self): | ||
if self.render_protocal is None: | ||
return None | ||
else: | ||
return self.render_protocal.render_prompt() | ||
|
||
def _create_example( | ||
self, | ||
model_type: Union[Type[BaseModel], Type[List[BaseModel]]], | ||
) -> Union[Dict[str, Any], List[Dict[str, Any]]]: | ||
if model_type is None: | ||
return None | ||
origin = get_origin(model_type) | ||
args = get_args(model_type) | ||
if origin is None: | ||
example = {} | ||
for field_name, field in model_type.__fields__.items(): | ||
field_info = field.field_info | ||
if field_info.description: | ||
example[field_name] = field_info.description | ||
elif field_info.default: | ||
example[field_name] = field_info.default | ||
else: | ||
example[field_name] = "" | ||
return example | ||
elif origin is list or origin is List: | ||
element_type = args[0] | ||
if issubclass(element_type, BaseModel): | ||
return [self._create_example(element_type)] | ||
else: | ||
raise TypeError("List elements must be BaseModel subclasses") | ||
else: | ||
raise ValueError( | ||
f"Model type {model_type} is not an instance of BaseModel." | ||
) | ||
|
||
@property | ||
def out_model_type(self) -> T: | ||
return None | ||
|
||
@property | ||
def ai_out_schema(self) -> Union[Dict[str, Any], List[Dict[str, Any]]]: | ||
if self.out_model_type is None: | ||
return None | ||
|
||
return f"""Please response in the following json format: | ||
{json.dumps(self._create_example(self.out_model_type), indent=2, ensure_ascii=False)} | ||
Make sure the response is correct json and can be parsed by Python json.loads. | ||
""" | ||
|
||
def _ai_mesage_2_json(self, ai_message: str) -> json: | ||
json_objects = find_json_objects(ai_message) | ||
json_count = len(json_objects) | ||
if json_count != 1: | ||
raise ValueError("Unable to obtain valid output.") | ||
return json_objects[0] | ||
|
||
def _input_convert(self, ai_message: str, cls: Type[T]) -> Union[T, List[T]]: | ||
json_result = self._ai_mesage_2_json(ai_message) | ||
if get_origin(cls) == list: | ||
inner_type = get_args(cls)[0] | ||
return [inner_type.parse_obj(item) for item in json_result] | ||
else: | ||
return cls.parse_obj(json_result) | ||
|
||
async def a_run( | ||
self, | ||
ai_message: str, | ||
resource: Optional[AgentResource] = None, | ||
rely_action_out: Optional[ActionOutput] = None, | ||
need_vis_render: bool = True, | ||
**kwargs, | ||
) -> ActionOutput: | ||
raise NotImplementedError("The run method should be implemented in a subclass.") |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import json | ||
import logging | ||
from typing import Any, Dict, List, Optional, Union | ||
|
||
from pydantic import BaseModel, Field | ||
|
||
from dbgpt.agent.actions.action import Action, ActionOutput, T | ||
from dbgpt.agent.common.schema import Status | ||
from dbgpt.agent.plugin.generator import PluginPromptGenerator | ||
from dbgpt.agent.resource.resource_api import AgentResource, ResourceType | ||
from dbgpt.agent.resource.resource_plugin_api import ResourcePluginClient | ||
from dbgpt.vis.tags.vis_plugin import Vis, VisPlugin | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class BlankAction(Action): | ||
def __init__(self, **kwargs): | ||
super().__init__(**kwargs) | ||
|
||
@property | ||
def resource_need(self) -> Optional[ResourceType]: | ||
return None | ||
|
||
@property | ||
def render_protocal(self) -> Optional[Vis]: | ||
return None | ||
|
||
@property | ||
def ai_out_schema(self) -> Union[Dict[str, Any], List[Dict[str, Any]]]: | ||
return None | ||
|
||
async def a_run( | ||
self, | ||
ai_message: str, | ||
resource: Optional[AgentResource] = None, | ||
rely_action_out: Optional[ActionOutput] = None, | ||
need_vis_render: bool = True, | ||
) -> ActionOutput: | ||
return ActionOutput(is_exe_success=True, content=ai_message, view=ai_message) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import json | ||
import logging | ||
from typing import Optional | ||
|
||
from pydantic import BaseModel, Field | ||
|
||
from dbgpt.agent.actions.action import ActionOutput, T | ||
from dbgpt.agent.resource.resource_api import AgentResource, ResourceType | ||
from dbgpt.agent.resource.resource_db_api import ResourceDbClient | ||
from dbgpt.vis.tags.vis_chart import Vis, VisChart | ||
|
||
from .action import Action | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class SqlInput(BaseModel): | ||
display_type: str = Field( | ||
..., | ||
description="The chart rendering method selected for SQL. If you don’t 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]): | ||
def __init__(self): | ||
self._render_protocal = VisChart() | ||
|
||
@property | ||
def resource_need(self) -> Optional[ResourceType]: | ||
return ResourceType.DB | ||
|
||
@property | ||
def render_protocal(self) -> Optional[Vis]: | ||
return self._render_protocal | ||
|
||
@property | ||
def out_model_type(self): | ||
return SqlInput | ||
|
||
async def a_run( | ||
self, | ||
ai_message: str, | ||
resource: Optional[AgentResource] = None, | ||
rely_action_out: Optional[ActionOutput] = None, | ||
need_vis_render: bool = True, | ||
) -> ActionOutput: | ||
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: | ||
resource_db_client: ResourceDbClient = ( | ||
self.resource_loader.get_resesource_api(self.resource_need) | ||
) | ||
if not resource_db_client: | ||
raise ValueError( | ||
"There is no implementation class bound to database resource execution!" | ||
) | ||
data_df = await resource_db_client.a_query_to_df(resource.value, param.sql) | ||
view = await self.render_protocal.disply( | ||
chart=json.loads(param.json()), data_df=data_df | ||
) | ||
return ActionOutput( | ||
is_exe_success=True, | ||
content=param.json(), | ||
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)}", | ||
) |
Oops, something went wrong.