mirror of
https://github.com/csunny/DB-GPT.git
synced 2025-09-14 05:31:40 +00:00
Native data AI application framework based on AWEL+AGENT (#1152)
Co-authored-by: Fangyin Cheng <staneyffer@gmail.com> Co-authored-by: lcx01800250 <lcx01800250@alibaba-inc.com> Co-authored-by: licunxing <864255598@qq.com> Co-authored-by: Aralhi <xiaoping0501@gmail.com> Co-authored-by: xuyuan23 <643854343@qq.com> Co-authored-by: aries_ckt <916701291@qq.com> Co-authored-by: hzh97 <2976151305@qq.com>
This commit is contained in:
@@ -4,7 +4,7 @@ import logging
|
||||
import uuid
|
||||
from abc import ABC
|
||||
from collections import defaultdict
|
||||
from typing import Any, Dict, List, Optional
|
||||
from typing import Any, Dict, List, Optional, Type
|
||||
|
||||
from fastapi import APIRouter, Body
|
||||
from fastapi.responses import StreamingResponse
|
||||
@@ -12,9 +12,12 @@ from fastapi.responses import StreamingResponse
|
||||
from dbgpt._private.config import Config
|
||||
from dbgpt.agent.agents.agent import Agent, AgentContext
|
||||
from dbgpt.agent.agents.agents_manage import agent_manage
|
||||
from dbgpt.agent.agents.base_agent_new import ConversableAgent
|
||||
from dbgpt.agent.agents.llm.llm import LLMConfig, LLMStrategyType
|
||||
from dbgpt.agent.agents.user_proxy_agent import UserProxyAgent
|
||||
from dbgpt.agent.common.schema import Status
|
||||
from dbgpt.agent.memory.gpts_memory import GptsMemory
|
||||
from dbgpt.agent.resource.resource_loader import ResourceLoader
|
||||
from dbgpt.app.openapi.api_view_model import Result
|
||||
from dbgpt.app.scene.base import ChatScene
|
||||
from dbgpt.component import BaseComponent, ComponentType, SystemApp
|
||||
@@ -26,12 +29,15 @@ from dbgpt.serve.agent.team.plan.team_auto_plan import AutoPlanChatManager
|
||||
from dbgpt.serve.conversation.serve import Serve as ConversationServe
|
||||
from dbgpt.util.json_utils import serialize
|
||||
|
||||
from ..db.gpts_app import GptsApp, GptsAppDao, GptsAppQuery
|
||||
from ..db.gpts_conversations_db import GptsConversationsDao, GptsConversationsEntity
|
||||
from ..db.gpts_manage_db import GptsInstanceDao, GptsInstanceEntity
|
||||
from ..resource_loader.datasource_load_client import DatasourceLoadClient
|
||||
from ..resource_loader.knowledge_space_load_client import KnowledgeSpaceLoadClient
|
||||
from ..resource_loader.plugin_hub_load_client import PluginHubLoadClient
|
||||
from ..team.base import TeamMode
|
||||
from ..team.layout.team_awel_layout import AwelLayoutChatManager
|
||||
from ..team.layout.team_awel_layout_new import AwelLayoutChatNewManager
|
||||
from .db_gpts_memory import MetaDbGptsMessageMemory, MetaDbGptsPlansMemory
|
||||
from .dbgpts import DbGptsInstance
|
||||
|
||||
CFG = Config()
|
||||
|
||||
@@ -70,8 +76,9 @@ class MultiAgents(BaseComponent, ABC):
|
||||
system_app.app.include_router(router, prefix="/api", tags=["Multi-Agents"])
|
||||
|
||||
def __init__(self):
|
||||
self.gpts_intance = GptsInstanceDao()
|
||||
self.gpts_conversations = GptsConversationsDao()
|
||||
|
||||
self.gpts_app = GptsAppDao()
|
||||
self.memory = GptsMemory(
|
||||
plans_memory=MetaDbGptsPlansMemory(),
|
||||
message_memory=MetaDbGptsMessageMemory(),
|
||||
@@ -81,68 +88,10 @@ class MultiAgents(BaseComponent, ABC):
|
||||
self.gpts_intance.add(entity)
|
||||
|
||||
def get_dbgpts(self, user_code: str = None, sys_code: str = None):
|
||||
return self.gpts_intance.get_by_user(user_code, sys_code)
|
||||
|
||||
async def _build_agent_context(
|
||||
self,
|
||||
name: str,
|
||||
conv_id: str,
|
||||
) -> AgentContext:
|
||||
gpts_instance: GptsInstanceEntity = self.gpts_intance.get_by_name(name)
|
||||
if gpts_instance is None:
|
||||
raise ValueError(f"can't find dbgpts!{name}")
|
||||
agents_names = json.loads(gpts_instance.gpts_agents)
|
||||
llm_models_priority = json.loads(gpts_instance.gpts_models)
|
||||
resource_db = (
|
||||
json.loads(gpts_instance.resource_db) if gpts_instance.resource_db else None
|
||||
apps = self.gpts_app.app_list(
|
||||
GptsAppQuery(user_code=user_code, sys_code=sys_code)
|
||||
)
|
||||
resource_knowledge = (
|
||||
json.loads(gpts_instance.resource_knowledge)
|
||||
if gpts_instance.resource_knowledge
|
||||
else None
|
||||
)
|
||||
resource_internet = (
|
||||
json.loads(gpts_instance.resource_internet)
|
||||
if gpts_instance.resource_internet
|
||||
else None
|
||||
)
|
||||
### init chat param
|
||||
worker_manager = CFG.SYSTEM_APP.get_component(
|
||||
ComponentType.WORKER_MANAGER_FACTORY, WorkerManagerFactory
|
||||
).create()
|
||||
llm_task = DefaultLLMClient(worker_manager, auto_convert_message=True)
|
||||
context: AgentContext = AgentContext(conv_id=conv_id, llm_provider=llm_task)
|
||||
context.gpts_name = gpts_instance.gpts_name
|
||||
context.resource_db = resource_db
|
||||
context.resource_internet = resource_internet
|
||||
context.resource_knowledge = resource_knowledge
|
||||
context.agents = agents_names
|
||||
|
||||
context.llm_models = await llm_task.models()
|
||||
context.model_priority = llm_models_priority
|
||||
return context, gpts_instance.team_mode
|
||||
|
||||
async def _build_chat_manager(
|
||||
self, context: AgentContext, mode: TeamMode, agents: List[Agent]
|
||||
):
|
||||
if mode == TeamMode.SINGLE_AGENT:
|
||||
manager = agents[0]
|
||||
else:
|
||||
if TeamMode.AUTO_PLAN == mode:
|
||||
manager = AutoPlanChatManager(
|
||||
agent_context=context,
|
||||
memory=self.memory,
|
||||
)
|
||||
elif TeamMode.AWEL_LAYOUT == mode:
|
||||
manager = AwelLayoutChatManager(
|
||||
agent_context=context,
|
||||
memory=self.memory,
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"Unknown Agent Team Mode!{mode}")
|
||||
manager.hire(agents)
|
||||
|
||||
return manager
|
||||
return apps
|
||||
|
||||
async def agent_chat(
|
||||
self,
|
||||
@@ -152,7 +101,8 @@ class MultiAgents(BaseComponent, ABC):
|
||||
user_code: str = None,
|
||||
sys_code: str = None,
|
||||
):
|
||||
context, team_mode = await self._build_agent_context(gpts_name, agent_conv_id)
|
||||
gpt_app: GptsApp = self.gpts_app.app_detail(gpts_name)
|
||||
|
||||
gpts_conversation = self.gpts_conversations.get_by_conv_id(agent_conv_id)
|
||||
is_retry_chat = True
|
||||
if not gpts_conversation:
|
||||
@@ -162,8 +112,9 @@ class MultiAgents(BaseComponent, ABC):
|
||||
conv_id=agent_conv_id,
|
||||
user_goal=user_query,
|
||||
gpts_name=gpts_name,
|
||||
team_mode=gpt_app.team_mode,
|
||||
state=Status.RUNNING.value,
|
||||
max_auto_reply_round=context.max_chat_round,
|
||||
max_auto_reply_round=0,
|
||||
auto_reply_count=0,
|
||||
user_code=user_code,
|
||||
sys_code=sys_code,
|
||||
@@ -171,26 +122,11 @@ class MultiAgents(BaseComponent, ABC):
|
||||
)
|
||||
|
||||
asyncio.create_task(
|
||||
multi_agents.agent_team_chat(user_query, context, team_mode, is_retry_chat)
|
||||
multi_agents.agent_team_chat_new(
|
||||
user_query, agent_conv_id, gpt_app, is_retry_chat
|
||||
)
|
||||
)
|
||||
|
||||
# def task_done_callback(task):
|
||||
# if task.cancelled():
|
||||
# logger.warning("The task was cancelled!")
|
||||
# elif task.exception():
|
||||
# logger.exception(f"The task raised an exception: {task.exception()}")
|
||||
# else:
|
||||
# logger.info(f"Callback: {task.result()}")
|
||||
# loop = asyncio.get_event_loop()
|
||||
# future = asyncio.run_coroutine_threadsafe(
|
||||
# self.stable_message(agent_conv_id), loop
|
||||
# )
|
||||
#
|
||||
# current_message.add_view_message(future.result())
|
||||
# current_message.end_current_round()
|
||||
# current_message.save_to_storage()
|
||||
#
|
||||
# task.add_done_callback(task_done_callback)
|
||||
async for chunk in multi_agents.chat_messages(agent_conv_id):
|
||||
if chunk:
|
||||
logger.info(chunk)
|
||||
@@ -244,68 +180,96 @@ class MultiAgents(BaseComponent, ABC):
|
||||
current_message.end_current_round()
|
||||
current_message.save_to_storage()
|
||||
|
||||
async def agent_team_chat(
|
||||
async def agent_team_chat_new(
|
||||
self,
|
||||
user_query: str,
|
||||
context: AgentContext,
|
||||
team_mode: TeamMode,
|
||||
conv_uid: str,
|
||||
gpts_app: GptsApp,
|
||||
is_retry_chat: bool = False,
|
||||
):
|
||||
"""Initiate an Agent-based conversation
|
||||
Args:
|
||||
user_query:
|
||||
context:
|
||||
team_mode:
|
||||
is_retry_chat:
|
||||
employees: List[Agent] = []
|
||||
# Prepare resource loader
|
||||
resource_loader = ResourceLoader()
|
||||
plugin_hub_loader = PluginHubLoadClient()
|
||||
resource_loader.register_resesource_api(plugin_hub_loader)
|
||||
datasource_loader = DatasourceLoadClient()
|
||||
resource_loader.register_resesource_api(datasource_loader)
|
||||
knowledge_space_loader = KnowledgeSpaceLoadClient()
|
||||
resource_loader.register_resesource_api(knowledge_space_loader)
|
||||
context: AgentContext = AgentContext(
|
||||
conv_id=conv_uid,
|
||||
gpts_app_name=gpts_app.app_name,
|
||||
language=gpts_app.language,
|
||||
)
|
||||
|
||||
Returns:
|
||||
# init llm provider
|
||||
### init chat param
|
||||
worker_manager = CFG.SYSTEM_APP.get_component(
|
||||
ComponentType.WORKER_MANAGER_FACTORY, WorkerManagerFactory
|
||||
).create()
|
||||
self.llm_provider = DefaultLLMClient(worker_manager, auto_convert_message=True)
|
||||
|
||||
"""
|
||||
try:
|
||||
agents = []
|
||||
for name in context.agents:
|
||||
cls = agent_manage.get_by_name(name)
|
||||
agent = cls(
|
||||
agent_context=context,
|
||||
memory=self.memory,
|
||||
)
|
||||
agents.append(agent)
|
||||
|
||||
manager = await self._build_chat_manager(
|
||||
context, TeamMode(team_mode), agents
|
||||
for record in gpts_app.details:
|
||||
cls: Type[ConversableAgent] = agent_manage.get_by_name(record.agent_name)
|
||||
llm_config = LLMConfig(
|
||||
llm_client=self.llm_provider,
|
||||
llm_strategy=LLMStrategyType(record.llm_strategy),
|
||||
strategy_context=record.llm_strategy_value,
|
||||
)
|
||||
user_proxy = UserProxyAgent(memory=self.memory, agent_context=context)
|
||||
|
||||
if not is_retry_chat:
|
||||
## dbgpts conversation save
|
||||
try:
|
||||
await user_proxy.a_initiate_chat(
|
||||
recipient=manager,
|
||||
message=user_query,
|
||||
memory=self.memory,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"chat abnormal termination!{str(e)}", e)
|
||||
self.gpts_conversations.update(context.conv_id, Status.FAILED.value)
|
||||
agent = (
|
||||
await cls()
|
||||
.bind(context)
|
||||
.bind(self.memory)
|
||||
.bind(llm_config)
|
||||
.bind(record.resources)
|
||||
.bind(resource_loader)
|
||||
.build()
|
||||
)
|
||||
employees.append(agent)
|
||||
|
||||
team_mode = TeamMode(gpts_app.team_mode)
|
||||
if team_mode == TeamMode.SINGLE_AGENT:
|
||||
recipient = employees[0]
|
||||
else:
|
||||
llm_config = LLMConfig(llm_client=self.llm_provider)
|
||||
if TeamMode.AUTO_PLAN == team_mode:
|
||||
manager = AutoPlanChatManager()
|
||||
elif TeamMode.AWEL_LAYOUT == team_mode:
|
||||
manager = AwelLayoutChatNewManager(dag=gpts_app.team_context)
|
||||
else:
|
||||
# retry chat
|
||||
self.gpts_conversations.update(context.conv_id, Status.RUNNING.value)
|
||||
try:
|
||||
await user_proxy.a_retry_chat(
|
||||
recipient=manager,
|
||||
memory=self.memory,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"chat abnormal termination!{str(e)}", e)
|
||||
self.gpts_conversations.update(context.conv_id, Status.FAILED.value)
|
||||
raise ValueError(f"Unknown Agent Team Mode!{team_mode}")
|
||||
manager = (
|
||||
await manager.bind(context)
|
||||
.bind(self.memory)
|
||||
.bind(llm_config)
|
||||
.bind(resource_loader)
|
||||
.build()
|
||||
)
|
||||
manager.hire(employees)
|
||||
recipient = manager
|
||||
|
||||
self.gpts_conversations.update(context.conv_id, Status.COMPLETE.value)
|
||||
return context.conv_id
|
||||
user_proxy: UserProxyAgent = (
|
||||
await UserProxyAgent()
|
||||
.bind(context)
|
||||
.bind(self.memory)
|
||||
.bind(resource_loader)
|
||||
.build()
|
||||
)
|
||||
if is_retry_chat:
|
||||
# retry chat
|
||||
self.gpts_conversations.update(conv_uid, Status.RUNNING.value)
|
||||
|
||||
try:
|
||||
await user_proxy.a_initiate_chat(
|
||||
recipient=recipient,
|
||||
message=user_query,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.exception("new chat compeletion failed!")
|
||||
self.gpts_conversations.update(context.conv_id, Status.FAILED.value)
|
||||
raise ValueError(f"Add chat failed!{str(e)}")
|
||||
logger.error(f"chat abnormal termination!{str(e)}", e)
|
||||
self.gpts_conversations.update(conv_uid, Status.FAILED.value)
|
||||
|
||||
self.gpts_conversations.update(conv_uid, Status.COMPLETE.value)
|
||||
return conv_uid
|
||||
|
||||
async def chat_messages(
|
||||
self, conv_id: str, user_code: str = None, system_app: str = None
|
||||
@@ -369,33 +333,6 @@ async def agents_list():
|
||||
return Result.failed(code="E30001", msg=str(e))
|
||||
|
||||
|
||||
@router.post("/v1/dbgpts/create", response_model=Result[str])
|
||||
async def create_dbgpts(gpts_instance: DbGptsInstance = Body()):
|
||||
logger.info(f"create_dbgpts:{gpts_instance}")
|
||||
try:
|
||||
multi_agents.gpts_create(
|
||||
GptsInstanceEntity(
|
||||
gpts_name=gpts_instance.gpts_name,
|
||||
gpts_describe=gpts_instance.gpts_describe,
|
||||
team_mode=gpts_instance.team_mode,
|
||||
resource_db=json.dumps(gpts_instance.resource_db.to_dict()),
|
||||
resource_internet=json.dumps(gpts_instance.resource_internet.to_dict()),
|
||||
resource_knowledge=json.dumps(
|
||||
gpts_instance.resource_knowledge.to_dict()
|
||||
),
|
||||
gpts_agents=json.dumps(gpts_instance.gpts_agents),
|
||||
gpts_models=json.dumps(gpts_instance.gpts_models),
|
||||
language=gpts_instance.language,
|
||||
user_code=gpts_instance.user_code,
|
||||
sys_code=gpts_instance.sys_code,
|
||||
)
|
||||
)
|
||||
return Result.succ(None)
|
||||
except Exception as e:
|
||||
logger.error(f"create_dbgpts failed:{str(e)}")
|
||||
return Result.failed(msg=str(e), code="E300002")
|
||||
|
||||
|
||||
@router.get("/v1/dbgpts/list", response_model=Result[str])
|
||||
async def get_dbgpts(user_code: str = None, sys_code: str = None):
|
||||
logger.info(f"get_dbgpts:{user_code},{sys_code}")
|
||||
|
@@ -5,31 +5,6 @@ from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from dbgpt.agent.agents.agent import AgentResource
|
||||
from dbgpt.serve.agent.team.base import TeamMode
|
||||
|
||||
|
||||
class AgentMode(Enum):
|
||||
PLAN_EXCUTE = "plan_excute"
|
||||
|
||||
|
||||
@dataclass
|
||||
class DbGptsInstance:
|
||||
gpts_name: str
|
||||
gpts_describe: str
|
||||
gpts_agents: list[str]
|
||||
team_mode: TeamMode
|
||||
resource_db: Optional[AgentResource] = None
|
||||
resource_internet: Optional[AgentResource] = None
|
||||
resource_knowledge: Optional[AgentResource] = None
|
||||
gpts_models: Optional[Dict[str, List[str]]] = None
|
||||
language: str = "en"
|
||||
user_code: str = None
|
||||
sys_code: str = None
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return dataclasses.asdict(self)
|
||||
|
||||
|
||||
@dataclass
|
||||
class DbGptsMessage:
|
||||
|
0
dbgpt/serve/agent/app/__init__.py
Normal file
0
dbgpt/serve/agent/app/__init__.py
Normal file
173
dbgpt/serve/agent/app/controller.py
Normal file
173
dbgpt/serve/agent/app/controller.py
Normal file
@@ -0,0 +1,173 @@
|
||||
import logging
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
from dbgpt._private.config import Config
|
||||
from dbgpt.agent.agents.agents_manage import agent_manage
|
||||
from dbgpt.agent.agents.llm.llm import LLMStrategyType
|
||||
from dbgpt.agent.resource.resource_api import ResourceType
|
||||
from dbgpt.app.knowledge.api import knowledge_space_service
|
||||
from dbgpt.app.knowledge.request.request import KnowledgeSpaceRequest
|
||||
from dbgpt.app.openapi.api_view_model import Result
|
||||
from dbgpt.serve.agent.app.gpts_server import available_llms
|
||||
from dbgpt.serve.agent.db.gpts_app import (
|
||||
GptsApp,
|
||||
GptsAppCollectionDao,
|
||||
GptsAppDao,
|
||||
GptsAppQuery,
|
||||
)
|
||||
from dbgpt.serve.agent.hub.plugin_hub import plugin_hub
|
||||
from dbgpt.serve.agent.team.base import TeamMode
|
||||
|
||||
CFG = Config()
|
||||
|
||||
router = APIRouter()
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
gpts_dao = GptsAppDao()
|
||||
collection_dao = GptsAppCollectionDao()
|
||||
|
||||
|
||||
@router.post("/v1/app/create")
|
||||
async def create(gpts_app: GptsApp):
|
||||
try:
|
||||
return Result.succ(gpts_dao.create(gpts_app))
|
||||
except Exception as ex:
|
||||
return Result.failed(code="E000X", msg=f"create app error: {ex}")
|
||||
|
||||
|
||||
@router.post("/v1/app/list")
|
||||
async def app_list(query: GptsAppQuery):
|
||||
try:
|
||||
return Result.succ(gpts_dao.app_list(query))
|
||||
except Exception as ex:
|
||||
return Result.failed(code="E000X", msg=f"query app error: {ex}")
|
||||
|
||||
|
||||
@router.post("/v1/app/detail")
|
||||
async def app_list(gpts_app: GptsApp):
|
||||
try:
|
||||
return Result.succ(gpts_dao.app_detail(gpts_app.app_code))
|
||||
except Exception as ex:
|
||||
return Result.failed(code="E000X", msg=f"query app error: {ex}")
|
||||
|
||||
|
||||
@router.post("/v1/app/edit")
|
||||
async def edit(gpts_app: GptsApp):
|
||||
try:
|
||||
return Result.succ(gpts_dao.edit(gpts_app))
|
||||
except Exception as ex:
|
||||
return Result.failed(code="E000X", msg=f"edit app error: {ex}")
|
||||
|
||||
|
||||
@router.get("/v1/agents/list")
|
||||
async def all_agents():
|
||||
try:
|
||||
return Result.succ(agent_manage.list_agents())
|
||||
except Exception as ex:
|
||||
return Result.failed(code="E000X", msg=f"query agents error: {ex}")
|
||||
|
||||
|
||||
@router.post("/v1/app/remove", response_model=Result[str])
|
||||
async def delete(gpts_app: GptsApp):
|
||||
try:
|
||||
gpts_dao.delete(gpts_app.app_code, gpts_app.user_code, gpts_app.sys_code)
|
||||
return Result.succ([])
|
||||
except Exception as ex:
|
||||
return Result.failed(code="E000X", msg=f"delete app error: {ex}")
|
||||
|
||||
|
||||
@router.post("/v1/app/collect", response_model=Result[str])
|
||||
async def collect(gpts_app: GptsApp):
|
||||
try:
|
||||
collection_dao.collect(gpts_app.app_code, gpts_app.user_code, gpts_app.sys_code)
|
||||
return Result.succ([])
|
||||
except Exception as ex:
|
||||
return Result.failed(code="E000X", msg=f"collect app error: {ex}")
|
||||
|
||||
|
||||
@router.post("/v1/app/uncollect", response_model=Result[str])
|
||||
async def uncollect(gpts_app: GptsApp):
|
||||
try:
|
||||
collection_dao.uncollect(
|
||||
gpts_app.app_code, gpts_app.user_code, gpts_app.sys_code
|
||||
)
|
||||
return Result.succ([])
|
||||
except Exception as ex:
|
||||
return Result.failed(code="E000X", msg=f"uncollect app error: {ex}")
|
||||
|
||||
|
||||
@router.get("/v1/team-mode/list")
|
||||
async def team_mode_list():
|
||||
try:
|
||||
return Result.succ([mode.value for mode in TeamMode])
|
||||
except Exception as ex:
|
||||
return Result.failed(code="E000X", msg=f"query team mode list error: {ex}")
|
||||
|
||||
|
||||
@router.get("/v1/resource-type/list")
|
||||
async def team_mode_list():
|
||||
try:
|
||||
return Result.succ([type.value for type in ResourceType])
|
||||
except Exception as ex:
|
||||
return Result.failed(code="E000X", msg=f"query resource type list error: {ex}")
|
||||
|
||||
|
||||
@router.get("/v1/llm-strategy/list")
|
||||
async def llm_strategies():
|
||||
try:
|
||||
return Result.succ([type.value for type in LLMStrategyType])
|
||||
except Exception as ex:
|
||||
return Result.failed(
|
||||
code="E000X", msg=f"query llm strategy type list error: {ex}"
|
||||
)
|
||||
|
||||
|
||||
@router.get("/v1/llm-strategy/value/list")
|
||||
async def llm_strategy_values(type: str):
|
||||
try:
|
||||
results = []
|
||||
match type:
|
||||
case LLMStrategyType.Priority.value:
|
||||
results = await available_llms()
|
||||
return Result.succ(results)
|
||||
except Exception as ex:
|
||||
return Result.failed(
|
||||
code="E000X", msg=f"query llm strategy type list error: {ex}"
|
||||
)
|
||||
|
||||
|
||||
@router.get("/v1/app/resources/list", response_model=Result[str])
|
||||
async def app_resources(
|
||||
type: str, name: str = None, user_code: str = None, sys_code: str = None
|
||||
):
|
||||
"""
|
||||
Get agent resources, such as db, knowledge, internet, plugin.
|
||||
"""
|
||||
try:
|
||||
results = []
|
||||
match type:
|
||||
case ResourceType.DB.value:
|
||||
dbs = CFG.LOCAL_DB_MANAGE.get_db_list()
|
||||
results = [db["db_name"] for db in dbs]
|
||||
if name:
|
||||
results = [r for r in results if name in r]
|
||||
case ResourceType.Knowledge.value:
|
||||
knowledge_spaces = knowledge_space_service.get_knowledge_space(
|
||||
KnowledgeSpaceRequest()
|
||||
)
|
||||
results = [ks.name for ks in knowledge_spaces]
|
||||
if name:
|
||||
results = [r for r in results if name in r]
|
||||
case ResourceType.Plugin.value:
|
||||
plugins = plugin_hub.get_my_plugin(user_code)
|
||||
results = [plugin.name for plugin in plugins]
|
||||
if name:
|
||||
results = [r for r in results if name in r]
|
||||
case ResourceType.Internet.value:
|
||||
return Result.succ(None)
|
||||
case ResourceType.File.value:
|
||||
return Result.succ(None)
|
||||
return Result.succ(results)
|
||||
except Exception as ex:
|
||||
return Result.failed(code="E000X", msg=f"query app resources error: {ex}")
|
22
dbgpt/serve/agent/app/gpts_server.py
Normal file
22
dbgpt/serve/agent/app/gpts_server.py
Normal file
@@ -0,0 +1,22 @@
|
||||
from dbgpt._private.config import Config
|
||||
from dbgpt.component import ComponentType
|
||||
from dbgpt.model.cluster import BaseModelController
|
||||
from dbgpt.serve.agent.db.gpts_app import GptsApp, GptsAppCollectionDao, GptsAppDao
|
||||
|
||||
CFG = Config()
|
||||
|
||||
collection_dao = GptsAppCollectionDao()
|
||||
gpts_dao = GptsAppDao()
|
||||
|
||||
|
||||
async def available_llms(worker_type: str = "llm"):
|
||||
controller = CFG.SYSTEM_APP.get_component(
|
||||
ComponentType.MODEL_CONTROLLER, BaseModelController
|
||||
)
|
||||
types = set()
|
||||
models = await controller.get_all_instances(healthy_only=True)
|
||||
for model in models:
|
||||
worker_name, wt = model.model_name.split("@")
|
||||
if wt == worker_type:
|
||||
types.add(worker_name)
|
||||
return list(types)
|
562
dbgpt/serve/agent/db/gpts_app.py
Normal file
562
dbgpt/serve/agent/db/gpts_app.py
Normal file
@@ -0,0 +1,562 @@
|
||||
import json
|
||||
import logging
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from itertools import groupby
|
||||
from typing import Any, Dict, List, Optional, Union
|
||||
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy import Column, DateTime, Integer, String, Text, UniqueConstraint
|
||||
|
||||
from dbgpt.agent.resource.resource_api import AgentResource
|
||||
from dbgpt.serve.agent.model import AwelTeamContext
|
||||
from dbgpt.serve.agent.team.base import TeamMode
|
||||
from dbgpt.storage.metadata import BaseDao, Model
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GptsAppDetail(BaseModel):
|
||||
app_code: Optional[str] = None
|
||||
app_name: Optional[str] = None
|
||||
agent_name: Optional[str] = None
|
||||
node_id: Optional[str] = None
|
||||
resources: Optional[list[AgentResource]] = None
|
||||
prompt_template: Optional[str] = None
|
||||
llm_strategy: Optional[str] = None
|
||||
llm_strategy_value: Optional[str] = None
|
||||
created_at: datetime = datetime.now()
|
||||
updated_at: datetime = datetime.now()
|
||||
|
||||
class Config:
|
||||
"""Configuration for this pydantic object."""
|
||||
|
||||
arbitrary_types_allowed = True
|
||||
|
||||
def to_dict(self):
|
||||
return {k: self._serialize(v) for k, v in self.__dict__.items()}
|
||||
|
||||
def _serialize(self, value):
|
||||
if isinstance(value, BaseModel):
|
||||
return value.to_dict()
|
||||
elif isinstance(value, list):
|
||||
return [self._serialize(item) for item in value]
|
||||
elif isinstance(value, dict):
|
||||
return {k: self._serialize(v) for k, v in value.items()}
|
||||
else:
|
||||
return value
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, d: Dict[str, Any]):
|
||||
return cls(
|
||||
app_code=d["app_code"],
|
||||
app_name=d["app_name"],
|
||||
agent_name=d["agent_name"],
|
||||
node_id=d["node_id"],
|
||||
resources=AgentResource.from_josn_list_str(d.get("resources", None)),
|
||||
prompt_template=d.get("prompt_template", None),
|
||||
llm_strategy=d.get("llm_strategy", None),
|
||||
llm_strategy_value=d.get("llm_strategy_value", None),
|
||||
created_at=d.get("created_at", None),
|
||||
updated_at=d.get("updated_at", None),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_entity(cls, entity):
|
||||
resources = AgentResource.from_josn_list_str(entity.resources)
|
||||
return cls(
|
||||
app_code=entity.app_code,
|
||||
app_name=entity.app_name,
|
||||
agent_name=entity.agent_name,
|
||||
node_id=entity.node_id,
|
||||
resources=resources,
|
||||
prompt_template=entity.prompt_template,
|
||||
llm_strategy=entity.llm_strategy,
|
||||
llm_strategy_value=entity.llm_strategy_value,
|
||||
created_at=entity.created_at,
|
||||
updated_at=entity.updated_at,
|
||||
)
|
||||
|
||||
|
||||
class GptsApp(BaseModel):
|
||||
app_code: Optional[str] = None
|
||||
app_name: Optional[str] = None
|
||||
app_describe: Optional[str] = None
|
||||
team_mode: Optional[str] = None
|
||||
language: Optional[str] = None
|
||||
team_context: Optional[Union[str, AwelTeamContext]] = None
|
||||
user_code: Optional[str] = None
|
||||
sys_code: Optional[str] = None
|
||||
is_collected: Optional[str] = None
|
||||
icon: Optional[str] = None
|
||||
created_at: datetime = datetime.now()
|
||||
updated_at: datetime = datetime.now()
|
||||
details: List[GptsAppDetail] = []
|
||||
|
||||
class Config:
|
||||
"""Configuration for this pydantic object."""
|
||||
|
||||
arbitrary_types_allowed = True
|
||||
|
||||
def to_dict(self):
|
||||
return {k: self._serialize(v) for k, v in self.__dict__.items()}
|
||||
|
||||
def _serialize(self, value):
|
||||
if isinstance(value, BaseModel):
|
||||
return value.to_dict()
|
||||
elif isinstance(value, list):
|
||||
return [self._serialize(item) for item in value]
|
||||
elif isinstance(value, dict):
|
||||
return {k: self._serialize(v) for k, v in value.items()}
|
||||
else:
|
||||
return value
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, d: Dict[str, Any]):
|
||||
return cls(
|
||||
app_code=d.get("app_code", None),
|
||||
app_name=d["app_name"],
|
||||
language=d["language"],
|
||||
app_describe=d["app_describe"],
|
||||
team_mode=d["team_mode"],
|
||||
team_context=d.get("team_context", None),
|
||||
user_code=d.get("user_code", None),
|
||||
sys_code=d.get("sys_code", None),
|
||||
is_collected=d.get("is_collected", None),
|
||||
created_at=d.get("created_at", None),
|
||||
updated_at=d.get("updated_at", None),
|
||||
details=d.get("details", None),
|
||||
)
|
||||
|
||||
|
||||
class GptsAppQuery(GptsApp):
|
||||
page_size: int = 100
|
||||
page_no: int = 1
|
||||
is_collected: Optional[str] = None
|
||||
|
||||
|
||||
class GptsAppCollection(BaseModel):
|
||||
app_code: Optional[str] = None
|
||||
user_code: Optional[str] = None
|
||||
sys_code: Optional[str] = None
|
||||
|
||||
def to_dict(self):
|
||||
return {k: self._serialize(v) for k, v in self.__dict__.items()}
|
||||
|
||||
def _serialize(self, value):
|
||||
if isinstance(value, BaseModel):
|
||||
return value.to_dict()
|
||||
elif isinstance(value, list):
|
||||
return [self._serialize(item) for item in value]
|
||||
elif isinstance(value, dict):
|
||||
return {k: self._serialize(v) for k, v in value.items()}
|
||||
else:
|
||||
return value
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, d: Dict[str, Any]):
|
||||
return cls(
|
||||
app_code=d.get("app_code", None),
|
||||
user_code=d.get("user_code", None),
|
||||
sys_code=d.get("sys_code", None),
|
||||
created_at=d.get("created_at", None),
|
||||
updated_at=d.get("updated_at", None),
|
||||
)
|
||||
|
||||
|
||||
class GptsAppCollectionEntity(Model):
|
||||
__tablename__ = "gpts_app_collection"
|
||||
id = Column(Integer, primary_key=True, comment="autoincrement id")
|
||||
app_code = Column(String(255), nullable=False, comment="Current AI assistant code")
|
||||
user_code = Column(String(255), nullable=True, comment="user code")
|
||||
sys_code = Column(String(255), nullable=True, comment="system app code")
|
||||
created_at = Column(DateTime, default=datetime.utcnow, comment="create time")
|
||||
updated_at = Column(
|
||||
DateTime,
|
||||
default=datetime.utcnow,
|
||||
onupdate=datetime.utcnow,
|
||||
comment="last update time",
|
||||
)
|
||||
|
||||
|
||||
class GptsAppEntity(Model):
|
||||
__tablename__ = "gpts_app"
|
||||
id = Column(Integer, primary_key=True, comment="autoincrement id")
|
||||
app_code = Column(String(255), nullable=False, comment="Current AI assistant code")
|
||||
app_name = Column(String(255), nullable=False, comment="Current AI assistant name")
|
||||
icon = Column(String(1024), nullable=True, comment="app icon, url")
|
||||
app_describe = Column(
|
||||
String(2255), nullable=False, comment="Current AI assistant describe"
|
||||
)
|
||||
language = Column(String(100), nullable=False, comment="gpts language")
|
||||
team_mode = Column(String(255), nullable=False, comment="Team work mode")
|
||||
team_context = Column(
|
||||
Text,
|
||||
nullable=True,
|
||||
comment="The execution logic and team member content that teams with different working modes rely on",
|
||||
)
|
||||
|
||||
user_code = Column(String(255), nullable=True, comment="user code")
|
||||
sys_code = Column(String(255), nullable=True, comment="system app code")
|
||||
|
||||
created_at = Column(DateTime, default=datetime.utcnow, comment="create time")
|
||||
updated_at = Column(
|
||||
DateTime,
|
||||
default=datetime.utcnow,
|
||||
onupdate=datetime.utcnow,
|
||||
comment="last update time",
|
||||
)
|
||||
|
||||
__table_args__ = (UniqueConstraint("app_name", name="uk_gpts_app"),)
|
||||
|
||||
|
||||
class GptsAppDetailEntity(Model):
|
||||
__tablename__ = "gpts_app_detail"
|
||||
id = Column(Integer, primary_key=True, comment="autoincrement id")
|
||||
app_code = Column(String(255), nullable=False, comment="Current AI assistant code")
|
||||
app_name = Column(String(255), nullable=False, comment="Current AI assistant name")
|
||||
agent_name = Column(String(255), nullable=False, comment=" Agent name")
|
||||
node_id = Column(
|
||||
String(255), nullable=False, comment="Current AI assistant Agent Node id"
|
||||
)
|
||||
resources = Column(Text, nullable=True, comment="Agent bind resource")
|
||||
prompt_template = Column(Text, nullable=True, comment="Agent bind template")
|
||||
llm_strategy = Column(String(25), nullable=True, comment="Agent use llm strategy")
|
||||
llm_strategy_value = Column(
|
||||
Text, nullable=True, comment="Agent use llm strategy value"
|
||||
)
|
||||
created_at = Column(DateTime, default=datetime.utcnow, comment="create time")
|
||||
updated_at = Column(
|
||||
DateTime,
|
||||
default=datetime.utcnow,
|
||||
onupdate=datetime.utcnow,
|
||||
comment="last update time",
|
||||
)
|
||||
|
||||
__table_args__ = (
|
||||
UniqueConstraint(
|
||||
"app_name", "agent_name", "node_id", name="uk_gpts_app_agent_node"
|
||||
),
|
||||
)
|
||||
|
||||
def to_dict(self):
|
||||
return {k: self._serialize(v) for k, v in self.__dict__.items()}
|
||||
|
||||
def _serialize(self, value):
|
||||
if isinstance(value, BaseModel):
|
||||
return value.to_dict()
|
||||
elif isinstance(value, list):
|
||||
return [self._serialize(item) for item in value]
|
||||
elif isinstance(value, dict):
|
||||
return {k: self._serialize(v) for k, v in value.items()}
|
||||
else:
|
||||
return value
|
||||
|
||||
|
||||
class GptsAppCollectionDao(BaseDao):
|
||||
def collect(
|
||||
self,
|
||||
app_code: str,
|
||||
user_code: Optional[str] = None,
|
||||
sys_code: Optional[str] = None,
|
||||
):
|
||||
with self.session() as session:
|
||||
app_qry = session.query(GptsAppCollectionEntity)
|
||||
if user_code:
|
||||
app_qry = app_qry.filter(GptsAppCollectionEntity.user_code == user_code)
|
||||
if sys_code:
|
||||
app_qry = app_qry.filter(GptsAppCollectionEntity.sys_code == sys_code)
|
||||
if app_code:
|
||||
app_qry = app_qry.filter(GptsAppCollectionEntity.app_code == app_code)
|
||||
app_entity = app_qry.one_or_none()
|
||||
if app_entity is not None:
|
||||
raise f"current app has been collected!"
|
||||
app_entity = GptsAppCollectionEntity(
|
||||
app_code=app_code,
|
||||
user_code=user_code,
|
||||
sys_code=sys_code,
|
||||
)
|
||||
session.add(app_entity)
|
||||
|
||||
def uncollect(
|
||||
self,
|
||||
app_code: str,
|
||||
user_code: Optional[str] = None,
|
||||
sys_code: Optional[str] = None,
|
||||
):
|
||||
with self.session() as session:
|
||||
app_qry = session.query(GptsAppCollectionEntity)
|
||||
if user_code:
|
||||
app_qry = app_qry.filter(GptsAppCollectionEntity.user_code == user_code)
|
||||
if sys_code:
|
||||
app_qry = app_qry.filter(GptsAppCollectionEntity.sys_code == sys_code)
|
||||
if app_code:
|
||||
app_qry = app_qry.filter(GptsAppCollectionEntity.app_code == app_code)
|
||||
app_entity = app_qry.one_or_none()
|
||||
if app_entity:
|
||||
session.delete(app_entity)
|
||||
session.commit()
|
||||
|
||||
def list(self, query: GptsAppCollection):
|
||||
with self.session() as session:
|
||||
app_qry = session.query(GptsAppCollectionEntity)
|
||||
if query.user_code:
|
||||
app_qry = app_qry.filter(
|
||||
GptsAppCollectionEntity.user_code == query.user_code
|
||||
)
|
||||
if query.sys_code:
|
||||
app_qry = app_qry.filter(
|
||||
GptsAppCollectionEntity.sys_code == query.sys_code
|
||||
)
|
||||
if query.app_code:
|
||||
app_qry = app_qry.filter(
|
||||
GptsAppCollectionEntity.app_code == query.app_code
|
||||
)
|
||||
res = app_qry.all()
|
||||
session.close()
|
||||
return res
|
||||
|
||||
|
||||
class GptsAppDao(BaseDao):
|
||||
def app_list(self, query: GptsAppQuery):
|
||||
collection_dao = GptsAppCollectionDao()
|
||||
gpts_collections = collection_dao.list(
|
||||
GptsAppCollection.from_dict(
|
||||
{"sys_code": query.sys_code, "user_code": query.user_code}
|
||||
)
|
||||
)
|
||||
app_codes = [gc.app_code for gc in gpts_collections]
|
||||
|
||||
with self.session() as session:
|
||||
app_qry = session.query(GptsAppEntity)
|
||||
if query.app_name:
|
||||
app_qry = app_qry.filter(
|
||||
GptsAppEntity.app_name.like(f"%{query.app_name}%")
|
||||
)
|
||||
if query.user_code:
|
||||
app_qry = app_qry.filter(GptsAppEntity.user_code == query.user_code)
|
||||
if query.sys_code:
|
||||
app_qry = app_qry.filter(GptsAppEntity.sys_code == query.sys_code)
|
||||
if query.is_collected and query.is_collected.lower() in ("true", "false"):
|
||||
app_qry = app_qry.filter(GptsAppEntity.app_code.in_(app_codes))
|
||||
app_qry = app_qry.order_by(GptsAppEntity.id.desc())
|
||||
app_qry = app_qry.offset((query.page_no - 1) * query.page_size).limit(
|
||||
query.page_size
|
||||
)
|
||||
results = app_qry.all()
|
||||
|
||||
result_app_codes = [res.app_code for res in results]
|
||||
app_details_group = self._group_app_details(result_app_codes, session)
|
||||
apps = []
|
||||
for app_info in results:
|
||||
app_details = app_details_group.get(app_info.app_code, [])
|
||||
|
||||
apps.append(
|
||||
GptsApp.from_dict(
|
||||
{
|
||||
"app_code": app_info.app_code,
|
||||
"app_name": app_info.app_name,
|
||||
"language": app_info.language,
|
||||
"app_describe": app_info.app_describe,
|
||||
"team_mode": app_info.team_mode,
|
||||
"team_context": _load_team_context(
|
||||
app_info.team_mode, app_info.team_context
|
||||
),
|
||||
"user_code": app_info.user_code,
|
||||
"sys_code": app_info.sys_code,
|
||||
"is_collected": "true"
|
||||
if app_info.app_code in app_codes
|
||||
else "false",
|
||||
"created_at": app_info.created_at,
|
||||
"updated_at": app_info.updated_at,
|
||||
"details": [
|
||||
GptsAppDetail.from_dict(item.to_dict())
|
||||
for item in app_details
|
||||
],
|
||||
}
|
||||
)
|
||||
)
|
||||
return apps
|
||||
|
||||
def _group_app_details(self, app_codes, session):
|
||||
app_detail_qry = session.query(GptsAppDetailEntity).filter(
|
||||
GptsAppDetailEntity.app_code.in_(app_codes)
|
||||
)
|
||||
app_details = app_detail_qry.all()
|
||||
app_details.sort(key=lambda x: x.app_code)
|
||||
app_details_group = {
|
||||
key: list(group)
|
||||
for key, group in groupby(app_details, key=lambda x: x.app_code)
|
||||
}
|
||||
return app_details_group
|
||||
|
||||
def app_detail(self, app_code: str):
|
||||
with self.session() as session:
|
||||
app_qry = session.query(GptsAppEntity).filter(
|
||||
GptsAppEntity.app_code == app_code
|
||||
)
|
||||
|
||||
app_info = app_qry.first()
|
||||
|
||||
app_detail_qry = session.query(GptsAppDetailEntity).filter(
|
||||
GptsAppDetailEntity.app_code == app_code
|
||||
)
|
||||
app_details = app_detail_qry.all()
|
||||
|
||||
app = GptsApp.from_dict(
|
||||
{
|
||||
"app_code": app_info.app_code,
|
||||
"app_name": app_info.app_name,
|
||||
"language": app_info.language,
|
||||
"app_describe": app_info.app_describe,
|
||||
"team_mode": app_info.team_mode,
|
||||
"team_context": _load_team_context(
|
||||
app_info.team_mode, app_info.team_context
|
||||
),
|
||||
"user_code": app_info.user_code,
|
||||
"sys_code": app_info.sys_code,
|
||||
"created_at": app_info.created_at,
|
||||
"updated_at": app_info.updated_at,
|
||||
"details": [
|
||||
GptsAppDetail.from_dict(item.to_dict()) for item in app_details
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
return app
|
||||
|
||||
def delete(
|
||||
self,
|
||||
app_code: str,
|
||||
user_code: Optional[str] = None,
|
||||
sys_code: Optional[str] = None,
|
||||
):
|
||||
"""
|
||||
To delete the application, you also need to delete the corresponding plug-ins and collections.
|
||||
"""
|
||||
if app_code is None:
|
||||
raise f"cannot delete app when app_code is None"
|
||||
with self.session() as session:
|
||||
app_qry = session.query(GptsAppEntity)
|
||||
app_qry = app_qry.filter(GptsAppEntity.app_code == app_code)
|
||||
app_qry.delete()
|
||||
|
||||
app_detail_qry = session.query(GptsAppDetailEntity).filter(
|
||||
GptsAppDetailEntity.app_code == app_code
|
||||
)
|
||||
app_detail_qry.delete()
|
||||
|
||||
app_collect_qry = session.query(GptsAppCollectionEntity).filter(
|
||||
GptsAppCollectionEntity.app_code == app_code
|
||||
)
|
||||
app_collect_qry.delete()
|
||||
|
||||
def create(self, gpts_app: GptsApp):
|
||||
with self.session() as session:
|
||||
app_entity = GptsAppEntity(
|
||||
app_code=str(uuid.uuid1()),
|
||||
app_name=gpts_app.app_name,
|
||||
app_describe=gpts_app.app_describe,
|
||||
team_mode=gpts_app.team_mode,
|
||||
team_context=_parse_team_context(gpts_app.team_context),
|
||||
language=gpts_app.language,
|
||||
user_code=gpts_app.user_code,
|
||||
sys_code=gpts_app.sys_code,
|
||||
created_at=gpts_app.created_at,
|
||||
updated_at=gpts_app.updated_at,
|
||||
icon=gpts_app.icon,
|
||||
)
|
||||
session.add(app_entity)
|
||||
|
||||
app_details = []
|
||||
for item in gpts_app.details:
|
||||
resource_dicts = [resource.to_dict() for resource in item.resources]
|
||||
if item.agent_name is None:
|
||||
raise f"agent name cannot be None"
|
||||
|
||||
app_details.append(
|
||||
GptsAppDetailEntity(
|
||||
app_code=app_entity.app_code,
|
||||
app_name=app_entity.app_name,
|
||||
agent_name=item.agent_name,
|
||||
node_id=str(uuid.uuid1()),
|
||||
resources=json.dumps(resource_dicts, ensure_ascii=False),
|
||||
prompt_template=item.prompt_template,
|
||||
llm_strategy=item.llm_strategy,
|
||||
llm_strategy_value=item.llm_strategy_value,
|
||||
created_at=item.created_at,
|
||||
updated_at=item.updated_at,
|
||||
)
|
||||
)
|
||||
session.add_all(app_details)
|
||||
gpts_app.app_code = app_entity.app_code
|
||||
return gpts_app
|
||||
|
||||
def edit(self, gpts_app: GptsApp):
|
||||
with self.session() as session:
|
||||
app_qry = session.query(GptsAppEntity)
|
||||
if gpts_app.app_code is None:
|
||||
raise f"app_code is None, don't allow to edit!"
|
||||
app_qry = app_qry.filter(GptsAppEntity.app_code == gpts_app.app_code)
|
||||
app_entity = app_qry.one()
|
||||
app_entity.app_name = gpts_app.app_name
|
||||
app_entity.app_describe = gpts_app.app_describe
|
||||
app_entity.language = gpts_app.language
|
||||
app_entity.team_mode = gpts_app.team_mode
|
||||
app_entity.icon = gpts_app.icon
|
||||
app_entity.team_context = _parse_team_context(gpts_app.team_context)
|
||||
session.merge(app_entity)
|
||||
|
||||
old_details = session.query(GptsAppDetailEntity).filter(
|
||||
GptsAppDetailEntity.app_code == gpts_app.app_code
|
||||
)
|
||||
old_details.delete()
|
||||
session.commit()
|
||||
|
||||
app_details = []
|
||||
for item in gpts_app.details:
|
||||
resource_dicts = [resource.to_dict() for resource in item.resources]
|
||||
app_details.append(
|
||||
GptsAppDetailEntity(
|
||||
app_code=gpts_app.app_code,
|
||||
app_name=gpts_app.app_name,
|
||||
agent_name=item.agent_name,
|
||||
node_id=str(uuid.uuid1()),
|
||||
resources=json.dumps(resource_dicts, ensure_ascii=False),
|
||||
prompt_template=item.prompt_template,
|
||||
llm_strategy=item.llm_strategy,
|
||||
llm_strategy_value=item.llm_strategy_value,
|
||||
created_at=item.created_at,
|
||||
updated_at=item.updated_at,
|
||||
)
|
||||
)
|
||||
session.add_all(app_details)
|
||||
return True
|
||||
|
||||
|
||||
def _parse_team_context(team_context: Optional[Union[str, AwelTeamContext]] = None):
|
||||
"""
|
||||
parse team_context to str
|
||||
"""
|
||||
if isinstance(team_context, AwelTeamContext):
|
||||
return team_context.json()
|
||||
return team_context
|
||||
|
||||
|
||||
def _load_team_context(
|
||||
team_mode: str = None, team_context: str = None
|
||||
) -> Union[str, AwelTeamContext]:
|
||||
"""
|
||||
load team_context to str or AwelTeamContext
|
||||
"""
|
||||
if team_mode is not None:
|
||||
match team_mode:
|
||||
case TeamMode.AWEL_LAYOUT.value:
|
||||
try:
|
||||
awel_team_ctx = AwelTeamContext(**json.loads(team_context))
|
||||
return awel_team_ctx
|
||||
except Exception as ex:
|
||||
logger.info(
|
||||
f"_load_team_context error, team_mode={team_mode}, team_context={team_context}, {ex}"
|
||||
)
|
||||
return team_context
|
@@ -25,6 +25,9 @@ class GptsConversationsEntity(Model):
|
||||
user_goal = Column(Text, nullable=False, comment="User's goals content")
|
||||
|
||||
gpts_name = Column(String(255), nullable=False, comment="The gpts name")
|
||||
team_mode = Column(
|
||||
String(255), nullable=False, comment="The conversation team mode"
|
||||
)
|
||||
state = Column(String(255), nullable=True, comment="The gpts state")
|
||||
|
||||
max_auto_reply_round = Column(
|
||||
|
@@ -28,6 +28,7 @@ class GptsInstanceEntity(Model):
|
||||
default=False,
|
||||
comment="Applications for sustainable dialogue",
|
||||
)
|
||||
|
||||
resource_db = Column(
|
||||
Text,
|
||||
nullable=True,
|
||||
|
@@ -1,73 +0,0 @@
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import Column, DateTime, Integer, String, Text, UniqueConstraint
|
||||
|
||||
from dbgpt.storage.metadata import BaseDao, Model
|
||||
|
||||
|
||||
class GptsInstanceEntity(Model):
|
||||
__tablename__ = "gpts_instance"
|
||||
id = Column(Integer, primary_key=True, comment="autoincrement id")
|
||||
|
||||
gpts_name = Column(String(255), nullable=False, comment="Current AI assistant name")
|
||||
gpts_describe = Column(
|
||||
String(2255), nullable=False, comment="Current AI assistant describe"
|
||||
)
|
||||
resource_db = Column(
|
||||
Text,
|
||||
nullable=True,
|
||||
comment="List of structured database names contained in the current gpts",
|
||||
)
|
||||
resource_internet = Column(
|
||||
Text,
|
||||
nullable=True,
|
||||
comment="Is it possible to retrieve information from the internet",
|
||||
)
|
||||
resource_knowledge = Column(
|
||||
Text,
|
||||
nullable=True,
|
||||
comment="List of unstructured database names contained in the current gpts",
|
||||
)
|
||||
gpts_agents = Column(
|
||||
String(1000),
|
||||
nullable=True,
|
||||
comment="List of agents names contained in the current gpts",
|
||||
)
|
||||
gpts_models = Column(
|
||||
String(1000),
|
||||
nullable=True,
|
||||
comment="List of llm model names contained in the current gpts",
|
||||
)
|
||||
language = Column(String(100), nullable=True, comment="gpts language")
|
||||
|
||||
user_code = Column(String(255), nullable=False, comment="user code")
|
||||
sys_code = Column(String(255), nullable=True, comment="system app code")
|
||||
|
||||
created_at = Column(DateTime, default=datetime.utcnow, comment="create time")
|
||||
updated_at = Column(
|
||||
DateTime,
|
||||
default=datetime.utcnow,
|
||||
onupdate=datetime.utcnow,
|
||||
comment="last update time",
|
||||
)
|
||||
|
||||
__table_args__ = (UniqueConstraint("gpts_name", name="uk_gpts"),)
|
||||
|
||||
|
||||
class GptsInstanceDao(BaseDao):
|
||||
def add(self, engity: GptsInstanceEntity):
|
||||
session = self.get_raw_session()
|
||||
session.add(engity)
|
||||
session.commit()
|
||||
id = engity.id
|
||||
session.close()
|
||||
return id
|
||||
|
||||
def get_by_name(self, name: str) -> GptsInstanceEntity:
|
||||
session = self.get_raw_session()
|
||||
gpts_instance = session.query(GptsInstanceEntity)
|
||||
if name:
|
||||
gpts_instance = gpts_instance.filter(GptsInstanceEntity.gpts_name == name)
|
||||
result = gpts_instance.first()
|
||||
session.close()
|
||||
return result
|
@@ -36,7 +36,9 @@ class GptsMessagesEntity(Model):
|
||||
)
|
||||
model_name = Column(String(255), nullable=True, comment="message generate model")
|
||||
rounds = Column(Integer, nullable=False, comment="dialogue turns")
|
||||
content = Column(Text, nullable=True, comment="Content of the speech")
|
||||
content = Column(
|
||||
Text(length=2**31 - 1), nullable=True, comment="Content of the speech"
|
||||
)
|
||||
current_gogal = Column(
|
||||
Text, nullable=True, comment="The target corresponding to the current message"
|
||||
)
|
||||
@@ -45,7 +47,9 @@ class GptsMessagesEntity(Model):
|
||||
Text, nullable=True, comment="Current conversation review info"
|
||||
)
|
||||
action_report = Column(
|
||||
Text, nullable=True, comment="Current conversation action report"
|
||||
Text(length=2**31 - 1),
|
||||
nullable=True,
|
||||
comment="Current conversation action report",
|
||||
)
|
||||
|
||||
role = Column(
|
||||
|
@@ -10,7 +10,7 @@ from dbgpt.app.openapi.api_view_model import Result
|
||||
from dbgpt.component import BaseComponent, ComponentType, SystemApp
|
||||
from dbgpt.configs.model_config import PLUGINS_DIR
|
||||
from dbgpt.serve.agent.db.plugin_hub_db import PluginHubEntity
|
||||
from dbgpt.serve.agent.hub.agent_hub import AgentHub
|
||||
from dbgpt.serve.agent.hub.plugin_hub import plugin_hub
|
||||
from dbgpt.serve.agent.model import (
|
||||
PagenationFilter,
|
||||
PagenationResult,
|
||||
@@ -22,8 +22,8 @@ router = APIRouter()
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ModuleAgent(BaseComponent, ABC):
|
||||
name = ComponentType.AGENT_HUB
|
||||
class ModulePlugin(BaseComponent, ABC):
|
||||
name = ComponentType.PLUGIN_HUB
|
||||
|
||||
def __init__(self):
|
||||
# load plugins
|
||||
@@ -48,14 +48,13 @@ class ModuleAgent(BaseComponent, ABC):
|
||||
return generator
|
||||
|
||||
|
||||
module_agent = ModuleAgent()
|
||||
module_plugin = ModulePlugin()
|
||||
|
||||
|
||||
@router.post("/v1/agent/hub/update", response_model=Result[str])
|
||||
async def agent_hub_update(update_param: PluginHubParam = Body()):
|
||||
logger.info(f"agent_hub_update:{update_param.__dict__}")
|
||||
async def plugin_hub_update(update_param: PluginHubParam = Body()):
|
||||
logger.info(f"plugin_hub_update:{update_param.__dict__}")
|
||||
try:
|
||||
agent_hub = AgentHub(PLUGINS_DIR)
|
||||
branch = (
|
||||
update_param.branch
|
||||
if update_param.branch is not None and len(update_param.branch) > 0
|
||||
@@ -67,7 +66,7 @@ async def agent_hub_update(update_param: PluginHubParam = Body()):
|
||||
else None
|
||||
)
|
||||
# TODO change it to async
|
||||
agent_hub.refresh_hub_from_git(update_param.url, branch, authorization)
|
||||
plugin_hub.refresh_hub_from_git(update_param.url, branch, authorization)
|
||||
return Result.succ(None)
|
||||
except Exception as e:
|
||||
logger.error("Agent Hub Update Error!", e)
|
||||
@@ -77,14 +76,13 @@ async def agent_hub_update(update_param: PluginHubParam = Body()):
|
||||
@router.post("/v1/agent/query", response_model=Result[str])
|
||||
async def get_agent_list(filter: PagenationFilter[PluginHubFilter] = Body()):
|
||||
logger.info(f"get_agent_list:{filter.__dict__}")
|
||||
agent_hub = AgentHub(PLUGINS_DIR)
|
||||
filter_enetity: PluginHubEntity = PluginHubEntity()
|
||||
if filter.filter:
|
||||
attrs = vars(filter.filter) # 获取原始对象的属性字典
|
||||
for attr, value in attrs.items():
|
||||
setattr(filter_enetity, attr, value) # 设置拷贝对象的属性值
|
||||
|
||||
datas, total_pages, total_count = agent_hub.hub_dao.list(
|
||||
datas, total_pages, total_count = plugin_hub.hub_dao.list(
|
||||
filter_enetity, filter.page_index, filter.page_size
|
||||
)
|
||||
result: PagenationResult[PluginHubEntity] = PagenationResult[PluginHubEntity]()
|
||||
@@ -100,8 +98,7 @@ async def get_agent_list(filter: PagenationFilter[PluginHubFilter] = Body()):
|
||||
@router.post("/v1/agent/my", response_model=Result[str])
|
||||
async def my_agents(user: str = None):
|
||||
logger.info(f"my_agents:{user}")
|
||||
agent_hub = AgentHub(PLUGINS_DIR)
|
||||
agents = agent_hub.get_my_plugin(user)
|
||||
agents = plugin_hub.get_my_plugin(user)
|
||||
agent_dicts = []
|
||||
for agent in agents:
|
||||
agent_dicts.append(agent.__dict__)
|
||||
@@ -113,10 +110,9 @@ async def my_agents(user: str = None):
|
||||
async def agent_install(plugin_name: str, user: str = None):
|
||||
logger.info(f"agent_install:{plugin_name},{user}")
|
||||
try:
|
||||
agent_hub = AgentHub(PLUGINS_DIR)
|
||||
agent_hub.install_plugin(plugin_name, user)
|
||||
plugin_hub.install_plugin(plugin_name, user)
|
||||
|
||||
module_agent.refresh_plugins()
|
||||
module_plugin.refresh_plugins()
|
||||
|
||||
return Result.succ(None)
|
||||
except Exception as e:
|
||||
@@ -128,10 +124,9 @@ async def agent_install(plugin_name: str, user: str = None):
|
||||
async def agent_uninstall(plugin_name: str, user: str = None):
|
||||
logger.info(f"agent_uninstall:{plugin_name},{user}")
|
||||
try:
|
||||
agent_hub = AgentHub(PLUGINS_DIR)
|
||||
agent_hub.uninstall_plugin(plugin_name, user)
|
||||
plugin_hub.uninstall_plugin(plugin_name, user)
|
||||
|
||||
module_agent.refresh_plugins()
|
||||
module_plugin.refresh_plugins()
|
||||
return Result.succ(None)
|
||||
except Exception as e:
|
||||
logger.error("Plugin Uninstall Error!", e)
|
||||
@@ -142,9 +137,8 @@ async def agent_uninstall(plugin_name: str, user: str = None):
|
||||
async def personal_agent_upload(doc_file: UploadFile = File(...), user: str = None):
|
||||
logger.info(f"personal_agent_upload:{doc_file.filename},{user}")
|
||||
try:
|
||||
agent_hub = AgentHub(PLUGINS_DIR)
|
||||
await agent_hub.upload_my_plugin(doc_file, user)
|
||||
module_agent.refresh_plugins()
|
||||
await plugin_hub.upload_my_plugin(doc_file, user)
|
||||
module_plugin.refresh_plugins()
|
||||
return Result.succ(None)
|
||||
except Exception as e:
|
||||
logger.error("Upload Personal Plugin Error!", e)
|
||||
|
@@ -10,6 +10,7 @@ from fastapi import UploadFile
|
||||
|
||||
from dbgpt.agent.common.schema import PluginStorageType
|
||||
from dbgpt.agent.plugin.plugins_util import scan_plugins, update_from_git
|
||||
from dbgpt.configs.model_config import PLUGINS_DIR
|
||||
|
||||
from ..db.my_plugin_db import MyPluginDao, MyPluginEntity
|
||||
from ..db.plugin_hub_db import PluginHubDao, PluginHubEntity
|
||||
@@ -20,7 +21,7 @@ DEFAULT_PLUGIN_REPO = "https://github.com/eosphoros-ai/DB-GPT-Plugins.git"
|
||||
TEMP_PLUGIN_PATH = ""
|
||||
|
||||
|
||||
class AgentHub:
|
||||
class PluginHub:
|
||||
def __init__(self, plugin_dir) -> None:
|
||||
self.hub_dao = PluginHubDao()
|
||||
self.my_plugin_dao = MyPluginDao()
|
||||
@@ -207,3 +208,6 @@ class AgentHub:
|
||||
if not user:
|
||||
user = Default_User
|
||||
return self.my_plugin_dao.get_by_user(user)
|
||||
|
||||
|
||||
plugin_hub = PluginHub(PLUGINS_DIR)
|
@@ -32,6 +32,59 @@ class PagenationResult(BaseModel, Generic[T]):
|
||||
}
|
||||
|
||||
|
||||
class AwelTeamContext(BaseModel):
|
||||
dag_id: str = Field(
|
||||
...,
|
||||
description="The unique id of dag",
|
||||
examples=["flow_dag_testflow_66d8e9d6-f32e-4540-a5bd-ea0648145d0e"],
|
||||
)
|
||||
uid: str = Field(
|
||||
default=None,
|
||||
description="The unique id of flow",
|
||||
examples=["66d8e9d6-f32e-4540-a5bd-ea0648145d0e"],
|
||||
)
|
||||
name: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The name of dag",
|
||||
)
|
||||
label: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The label of dag",
|
||||
)
|
||||
version: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The version of dag",
|
||||
)
|
||||
description: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The description of dag",
|
||||
)
|
||||
editable: bool = Field(
|
||||
default=False,
|
||||
description="is the dag is editable",
|
||||
examples=[True, False],
|
||||
)
|
||||
state: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The state of dag",
|
||||
)
|
||||
user_name: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The owner of current dag",
|
||||
)
|
||||
sys_code: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The system code of current dag",
|
||||
)
|
||||
flow_category: Optional[str] = Field(
|
||||
default="common",
|
||||
description="The flow category of current dag",
|
||||
)
|
||||
|
||||
def to_dict(self):
|
||||
return self.dict()
|
||||
|
||||
|
||||
@dataclass
|
||||
class PluginHubFilter(BaseModel):
|
||||
name: str
|
||||
|
0
dbgpt/serve/agent/resource_loader/__init__.py
Normal file
0
dbgpt/serve/agent/resource_loader/__init__.py
Normal file
64
dbgpt/serve/agent/resource_loader/datasource_load_client.py
Normal file
64
dbgpt/serve/agent/resource_loader/datasource_load_client.py
Normal file
@@ -0,0 +1,64 @@
|
||||
import logging
|
||||
from typing import Any, Dict, List, Optional, Tuple, Union
|
||||
|
||||
from dbgpt._private.config import Config
|
||||
from dbgpt.agent.resource.resource_api import AgentResource, ResourceType
|
||||
from dbgpt.agent.resource.resource_db_api import ResourceDbClient
|
||||
from dbgpt.component import ComponentType
|
||||
from dbgpt.util.executor_utils import ExecutorFactory, blocking_func_to_async
|
||||
from dbgpt.util.tracer import root_tracer, trace
|
||||
|
||||
CFG = Config()
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DatasourceLoadClient(ResourceDbClient):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
# The executor to submit blocking function
|
||||
self._executor = CFG.SYSTEM_APP.get_component(
|
||||
ComponentType.EXECUTOR_DEFAULT, ExecutorFactory
|
||||
).create()
|
||||
|
||||
def get_data_type(self, resource: AgentResource) -> str:
|
||||
conn = CFG.LOCAL_DB_MANAGE.get_connect(resource.value)
|
||||
return conn.db_type
|
||||
|
||||
async def a_get_schema_link(self, db: str, question: Optional[str] = None) -> str:
|
||||
try:
|
||||
from dbgpt.rag.summary.db_summary_client import DBSummaryClient
|
||||
except ImportError:
|
||||
raise ValueError("Could not import DBSummaryClient. ")
|
||||
client = DBSummaryClient(system_app=CFG.SYSTEM_APP)
|
||||
table_infos = None
|
||||
try:
|
||||
with root_tracer.start_span("ChatWithDbAutoExecute.get_db_summary"):
|
||||
table_infos = await blocking_func_to_async(
|
||||
self._executor,
|
||||
client.get_db_summary,
|
||||
db,
|
||||
question,
|
||||
CFG.KNOWLEDGE_SEARCH_TOP_SIZE,
|
||||
)
|
||||
except Exception as e:
|
||||
print("db summary find error!" + str(e))
|
||||
if not table_infos:
|
||||
conn = CFG.LOCAL_DB_MANAGE.get_connect(db)
|
||||
table_infos = await blocking_func_to_async(
|
||||
self._executor, conn.table_simple_info
|
||||
)
|
||||
|
||||
return table_infos
|
||||
|
||||
async def a_query_to_df(self, db: str, sql: str):
|
||||
conn = CFG.LOCAL_DB_MANAGE.get_connect(db)
|
||||
return conn.run_to_df(sql)
|
||||
|
||||
async def a_query(self, db: str, sql: str):
|
||||
conn = CFG.LOCAL_DB_MANAGE.get_connect(db)
|
||||
return conn.query_ex(sql)
|
||||
|
||||
async def a_run_sql(self, db: str, sql: str):
|
||||
conn = CFG.LOCAL_DB_MANAGE.get_connect(db)
|
||||
return conn.run(sql)
|
@@ -0,0 +1,43 @@
|
||||
import json
|
||||
import logging
|
||||
from typing import Any, Dict, List, Optional, Tuple, Union
|
||||
|
||||
from dbgpt._private.config import Config
|
||||
from dbgpt.agent.plugin.generator import PluginPromptGenerator
|
||||
from dbgpt.agent.resource.resource_api import AgentResource, ResourceType
|
||||
from dbgpt.agent.resource.resource_knowledge_api import ResourceKnowledgeClient
|
||||
from dbgpt.component import ComponentType
|
||||
from dbgpt.rag.chunk import Chunk
|
||||
from dbgpt.serve.agent.hub.controller import ModulePlugin
|
||||
from dbgpt.serve.rag.retriever.knowledge_space import KnowledgeSpaceRetriever
|
||||
from dbgpt.util.executor_utils import ExecutorFactory, blocking_func_to_async
|
||||
from dbgpt.util.tracer import root_tracer, trace
|
||||
|
||||
CFG = Config()
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class KnowledgeSpaceLoadClient(ResourceKnowledgeClient):
|
||||
async def a_get_space_desc(self, space_name) -> str:
|
||||
pass
|
||||
|
||||
async def a_get_kn(
|
||||
self, space_name: str, question: Optional[str] = None
|
||||
) -> List[Chunk]:
|
||||
kn_retriver = KnowledgeSpaceRetriever(space_name=space_name)
|
||||
chunks: List[Chunk] = kn_retriver.retrieve(question)
|
||||
return chunks
|
||||
|
||||
async def add_kn(
|
||||
self, space_name: str, kn_name: str, type: str, content: Optional[Any]
|
||||
):
|
||||
kn_retriver = KnowledgeSpaceRetriever(space_name=space_name)
|
||||
|
||||
pass
|
||||
|
||||
async def get_data_introduce(
|
||||
self, resource: AgentResource, question: Optional[str] = None
|
||||
) -> str:
|
||||
docs = await self.a_get_kn(resource.value, question)
|
||||
return "\n".join([doc.content for doc in docs])
|
40
dbgpt/serve/agent/resource_loader/plugin_hub_load_client.py
Normal file
40
dbgpt/serve/agent/resource_loader/plugin_hub_load_client.py
Normal file
@@ -0,0 +1,40 @@
|
||||
import json
|
||||
import logging
|
||||
from typing import Any, Dict, List, Optional, Tuple, Union
|
||||
|
||||
from dbgpt._private.config import Config
|
||||
from dbgpt.agent.plugin.generator import PluginPromptGenerator
|
||||
from dbgpt.agent.resource.resource_plugin_api import ResourcePluginClient
|
||||
from dbgpt.component import ComponentType
|
||||
from dbgpt.serve.agent.hub.controller import ModulePlugin
|
||||
from dbgpt.util.executor_utils import ExecutorFactory, blocking_func_to_async
|
||||
from dbgpt.util.tracer import root_tracer, trace
|
||||
|
||||
CFG = Config()
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PluginHubLoadClient(ResourcePluginClient):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
# The executor to submit blocking function
|
||||
self._executor = CFG.SYSTEM_APP.get_component(
|
||||
ComponentType.EXECUTOR_DEFAULT, ExecutorFactory
|
||||
).create()
|
||||
|
||||
async def a_load_plugin(
|
||||
self, value: str, plugin_generator: Optional[PluginPromptGenerator] = None
|
||||
) -> PluginPromptGenerator:
|
||||
logger.info(f"PluginHubLoadClient load plugin:{value}")
|
||||
plugins_prompt_generator = PluginPromptGenerator()
|
||||
plugins_prompt_generator.command_registry = CFG.command_registry
|
||||
|
||||
agent_module = CFG.SYSTEM_APP.get_component(
|
||||
ComponentType.PLUGIN_HUB, ModulePlugin
|
||||
)
|
||||
plugins_prompt_generator = agent_module.load_select_plugin(
|
||||
plugins_prompt_generator, json.dumps(value)
|
||||
)
|
||||
|
||||
return plugins_prompt_generator
|
@@ -2,8 +2,23 @@ from abc import ABC
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
from dbgpt.agent.agents.agent import Agent, AgentGenerateContext
|
||||
from dbgpt.agent.agents.agents_manage import agent_manage
|
||||
from dbgpt.agent.agents.base_agent_new import ConversableAgent
|
||||
from dbgpt.agent.agents.llm.llm import LLMConfig
|
||||
from dbgpt.core.awel import BranchFunc, BranchOperator, MapOperator
|
||||
from dbgpt.core.awel.flow import (
|
||||
IOField,
|
||||
OperatorCategory,
|
||||
OperatorType,
|
||||
Parameter,
|
||||
ResourceCategory,
|
||||
ViewMetadata,
|
||||
)
|
||||
from dbgpt.core.awel.trigger.base import Trigger
|
||||
from dbgpt.core.interface.message import ModelMessageRoleType
|
||||
from dbgpt.model.operators.llm_operator import MixinLLMOperator
|
||||
|
||||
from .agent_operator_resource import AwelAgent
|
||||
|
||||
|
||||
class BaseAgentOperator:
|
||||
@@ -12,7 +27,7 @@ class BaseAgentOperator:
|
||||
SHARE_DATA_KEY_MODEL_NAME = "share_data_key_agent_name"
|
||||
|
||||
def __init__(self, agent: Optional[Agent] = None):
|
||||
self._agent = agent
|
||||
self._agent: ConversableAgent = agent
|
||||
|
||||
@property
|
||||
def agent(self) -> Agent:
|
||||
@@ -32,9 +47,11 @@ class AgentOperator(
|
||||
async def map(self, input_value: AgentGenerateContext) -> AgentGenerateContext:
|
||||
now_rely_messages: List[Dict] = []
|
||||
|
||||
# input_value.message["current_gogal"] = (
|
||||
# self._agent.name + ":" + input_value.message["current_gogal"]
|
||||
# )
|
||||
# Isolate the message delivery mechanism and pass it to the operator
|
||||
input_value.message["current_gogal"] = (
|
||||
f"[{self._agent.name if self._agent.name else self._agent.profile}]:"
|
||||
+ input_value.message["content"]
|
||||
)
|
||||
###What was received was the User message
|
||||
human_message = input_value.message.copy()
|
||||
human_message["role"] = ModelMessageRoleType.HUMAN
|
||||
@@ -48,39 +65,20 @@ class AgentOperator(
|
||||
now_message, self._agent, input_value.reviewer, False
|
||||
)
|
||||
|
||||
### Retry on failure
|
||||
current_message = input_value.message
|
||||
final_sucess = False
|
||||
final_message = None
|
||||
while self.agent.current_retry_counter < self.agent.max_retry_count:
|
||||
verify_paas, reply_message = await self._agent.a_generate_reply(
|
||||
message=current_message,
|
||||
sender=input_value.sender,
|
||||
reviewer=input_value.reviewer,
|
||||
silent=input_value.silent,
|
||||
rely_messages=input_value.rely_messages,
|
||||
)
|
||||
final_message = reply_message
|
||||
if verify_paas:
|
||||
final_sucess = True
|
||||
break
|
||||
else:
|
||||
# retry
|
||||
current_message = {
|
||||
"content": reply_message["content"],
|
||||
"current_gogal": input_value.message.get("current_gogal", None),
|
||||
}
|
||||
await input_value.sender.a_send(
|
||||
current_message, self.agent, input_value.reviewer, False
|
||||
)
|
||||
self.agent.current_retry_counter += 1
|
||||
if not final_sucess:
|
||||
is_success, reply_message = await self._agent.a_generate_reply(
|
||||
recive_message=input_value.message,
|
||||
sender=input_value.sender,
|
||||
reviewer=input_value.reviewer,
|
||||
rely_messages=input_value.rely_messages,
|
||||
)
|
||||
|
||||
if not is_success:
|
||||
raise ValueError(
|
||||
f"After trying {self.agent.current_retry_counter} times, I still can't generate a valid answer. The current problem is:{final_message['content']}!"
|
||||
f"The task failed at step {self._agent.profile} and the attempt to repair it failed. The final reason for failure:{reply_message['content']}!"
|
||||
)
|
||||
|
||||
###What is sent is an AI message
|
||||
ai_message = final_message
|
||||
ai_message = reply_message
|
||||
ai_message["role"] = ModelMessageRoleType.AI
|
||||
now_rely_messages.append(ai_message)
|
||||
|
||||
@@ -92,3 +90,160 @@ class AgentOperator(
|
||||
rely_messages=now_rely_messages, ## Default single step transfer of information
|
||||
silent=input_value.silent,
|
||||
)
|
||||
|
||||
|
||||
class AwelAgentOperator(
|
||||
MixinLLMOperator, MapOperator[AgentGenerateContext, AgentGenerateContext]
|
||||
):
|
||||
metadata = ViewMetadata(
|
||||
label="Agent Operator",
|
||||
name="agent_operator",
|
||||
category=OperatorCategory.AGENT,
|
||||
description="The Agent operator.",
|
||||
parameters=[
|
||||
Parameter.build_from(
|
||||
"Agent",
|
||||
"awel_agent",
|
||||
AwelAgent,
|
||||
description="The dbgpt agent.",
|
||||
),
|
||||
],
|
||||
inputs=[
|
||||
IOField.build_from(
|
||||
"Agent Operator Request",
|
||||
"agent_operator_request",
|
||||
AgentGenerateContext,
|
||||
"The Agent Operator request.",
|
||||
)
|
||||
],
|
||||
outputs=[
|
||||
IOField.build_from(
|
||||
"Agent Operator Output",
|
||||
"agent_operator_output",
|
||||
AgentGenerateContext,
|
||||
description="The Agent Operator output.",
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
def __init__(self, awel_agent: AwelAgent, **kwargs):
|
||||
MixinLLMOperator.__init__(self)
|
||||
MapOperator.__init__(self, **kwargs)
|
||||
self.awel_agent = awel_agent
|
||||
|
||||
async def map(
|
||||
self,
|
||||
input_value: AgentGenerateContext,
|
||||
) -> AgentGenerateContext:
|
||||
now_rely_messages: List[Dict] = []
|
||||
|
||||
agent = await self.get_agent(input_value)
|
||||
|
||||
# Isolate the message delivery mechanism and pass it to the operator
|
||||
input_value.message["current_gogal"] = (
|
||||
f"[{agent.name if agent.name else agent.profile}]:"
|
||||
+ input_value.message["content"]
|
||||
)
|
||||
###What was received was the User message
|
||||
human_message = input_value.message.copy()
|
||||
human_message["role"] = ModelMessageRoleType.HUMAN
|
||||
now_rely_messages.append(human_message)
|
||||
|
||||
###Send a message (no reply required) and pass the message content
|
||||
now_message = input_value.message
|
||||
if input_value.rely_messages and len(input_value.rely_messages) > 0:
|
||||
now_message = input_value.rely_messages[-1]
|
||||
await input_value.sender.a_send(now_message, agent, input_value.reviewer, False)
|
||||
|
||||
is_success, reply_message = await agent.a_generate_reply(
|
||||
recive_message=input_value.message,
|
||||
sender=input_value.sender,
|
||||
reviewer=input_value.reviewer,
|
||||
rely_messages=input_value.rely_messages,
|
||||
)
|
||||
|
||||
if not is_success:
|
||||
raise ValueError(
|
||||
f"The task failed at step {agent.profile} and the attempt to repair it failed. The final reason for failure:{reply_message['content']}!"
|
||||
)
|
||||
|
||||
###What is sent is an AI message
|
||||
ai_message = reply_message
|
||||
ai_message["role"] = ModelMessageRoleType.AI
|
||||
now_rely_messages.append(ai_message)
|
||||
|
||||
### Handle user goals and outcome dependencies
|
||||
return AgentGenerateContext(
|
||||
message=input_value.message,
|
||||
sender=agent,
|
||||
reviewer=input_value.reviewer,
|
||||
rely_messages=now_rely_messages, ## Default single step transfer of information
|
||||
silent=input_value.silent,
|
||||
memory=input_value.memory,
|
||||
agent_context=input_value.agent_context,
|
||||
resource_loader=input_value.resource_loader,
|
||||
llm_client=input_value.llm_client,
|
||||
)
|
||||
|
||||
async def get_agent(
|
||||
self,
|
||||
input_value: AgentGenerateContext,
|
||||
):
|
||||
### agent build
|
||||
agent_cls: ConversableAgent = agent_manage.get_by_name(
|
||||
self.awel_agent.agent_profile
|
||||
)
|
||||
llm_config = self.awel_agent.llm_config
|
||||
|
||||
if not llm_config:
|
||||
if input_value.llm_client:
|
||||
llm_config = LLMConfig(llm_client=input_value.llm_client)
|
||||
else:
|
||||
llm_config = LLMConfig(llm_client=self.llm_client)
|
||||
|
||||
agent = (
|
||||
await agent_cls(name=self.awel_agent.role_name)
|
||||
.bind(input_value.memory)
|
||||
.bind(llm_config)
|
||||
.bind(input_value.agent_context)
|
||||
.bind(self.awel_agent.resources)
|
||||
.bind(input_value.resource_loader)
|
||||
.build()
|
||||
)
|
||||
return agent
|
||||
|
||||
|
||||
class AgentDummyTrigger(Trigger):
|
||||
"""Http trigger for AWEL.
|
||||
|
||||
Http trigger is used to trigger a DAG by http request.
|
||||
"""
|
||||
|
||||
metadata = ViewMetadata(
|
||||
label="Agent Trigger",
|
||||
name="agent_trigger",
|
||||
category=OperatorCategory.AGENT,
|
||||
operator_type=OperatorType.INPUT,
|
||||
description="Trigger your workflow by agent",
|
||||
inputs=[],
|
||||
parameters=[],
|
||||
outputs=[
|
||||
IOField.build_from(
|
||||
"Agent Operator Context",
|
||||
"agent_operator_context",
|
||||
AgentGenerateContext,
|
||||
description="The Agent Operator output.",
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
"""Initialize a HttpTrigger."""
|
||||
super().__init__(**kwargs)
|
||||
|
||||
async def trigger(self) -> None:
|
||||
"""Trigger the DAG. Not used in HttpTrigger."""
|
||||
pass
|
||||
|
182
dbgpt/serve/agent/team/layout/agent_operator_resource.py
Normal file
182
dbgpt/serve/agent/team/layout/agent_operator_resource.py
Normal file
@@ -0,0 +1,182 @@
|
||||
from typing import Any, Dict, List, Optional, Union
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from dbgpt._private.pydantic import root_validator
|
||||
from dbgpt.agent.agents.agents_manage import agent_manage
|
||||
from dbgpt.agent.agents.base_agent_new import ConversableAgent
|
||||
from dbgpt.agent.agents.llm.llm import LLMConfig, LLMStrategyType
|
||||
from dbgpt.agent.resource.resource_api import AgentResource, ResourceType
|
||||
from dbgpt.core import LLMClient
|
||||
from dbgpt.core.awel.flow import (
|
||||
IOField,
|
||||
OperatorCategory,
|
||||
OperatorType,
|
||||
OptionValue,
|
||||
Parameter,
|
||||
ResourceCategory,
|
||||
ViewMetadata,
|
||||
register_resource,
|
||||
)
|
||||
from dbgpt.core.interface.operators.prompt_operator import CommonChatPromptTemplate
|
||||
|
||||
|
||||
@register_resource(
|
||||
label="Awel Agent Resource",
|
||||
name="agent_operator_resource",
|
||||
description="The Agent Resource.",
|
||||
category=ResourceCategory.AGENT,
|
||||
parameters=[
|
||||
Parameter.build_from(
|
||||
label="Agent Resource Type",
|
||||
name="agent_resource_type",
|
||||
type=str,
|
||||
optional=True,
|
||||
default=None,
|
||||
options=[
|
||||
OptionValue(label=item.name, name=item.value, value=item.value)
|
||||
for item in ResourceType
|
||||
],
|
||||
),
|
||||
Parameter.build_from(
|
||||
label="Agent Resource Name",
|
||||
name="agent_resource_name",
|
||||
type=str,
|
||||
optional=True,
|
||||
default=None,
|
||||
description="The agent resource name.",
|
||||
),
|
||||
Parameter.build_from(
|
||||
label="Agent Resource Value",
|
||||
name="agent_resource_value",
|
||||
type=str,
|
||||
optional=True,
|
||||
default=None,
|
||||
description="The agent resource value.",
|
||||
),
|
||||
],
|
||||
)
|
||||
class AwelAgentResource(AgentResource):
|
||||
@root_validator(pre=True)
|
||||
def pre_fill(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""Pre fill the agent ResourceType"""
|
||||
|
||||
name = values.pop("agent_resource_name")
|
||||
type = values.pop("agent_resource_type")
|
||||
value = values.pop("agent_resource_value")
|
||||
|
||||
values["name"] = name
|
||||
values["type"] = ResourceType(type)
|
||||
values["value"] = value
|
||||
|
||||
return values
|
||||
|
||||
|
||||
@register_resource(
|
||||
label="Awel Agent LLM Config",
|
||||
name="agent_operator_llm_config",
|
||||
description="The Agent LLM Config.",
|
||||
category=ResourceCategory.AGENT,
|
||||
parameters=[
|
||||
Parameter.build_from(
|
||||
"LLM Client",
|
||||
"llm_client",
|
||||
LLMClient,
|
||||
optional=True,
|
||||
default=None,
|
||||
description="The LLM Client.",
|
||||
),
|
||||
Parameter.build_from(
|
||||
label="Agent LLM Strategy",
|
||||
name="llm_strategy",
|
||||
type=str,
|
||||
optional=True,
|
||||
default=None,
|
||||
options=[
|
||||
OptionValue(label=item.name, name=item.value, value=item.value)
|
||||
for item in LLMStrategyType
|
||||
],
|
||||
description="The Agent LLM Strategy.",
|
||||
),
|
||||
Parameter.build_from(
|
||||
label="Agent LLM Strategy Value",
|
||||
name="strategy_context",
|
||||
type=str,
|
||||
optional=True,
|
||||
default=None,
|
||||
description="The agent LLM Strategy Value.",
|
||||
),
|
||||
],
|
||||
)
|
||||
class AwelAgentConfig(LLMConfig):
|
||||
@root_validator(pre=True)
|
||||
def pre_fill(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""Pre fill the agent ResourceType"""
|
||||
return values
|
||||
|
||||
|
||||
@register_resource(
|
||||
label="Awel Layout Agent",
|
||||
name="agent_operator_agent",
|
||||
description="The Agent to build the Agent Operator.",
|
||||
category=ResourceCategory.AGENT,
|
||||
parameters=[
|
||||
Parameter.build_from(
|
||||
label="Agent Profile",
|
||||
name="agent_profile",
|
||||
type=str,
|
||||
description="Which agent want use.",
|
||||
options=[
|
||||
OptionValue(label=item["name"], name=item["name"], value=item["name"])
|
||||
for item in agent_manage.list_agents()
|
||||
],
|
||||
),
|
||||
Parameter.build_from(
|
||||
label="Role Name",
|
||||
name="role_name",
|
||||
type=str,
|
||||
optional=True,
|
||||
default=None,
|
||||
description="The agent role name.",
|
||||
),
|
||||
Parameter.build_from(
|
||||
label="Agent Resource",
|
||||
name="agent_resource",
|
||||
type=AwelAgentResource,
|
||||
optional=True,
|
||||
default=None,
|
||||
description="The agent resource.",
|
||||
),
|
||||
Parameter.build_from(
|
||||
label="Agent LLM Config",
|
||||
name="agent_llm_Config",
|
||||
type=AwelAgentConfig,
|
||||
optional=True,
|
||||
default=None,
|
||||
description="The agent llm config.",
|
||||
),
|
||||
],
|
||||
)
|
||||
class AwelAgent(BaseModel):
|
||||
agent_profile: str
|
||||
role_name: Optional[str] = None
|
||||
llm_config: Optional[LLMConfig] = None
|
||||
resources: List[AgentResource] = Field(default_factory=list)
|
||||
|
||||
class Config:
|
||||
arbitrary_types_allowed = True
|
||||
|
||||
@root_validator(pre=True)
|
||||
def pre_fill(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""Pre fill the agent ResourceType"""
|
||||
|
||||
resource = values.pop("agent_resource")
|
||||
llm_config = values.pop("agent_llm_Config")
|
||||
|
||||
if resource is not None:
|
||||
values["resources"] = [resource]
|
||||
|
||||
if llm_config is not None:
|
||||
values["llm_config"] = llm_config
|
||||
|
||||
return values
|
@@ -1,10 +1,10 @@
|
||||
import logging
|
||||
import sys
|
||||
from typing import Any, Optional
|
||||
from typing import Any, List, Optional
|
||||
|
||||
from dbgpt.agent.actions.action import ActionOutput, T
|
||||
from dbgpt.agent.agents.agent import Agent, AgentContext, AgentGenerateContext
|
||||
from dbgpt.agent.agents.base_agent_new import ConversableAgent
|
||||
from dbgpt.agent.agents.base_team import ManagerAgent
|
||||
from dbgpt.agent.memory.gpts_memory import GptsMemory
|
||||
from dbgpt.core.awel import DAG
|
||||
from dbgpt.serve.agent.team.layout.agent_operator import AgentOperator
|
||||
|
||||
@@ -12,44 +12,27 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AwelLayoutChatManager(ManagerAgent):
|
||||
NAME = "layout_manager"
|
||||
profile: str = "AwelManager"
|
||||
goal: str = (
|
||||
"Promote and solve user problems according to the process arranged by Awel."
|
||||
)
|
||||
constraints: List[str] = []
|
||||
desc: str = goal
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
memory: GptsMemory,
|
||||
agent_context: AgentContext,
|
||||
# unlimited consecutive auto reply by default
|
||||
max_consecutive_auto_reply: Optional[int] = sys.maxsize,
|
||||
human_input_mode: Optional[str] = "NEVER",
|
||||
describe: Optional[str] = "layout chat manager.",
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(
|
||||
name=self.NAME,
|
||||
describe=describe,
|
||||
memory=memory,
|
||||
max_consecutive_auto_reply=max_consecutive_auto_reply,
|
||||
human_input_mode=human_input_mode,
|
||||
agent_context=agent_context,
|
||||
**kwargs,
|
||||
)
|
||||
# Allow async chat if initiated using a_initiate_chat
|
||||
self.register_reply(
|
||||
Agent,
|
||||
AwelLayoutChatManager.a_run_chat,
|
||||
)
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
async def a_run_chat(
|
||||
async def a_act(
|
||||
self,
|
||||
message: Optional[str] = None,
|
||||
sender: Optional[Agent] = None,
|
||||
reviewer: Agent = None,
|
||||
config: Optional[Any] = None,
|
||||
):
|
||||
message: Optional[str],
|
||||
sender: Optional[ConversableAgent] = None,
|
||||
reviewer: Optional[ConversableAgent] = None,
|
||||
) -> Optional[ActionOutput]:
|
||||
try:
|
||||
# TODO Use programmed DAG
|
||||
last_node: AgentOperator = None
|
||||
with DAG(
|
||||
f"layout_agents_{self.agent_context.gpts_name}_{self.agent_context.conv_id}"
|
||||
f"layout_agents_{self.agent_context.gpts_app_name}_{self.agent_context.conv_id}"
|
||||
) as dag:
|
||||
for agent in self.agents:
|
||||
now_node = AgentOperator(agent=agent)
|
||||
@@ -59,12 +42,13 @@ class AwelLayoutChatManager(ManagerAgent):
|
||||
last_node >> now_node
|
||||
last_node = now_node
|
||||
|
||||
start_message = {
|
||||
"content": message,
|
||||
"current_gogal": message,
|
||||
}
|
||||
start_message_context: AgentGenerateContext = AgentGenerateContext(
|
||||
message=start_message, sender=self, reviewer=reviewer
|
||||
message={
|
||||
"content": message,
|
||||
"current_gogal": message,
|
||||
},
|
||||
sender=self,
|
||||
reviewer=reviewer,
|
||||
)
|
||||
final_generate_context: AgentGenerateContext = await last_node.call(
|
||||
call_data=start_message_context
|
||||
@@ -76,14 +60,14 @@ class AwelLayoutChatManager(ManagerAgent):
|
||||
last_message, self, start_message_context.reviewer, False
|
||||
)
|
||||
|
||||
return True, {
|
||||
"is_exe_success": True,
|
||||
"content": last_message.get("content", None),
|
||||
"view": last_message.get("view", None),
|
||||
}
|
||||
return ActionOutput(
|
||||
content=last_message.get("content", None),
|
||||
view=last_message.get("view", None),
|
||||
)
|
||||
except Exception as e:
|
||||
logger.exception("DAG run failed!")
|
||||
return True, {
|
||||
"content": f"Failed to complete goal! {str(e)}",
|
||||
"is_exe_success": False,
|
||||
}
|
||||
logger.exception(f"DAG run failed!{str(e)}")
|
||||
|
||||
return ActionOutput(
|
||||
is_exe_success=False,
|
||||
content=f"Failed to complete goal! {str(e)}",
|
||||
)
|
||||
|
90
dbgpt/serve/agent/team/layout/team_awel_layout_new.py
Normal file
90
dbgpt/serve/agent/team/layout/team_awel_layout_new.py
Normal file
@@ -0,0 +1,90 @@
|
||||
import json
|
||||
import logging
|
||||
from typing import Any, List, Optional
|
||||
|
||||
from pydantic import BaseModel, Field, validator
|
||||
|
||||
from dbgpt._private.config import Config
|
||||
from dbgpt.agent.actions.action import ActionOutput, T
|
||||
from dbgpt.agent.agents.agent import Agent, AgentContext, AgentGenerateContext
|
||||
from dbgpt.agent.agents.base_agent_new import ConversableAgent
|
||||
from dbgpt.agent.agents.base_team import ManagerAgent
|
||||
from dbgpt.core.awel import DAG
|
||||
from dbgpt.core.awel.dag.dag_manager import DAGManager
|
||||
from dbgpt.serve.agent.model import AwelTeamContext
|
||||
from dbgpt.serve.agent.team.layout.agent_operator import AwelAgentOperator
|
||||
from dbgpt.serve.flow.api.endpoints import get_service as get_flow_service
|
||||
from dbgpt.serve.flow.service.service import Service as FlowService
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
CFG = Config()
|
||||
|
||||
|
||||
class AwelLayoutChatNewManager(ManagerAgent):
|
||||
dag: AwelTeamContext = Field(...)
|
||||
profile: str = "AwelNewManager"
|
||||
goal: str = (
|
||||
"Promote and solve user problems according to the process arranged by Awel."
|
||||
)
|
||||
constraints: List[str] = []
|
||||
desc: str = goal
|
||||
|
||||
@validator("dag")
|
||||
def check_dag(cls, value):
|
||||
assert value is not None and value != "", "dag must not be empty"
|
||||
return value
|
||||
|
||||
async def a_act(
|
||||
self,
|
||||
message: Optional[str],
|
||||
sender: Optional[ConversableAgent] = None,
|
||||
reviewer: Optional[ConversableAgent] = None,
|
||||
) -> Optional[ActionOutput]:
|
||||
try:
|
||||
flow_service: FlowService = get_flow_service()
|
||||
flow = flow_service.get({"uid": self.dag.uid})
|
||||
_dag_manager = DAGManager.get_instance(CFG.SYSTEM_APP)
|
||||
|
||||
dag_id = flow.dag_id
|
||||
|
||||
agent_dag = _dag_manager.dag_map[dag_id]
|
||||
if agent_dag is None:
|
||||
raise ValueError(
|
||||
f"The configured flow cannot be found![{self.dag.name}]"
|
||||
)
|
||||
last_node: AwelAgentOperator = agent_dag.leaf_nodes[0]
|
||||
|
||||
start_message_context: AgentGenerateContext = AgentGenerateContext(
|
||||
message={
|
||||
"content": message,
|
||||
"current_gogal": message,
|
||||
},
|
||||
sender=self,
|
||||
reviewer=reviewer,
|
||||
memory=self.memory,
|
||||
agent_context=self.agent_context,
|
||||
resource_loader=self.resource_loader,
|
||||
llm_client=self.llm_config.llm_client,
|
||||
)
|
||||
final_generate_context: AgentGenerateContext = await last_node.call(
|
||||
call_data=start_message_context
|
||||
)
|
||||
last_message = final_generate_context.rely_messages[-1]
|
||||
|
||||
last_agent = await last_node.get_agent(final_generate_context)
|
||||
await last_agent.a_send(
|
||||
last_message, self, start_message_context.reviewer, False
|
||||
)
|
||||
|
||||
return ActionOutput(
|
||||
content=last_message.get("content", None),
|
||||
view=last_message.get("view", None),
|
||||
)
|
||||
except Exception as e:
|
||||
logger.exception(f"DAG run failed!{str(e)}")
|
||||
|
||||
return ActionOutput(
|
||||
is_exe_success=False,
|
||||
content=f"Failed to complete goal! {str(e)}",
|
||||
)
|
121
dbgpt/serve/agent/team/plan/plan_action.py
Normal file
121
dbgpt/serve/agent/team/plan/plan_action.py
Normal file
@@ -0,0 +1,121 @@
|
||||
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.agents.agent import AgentContext
|
||||
from dbgpt.agent.common.schema import Status
|
||||
from dbgpt.agent.memory.base import GptsPlan
|
||||
from dbgpt.agent.memory.gpts_memory import GptsPlansMemory
|
||||
from dbgpt.agent.resource.resource_api import AgentResource, ResourceType
|
||||
from dbgpt.vis.tags.vis_agent_plans import Vis, VisAgentPlans
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PlanInput(BaseModel):
|
||||
serial_number: int = Field(
|
||||
0,
|
||||
description="子任务的步骤编号",
|
||||
)
|
||||
agent: str = Field(..., description="用来完成当前步骤的智能代理")
|
||||
content: str = Field(..., description="当前步骤的任务内容,确保可以被智能代理执行")
|
||||
rely: str = Field(..., description="当前任务执行依赖的其他任务serial_number, 如:1,2,3, 无依赖为空")
|
||||
|
||||
|
||||
class PlanAction(Action[List[PlanInput]]):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self._render_protocal = VisAgentPlans()
|
||||
|
||||
@property
|
||||
def resource_need(self) -> Optional[ResourceType]:
|
||||
return None
|
||||
|
||||
@property
|
||||
def render_protocal(self) -> Optional[Vis]:
|
||||
return self._render_protocal
|
||||
|
||||
@property
|
||||
def out_model_type(self):
|
||||
return List[PlanInput]
|
||||
|
||||
async def a_run(
|
||||
self,
|
||||
ai_message: str,
|
||||
context: AgentContext,
|
||||
plans_memory: GptsPlansMemory,
|
||||
resource: Optional[AgentResource] = None,
|
||||
rely_action_out: Optional[ActionOutput] = None,
|
||||
need_vis_render: bool = True,
|
||||
) -> ActionOutput:
|
||||
try:
|
||||
param: List[PlanInput] = self._input_convert(ai_message, List[PlanInput])
|
||||
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:
|
||||
rensponse_succ = True
|
||||
plan_objects = []
|
||||
try:
|
||||
for item in param:
|
||||
plan = GptsPlan(
|
||||
conv_id=context.conv_id,
|
||||
sub_task_num=item.serial_number,
|
||||
sub_task_content=item.content,
|
||||
)
|
||||
plan.resource_name = ""
|
||||
plan.max_retry_times = context.max_retry_round
|
||||
plan.sub_task_agent = item.agent
|
||||
plan.sub_task_title = item.content
|
||||
plan.rely = item.rely
|
||||
plan.retry_times = 0
|
||||
plan.status = Status.TODO.value
|
||||
plan_objects.append(plan)
|
||||
|
||||
plans_memory.remove_by_conv_id(context.conv_id)
|
||||
plans_memory.batch_save(plan_objects)
|
||||
|
||||
except Exception as e:
|
||||
logger.exception(str(e))
|
||||
fail_reason = f"The generated plan cannot be stored, reason: {str(e)}. Please check whether it is a problem with the plan content. If so, please regenerate the correct plan. If not, please return 'TERMINATE'."
|
||||
rensponse_succ = False
|
||||
|
||||
if rensponse_succ:
|
||||
plan_content = []
|
||||
mk_plans = []
|
||||
for item in param:
|
||||
plan_content.append(
|
||||
{
|
||||
"name": item.content,
|
||||
"num": item.serial_number,
|
||||
"status": Status.TODO.value,
|
||||
"agent": item.agent,
|
||||
"rely": item.rely,
|
||||
"markdown": "",
|
||||
}
|
||||
)
|
||||
mk_plans.append(
|
||||
f"- {item.serial_number}.{item.content}[{item.agent}]"
|
||||
)
|
||||
|
||||
# view = await self.render_protocal.disply(content=plan_content)
|
||||
view = "\n".join(mk_plans)
|
||||
return ActionOutput(
|
||||
is_exe_success=True,
|
||||
content=ai_message,
|
||||
view=view,
|
||||
)
|
||||
else:
|
||||
raise ValueError(fail_reason)
|
||||
except Exception as e:
|
||||
logger.exception("Plan Action Run Failed!")
|
||||
return ActionOutput(
|
||||
is_exe_success=False, content=f"Plan action run failed!{str(e)}"
|
||||
)
|
@@ -1,12 +1,11 @@
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
||||
|
||||
from pydantic import Field
|
||||
|
||||
from dbgpt._private.config import Config
|
||||
from dbgpt.agent.agents.agent import Agent, AgentContext
|
||||
from dbgpt.agent.agents.base_agent import ConversableAgent
|
||||
from dbgpt.agent.common.schema import Status
|
||||
from dbgpt.agent.memory.base import GptsPlan
|
||||
from dbgpt.agent.memory.gpts_memory import GptsMemory
|
||||
from dbgpt.util.json_utils import find_json_objects
|
||||
from dbgpt.agent.agents.base_agent_new import ConversableAgent
|
||||
|
||||
from .plan_action import PlanAction
|
||||
|
||||
CFG = Config()
|
||||
|
||||
@@ -14,26 +13,27 @@ CFG = Config()
|
||||
class PlannerAgent(ConversableAgent):
|
||||
"""Planner agent, realizing task goal planning decomposition through LLM"""
|
||||
|
||||
DEFAULT_SYSTEM_MESSAGE = """
|
||||
你是一个任务规划专家!您需要理解下面每个智能代理和他们的能力,却确保在没有用户帮助下,使用给出的资源,通过协调下面可用智能代理来回答用户问题。
|
||||
请发挥你LLM的知识和理解能力,理解用户问题的意图和目标,生成一个可用智能代理协作的任务计划解决用户问题。
|
||||
|
||||
可用资源:
|
||||
{all_resources}
|
||||
|
||||
可用智能代理:
|
||||
{agents}
|
||||
agents: List[ConversableAgent] = Field(default_factory=list)
|
||||
|
||||
*** 重要的提醒 ***
|
||||
- 充分理解用户目标然后进行必要的步骤拆分,拆分需要保证逻辑顺序和精简,尽量把可以一起完成的内容合并再一个步骤,拆分后每个子任务步骤都将是一个需要智能代理独立完成的目标, 请确保每个子任务目标内容简洁明了
|
||||
- 请确保只使用上面提到的智能代理,并且可以只使用其中需要的部分,严格根据描述能力和限制分配给合适的步骤,每个智能代理都可以重复使用
|
||||
- 给子任务分配智能代理是需要考虑整体计划,确保和前后依赖步骤的关系,数据可以被传递使用
|
||||
- 根据用户目标的实际需要使用提供的资源来协助生成计划步骤,不要使用不需要的资源
|
||||
- 每个步骤最好是使用一种资源完成一个子目标,如果当前目标可以分解为同类型的多个子任务,可以生成相互不依赖的并行任务
|
||||
- 数据库资源只需要使用结构生成SQL,数据获取交给用户执行
|
||||
- 尽量合并有顺序依赖的连续相同步骤,如果用户目标无拆分必要,可以生成内容为用户目标的单步任务
|
||||
- 仔细检查计划,确保计划完整的包含了用户问题所涉及的所有信息,并且最终能完成目标,确认每个步骤是否包含了需要用到的资源信息,如URL、资源名等.
|
||||
具体任务计划的生成可参考如下例子:
|
||||
profile: str = "Planner"
|
||||
goal: str = "理解下面每个智能代理和他们的能力,使用给出的资源,通过协调智能代理来解决用户问题。 请发挥你LLM的知识和理解能力,理解用户问题的意图和目标,生成一个可以在没有用户帮助下,由智能代理协作完成目标的任务计划。"
|
||||
expand_prompt: str = """可用智能代理:
|
||||
{agents}
|
||||
"""
|
||||
constraints: List[str] = [
|
||||
"任务计划的每个步骤都应该是为了推进解决用户目标而存在,不要生成无意义的任务步骤,确保每个步骤内目标明确内容完整。",
|
||||
"关注任务计划每个步骤的依赖关系和逻辑,被依赖步骤要考虑被依赖的数据,是否能基于当前目标得到,如果不能请在目标中提示要生成被依赖数据。",
|
||||
"每个步骤都是一个独立可完成的目标,一定要确保逻辑和信息完整,不要出现类似:'Analyze the retrieved issues data'这样目标不明确,不知道具体要分析啥内容的步骤",
|
||||
"请确保只使用上面提到的智能代理,并且可以只使用其中需要的部分,严格根据描述能力和限制分配给合适的步骤,每个智能代理都可以重复使用。",
|
||||
"根据用户目标的实际需要使用提供的资源来协助生成计划步骤,不要使用不需要的资源。",
|
||||
"每个步骤最好只使用一种资源完成一个子目标,如果当前目标可以分解为同类型的多个子任务,可以生成相互不依赖的并行任务。",
|
||||
"数据资源可以被合适的智能代理加载使用,不用考虑数据资源的加载链接问题",
|
||||
"尽量合并有顺序依赖的连续相同步骤,如果用户目标无拆分必要,可以生成内容为用户目标的单步任务。",
|
||||
"仔细检查计划,确保计划完整的包含了用户问题所涉及的所有信息,并且最终能完成目标,确认每个步骤是否包含了需要用到的资源信息,如URL、资源名等. ",
|
||||
]
|
||||
desc: str = "你是一个任务规划专家!可以协调智能代理,分配资源完成复杂的任务目标。"
|
||||
|
||||
examples = """
|
||||
user:help me build a sales report summarizing our key metrics and trends
|
||||
assisant:[
|
||||
{{
|
||||
@@ -50,152 +50,32 @@ class PlannerAgent(ConversableAgent):
|
||||
}},
|
||||
{{
|
||||
"serial_number": "3",
|
||||
"agent": "DataScientist",
|
||||
"content": "Count the number of transactions with "pay_status" as "paid" among all transactions to retrieve the sales conversion rate.",
|
||||
"rely": ""
|
||||
}},
|
||||
{{
|
||||
"serial_number": "4",
|
||||
"agent": "Reporter",
|
||||
"content": "Integrate analytical data into the format required to build sales reports.",
|
||||
"rely": "1,2,3"
|
||||
"rely": "1,2"
|
||||
}}
|
||||
]
|
||||
|
||||
请一步步思考,并以如下json格式返回你的行动计划内容:
|
||||
[{{
|
||||
"serial_number":"0",
|
||||
"agent": "用来完成当前步骤的智能代理",
|
||||
"content": "当前步骤的任务内容,确保可以被智能代理执行",
|
||||
"rely":"当前任务执行依赖的其他任务serial_number, 如:1,2,3, 无依赖为空"
|
||||
}}]
|
||||
确保回答的json可以被Python代码的json.loads函数加载解析.
|
||||
"""
|
||||
|
||||
REPAIR_SYSTEM_MESSAGE = """
|
||||
You are a planning expert! Now you need to use your professional knowledge to carefully check the generated plan, re-evaluate and analyze it, and ensure that each step of the plan is clear and complete and can be understood by the intelligent agent to solve the current plan Problems encountered! and return new program content as requested.
|
||||
"""
|
||||
NAME = "Planner"
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self._init_actions([PlanAction])
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
memory: GptsMemory,
|
||||
agent_context: AgentContext,
|
||||
agents: Optional[List[Agent]] = None,
|
||||
max_consecutive_auto_reply: Optional[int] = None,
|
||||
human_input_mode: Optional[str] = "NEVER",
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(
|
||||
name=self.NAME,
|
||||
memory=memory,
|
||||
system_message=self.DEFAULT_SYSTEM_MESSAGE,
|
||||
max_consecutive_auto_reply=max_consecutive_auto_reply,
|
||||
human_input_mode=human_input_mode,
|
||||
agent_context=agent_context,
|
||||
**kwargs,
|
||||
)
|
||||
self._agents = agents
|
||||
### register planning funtion
|
||||
self.register_reply(Agent, PlannerAgent._a_planning)
|
||||
|
||||
def build_param(self, agent_context: AgentContext):
|
||||
resources = []
|
||||
if agent_context.resource_db is not None:
|
||||
db_connect = CFG.LOCAL_DB_MANAGE.get_connect(
|
||||
agent_context.resource_db.get("name")
|
||||
)
|
||||
|
||||
resources.append(
|
||||
f"{agent_context.resource_db.get('type')}:{agent_context.resource_db.get('name')}\n{db_connect.get_table_info()}"
|
||||
)
|
||||
if agent_context.resource_knowledge is not None:
|
||||
resources.append(
|
||||
f"{agent_context.resource_knowledge.get('type')}:{agent_context.resource_knowledge.get('name')}\n{agent_context.resource_knowledge.get('introduce')}"
|
||||
)
|
||||
if agent_context.resource_internet is not None:
|
||||
resources.append(
|
||||
f"{agent_context.resource_internet.get('type')}:{agent_context.resource_internet.get('name')}\n{agent_context.resource_internet.get('introduce')}"
|
||||
)
|
||||
return {
|
||||
"all_resources": "\n".join([f"- {item}" for item in resources]),
|
||||
def _init_reply_message(self, recive_message):
|
||||
reply_message = super()._init_reply_message(recive_message)
|
||||
reply_message["context"] = {
|
||||
"agents": "\n".join(
|
||||
[f"- {item.name}:{item.describe}" for item in self._agents]
|
||||
[f"- {item.profile}:{item.desc}" for item in self.agents]
|
||||
),
|
||||
}
|
||||
return reply_message
|
||||
|
||||
async def a_system_fill_param(self):
|
||||
params = self.build_param(self.agent_context)
|
||||
self.update_system_message(self.DEFAULT_SYSTEM_MESSAGE.format(**params))
|
||||
def bind_agents(self, agents: List[ConversableAgent]) -> ConversableAgent:
|
||||
self.agents = agents
|
||||
for agent in self.agents:
|
||||
if agent.resources and len(agent.resources) > 0:
|
||||
self.resources.extend(agent.resources)
|
||||
return self
|
||||
|
||||
async def a_generate_reply(
|
||||
self,
|
||||
message: Optional[Dict],
|
||||
sender: Agent,
|
||||
reviewer: Agent,
|
||||
silent: Optional[bool] = False,
|
||||
rely_messages: Optional[List[Dict]] = None,
|
||||
):
|
||||
final, reply_message = await super().a_generate_reply(
|
||||
message, sender, reviewer, silent, rely_messages
|
||||
)
|
||||
reply_message["is_termination"] = True
|
||||
return final, reply_message
|
||||
|
||||
async def _a_planning(
|
||||
self,
|
||||
message: Optional[str] = None,
|
||||
sender: Optional[Agent] = None,
|
||||
reviewer: Optional[Agent] = None,
|
||||
config: Optional[Any] = None,
|
||||
) -> Tuple[bool, Union[str, Dict, None]]:
|
||||
json_objects = find_json_objects(message)
|
||||
plan_objects = []
|
||||
fail_reason = (
|
||||
"Please recheck your answer,no usable plans generated in correct format,"
|
||||
)
|
||||
json_count = len(json_objects)
|
||||
rensponse_succ = True
|
||||
if json_count != 1:
|
||||
### Answer failed, turn on automatic repair
|
||||
fail_reason += f"There are currently {json_count} json contents"
|
||||
rensponse_succ = False
|
||||
else:
|
||||
try:
|
||||
for item in json_objects[0]:
|
||||
plan = GptsPlan(
|
||||
conv_id=self.agent_context.conv_id,
|
||||
sub_task_num=item.get("serial_number"),
|
||||
sub_task_content=item.get("content"),
|
||||
)
|
||||
plan.resource_name = item.get("resource")
|
||||
plan.max_retry_times = self.agent_context.max_retry_round
|
||||
plan.sub_task_agent = item.get("agent")
|
||||
plan.sub_task_title = item.get("content")
|
||||
plan.rely = item.get("rely")
|
||||
plan.retry_times = 0
|
||||
plan.status = Status.TODO.value
|
||||
plan_objects.append(plan)
|
||||
except Exception as e:
|
||||
fail_reason += f"Return json structure error and cannot be converted to a usable plan,{str(e)}"
|
||||
rensponse_succ = False
|
||||
|
||||
if rensponse_succ:
|
||||
if len(plan_objects) > 0:
|
||||
### Delete the old plan every time before saving it
|
||||
self.memory.plans_memory.remove_by_conv_id(self.agent_context.conv_id)
|
||||
self.memory.plans_memory.batch_save(plan_objects)
|
||||
|
||||
content = "\n".join(
|
||||
[
|
||||
"{},{}".format(index + 1, item.get("content"))
|
||||
for index, item in enumerate(json_objects[0])
|
||||
]
|
||||
)
|
||||
else:
|
||||
content = fail_reason
|
||||
return True, {
|
||||
"is_exe_success": rensponse_succ,
|
||||
"content": content,
|
||||
"view": content,
|
||||
}
|
||||
def prepare_act_param(self) -> Optional[Dict]:
|
||||
return {"context": self.agent_context, "plans_memory": self.memory.plans_memory}
|
||||
|
@@ -1,14 +1,14 @@
|
||||
import logging
|
||||
import sys
|
||||
from typing import Any, List, Optional
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from dbgpt.agent.agents.agent import Agent, AgentContext
|
||||
from dbgpt.agent.actions.action import ActionOutput
|
||||
from dbgpt.agent.agents.agent_new import Agent
|
||||
from dbgpt.agent.agents.agents_manage import mentioned_agents, participant_roles
|
||||
from dbgpt.agent.agents.base_agent import ConversableAgent
|
||||
from dbgpt.agent.agents.base_agent_new import ConversableAgent
|
||||
from dbgpt.agent.agents.base_team import ManagerAgent
|
||||
from dbgpt.agent.common.schema import Status
|
||||
from dbgpt.agent.memory.base import GptsPlan
|
||||
from dbgpt.agent.memory.gpts_memory import GptsMemory
|
||||
from dbgpt.core.interface.message import ModelMessageRoleType
|
||||
|
||||
from .planner_agent import PlannerAgent
|
||||
@@ -19,53 +19,39 @@ logger = logging.getLogger(__name__)
|
||||
class AutoPlanChatManager(ManagerAgent):
|
||||
"""(In preview) A chat manager agent that can manage a team chat of multiple agents."""
|
||||
|
||||
NAME = "plan_manager"
|
||||
profile: str = "PlanManager"
|
||||
goal: str = "Advance the task plan generated by the planning agent. If the plan does not pre-allocate an agent, it needs to be coordinated with the appropriate agent to complete."
|
||||
constraints: List[str] = []
|
||||
desc: str = "Advance the task plan generated by the planning agent."
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
memory: GptsMemory,
|
||||
agent_context: AgentContext,
|
||||
# unlimited consecutive auto reply by default
|
||||
max_consecutive_auto_reply: Optional[int] = sys.maxsize,
|
||||
human_input_mode: Optional[str] = "NEVER",
|
||||
describe: Optional[str] = "Plan chat manager.",
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(
|
||||
name=self.NAME,
|
||||
describe=describe,
|
||||
memory=memory,
|
||||
max_consecutive_auto_reply=max_consecutive_auto_reply,
|
||||
human_input_mode=human_input_mode,
|
||||
agent_context=agent_context,
|
||||
**kwargs,
|
||||
)
|
||||
# Order of register_reply is important.
|
||||
|
||||
# Allow async chat if initiated using a_initiate_chat
|
||||
self.register_reply(Agent, AutoPlanChatManager.a_run_chat)
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
async def a_process_rely_message(
|
||||
self, conv_id: str, now_plan: GptsPlan, speaker: ConversableAgent
|
||||
):
|
||||
rely_prompt = ""
|
||||
speaker.reset_rely_message()
|
||||
rely_prompt = None
|
||||
rely_messages: List[Dict] = []
|
||||
|
||||
if now_plan.rely and len(now_plan.rely) > 0:
|
||||
rely_tasks_list = now_plan.rely.split(",")
|
||||
rely_tasks = self.memory.plans_memory.get_by_conv_id_and_num(
|
||||
conv_id, rely_tasks_list
|
||||
)
|
||||
rely_tasks = self.memory.plans_memory.get_by_conv_id_and_num(conv_id, [])
|
||||
if rely_tasks:
|
||||
rely_prompt = "Read the result data of the dependent steps in the above historical message to complete the current goal:"
|
||||
for rely_task in rely_tasks:
|
||||
speaker.append_rely_message(
|
||||
{"content": rely_task.sub_task_content},
|
||||
ModelMessageRoleType.HUMAN,
|
||||
rely_messages.append(
|
||||
{
|
||||
"content": rely_task.sub_task_content,
|
||||
"role": ModelMessageRoleType.HUMAN,
|
||||
}
|
||||
)
|
||||
speaker.append_rely_message(
|
||||
{"content": rely_task.result}, ModelMessageRoleType.AI
|
||||
rely_messages.append(
|
||||
{
|
||||
"content": rely_task.result,
|
||||
"role": ModelMessageRoleType.AI,
|
||||
}
|
||||
)
|
||||
return rely_prompt
|
||||
return rely_prompt, rely_messages
|
||||
|
||||
def select_speaker_msg(self, agents: List[Agent]):
|
||||
"""Return the message for selecting the next speaker."""
|
||||
@@ -92,10 +78,9 @@ class AutoPlanChatManager(ManagerAgent):
|
||||
model = None
|
||||
else:
|
||||
# auto speaker selection
|
||||
selector.update_system_message(self.select_speaker_msg(agents))
|
||||
final, name, model = await selector.a_reasoning_reply(
|
||||
self.messages
|
||||
+ [
|
||||
# TODO selector a_thinking It has been overwritten and cannot be used.
|
||||
final, name, model = await selector.a_thinking(
|
||||
messages=[
|
||||
{
|
||||
"role": ModelMessageRoleType.HUMAN,
|
||||
"content": f"""Read and understand the following task content and assign the appropriate role to complete the task.
|
||||
@@ -103,7 +88,8 @@ class AutoPlanChatManager(ManagerAgent):
|
||||
select the role from: {[agent.name for agent in agents]},
|
||||
Please only return the role, such as: {agents[0].name}""",
|
||||
}
|
||||
]
|
||||
],
|
||||
prompt=self.select_speaker_msg(agents),
|
||||
)
|
||||
if not final:
|
||||
raise ValueError("Unable to select next speaker!")
|
||||
@@ -124,44 +110,38 @@ class AutoPlanChatManager(ManagerAgent):
|
||||
logger.exception(f"auto select speaker failed!{str(e)}")
|
||||
raise ValueError("Unable to select next speaker!")
|
||||
|
||||
async def a_generate_speech_process(
|
||||
async def a_act(
|
||||
self,
|
||||
message: Optional[str],
|
||||
reviewer: Agent,
|
||||
agents: Optional[List[Agent]] = None,
|
||||
) -> None:
|
||||
planner = PlannerAgent(
|
||||
agent_context=self.agent_context,
|
||||
memory=self.memory,
|
||||
agents=agents,
|
||||
)
|
||||
|
||||
await self.a_initiate_chat(
|
||||
message=message, recipient=planner, reviewer=reviewer
|
||||
)
|
||||
|
||||
async def a_run_chat(
|
||||
self,
|
||||
message: Optional[str] = None,
|
||||
sender: Optional[Agent] = None,
|
||||
reviewer: Agent = None,
|
||||
config: Optional[Any] = None,
|
||||
):
|
||||
"""Run a team chat asynchronously."""
|
||||
|
||||
sender: Optional[ConversableAgent] = None,
|
||||
reviewer: Optional[ConversableAgent] = None,
|
||||
) -> Optional[ActionOutput]:
|
||||
speaker = sender
|
||||
last_message = None
|
||||
for i in range(self.max_round):
|
||||
plans = self.memory.plans_memory.get_by_conv_id(self.agent_context.conv_id)
|
||||
|
||||
if not plans or len(plans) <= 0:
|
||||
if i > 3:
|
||||
error_report = {
|
||||
"content": f"Retrying 3 times based on current application resources still fails to build a valid plan!",
|
||||
"is_exe_success": False,
|
||||
}
|
||||
return True, error_report
|
||||
###Have no plan, generate a new plan
|
||||
await self.a_generate_speech_process(message, reviewer, self.agents)
|
||||
return ActionOutput(
|
||||
is_exe_success=False,
|
||||
content="Retrying 3 times based on current application resources still fails to build a valid plan!",
|
||||
)
|
||||
planner: ConversableAgent = (
|
||||
await PlannerAgent()
|
||||
.bind(self.memory)
|
||||
.bind(self.agent_context)
|
||||
.bind(self.llm_config)
|
||||
.bind(self.resource_loader)
|
||||
.bind_agents(self.agents)
|
||||
.build()
|
||||
)
|
||||
|
||||
is_success, plan_message = await planner.a_generate_reply(
|
||||
recive_message={"content": message}, sender=self, reviewer=reviewer
|
||||
)
|
||||
await planner.a_send(
|
||||
message=plan_message, recipient=self, request_reply=False
|
||||
)
|
||||
else:
|
||||
todo_plans = [
|
||||
plan
|
||||
@@ -171,51 +151,21 @@ class AutoPlanChatManager(ManagerAgent):
|
||||
if not todo_plans or len(todo_plans) <= 0:
|
||||
### The plan has been fully executed and a success message is sent to the user.
|
||||
# complete
|
||||
print(f"fDEBUG:[{last_message}]")
|
||||
return (
|
||||
True,
|
||||
last_message.get("action_report") if last_message else None,
|
||||
return ActionOutput(
|
||||
is_exe_success=True,
|
||||
content=f"{plans[-1].result}", # work results message
|
||||
)
|
||||
else:
|
||||
now_plan: GptsPlan = todo_plans[0]
|
||||
|
||||
# There is no need to broadcast the message to other agents, it will be automatically obtained from the collective memory according to the dependency relationship.
|
||||
try:
|
||||
if Status.RETRYING.value == now_plan.state:
|
||||
if now_plan.retry_times <= now_plan.max_retry_times:
|
||||
current_goal_message = {
|
||||
"content": now_plan.result,
|
||||
"current_gogal": now_plan.sub_task_content,
|
||||
"context": {
|
||||
"plan_task": now_plan.sub_task_content,
|
||||
"plan_task_num": now_plan.sub_task_num,
|
||||
},
|
||||
}
|
||||
else:
|
||||
self.memory.plans_memory.update_task(
|
||||
self.agent_context.conv_id,
|
||||
now_plan.sub_task_num,
|
||||
Status.FAILED.value,
|
||||
now_plan.retry_times + 1,
|
||||
speaker.name,
|
||||
"",
|
||||
plan_result,
|
||||
)
|
||||
faild_report = {
|
||||
"content": f"ReTask [{now_plan.sub_task_content}] was retried more than the maximum number of times and still failed.{now_plan.result}",
|
||||
"is_exe_success": False,
|
||||
}
|
||||
return True, faild_report
|
||||
else:
|
||||
current_goal_message = {
|
||||
"content": now_plan.sub_task_content,
|
||||
"current_gogal": now_plan.sub_task_content,
|
||||
"context": {
|
||||
"plan_task": now_plan.sub_task_content,
|
||||
"plan_task_num": now_plan.sub_task_num,
|
||||
},
|
||||
}
|
||||
|
||||
now_plan: GptsPlan = todo_plans[0]
|
||||
current_goal_message = {
|
||||
"content": now_plan.sub_task_content,
|
||||
"current_gogal": now_plan.sub_task_content,
|
||||
"context": {
|
||||
"plan_task": now_plan.sub_task_content,
|
||||
"plan_task_num": now_plan.sub_task_num,
|
||||
},
|
||||
}
|
||||
# select the next speaker
|
||||
speaker, model = await self.a_select_speaker(
|
||||
speaker,
|
||||
@@ -224,7 +174,7 @@ class AutoPlanChatManager(ManagerAgent):
|
||||
now_plan.sub_task_agent,
|
||||
)
|
||||
# Tell the speaker the dependent history information
|
||||
rely_prompt = await self.a_process_rely_message(
|
||||
rely_prompt, rely_messages = await self.a_process_rely_message(
|
||||
conv_id=self.agent_context.conv_id,
|
||||
now_plan=now_plan,
|
||||
speaker=speaker,
|
||||
@@ -234,27 +184,26 @@ class AutoPlanChatManager(ManagerAgent):
|
||||
rely_prompt + current_goal_message["content"]
|
||||
)
|
||||
|
||||
is_recovery = False
|
||||
if message == current_goal_message["content"]:
|
||||
is_recovery = True
|
||||
await self.a_send(
|
||||
message=current_goal_message,
|
||||
recipient=speaker,
|
||||
reviewer=reviewer,
|
||||
request_reply=False,
|
||||
is_recovery=is_recovery,
|
||||
)
|
||||
verify_pass, reply = await speaker.a_generate_reply(
|
||||
current_goal_message, self, reviewer
|
||||
is_success, reply_message = await speaker.a_generate_reply(
|
||||
recive_message=current_goal_message,
|
||||
sender=self,
|
||||
reviewer=reviewer,
|
||||
rely_messages=rely_messages,
|
||||
)
|
||||
await speaker.a_send(
|
||||
reply_message, self, reviewer, request_reply=False
|
||||
)
|
||||
|
||||
last_message = reply
|
||||
print(f"DEBUG2:[{last_message}]")
|
||||
plan_result = ""
|
||||
|
||||
if verify_pass:
|
||||
if reply:
|
||||
action_report = reply.get("action_report", None)
|
||||
if is_success:
|
||||
if reply_message:
|
||||
action_report = reply_message.get("action_report", None)
|
||||
if action_report:
|
||||
plan_result = action_report.get("content", "")
|
||||
### The current planned Agent generation verification is successful
|
||||
@@ -264,31 +213,30 @@ class AutoPlanChatManager(ManagerAgent):
|
||||
now_plan.sub_task_num,
|
||||
plan_result,
|
||||
)
|
||||
await speaker.a_send(
|
||||
reply, self, reviewer, request_reply=False
|
||||
)
|
||||
|
||||
else:
|
||||
plan_result = reply["content"]
|
||||
plan_result = reply_message["content"]
|
||||
self.memory.plans_memory.update_task(
|
||||
self.agent_context.conv_id,
|
||||
now_plan.sub_task_num,
|
||||
Status.RETRYING.value,
|
||||
Status.FAILED.value,
|
||||
now_plan.retry_times + 1,
|
||||
speaker.name,
|
||||
"",
|
||||
plan_result,
|
||||
)
|
||||
return ActionOutput(
|
||||
is_exe_success=False, content=plan_result
|
||||
)
|
||||
except Exception as e:
|
||||
logger.exception(
|
||||
f"An exception was encountered during the execution of the current plan step.{str(e)}"
|
||||
)
|
||||
error_report = {
|
||||
"content": f"An exception was encountered during the execution of the current plan step.{str(e)}",
|
||||
"is_exe_success": False,
|
||||
}
|
||||
return True, error_report
|
||||
|
||||
return True, {
|
||||
"content": f"Maximum number of dialogue rounds exceeded.{self.MAX_CONSECUTIVE_AUTO_REPLY}",
|
||||
"is_exe_success": False,
|
||||
}
|
||||
return ActionOutput(
|
||||
is_exe_success=False,
|
||||
content=f"An exception was encountered during the execution of the current plan step.{str(e)}",
|
||||
)
|
||||
return ActionOutput(
|
||||
is_exe_success=False,
|
||||
content=f"Maximum number of dialogue rounds exceeded.{self.max_round}",
|
||||
)
|
||||
|
Reference in New Issue
Block a user