From db8708b2261081d3d3c3cfcab8b0c5f002cb2dc3 Mon Sep 17 00:00:00 2001 From: yhjun1026 <460342015@qq.com> Date: Fri, 16 Aug 2024 18:08:33 +0800 Subject: [PATCH] feat(feedback): feedback upgrade --- dbgpt/agent/core/action/base.py | 1 + .../agents/expand/actions/app_start_action.py | 37 ++++---- .../actions/intent_recognition_action.py | 53 ++++++----- .../agents/expand/intent_recognition_agent.py | 92 +++++++++++++++---- 4 files changed, 121 insertions(+), 62 deletions(-) diff --git a/dbgpt/agent/core/action/base.py b/dbgpt/agent/core/action/base.py index 17c22c21f..50b36af45 100644 --- a/dbgpt/agent/core/action/base.py +++ b/dbgpt/agent/core/action/base.py @@ -85,6 +85,7 @@ class Action(ABC, Generic[T]): def __init__(self): """Create an action.""" self.resource: Optional[Resource] = None + self.language: str = "en" def init_resource(self, resource: Optional[Resource]): """Initialize the resource.""" diff --git a/dbgpt/serve/agent/agents/expand/actions/app_start_action.py b/dbgpt/serve/agent/agents/expand/actions/app_start_action.py index 15de8be5f..4665c3d76 100644 --- a/dbgpt/serve/agent/agents/expand/actions/app_start_action.py +++ b/dbgpt/serve/agent/agents/expand/actions/app_start_action.py @@ -1,8 +1,10 @@ import logging from typing import Optional -from dbgpt.agent import Action, ActionOutput, AgentResource, ConversableAgent -from dbgpt.serve.agent.agents.expand.actions.app_link_action import LinkAppInput +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 @@ -10,7 +12,7 @@ from dbgpt.vis.tags.vis_plugin import Vis, VisPlugin logger = logging.getLogger(__name__) -class StartAppAction(Action[LinkAppInput]): +class StartAppAction(Action[IntentRecognitionInput]): def __init__(self, **kwargs): super().__init__(**kwargs) self._render_protocal = VisPlugin() @@ -21,23 +23,25 @@ class StartAppAction(Action[LinkAppInput]): @property def out_model_type(self): - return LinkAppInput + return IntentRecognitionInput async def run( self, ai_message: str, - user_input: str, - conv_id: str, - paren_agent: ConversableAgent, - init_message_rounds: int, - sender: Optional[ConversableAgent] = None, resource: Optional[AgentResource] = None, rely_action_out: Optional[ActionOutput] = None, need_vis_render: bool = True, **kwargs, ) -> ActionOutput: + user_input = kwargs.get("user_input") + 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) + param: IntentRecognitionInput = self._input_convert( + ai_message, IntentRecognitionInput + ) except Exception as e: logger.exception(str(e)) return ActionOutput( @@ -51,21 +55,20 @@ class StartAppAction(Action[LinkAppInput]): if not gpts_app: return ActionOutput( is_exe_success=False, - content=f"链接智能体{param.app_name}信息配置异常无法找到", - view=f"链接智能体{param.app_name}信息配置异常无法找到", + content=ai_message, + view=f"[DBGPT Warning] Intent definition application cannot be found [{param.app_code}]{param.intent}", have_retry=False, ) if TeamMode.NATIVE_APP.value == gpts_app.team_mode: return ActionOutput( is_exe_success=False, - content="暂时不支持原生应用连接启动", - view="暂时不支持原生应用连接启动", + 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 - # TODO 仅启动应用,不需要返回信息 await multi_agents.agent_team_chat_new( user_input, conv_id, @@ -84,7 +87,7 @@ class StartAppAction(Action[LinkAppInput]): logger.exception(f"App [{param.app_code}] excute Failed!") return ActionOutput( is_exe_success=False, - content=f"应用[{param.app_name}]回答失败!{str(e)}", - view=f"应用[{param.app_name}]回答失败!{str(e)}", + 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, ) diff --git a/dbgpt/serve/agent/agents/expand/actions/intent_recognition_action.py b/dbgpt/serve/agent/agents/expand/actions/intent_recognition_action.py index 6525a4039..3009c2af1 100644 --- a/dbgpt/serve/agent/agents/expand/actions/intent_recognition_action.py +++ b/dbgpt/serve/agent/agents/expand/actions/intent_recognition_action.py @@ -2,7 +2,7 @@ import json import logging from typing import Any, Dict, List, Optional, Union -from dbgpt._private.pydantic import BaseModel, Field +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 @@ -22,19 +22,18 @@ class IntentRecognitionInput(BaseModel): ..., description="The slots of user question.", ) - thought: Optional[str] = Field( - ..., - description="Logic and rationale for selecting the current application.", - ) ask_user: Optional[str] = Field( ..., description="Questions to users.", ) user_input: Optional[str] = Field( ..., - description="Instructions generated based on intent and slot.", + 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): @@ -54,20 +53,25 @@ class IntentRecognitionAction(Action[IntentRecognitionInput]): return IntentRecognitionInput @property - def ai_out_schema(self) -> Union[Dict[str, Any], List[Dict[str, Any]]]: + def ai_out_schema(self) -> Optional[str]: out_put_schema = { - "intent": "[意图占位符]", - "thought": "你的推理思路", - "app_code": "预定义意图的代码", - "slots": {"意图定义中槽位属性1": "具体值", "意图定义中槽位属性2": "具体值"}, - "ask_user": "如果要用户补充槽位数据,向用户发起的问题", - "user_input": "[根据意图和槽位生成的完整指令]", + "intent": "[The recognized intent is placed here]", + "app_code": "[App code in selected intent]", + "slots": { + "Slot_1": "[The value of the slot attribute]", + "Slot_2": "[The value of the slot attribute]", + }, + "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]", } - - return f"""请按如下JSON格式输出: - {json.dumps(out_put_schema, indent=2, ensure_ascii=False)} - 确保只输出json,且可以被python json.loads加载. - """ + 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 reply content only has correct 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加载.""" async def run( self, @@ -75,6 +79,7 @@ class IntentRecognitionAction(Action[IntentRecognitionInput]): resource: Optional[AgentResource] = None, rely_action_out: Optional[ActionOutput] = None, need_vis_render: bool = True, + **kwargs, ) -> ActionOutput: try: intent: IntentRecognitionInput = self._input_convert( @@ -84,17 +89,17 @@ class IntentRecognitionAction(Action[IntentRecognitionInput]): logger.exception(str(e)) return ActionOutput( is_exe_success=False, - content=ai_message, - have_retry=False, + content="Error:The answer is not output in the required format.", + have_retry=True, ) - # 检查意图是否完整,是否需要向用户补充信息 + # 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: return ActionOutput( is_exe_success=False, - content=json.dumps(intent.dict(), ensure_ascii=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, @@ -104,13 +109,11 @@ class IntentRecognitionAction(Action[IntentRecognitionInput]): "app_code": intent.app_code, "app_name": intent.intent, "app_desc": intent.user_input, - "thought": intent.thought, "app_logo": "", "status": "TODO", - "intent": json.dumps(intent.dict(), ensure_ascii=False), } return ActionOutput( is_exe_success=True, - content=json.dumps(app_link_param, ensure_ascii=False), + content=json.dumps(intent.to_dict(), ensure_ascii=False), view=await self.render_protocal.display(content=app_link_param), ) diff --git a/dbgpt/serve/agent/agents/expand/intent_recognition_agent.py b/dbgpt/serve/agent/agents/expand/intent_recognition_agent.py index 3bcaf776f..ddf56117b 100644 --- a/dbgpt/serve/agent/agents/expand/intent_recognition_agent.py +++ b/dbgpt/serve/agent/agents/expand/intent_recognition_agent.py @@ -8,6 +8,72 @@ from dbgpt.serve.agent.agents.expand.actions.intent_recognition_action import ( 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 " + "extract the information and output the complete 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.", + "Extract the value of the slot attribute in the intent definition from user input and historical " + "dialogue information. If the target information corresponding to the slot attribute cannot be " + "obtained, the slot value output is empty.", + "When extracting slot values, please be careful to only obtain the valid value part and do not " + "fill in auxiliary descriptions or attributes.", + "Make sure that the slot attributes defined by intention will output all the slot attributes " + "given by the definition regardless of whether the value is obtained. If the value is not found, " + "the slot name and null value will be output.", + "Please ensure that if the content of the intent slot definition is not provided in the user " + "question, the slot value must be empty, and do not fill in invalid information such as 'user " + "not provided' in the slot value.", + "If the information extracted from the user's question content does not completely correspond to " + "the matched intention slot, a new question will be generated to ask the user and prompt the user " + "to supplement the missing slot data.", +] +CONSTRAINTS_ZH = [ + "严格根给出的意图定义输出,不要自行生成意图和槽位属性,意图没有定义槽位则输出也不应该包含槽位.", + "从用户输入和历史对话信息中提取意图定义中槽位属性的值,如果无法获取到槽位属性对应的目标信息,则槽位值输出空.", + "槽位值提取时请注意只获取有效值部分,不要填入辅助描述或定语", + "确保意图定义的槽位属性不管是否获取到值,都要输出全部定义给出的槽位属性,没有找到值的输出槽位名和空值.", + "请确保如果用户问题中未提供意图槽位定义的内容,则槽位值必须为空,不要在槽位值里填‘用户未提供’这类无效信息.", + "如果用户问题内容提取的信息和匹配到的意图槽位无法完全对应,则生成新的问题向用户提问,提示用户补充缺少的槽位数据.", +] + +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( @@ -17,46 +83,32 @@ class IntentRecognitionAgent(ConversableAgent): key="dbgpt_ant_agent_agents_intent_recognition_agent_profile_name", ), role=DynConfig( - "IntentRecognitionExpert", + "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", ),