mirror of
https://github.com/csunny/DB-GPT.git
synced 2025-09-11 22:09:44 +00:00
feat: (0.6)New UI (#1855)
Co-authored-by: 夏姜 <wenfengjiang.jwf@digital-engine.com> Co-authored-by: aries_ckt <916701291@qq.com> Co-authored-by: wb-lh513319 <wb-lh513319@alibaba-inc.com> Co-authored-by: csunny <cfqsunny@163.com>
This commit is contained in:
@@ -1,47 +1,59 @@
|
||||
import asyncio
|
||||
import datetime
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
import time
|
||||
import uuid
|
||||
from abc import ABC
|
||||
from typing import Any, Dict, List, Optional, Type
|
||||
|
||||
from fastapi import APIRouter, Body
|
||||
from fastapi import APIRouter, Body, Depends
|
||||
from fastapi.responses import StreamingResponse
|
||||
|
||||
from dbgpt._private.config import Config
|
||||
from dbgpt.agent.core.agent import Agent, AgentContext
|
||||
from dbgpt.agent.core.agent_manage import get_agent_manager
|
||||
from dbgpt.agent.core.base_agent import ConversableAgent
|
||||
from dbgpt.agent.core.memory.agent_memory import AgentMemory
|
||||
from dbgpt.agent.core.memory.gpts.gpts_memory import GptsMemory
|
||||
from dbgpt.agent.core.plan import AutoPlanChatManager, DefaultAWELLayoutManager
|
||||
from dbgpt.agent import (
|
||||
Agent,
|
||||
AgentContext,
|
||||
AgentMemory,
|
||||
AutoPlanChatManager,
|
||||
ConversableAgent,
|
||||
DefaultAWELLayoutManager,
|
||||
GptsMemory,
|
||||
LLMConfig,
|
||||
ShortTermMemory,
|
||||
UserProxyAgent,
|
||||
get_agent_manager,
|
||||
)
|
||||
from dbgpt.agent.core.memory.gpts import GptsMessage
|
||||
from dbgpt.agent.core.schema import Status
|
||||
from dbgpt.agent.core.user_proxy_agent import UserProxyAgent
|
||||
from dbgpt.agent.resource.base import Resource
|
||||
from dbgpt.agent.resource.manage import get_resource_manager
|
||||
from dbgpt.agent.util.llm.llm import LLMConfig, LLMStrategyType
|
||||
from dbgpt.app.openapi.api_view_model import Result
|
||||
from dbgpt.agent.resource import get_resource_manager
|
||||
from dbgpt.agent.util.llm.llm import LLMStrategyType
|
||||
from dbgpt.app.dbgpt_server import system_app
|
||||
from dbgpt.app.scene.base import ChatScene
|
||||
from dbgpt.component import BaseComponent, ComponentType, SystemApp
|
||||
from dbgpt.core import PromptTemplate
|
||||
from dbgpt.core.awel.flow.flow_factory import FlowCategory
|
||||
from dbgpt.core.interface.message import StorageConversation
|
||||
from dbgpt.model.cluster import WorkerManagerFactory
|
||||
from dbgpt.model.cluster.client import DefaultLLMClient
|
||||
from dbgpt.serve.agent.model import PagenationFilter, PluginHubFilter
|
||||
from dbgpt.serve.conversation.serve import Serve as ConversationServe
|
||||
from dbgpt.serve.prompt.api.endpoints import get_service
|
||||
from dbgpt.serve.prompt.service import service as PromptService
|
||||
from dbgpt.util.json_utils import serialize
|
||||
from dbgpt.util.tracer import root_tracer
|
||||
from dbgpt.util.tracer import TracerManager
|
||||
|
||||
from ..db import GptsMessagesDao
|
||||
from ..db.gpts_app import GptsApp, GptsAppDao, GptsAppQuery
|
||||
from ..db.gpts_conversations_db import GptsConversationsDao, GptsConversationsEntity
|
||||
from ..db.gpts_manage_db import GptsInstanceEntity
|
||||
from ..team.base import TeamMode
|
||||
from .db_gpts_memory import MetaDbGptsMessageMemory, MetaDbGptsPlansMemory
|
||||
|
||||
CFG = Config()
|
||||
|
||||
|
||||
router = APIRouter()
|
||||
logger = logging.getLogger(__name__)
|
||||
root_tracer: TracerManager = TracerManager()
|
||||
|
||||
|
||||
def _build_conversation(
|
||||
@@ -49,6 +61,7 @@ def _build_conversation(
|
||||
select_param: Dict[str, Any],
|
||||
model_name: str,
|
||||
summary: str,
|
||||
app_code: str,
|
||||
conv_serve: ConversationServe,
|
||||
user_name: Optional[str] = "",
|
||||
sys_code: Optional[str] = "",
|
||||
@@ -62,6 +75,7 @@ def _build_conversation(
|
||||
summary=summary,
|
||||
param_type="DbGpts",
|
||||
param_value=select_param,
|
||||
app_code=app_code,
|
||||
conv_storage=conv_serve.conv_storage,
|
||||
message_storage=conv_serve.message_storage,
|
||||
)
|
||||
@@ -72,9 +86,14 @@ class MultiAgents(BaseComponent, ABC):
|
||||
|
||||
def init_app(self, system_app: SystemApp):
|
||||
system_app.app.include_router(router, prefix="/api", tags=["Multi-Agents"])
|
||||
self.system_app = system_app
|
||||
from dbgpt.serve.agent.app.controller import gpts_dao
|
||||
|
||||
def __init__(self):
|
||||
gpts_dao.init_native_apps()
|
||||
|
||||
def __init__(self, system_app: SystemApp):
|
||||
self.gpts_conversations = GptsConversationsDao()
|
||||
self.gpts_messages_dao = GptsMessagesDao()
|
||||
|
||||
self.gpts_app = GptsAppDao()
|
||||
self.memory = GptsMemory(
|
||||
@@ -82,13 +101,21 @@ class MultiAgents(BaseComponent, ABC):
|
||||
message_memory=MetaDbGptsMessageMemory(),
|
||||
)
|
||||
self.agent_memory_map = {}
|
||||
super().__init__()
|
||||
|
||||
super().__init__(system_app)
|
||||
self.system_app = system_app
|
||||
|
||||
def get_dbgpts(self, user_code: str = None, sys_code: str = None):
|
||||
apps = self.gpts_app.app_list(
|
||||
GptsAppQuery(user_code=user_code, sys_code=sys_code)
|
||||
).app_list
|
||||
return apps
|
||||
|
||||
def get_app(self, app_code) -> GptsApp:
|
||||
"""get app"""
|
||||
return self.gpts_app.app_detail(app_code)
|
||||
|
||||
def get_or_build_agent_memory(self, conv_id: str, dbgpts_name: str) -> AgentMemory:
|
||||
from dbgpt.agent.core.memory.agent_memory import (
|
||||
AgentMemory,
|
||||
AgentMemoryFragment,
|
||||
)
|
||||
from dbgpt.agent.core.memory.hybrid import HybridMemory
|
||||
from dbgpt.configs.model_config import EMBEDDING_MODEL_CONFIG
|
||||
from dbgpt.rag.embedding.embedding_factory import EmbeddingFactory
|
||||
@@ -97,11 +124,11 @@ class MultiAgents(BaseComponent, ABC):
|
||||
if memory_key in self.agent_memory_map:
|
||||
return self.agent_memory_map[memory_key]
|
||||
|
||||
embedding_factory = EmbeddingFactory.get_instance(CFG.SYSTEM_APP)
|
||||
embedding_fn = embedding_factory.create(
|
||||
model_name=EMBEDDING_MODEL_CONFIG[CFG.EMBEDDING_MODEL]
|
||||
)
|
||||
vstore_name = f"_chroma_agent_memory_{dbgpts_name}_{conv_id}"
|
||||
# embedding_factory = EmbeddingFactory.get_instance(CFG.SYSTEM_APP)
|
||||
# embedding_fn = embedding_factory.create(
|
||||
# model_name=EMBEDDING_MODEL_CONFIG[CFG.EMBEDDING_MODEL]
|
||||
# )
|
||||
# vstore_name = f"_chroma_agent_memory_{dbgpts_name}_{conv_id}"
|
||||
# Just use chroma store now
|
||||
# vector_store_connector = VectorStoreConnector(
|
||||
# vector_store_type=CFG.VECTOR_STORE_TYPE,
|
||||
@@ -109,40 +136,79 @@ class MultiAgents(BaseComponent, ABC):
|
||||
# name=vstore_name, embedding_fn=embedding_fn
|
||||
# ),
|
||||
# )
|
||||
memory = HybridMemory[AgentMemoryFragment].from_chroma(
|
||||
vstore_name=vstore_name,
|
||||
embeddings=embedding_fn,
|
||||
)
|
||||
agent_memory = AgentMemory(memory, gpts_memory=self.memory)
|
||||
# memory = HybridMemory[AgentMemoryFragment].from_chroma(
|
||||
# vstore_name=vstore_name,
|
||||
# embeddings=embedding_fn,
|
||||
# )
|
||||
|
||||
agent_memory = AgentMemory(gpts_memory=self.memory)
|
||||
self.agent_memory_map[memory_key] = agent_memory
|
||||
return agent_memory
|
||||
|
||||
def gpts_create(self, entity: GptsInstanceEntity):
|
||||
self.gpts_intance.add(entity)
|
||||
|
||||
def get_dbgpts(
|
||||
self, user_code: str = None, sys_code: str = None
|
||||
) -> Optional[List[GptsApp]]:
|
||||
apps = self.gpts_app.app_list(
|
||||
GptsAppQuery(user_code=user_code, sys_code=sys_code)
|
||||
).app_list
|
||||
return apps
|
||||
|
||||
async def agent_chat(
|
||||
async def agent_chat_v2(
|
||||
self,
|
||||
agent_conv_id: str,
|
||||
conv_id: str,
|
||||
new_order: int,
|
||||
gpts_name: str,
|
||||
user_query: str,
|
||||
user_code: str = None,
|
||||
sys_code: str = None,
|
||||
agent_memory: Optional[AgentMemory] = None,
|
||||
enable_verbose: bool = True,
|
||||
stream: Optional[bool] = True,
|
||||
**ext_info,
|
||||
):
|
||||
gpt_app: GptsApp = self.gpts_app.app_detail(gpts_name)
|
||||
logger.info(
|
||||
f"agent_chat_v2 conv_id:{conv_id},gpts_name:{gpts_name},user_query:{user_query}"
|
||||
)
|
||||
gpts_conversations: List[
|
||||
GptsConversationsEntity
|
||||
] = self.gpts_conversations.get_like_conv_id_asc(conv_id)
|
||||
logger.info(
|
||||
f"gpts_conversations count:{conv_id},{len(gpts_conversations) if gpts_conversations else 0}"
|
||||
)
|
||||
gpt_chat_order = (
|
||||
"1" if not gpts_conversations else str(len(gpts_conversations) + 1)
|
||||
)
|
||||
agent_conv_id = conv_id + "_" + gpt_chat_order
|
||||
message_round = 0
|
||||
history_message_count = 0
|
||||
is_retry_chat = False
|
||||
last_speaker_name = None
|
||||
history_messages = None
|
||||
# 检查最后一个对话记录是否完成,如果是等待状态,则要继续进行当前对话
|
||||
if gpts_conversations and len(gpts_conversations) > 0:
|
||||
last_gpts_conversation: GptsConversationsEntity = gpts_conversations[-1]
|
||||
logger.info(f"last conversation status:{last_gpts_conversation.__dict__}")
|
||||
if last_gpts_conversation.state == Status.WAITING.value:
|
||||
is_retry_chat = True
|
||||
agent_conv_id = last_gpts_conversation.conv_id
|
||||
|
||||
gpts_conversation = self.gpts_conversations.get_by_conv_id(agent_conv_id)
|
||||
is_retry_chat = True
|
||||
if not gpts_conversation:
|
||||
is_retry_chat = False
|
||||
gpts_messages: List[
|
||||
GptsMessage
|
||||
] = self.gpts_messages_dao.get_by_conv_id(agent_conv_id)
|
||||
history_message_count = len(gpts_messages)
|
||||
history_messages = gpts_messages
|
||||
last_message = gpts_messages[-1]
|
||||
message_round = last_message.rounds + 1
|
||||
|
||||
from dbgpt.serve.agent.agents.expand.app_start_assisant_agent import (
|
||||
StartAppAssistantAgent,
|
||||
)
|
||||
|
||||
if last_message.sender == StartAppAssistantAgent().role:
|
||||
last_message = gpts_messages[-2]
|
||||
last_speaker_name = last_message.sender
|
||||
|
||||
gpt_app: GptsApp = self.gpts_app.app_detail(last_message.app_code)
|
||||
|
||||
if not gpt_app:
|
||||
raise ValueError(f"Not found app {gpts_name}!")
|
||||
|
||||
if not is_retry_chat:
|
||||
# 新建gpts对话记录
|
||||
gpt_app: GptsApp = self.gpts_app.app_detail(gpts_name)
|
||||
if not gpt_app:
|
||||
raise ValueError(f"Not found app {gpts_name}!")
|
||||
self.gpts_conversations.add(
|
||||
GptsConversationsEntity(
|
||||
conv_id=agent_conv_id,
|
||||
@@ -157,32 +223,117 @@ class MultiAgents(BaseComponent, ABC):
|
||||
)
|
||||
)
|
||||
|
||||
task = asyncio.create_task(
|
||||
multi_agents.agent_team_chat_new(
|
||||
user_query,
|
||||
agent_conv_id,
|
||||
gpt_app,
|
||||
is_retry_chat,
|
||||
agent_memory,
|
||||
if (
|
||||
TeamMode.AWEL_LAYOUT.value == gpt_app.team_mode
|
||||
and gpt_app.team_context.flow_category == FlowCategory.CHAT_FLOW
|
||||
):
|
||||
team_context = gpt_app.team_context
|
||||
from dbgpt.core.awel import CommonLLMHttpRequestBody
|
||||
|
||||
flow_req = CommonLLMHttpRequestBody(
|
||||
model=ext_info.get("model_name", None),
|
||||
messages=user_query,
|
||||
stream=True,
|
||||
# context=flow_ctx,
|
||||
# temperature=
|
||||
# max_new_tokens=
|
||||
# enable_vis=
|
||||
conv_uid=agent_conv_id,
|
||||
span_id=root_tracer.get_current_span_id(),
|
||||
chat_mode=ext_info.get("chat_mode", None),
|
||||
chat_param=team_context.uid,
|
||||
user_name=user_code,
|
||||
sys_code=sys_code,
|
||||
incremental=ext_info.get("incremental", True),
|
||||
)
|
||||
)
|
||||
from dbgpt.app.openapi.api_v1.api_v1 import get_chat_flow
|
||||
|
||||
async for chunk in multi_agents.chat_messages(agent_conv_id):
|
||||
if chunk:
|
||||
try:
|
||||
chunk = json.dumps(
|
||||
{"vis": chunk}, default=serialize, ensure_ascii=False
|
||||
flow_service = get_chat_flow()
|
||||
async for chunk in flow_service.chat_stream_flow_str(
|
||||
team_context.uid, flow_req
|
||||
):
|
||||
yield None, chunk, agent_conv_id
|
||||
else:
|
||||
# init gpts memory
|
||||
self.memory.init(
|
||||
agent_conv_id,
|
||||
enable_vis_message=enable_verbose,
|
||||
history_messages=history_messages,
|
||||
start_round=history_message_count,
|
||||
)
|
||||
# init agent memory
|
||||
agent_memory = self.get_or_build_agent_memory(conv_id, gpts_name)
|
||||
|
||||
try:
|
||||
task = asyncio.create_task(
|
||||
multi_agents.agent_team_chat_new(
|
||||
user_query,
|
||||
agent_conv_id,
|
||||
gpt_app,
|
||||
agent_memory,
|
||||
is_retry_chat,
|
||||
last_speaker_name=last_speaker_name,
|
||||
init_message_rounds=message_round,
|
||||
**ext_info,
|
||||
)
|
||||
if chunk is None or len(chunk) <= 0:
|
||||
continue
|
||||
resp = f"data:{chunk}\n\n"
|
||||
yield task, resp
|
||||
except Exception as e:
|
||||
logger.exception(f"get messages {gpts_name} Exception!" + str(e))
|
||||
yield f"data: {str(e)}\n\n"
|
||||
)
|
||||
if enable_verbose:
|
||||
async for chunk in multi_agents.chat_messages(agent_conv_id):
|
||||
if chunk:
|
||||
try:
|
||||
chunk = json.dumps(
|
||||
{"vis": chunk},
|
||||
default=serialize,
|
||||
ensure_ascii=False,
|
||||
)
|
||||
if chunk is None or len(chunk) <= 0:
|
||||
continue
|
||||
resp = f"data:{chunk}\n\n"
|
||||
yield task, resp, agent_conv_id
|
||||
except Exception as e:
|
||||
logger.exception(
|
||||
f"get messages {gpts_name} Exception!" + str(e)
|
||||
)
|
||||
yield f"data: {str(e)}\n\n"
|
||||
|
||||
yield task, f'data:{json.dumps({"vis": "[DONE]"}, default=serialize, ensure_ascii=False)} \n\n'
|
||||
yield task, f'data:{json.dumps({"vis": "[DONE]"}, default=serialize, ensure_ascii=False)} \n\n', agent_conv_id
|
||||
|
||||
else:
|
||||
logger.info(f"{agent_conv_id}开启简略消息模式,不进行vis协议封装,获取极简流式消息直接输出")
|
||||
# 开启简略消息模式,不进行vis协议封装,获取极简流式消息直接输出
|
||||
final_message_chunk = None
|
||||
async for chunk in multi_agents.chat_messages(agent_conv_id):
|
||||
if chunk:
|
||||
try:
|
||||
if chunk is None or len(chunk) <= 0:
|
||||
continue
|
||||
final_message_chunk = chunk[-1]
|
||||
if stream:
|
||||
yield task, final_message_chunk, agent_conv_id
|
||||
logger.info(
|
||||
f"agent_chat_v2 executing, timestamp={int(time.time() * 1000)}"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.exception(
|
||||
f"get messages {gpts_name} Exception!" + str(e)
|
||||
)
|
||||
final_message_chunk = str(e)
|
||||
|
||||
logger.info(
|
||||
f"agent_chat_v2 finish, timestamp={int(time.time() * 1000)}"
|
||||
)
|
||||
yield task, final_message_chunk, agent_conv_id
|
||||
|
||||
except Exception as e:
|
||||
logger.exception(f"Agent chat have error!{str(e)}")
|
||||
if enable_verbose:
|
||||
yield task, f'data:{json.dumps({"vis": f"{str(e)}"}, default=serialize, ensure_ascii=False)} \n\n', agent_conv_id
|
||||
yield task, f'data:{json.dumps({"vis": "[DONE]"}, default=serialize, ensure_ascii=False)} \n\n', agent_conv_id
|
||||
else:
|
||||
yield task, str(e), agent_conv_id
|
||||
|
||||
finally:
|
||||
self.memory.clear(agent_conv_id)
|
||||
|
||||
async def app_agent_chat(
|
||||
self,
|
||||
@@ -191,8 +342,11 @@ class MultiAgents(BaseComponent, ABC):
|
||||
user_query: str,
|
||||
user_code: str = None,
|
||||
sys_code: str = None,
|
||||
enable_verbose: bool = True,
|
||||
stream: Optional[bool] = True,
|
||||
**ext_info,
|
||||
):
|
||||
logger.info(f"app_agent_chat:{gpts_name},{user_query},{conv_uid}")
|
||||
# logger.info(f"app_agent_chat:{gpts_name},{user_query},{conv_uid}")
|
||||
|
||||
# Temporary compatible scenario messages
|
||||
conv_serve = ConversationServe.get_instance(CFG.SYSTEM_APP)
|
||||
@@ -201,24 +355,26 @@ class MultiAgents(BaseComponent, ABC):
|
||||
select_param=gpts_name,
|
||||
summary=user_query,
|
||||
model_name="",
|
||||
app_code=gpts_name,
|
||||
conv_serve=conv_serve,
|
||||
user_name=user_code,
|
||||
)
|
||||
|
||||
current_message.save_to_storage()
|
||||
current_message.start_new_round()
|
||||
current_message.add_user_message(user_query)
|
||||
agent_conv_id = conv_uid + "_" + str(current_message.chat_order)
|
||||
agent_conv_id = None
|
||||
agent_task = None
|
||||
try:
|
||||
agent_memory = self.get_or_build_agent_memory(conv_uid, gpts_name)
|
||||
agent_conv_id = conv_uid + "_" + str(current_message.chat_order)
|
||||
async for task, chunk in multi_agents.agent_chat(
|
||||
agent_conv_id,
|
||||
async for task, chunk, agent_conv_id in multi_agents.agent_chat_v2(
|
||||
conv_uid,
|
||||
current_message.chat_order,
|
||||
gpts_name,
|
||||
user_query,
|
||||
user_code,
|
||||
sys_code,
|
||||
agent_memory,
|
||||
enable_verbose=enable_verbose,
|
||||
stream=stream,
|
||||
**ext_info,
|
||||
):
|
||||
agent_task = task
|
||||
yield chunk
|
||||
@@ -234,9 +390,10 @@ class MultiAgents(BaseComponent, ABC):
|
||||
raise
|
||||
finally:
|
||||
logger.info(f"save agent chat info!{conv_uid}")
|
||||
final_message = await self.stable_message(agent_conv_id)
|
||||
if final_message:
|
||||
current_message.add_view_message(final_message)
|
||||
if agent_conv_id:
|
||||
final_message = await self.stable_message(agent_conv_id)
|
||||
if final_message:
|
||||
current_message.add_view_message(final_message)
|
||||
current_message.end_current_round()
|
||||
current_message.save_to_storage()
|
||||
|
||||
@@ -245,110 +402,159 @@ class MultiAgents(BaseComponent, ABC):
|
||||
user_query: str,
|
||||
conv_uid: str,
|
||||
gpts_app: GptsApp,
|
||||
agent_memory: AgentMemory,
|
||||
is_retry_chat: bool = False,
|
||||
agent_memory: Optional[AgentMemory] = None,
|
||||
span_id: Optional[str] = None,
|
||||
last_speaker_name: str = None,
|
||||
init_message_rounds: int = 0,
|
||||
link_sender: ConversableAgent = None,
|
||||
app_link_start: bool = False,
|
||||
enable_verbose: bool = True,
|
||||
**ext_info,
|
||||
):
|
||||
employees: List[Agent] = []
|
||||
rm = get_resource_manager()
|
||||
context: AgentContext = AgentContext(
|
||||
conv_id=conv_uid,
|
||||
gpts_app_name=gpts_app.app_name,
|
||||
language=gpts_app.language,
|
||||
)
|
||||
|
||||
# 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)
|
||||
|
||||
depend_resource: Optional[Resource] = None
|
||||
for record in gpts_app.details:
|
||||
cls: Type[ConversableAgent] = get_agent_manager().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,
|
||||
)
|
||||
depend_resource = rm.build_resource(record.resources, version="v1")
|
||||
|
||||
agent = (
|
||||
await cls()
|
||||
.bind(context)
|
||||
.bind(llm_config)
|
||||
.bind(depend_resource)
|
||||
.bind(agent_memory)
|
||||
.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 = DefaultAWELLayoutManager(dag=gpts_app.team_context)
|
||||
else:
|
||||
raise ValueError(f"Unknown Agent Team Mode!{team_mode}")
|
||||
manager = (
|
||||
await manager.bind(context).bind(llm_config).bind(agent_memory).build()
|
||||
)
|
||||
manager.hire(employees)
|
||||
recipient = manager
|
||||
|
||||
user_proxy: UserProxyAgent = (
|
||||
await UserProxyAgent().bind(context).bind(agent_memory).build()
|
||||
)
|
||||
if is_retry_chat:
|
||||
# retry chat
|
||||
self.gpts_conversations.update(conv_uid, Status.RUNNING.value)
|
||||
|
||||
gpts_status = Status.COMPLETE.value
|
||||
try:
|
||||
with root_tracer.start_span(
|
||||
"dbgpt.serve.agent.run_agent", parent_span_id=span_id
|
||||
):
|
||||
employees: List[Agent] = []
|
||||
|
||||
self.agent_manage = get_agent_manager()
|
||||
|
||||
context: AgentContext = AgentContext(
|
||||
conv_id=conv_uid,
|
||||
gpts_app_code=gpts_app.app_code,
|
||||
gpts_app_name=gpts_app.app_name,
|
||||
language=gpts_app.language,
|
||||
app_link_start=app_link_start,
|
||||
enable_vis_message=enable_verbose,
|
||||
)
|
||||
|
||||
prompt_service: PromptService = get_service()
|
||||
rm = get_resource_manager()
|
||||
|
||||
# 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
|
||||
)
|
||||
|
||||
for record in gpts_app.details:
|
||||
cls: Type[ConversableAgent] = self.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,
|
||||
)
|
||||
prompt_template = None
|
||||
if record.prompt_template:
|
||||
prompt_template: PromptTemplate = prompt_service.get_template(
|
||||
prompt_code=record.prompt_template
|
||||
)
|
||||
depend_resource = rm.build_resource(record.resources, version="v1")
|
||||
agent = (
|
||||
await cls()
|
||||
.bind(context)
|
||||
.bind(agent_memory)
|
||||
.bind(llm_config)
|
||||
.bind(depend_resource)
|
||||
.bind(prompt_template)
|
||||
.build(is_retry_chat=is_retry_chat)
|
||||
)
|
||||
employees.append(agent)
|
||||
|
||||
team_mode = TeamMode(gpts_app.team_mode)
|
||||
if team_mode == TeamMode.SINGLE_AGENT:
|
||||
recipient = employees[0]
|
||||
else:
|
||||
if TeamMode.AUTO_PLAN == team_mode:
|
||||
if not gpts_app.details or len(gpts_app.details) < 0:
|
||||
raise ValueError("APP exception no available agent!")
|
||||
llm_config = employees[0].llm_config
|
||||
manager = AutoPlanChatManager()
|
||||
elif TeamMode.AWEL_LAYOUT == team_mode:
|
||||
if not gpts_app.team_context:
|
||||
raise ValueError(
|
||||
"Your APP has not been developed yet, please bind Flow!"
|
||||
)
|
||||
manager = DefaultAWELLayoutManager(dag=gpts_app.team_context)
|
||||
llm_config = LLMConfig(
|
||||
llm_client=self.llm_provider,
|
||||
llm_strategy=LLMStrategyType.Priority,
|
||||
strategy_context=json.dumps(["bailing_proxyllm"]),
|
||||
) # TODO
|
||||
elif TeamMode.NATIVE_APP == team_mode:
|
||||
raise ValueError(f"Native APP chat not supported!")
|
||||
else:
|
||||
raise ValueError(f"Unknown Agent Team Mode!{team_mode}")
|
||||
manager = (
|
||||
await manager.bind(context)
|
||||
.bind(agent_memory)
|
||||
.bind(llm_config)
|
||||
.build()
|
||||
)
|
||||
manager.hire(employees)
|
||||
recipient = manager
|
||||
|
||||
if is_retry_chat:
|
||||
# retry chat
|
||||
self.gpts_conversations.update(conv_uid, Status.RUNNING.value)
|
||||
|
||||
user_proxy = None
|
||||
if link_sender:
|
||||
await link_sender.initiate_chat(
|
||||
recipient=recipient,
|
||||
message=user_query,
|
||||
is_retry_chat=is_retry_chat,
|
||||
last_speaker_name=last_speaker_name,
|
||||
message_rounds=init_message_rounds,
|
||||
)
|
||||
else:
|
||||
user_proxy: UserProxyAgent = (
|
||||
await UserProxyAgent().bind(context).bind(agent_memory).build()
|
||||
)
|
||||
await user_proxy.initiate_chat(
|
||||
recipient=recipient,
|
||||
message=user_query,
|
||||
is_retry_chat=is_retry_chat,
|
||||
last_speaker_name=last_speaker_name,
|
||||
message_rounds=init_message_rounds,
|
||||
**ext_info,
|
||||
)
|
||||
|
||||
if user_proxy:
|
||||
# Check if the user has received a question.
|
||||
if user_proxy.have_ask_user():
|
||||
gpts_status = Status.WAITING.value
|
||||
if not app_link_start:
|
||||
self.gpts_conversations.update(conv_uid, gpts_status)
|
||||
except Exception as e:
|
||||
logger.error(f"chat abnormal termination!{str(e)}", e)
|
||||
self.gpts_conversations.update(conv_uid, Status.FAILED.value)
|
||||
finally:
|
||||
if not app_link_start:
|
||||
await self.memory.complete(conv_uid)
|
||||
|
||||
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
|
||||
self,
|
||||
conv_id: str,
|
||||
user_code: str = None,
|
||||
system_app: str = None,
|
||||
):
|
||||
is_complete = False
|
||||
while True:
|
||||
gpts_conv = self.gpts_conversations.get_by_conv_id(conv_id)
|
||||
if gpts_conv:
|
||||
is_complete = (
|
||||
True
|
||||
if gpts_conv.state
|
||||
in [
|
||||
Status.COMPLETE.value,
|
||||
Status.WAITING.value,
|
||||
Status.FAILED.value,
|
||||
]
|
||||
else False
|
||||
)
|
||||
message = await self.memory.one_chat_completions_v2(conv_id)
|
||||
yield message
|
||||
|
||||
if is_complete:
|
||||
queue = self.memory.queue(conv_id)
|
||||
if not queue:
|
||||
break
|
||||
item = await queue.get()
|
||||
if item == "[DONE]":
|
||||
queue.task_done()
|
||||
break
|
||||
else:
|
||||
await asyncio.sleep(2)
|
||||
yield item
|
||||
await asyncio.sleep(0.005)
|
||||
|
||||
async def stable_message(
|
||||
self, conv_id: str, user_code: str = None, system_app: str = None
|
||||
@@ -362,80 +568,32 @@ class MultiAgents(BaseComponent, ABC):
|
||||
else False
|
||||
)
|
||||
if is_complete:
|
||||
return await self.memory.one_chat_completions_v2(conv_id)
|
||||
return await self.memory.app_link_chat_message(conv_id)
|
||||
else:
|
||||
pass
|
||||
# raise ValueError(
|
||||
# "The conversation has not been completed yet, so we cannot directly obtain information."
|
||||
# )
|
||||
else:
|
||||
raise ValueError("No conversation record found!")
|
||||
raise Exception("No conversation record found!")
|
||||
|
||||
def gpts_conv_list(self, user_code: str = None, system_app: str = None):
|
||||
return self.gpts_conversations.get_convs(user_code, system_app)
|
||||
|
||||
|
||||
multi_agents = MultiAgents()
|
||||
async def topic_terminate(
|
||||
self,
|
||||
conv_id: str,
|
||||
):
|
||||
gpts_conversations: List[
|
||||
GptsConversationsEntity
|
||||
] = self.gpts_conversations.get_like_conv_id_asc(conv_id)
|
||||
# 检查最后一个对话记录是否完成,如果是等待状态,则要继续进行当前对话
|
||||
if gpts_conversations and len(gpts_conversations) > 0:
|
||||
last_gpts_conversation: GptsConversationsEntity = gpts_conversations[-1]
|
||||
if last_gpts_conversation.state == Status.WAITING.value:
|
||||
self.gpts_conversations.update(
|
||||
last_gpts_conversation.conv_id, Status.COMPLETE.value
|
||||
)
|
||||
|
||||
|
||||
@router.post("/v1/dbgpts/agents/list", response_model=Result[Dict[str, str]])
|
||||
async def agents_list():
|
||||
logger.info("agents_list!")
|
||||
try:
|
||||
agents = get_agent_manager().all_agents()
|
||||
return Result.succ(agents)
|
||||
except Exception as e:
|
||||
return Result.failed(code="E30001", msg=str(e))
|
||||
|
||||
|
||||
@router.get("/v1/dbgpts/list", response_model=Result[List[GptsApp]])
|
||||
async def get_dbgpts(user_code: str = None, sys_code: str = None):
|
||||
logger.info(f"get_dbgpts:{user_code},{sys_code}")
|
||||
try:
|
||||
return Result.succ(multi_agents.get_dbgpts())
|
||||
except Exception as e:
|
||||
logger.error(f"get_dbgpts failed:{str(e)}")
|
||||
return Result.failed(msg=str(e), code="E300003")
|
||||
|
||||
|
||||
@router.post("/v1/dbgpts/chat/completions", response_model=Result[str])
|
||||
async def dbgpts_completions(
|
||||
gpts_name: str,
|
||||
user_query: str,
|
||||
conv_id: str = None,
|
||||
user_code: str = None,
|
||||
sys_code: str = None,
|
||||
):
|
||||
logger.info(f"dbgpts_completions:{gpts_name},{user_query},{conv_id}")
|
||||
if conv_id is None:
|
||||
conv_id = str(uuid.uuid1())
|
||||
|
||||
headers = {
|
||||
"Content-Type": "text/event-stream",
|
||||
"Cache-Control": "no-cache",
|
||||
"Connection": "keep-alive",
|
||||
"Transfer-Encoding": "chunked",
|
||||
}
|
||||
return StreamingResponse(
|
||||
multi_agents.agent_chat(
|
||||
agent_conv_id=conv_id,
|
||||
gpts_name=gpts_name,
|
||||
user_query=user_query,
|
||||
user_code=user_code,
|
||||
sys_code=sys_code,
|
||||
),
|
||||
headers=headers,
|
||||
media_type="text/plain",
|
||||
)
|
||||
|
||||
|
||||
@router.post("/v1/dbgpts/chat/cancel", response_model=Result[str])
|
||||
async def dbgpts_chat_cancel(
|
||||
conv_id: str = None, user_code: str = None, sys_code: str = None
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
@router.post("/v1/dbgpts/chat/feedback", response_model=Result[str])
|
||||
async def dbgpts_chat_feedback(filter: PagenationFilter[PluginHubFilter] = Body()):
|
||||
pass
|
||||
multi_agents = MultiAgents(system_app)
|
||||
|
@@ -1,9 +1,9 @@
|
||||
from typing import List, Optional
|
||||
|
||||
from dbgpt.agent.core.memory.gpts.base import GptsPlan
|
||||
from dbgpt.agent.core.memory.gpts.gpts_memory import (
|
||||
from dbgpt.agent.core.memory.gpts import (
|
||||
GptsMessage,
|
||||
GptsMessageMemory,
|
||||
GptsPlan,
|
||||
GptsPlansMemory,
|
||||
)
|
||||
|
||||
@@ -56,9 +56,9 @@ class MetaDbGptsPlansMemory(GptsPlansMemory):
|
||||
task_num: int,
|
||||
state: str,
|
||||
retry_times: int,
|
||||
agent: Optional[str] = None,
|
||||
model: Optional[str] = None,
|
||||
result: Optional[str] = None,
|
||||
agent: str = None,
|
||||
model: str = None,
|
||||
result: str = None,
|
||||
):
|
||||
self.gpts_plan.update_task(
|
||||
conv_id=conv_id,
|
||||
@@ -95,7 +95,7 @@ class MetaDbGptsMessageMemory(GptsMessageMemory):
|
||||
agent1: str,
|
||||
agent2: str,
|
||||
current_goal: Optional[str] = None,
|
||||
) -> List[GptsMessage]:
|
||||
) -> Optional[List[GptsMessage]]:
|
||||
db_results = self.gpts_message.get_between_agents(
|
||||
conv_id, agent1, agent2, current_goal
|
||||
)
|
||||
@@ -105,7 +105,7 @@ class MetaDbGptsMessageMemory(GptsMessageMemory):
|
||||
results.append(GptsMessage.from_dict(item.__dict__))
|
||||
return results
|
||||
|
||||
def get_by_conv_id(self, conv_id: str) -> List[GptsMessage]:
|
||||
def get_by_conv_id(self, conv_id: str) -> Optional[List[GptsMessage]]:
|
||||
db_results = self.gpts_message.get_by_conv_id(conv_id)
|
||||
|
||||
results = []
|
||||
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
|
||||
|
0
dbgpt/serve/agent/agents/expand/__init__.py
Normal file
0
dbgpt/serve/agent/agents/expand/__init__.py
Normal file
0
dbgpt/serve/agent/agents/expand/actions/__init__.py
Normal file
0
dbgpt/serve/agent/agents/expand/actions/__init__.py
Normal file
92
dbgpt/serve/agent/agents/expand/actions/app_link_action.py
Normal file
92
dbgpt/serve/agent/agents/expand/actions/app_link_action.py
Normal file
@@ -0,0 +1,92 @@
|
||||
import json
|
||||
import logging
|
||||
from typing import Any, Dict, List, Optional, Union
|
||||
|
||||
from dbgpt._private.pydantic import BaseModel, Field, model_to_dict
|
||||
from dbgpt.agent import Action, ActionOutput, AgentResource, ResourceType
|
||||
from dbgpt.vis.tags.vis_app_link import Vis, VisAppLink
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class LinkAppInput(BaseModel):
|
||||
app_code: Optional[str] = Field(
|
||||
...,
|
||||
description="The code of selected app.",
|
||||
)
|
||||
app_name: Optional[str] = Field(
|
||||
...,
|
||||
description="The name of selected app.",
|
||||
)
|
||||
|
||||
|
||||
class LinkAppAction(Action[LinkAppInput]):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self._render_protocal = VisAppLink()
|
||||
|
||||
@property
|
||||
def resource_need(self) -> Optional[ResourceType]:
|
||||
return ResourceType.Knowledge
|
||||
|
||||
@property
|
||||
def render_protocal(self) -> Optional[Vis]:
|
||||
return self._render_protocal
|
||||
|
||||
@property
|
||||
def out_model_type(self):
|
||||
return LinkAppInput
|
||||
|
||||
async def run(
|
||||
self,
|
||||
ai_message: str,
|
||||
resource: Optional[AgentResource] = None,
|
||||
rely_action_out: Optional[ActionOutput] = None,
|
||||
need_vis_render: bool = True,
|
||||
**kwargs,
|
||||
) -> ActionOutput:
|
||||
try:
|
||||
param: LinkAppInput = self._input_convert(ai_message, LinkAppInput)
|
||||
except Exception as e:
|
||||
logger.warning(str(e))
|
||||
return ActionOutput(
|
||||
is_exe_success=False,
|
||||
content=ai_message,
|
||||
have_retry=False,
|
||||
)
|
||||
if not param.app_code or len(param.app_code) <= 0:
|
||||
app_link_param = {
|
||||
"app_code": "Personal assistant",
|
||||
"app_name": "Personal assistant",
|
||||
"app_desc": "",
|
||||
"app_logo": "",
|
||||
"status": "TODO",
|
||||
}
|
||||
|
||||
from dbgpt.agent.expand.summary_assistant_agent import SummaryAssistantAgent
|
||||
|
||||
return ActionOutput(
|
||||
is_exe_success=True,
|
||||
content=json.dumps(app_link_param, ensure_ascii=False),
|
||||
view=await self.render_protocal.display(content=app_link_param),
|
||||
next_speakers=[SummaryAssistantAgent().role],
|
||||
)
|
||||
else:
|
||||
app_link_param = {
|
||||
"app_code": param.app_code,
|
||||
"app_name": param.app_name,
|
||||
"app_desc": "",
|
||||
"app_logo": "",
|
||||
"status": "TODO",
|
||||
}
|
||||
|
||||
from dbgpt.serve.agent.agents.expand.app_start_assisant_agent import (
|
||||
StartAppAssistantAgent,
|
||||
)
|
||||
|
||||
return ActionOutput(
|
||||
is_exe_success=True,
|
||||
content=json.dumps(model_to_dict(param), ensure_ascii=False),
|
||||
view=await self.render_protocal.display(content=app_link_param),
|
||||
next_speakers=[StartAppAssistantAgent().role],
|
||||
)
|
106
dbgpt/serve/agent/agents/expand/actions/app_start_action.py
Normal file
106
dbgpt/serve/agent/agents/expand/actions/app_start_action.py
Normal file
@@ -0,0 +1,106 @@
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
from dbgpt._private.pydantic import BaseModel, Field, model_to_dict
|
||||
from dbgpt.agent import Action, ActionOutput, AgentResource
|
||||
from dbgpt.serve.agent.agents.expand.actions.intent_recognition_action import (
|
||||
IntentRecognitionInput,
|
||||
)
|
||||
from dbgpt.serve.agent.db.gpts_app import GptsApp, GptsAppDao
|
||||
from dbgpt.serve.agent.team.base import TeamMode
|
||||
from dbgpt.vis.tags.vis_plugin import Vis, VisPlugin
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class LinkAppInput(BaseModel):
|
||||
app_code: Optional[str] = Field(
|
||||
...,
|
||||
description="The code of selected app.",
|
||||
)
|
||||
app_name: Optional[str] = Field(
|
||||
...,
|
||||
description="The name of selected app.",
|
||||
)
|
||||
app_desc: Optional[str] = Field(
|
||||
...,
|
||||
description="The new user input.",
|
||||
)
|
||||
|
||||
|
||||
class StartAppAction(Action[LinkAppInput]):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self._render_protocal = VisPlugin()
|
||||
|
||||
@property
|
||||
def render_protocal(self) -> Optional[Vis]:
|
||||
return self._render_protocal
|
||||
|
||||
@property
|
||||
def out_model_type(self):
|
||||
return IntentRecognitionInput
|
||||
|
||||
async def run(
|
||||
self,
|
||||
ai_message: str,
|
||||
resource: Optional[AgentResource] = None,
|
||||
rely_action_out: Optional[ActionOutput] = None,
|
||||
need_vis_render: bool = True,
|
||||
**kwargs,
|
||||
) -> ActionOutput:
|
||||
conv_id = kwargs.get("conv_id")
|
||||
paren_agent = kwargs.get("paren_agent")
|
||||
init_message_rounds = kwargs.get("init_message_rounds")
|
||||
|
||||
try:
|
||||
param: LinkAppInput = self._input_convert(ai_message, LinkAppInput)
|
||||
except Exception as e:
|
||||
logger.exception(str(e))
|
||||
return ActionOutput(
|
||||
is_exe_success=False,
|
||||
content="The requested correctly structured answer could not be found.",
|
||||
)
|
||||
new_user_input = param.app_desc
|
||||
try:
|
||||
gpts_dao = GptsAppDao()
|
||||
gpts_app: GptsApp = gpts_dao.app_detail(param.app_code)
|
||||
if not gpts_app:
|
||||
return ActionOutput(
|
||||
is_exe_success=False,
|
||||
content=ai_message,
|
||||
view=f"[DBGPT Warning] Intent definition application cannot be found [{param.app_code}]{param.app_name}",
|
||||
have_retry=False,
|
||||
)
|
||||
if TeamMode.NATIVE_APP.value == gpts_app.team_mode:
|
||||
return ActionOutput(
|
||||
is_exe_success=False,
|
||||
content=ai_message,
|
||||
view="[DBGPT Warning] Native application connection startup is not supported for the time being.",
|
||||
have_retry=False,
|
||||
)
|
||||
else:
|
||||
from dbgpt.serve.agent.agents.controller import multi_agents
|
||||
|
||||
await multi_agents.agent_team_chat_new(
|
||||
new_user_input,
|
||||
conv_id,
|
||||
gpts_app,
|
||||
paren_agent.memory,
|
||||
False,
|
||||
link_sender=paren_agent,
|
||||
app_link_start=True,
|
||||
init_message_rounds=init_message_rounds,
|
||||
)
|
||||
|
||||
return ActionOutput(
|
||||
is_exe_success=True, content="", view=None, have_retry=False
|
||||
)
|
||||
except Exception as e:
|
||||
logger.exception(f"App [{param.app_code}] excute Failed!")
|
||||
return ActionOutput(
|
||||
is_exe_success=False,
|
||||
content=ai_message,
|
||||
view=f"[DBGPT Warning] An exception occurred during the answering process of linked application [{param.app_code}]{param.intent},{str(e)}",
|
||||
have_retry=False,
|
||||
)
|
@@ -0,0 +1,147 @@
|
||||
import json
|
||||
import logging
|
||||
from typing import Any, Dict, List, Optional, Union
|
||||
|
||||
from dbgpt._private.pydantic import BaseModel, Field, model_to_dict
|
||||
from dbgpt.agent import Action, ActionOutput, AgentResource, ResourceType
|
||||
from dbgpt.vis.tags.vis_app_link import Vis, VisAppLink
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class IntentRecognitionInput(BaseModel):
|
||||
intent: Optional[str] = Field(
|
||||
...,
|
||||
description="The intent of user question.",
|
||||
)
|
||||
app_code: Optional[str] = Field(
|
||||
...,
|
||||
description="The app code of intent.",
|
||||
)
|
||||
slots: Optional[dict] = Field(
|
||||
None,
|
||||
description="The slots of user question.",
|
||||
)
|
||||
ask_user: Optional[str] = Field(
|
||||
None,
|
||||
description="Questions to users.",
|
||||
)
|
||||
user_input: Optional[str] = Field(
|
||||
None,
|
||||
description="Generate new complete user instructions based on current intent and all slot information.",
|
||||
)
|
||||
|
||||
def to_dict(self):
|
||||
return model_to_dict(self)
|
||||
|
||||
|
||||
class IntentRecognitionAction(Action[IntentRecognitionInput]):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self._render_protocal = VisAppLink()
|
||||
|
||||
@property
|
||||
def resource_need(self) -> Optional[ResourceType]:
|
||||
return ResourceType.Knowledge
|
||||
|
||||
@property
|
||||
def render_protocal(self) -> Optional[Vis]:
|
||||
return self._render_protocal
|
||||
|
||||
@property
|
||||
def out_model_type(self):
|
||||
return IntentRecognitionInput
|
||||
|
||||
@property
|
||||
def ai_out_schema(self) -> Optional[str]:
|
||||
out_put_schema = {
|
||||
"intent": "[The recognized intent is placed here]",
|
||||
"app_code": "[App code in selected intent]",
|
||||
"slots": {"意图定义中槽位属性1": "具体值", "意图定义中槽位属性2": "具体值"},
|
||||
"ask_user": "If you want the user to supplement slot data, ask the user a question",
|
||||
"user_input": "[Complete instructions generated based on intent and slot]",
|
||||
}
|
||||
if self.language == "en":
|
||||
return f"""Please reply in the following json format:
|
||||
{json.dumps(out_put_schema, indent=2, ensure_ascii=False)}
|
||||
Make sure the output is only json and can be parsed by Python json.loads.""" # noqa: E501
|
||||
else:
|
||||
return f"""请按如下JSON格式输出:
|
||||
{json.dumps(out_put_schema, indent=2, ensure_ascii=False)}
|
||||
确保输出只有json,且可以被python json.loads加载."""
|
||||
|
||||
def _get_default_next_speakers(self):
|
||||
next_speakers = []
|
||||
from dbgpt.agent.expand.summary_assistant_agent import SummaryAssistantAgent
|
||||
|
||||
next_speakers.append(SummaryAssistantAgent().role)
|
||||
|
||||
from dbgpt.agent.expand.simple_assistant_agent import SimpleAssistantAgent
|
||||
|
||||
next_speakers.append(SimpleAssistantAgent().role)
|
||||
|
||||
return next_speakers
|
||||
|
||||
async def run(
|
||||
self,
|
||||
ai_message: str,
|
||||
resource: Optional[AgentResource] = None,
|
||||
rely_action_out: Optional[ActionOutput] = None,
|
||||
need_vis_render: bool = True,
|
||||
**kwargs,
|
||||
) -> ActionOutput:
|
||||
next_speakers = self._get_default_next_speakers()
|
||||
try:
|
||||
intent: IntentRecognitionInput = self._input_convert(
|
||||
ai_message, IntentRecognitionInput
|
||||
)
|
||||
except Exception as e:
|
||||
logger.exception(str(e))
|
||||
return ActionOutput(
|
||||
is_exe_success=False,
|
||||
content="Error:The answer is not output in the required format.",
|
||||
have_retry=True,
|
||||
next_speakers=next_speakers,
|
||||
)
|
||||
|
||||
# Check whether the message is complete and whether additional information needs to be provided to the user
|
||||
if intent.slots:
|
||||
for key, value in intent.slots.items():
|
||||
if not value or len(value) <= 0:
|
||||
logger.info("slots check, need additional information!")
|
||||
return ActionOutput(
|
||||
is_exe_success=False,
|
||||
content=json.dumps(intent.to_dict(), ensure_ascii=False),
|
||||
view=intent.ask_user if intent.ask_user else ai_message,
|
||||
have_retry=False,
|
||||
ask_user=True,
|
||||
next_speakers=next_speakers,
|
||||
)
|
||||
|
||||
if intent.app_code and len(intent.app_code) > 0:
|
||||
from dbgpt.serve.agent.agents.expand.app_start_assisant_agent import (
|
||||
StartAppAssistantAgent,
|
||||
)
|
||||
|
||||
next_speakers = [StartAppAssistantAgent().role]
|
||||
|
||||
app_link_param = {
|
||||
"app_code": intent.app_code,
|
||||
"app_name": intent.intent,
|
||||
"app_desc": intent.user_input,
|
||||
}
|
||||
|
||||
return ActionOutput(
|
||||
is_exe_success=True,
|
||||
content=json.dumps(app_link_param, ensure_ascii=False),
|
||||
view=await self.render_protocal.display(
|
||||
content={
|
||||
"app_code": intent.app_code,
|
||||
"app_name": intent.intent,
|
||||
"app_desc": intent.user_input,
|
||||
"app_logo": "",
|
||||
"status": "TODO",
|
||||
}
|
||||
),
|
||||
next_speakers=next_speakers,
|
||||
)
|
53
dbgpt/serve/agent/agents/expand/app_link_assisant_agent.py
Normal file
53
dbgpt/serve/agent/agents/expand/app_link_assisant_agent.py
Normal file
@@ -0,0 +1,53 @@
|
||||
import logging
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
from dbgpt.agent import Agent, ConversableAgent, get_agent_manager
|
||||
from dbgpt.agent.core.profile import DynConfig, ProfileConfig
|
||||
from dbgpt.serve.agent.agents.expand.actions.app_link_action import LinkAppAction
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
class LinkAppAssistantAgent(ConversableAgent):
|
||||
profile: ProfileConfig = ProfileConfig(
|
||||
name=DynConfig(
|
||||
"dbgpt",
|
||||
category="agent",
|
||||
key="dbgpt_ant_agent_agents_app_link_assistant_agent_profile_name",
|
||||
),
|
||||
role=DynConfig(
|
||||
"App Link",
|
||||
category="agent",
|
||||
key="dbgpt_ant_agent_agents_app_link_assistant_agent_profile_role",
|
||||
),
|
||||
goal=DynConfig(
|
||||
"根据用户的问题和提供的应用信息,选择一个合适的应用来解决和回答用户的问题,并提取用户输入的关键信息到应用意图的槽位中。",
|
||||
category="agent",
|
||||
key="dbgpt_ant_agent_agents_app_link_assistant_agent_profile_goal",
|
||||
),
|
||||
constraints=DynConfig(
|
||||
[
|
||||
"请一步一步思考参为用户问题选择一个最匹配的应用来进行用户问题回答,可参考给出示例的应用选择逻辑.",
|
||||
"请阅读用户问题,确定问题所属领域和问题意图,按领域和意图匹配应用,如果用户问题意图缺少操作类应用需要的参数,优先使用咨询类型应用,有明确操作目标才使用操作类应用.",
|
||||
"仅选择可回答问题的应用即可,不要直接回答用户问题.",
|
||||
"如果用户的问题和提供的所有应用全都不相关,则应用code和name都输出为空",
|
||||
"注意应用意图定义中如果有槽位信息,再次阅读理解用户输入信息,将对应的内容填入对应槽位参数定义中.",
|
||||
],
|
||||
category="agent",
|
||||
key="dbgpt_ant_agent_agents_app_link_assistant_agent_profile_constraints",
|
||||
),
|
||||
desc=DynConfig(
|
||||
"根据用户问题匹配合适的应用来进行回答.",
|
||||
category="agent",
|
||||
key="dbgpt_ant_agent_agents_app_link_assistant_agent_profile_desc",
|
||||
),
|
||||
)
|
||||
stream_out: bool = False
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self._init_actions([LinkAppAction])
|
||||
|
||||
|
||||
agent_manage = get_agent_manager()
|
||||
agent_manage.register_agent(LinkAppAssistantAgent)
|
154
dbgpt/serve/agent/agents/expand/app_start_assisant_agent.py
Normal file
154
dbgpt/serve/agent/agents/expand/app_start_assisant_agent.py
Normal file
@@ -0,0 +1,154 @@
|
||||
import json
|
||||
import logging
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
from dbgpt.agent import (
|
||||
ActionOutput,
|
||||
Agent,
|
||||
AgentMessage,
|
||||
ConversableAgent,
|
||||
get_agent_manager,
|
||||
)
|
||||
from dbgpt.agent.core.memory.gpts import GptsMessage
|
||||
from dbgpt.agent.core.profile import DynConfig, ProfileConfig
|
||||
from dbgpt.serve.agent.agents.expand.actions.app_start_action import StartAppAction
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
class StartAppAssistantAgent(ConversableAgent):
|
||||
profile: ProfileConfig = ProfileConfig(
|
||||
name=DynConfig(
|
||||
"AppLauncher",
|
||||
category="agent",
|
||||
key="dbgpt_ant_agent_agents_app_start_assistant_agent_profile_name",
|
||||
),
|
||||
role=DynConfig(
|
||||
"AppLauncher",
|
||||
category="agent",
|
||||
key="dbgpt_ant_agent_agents_app_start_assistant_agent_profile_role",
|
||||
),
|
||||
goal=DynConfig(
|
||||
"The agent starts the selected application.",
|
||||
category="agent",
|
||||
key="dbgpt_ant_agent_agents_app_start_assistant_agent_profile_goal",
|
||||
),
|
||||
constraints=DynConfig(
|
||||
[],
|
||||
category="agent",
|
||||
key="dbgpt_ant_agent_agents_app_start_assistant_agent_profile_constraints",
|
||||
),
|
||||
desc=DynConfig(
|
||||
"The agent starts the selected application.",
|
||||
category="agent",
|
||||
key="dbgpt_ant_agent_agents_app_start_assistant_agent_profile_desc",
|
||||
),
|
||||
)
|
||||
last_rounds: int = 0
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self._init_actions([StartAppAction])
|
||||
|
||||
def prepare_act_param(
|
||||
self,
|
||||
received_message: Optional[AgentMessage],
|
||||
sender: Agent,
|
||||
rely_messages: Optional[List[AgentMessage]] = None,
|
||||
) -> Dict[str, Any]:
|
||||
return {
|
||||
"user_input": received_message.content,
|
||||
"conv_id": self.agent_context.conv_id,
|
||||
"paren_agent": self,
|
||||
}
|
||||
|
||||
async def _load_thinking_messages(
|
||||
self,
|
||||
received_message: AgentMessage,
|
||||
sender: Agent,
|
||||
rely_messages: Optional[List[AgentMessage]] = None,
|
||||
context: Optional[Dict[str, Any]] = None,
|
||||
is_retry_chat: Optional[bool] = False,
|
||||
) -> (List[AgentMessage], Optional[Dict]):
|
||||
if rely_messages and len(rely_messages) > 0:
|
||||
return rely_messages[-1:], None
|
||||
else:
|
||||
raise ValueError("没有可用的应用链接消息!")
|
||||
|
||||
async def thinking(
|
||||
self,
|
||||
messages: List[AgentMessage],
|
||||
sender: Optional[Agent] = None,
|
||||
prompt: Optional[str] = None,
|
||||
) -> Tuple[Optional[str], Optional[str]]:
|
||||
return messages[0].action_report.content, None
|
||||
|
||||
async def receive(
|
||||
self,
|
||||
message: AgentMessage,
|
||||
sender: Agent,
|
||||
reviewer: Optional[Agent] = None,
|
||||
request_reply: Optional[bool] = None,
|
||||
silent: Optional[bool] = False,
|
||||
is_recovery: Optional[bool] = False,
|
||||
is_retry_chat: bool = False,
|
||||
last_speaker_name: str = None,
|
||||
) -> None:
|
||||
await self._a_process_received_message(message, sender)
|
||||
if request_reply is False or request_reply is None:
|
||||
return
|
||||
|
||||
if sender.agent_context.app_link_start:
|
||||
self.last_rounds = message.rounds
|
||||
|
||||
elif not self.is_human and not sender.agent_context.app_link_start:
|
||||
is_success, reply = await self.generate_reply(
|
||||
received_message=message,
|
||||
sender=sender,
|
||||
reviewer=reviewer,
|
||||
is_retry_chat=is_retry_chat,
|
||||
last_speaker_name=last_speaker_name,
|
||||
)
|
||||
if reply is not None:
|
||||
await self.a_send(reply, sender, silent=True)
|
||||
|
||||
async def adjust_final_message(
|
||||
self,
|
||||
is_success: bool,
|
||||
reply_message: AgentMessage,
|
||||
):
|
||||
if self.last_rounds > 0:
|
||||
reply_message.rounds = self.last_rounds
|
||||
return is_success, reply_message
|
||||
|
||||
async def act(
|
||||
self,
|
||||
message: AgentMessage,
|
||||
sender: Agent,
|
||||
reviewer: Optional[Agent] = None,
|
||||
is_retry_chat: bool = False,
|
||||
last_speaker_name: Optional[str] = None,
|
||||
**kwargs,
|
||||
) -> ActionOutput:
|
||||
last_out = None
|
||||
for action in self.actions:
|
||||
# Select the resources required by acton
|
||||
last_out: ActionOutput = await action.run(
|
||||
ai_message=message.content,
|
||||
resource=self.resource,
|
||||
rely_action_out=last_out,
|
||||
init_message_rounds=message.rounds,
|
||||
**kwargs,
|
||||
)
|
||||
history_messages: List[
|
||||
GptsMessage
|
||||
] = await self.memory.gpts_memory.get_messages(self.agent_context.conv_id)
|
||||
last_gpt_message = history_messages[-1]
|
||||
if history_messages:
|
||||
message.rounds = last_gpt_message.rounds
|
||||
|
||||
return ActionOutput.from_dict(json.loads(last_gpt_message.action_report))
|
||||
|
||||
|
||||
agent_manage = get_agent_manager()
|
||||
agent_manage.register_agent(StartAppAssistantAgent)
|
137
dbgpt/serve/agent/agents/expand/intent_recognition_agent.py
Normal file
137
dbgpt/serve/agent/agents/expand/intent_recognition_agent.py
Normal file
@@ -0,0 +1,137 @@
|
||||
import logging
|
||||
|
||||
from dbgpt.agent import ConversableAgent, get_agent_manager
|
||||
from dbgpt.agent.core.profile import DynConfig, ProfileConfig
|
||||
from dbgpt.serve.agent.agents.expand.actions.intent_recognition_action import (
|
||||
IntentRecognitionAction,
|
||||
)
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
GOAL_EN = (
|
||||
"Understand the user input information, select an intention that best matches the "
|
||||
"user input from the intention definition of the known information, and output the "
|
||||
"intention information as required."
|
||||
)
|
||||
GOAL_ZH = "理解用户输入信息,从已知信息的意图定义中选择一个和用户输入最匹配的意图,并按要求输出意图信息."
|
||||
|
||||
RETRY_GOAL_EN = (
|
||||
"Read the content of the recent messages provided by the following users, "
|
||||
"extract and supplement the current user input information into the intent "
|
||||
"information in the recent messages, and return the supplemented intent information."
|
||||
)
|
||||
|
||||
RETRY_GOAL_ZH = "阅读下面用户提供的最近消息内容,并把当前用户输入信息提取补充到最近消息中的意图信息里,并返回补充后的意图信息。"
|
||||
|
||||
CONSTRAINTS_EN = [
|
||||
"Strictly define the output based on the given intent. Do not generate the intent and "
|
||||
"slot attributes by yourself. If the intent does not define a slot, the output should "
|
||||
"not include the slot.",
|
||||
"Select the appropriate intent to answer the user's question based on user input. "
|
||||
"If no intent can be matched, the output of app_code' will be empty.",
|
||||
"If there is no 'Slots' definition in the selected intent definition, make sure the "
|
||||
"output slot content is empty and do not create any slot information yourself.",
|
||||
"If there is a 'Slots' definition in the selected intent definition, extract the value "
|
||||
"of the specific slot attribute from the user input. If the value of the slot attribute "
|
||||
"cannot be obtained, ensure that the slot attribute value output is empty.",
|
||||
"When extracting the slot value, please be careful to only obtain the valid value part. "
|
||||
"Do not fill in auxiliary descriptions, attributes, prompts or description information, "
|
||||
"and do not appear content like 'not provided by the user'.",
|
||||
"When the complete slot attribute value defined by the intent cannot be collected, a "
|
||||
"prompt will be proactively sent to the user to remind the user to supplement the missing "
|
||||
"slot data.",
|
||||
]
|
||||
CONSTRAINTS_ZH = [
|
||||
"严格根给出的意图定义输出,不要自行生成意图和槽位属性,意图没有定义槽位则输出也不应该包含槽位.",
|
||||
"根据用户输入选择合适的意图回答用户问题,如无法匹配到任何意图,app_code'输出为空.",
|
||||
"如果选择的意图定义中没有'Slots'定义,则确保输出槽位内容为空,不要自行创造任何槽位信息",
|
||||
"如果选择的意图定义中有'Slots'定义,从用户输入中提取具体槽位属性的值,如果无法获取到槽位属性的值,则确保槽位属性值输出空.",
|
||||
"槽位值提取时请注意只获取有效值部分,不要填入辅助描述、定语、提示或者描述信息,不要出现类似'用户未提供'这样的内容.",
|
||||
"无法收集到完整的意图定义的槽位属性值时,主动像用户发起提示,提醒用户补充缺槽位数据.",
|
||||
]
|
||||
|
||||
RETRY_CONSTRAINTS_EN = [
|
||||
"Read the recent message dialogue information provided by the user, extract and supplement the "
|
||||
"information input by the current user into the historical dialogue intent, and output it in the "
|
||||
"original intent format without losing attributes.",
|
||||
"If the user does not explicitly request modification, do not modify the existing intent and "
|
||||
"slot value in the intent in the recent message, only add new content.",
|
||||
"When extracting slot values, please be careful to only obtain the valid value part "
|
||||
"and do not fill in auxiliary descriptions or attributes.",
|
||||
"Extract the value of the slot in the intent definition from user input and recent messages. "
|
||||
"If the target information corresponding to the slot cannot be obtained, the slot value output is empty.",
|
||||
"Make sure that all slot attributes of the slot defined by the intention are output regardless of "
|
||||
"whether the value is obtained, and the slot name and null value are output if the value is not found.",
|
||||
"If the slot value still cannot be completely filled, new questions will continue to be generated "
|
||||
"to ask the user, prompting the user to supplement the missing slot data.",
|
||||
]
|
||||
RETRY_CONSTRAINTS_ZH = [
|
||||
"阅读用户提供最近消息对话信息,把当前用户输入中信息提取补充到历史对话意图中并按原意图格式输出,不要丢失属性.",
|
||||
"如果用户没有明确要求修改,不要修改最近消息中意图中已经存在的意图和槽位值,仅补充新的内容进去.",
|
||||
"槽位值提取时请注意只获取有效值部分,不要填入辅助描述或定语",
|
||||
"从用户输入和最近消息息中提取意图定义中槽位的值,如果无法获取到槽位对应的目标信息,则槽位值输出空.",
|
||||
"确保意图定义的槽位不管是否获取到值,都要输出全部槽位属性,没有找到值的输出槽位名和空值.",
|
||||
"如果槽位值依然无法完全对应填满,则继续生成新的问题向用户提问,提示用户补充缺少的槽位数据.",
|
||||
]
|
||||
|
||||
|
||||
class IntentRecognitionAgent(ConversableAgent):
|
||||
profile: ProfileConfig = ProfileConfig(
|
||||
name=DynConfig(
|
||||
"Kevin",
|
||||
category="agent",
|
||||
key="dbgpt_ant_agent_agents_intent_recognition_agent_profile_name",
|
||||
),
|
||||
role=DynConfig(
|
||||
"Intent Recognition Expert",
|
||||
category="agent",
|
||||
key="dbgpt_ant_agent_agents_intent_recognition_agent_profile_role",
|
||||
),
|
||||
goal=DynConfig(
|
||||
GOAL_EN,
|
||||
category="agent",
|
||||
key="dbgpt_ant_agent_agents_intent_recognition_agent_profile_goal",
|
||||
),
|
||||
retry_goal=DynConfig(
|
||||
RETRY_GOAL_EN,
|
||||
category="agent",
|
||||
key="dbgpt_ant_agent_agents_intent_recognition_agent_profile_retry_goal",
|
||||
),
|
||||
constraints=DynConfig(
|
||||
CONSTRAINTS_EN,
|
||||
category="agent",
|
||||
key="dbgpt_ant_agent_agents_intent_recognition_agent_profile_retry_constraints",
|
||||
),
|
||||
retry_constraints=DynConfig(
|
||||
RETRY_CONSTRAINTS_EN,
|
||||
category="agent",
|
||||
key="dbgpt_ant_agent_agents_intent_recognition_agent_profile_constraints",
|
||||
),
|
||||
desc=DynConfig(
|
||||
"Identify user intent.",
|
||||
category="agent",
|
||||
key="dbgpt_ant_agent_agents_intent_recognition_agent_profile_desc",
|
||||
),
|
||||
)
|
||||
|
||||
stream_out: bool = False
|
||||
language: str = "zh"
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self._init_actions([IntentRecognitionAction])
|
||||
if self.language == "zh":
|
||||
self.profile.goal.default = GOAL_ZH
|
||||
self.profile.retry_goal.default = RETRY_GOAL_ZH
|
||||
self.profile.constraints.default = CONSTRAINTS_ZH
|
||||
self.profile.retry_constraints.default = RETRY_CONSTRAINTS_ZH
|
||||
|
||||
async def load_resource(self, question: str, is_retry_chat: bool = False):
|
||||
if is_retry_chat:
|
||||
return ("", None)
|
||||
else:
|
||||
return await super().load_resource(question, is_retry_chat)
|
||||
|
||||
|
||||
agent_manage = get_agent_manager()
|
||||
agent_manage.register_agent(IntentRecognitionAgent)
|
Reference in New Issue
Block a user