From e046431d9bdfc7ef83a77d27082e9e269b56adb1 Mon Sep 17 00:00:00 2001 From: chase Date: Wed, 3 Jun 2026 17:18:50 +0800 Subject: [PATCH 01/35] add_greeting_fields_to_agent-develop --- backend/consts/model.py | 2 + backend/database/agent_db.py | 2 + backend/database/db_models.py | 2 + .../prompts/utils/greeting_generate_en.yaml | 54 ++++++++++++++ .../prompts/utils/greeting_generate_zh.yaml | 53 ++++++++++++++ backend/services/agent_service.py | 9 ++- backend/services/agent_version_service.py | 2 + backend/services/prompt_service.py | 66 ++++++++++++++++- backend/utils/prompt_template_utils.py | 4 ++ ...d_greeting_fields_to_ag_tenant_agent_t.sql | 15 ++++ .../agentInfo/AgentGenerateDetail.tsx | 70 ++++++++++++++++++- .../chat/components/chatAgentSelector.tsx | 3 +- .../[locale]/chat/components/chatInput.tsx | 54 ++++++++++---- .../[locale]/chat/internal/chatInterface.tsx | 12 +++- .../chat/streaming/chatStreamMain.tsx | 6 ++ frontend/const/agentConfig.ts | 2 + frontend/hooks/agent/useAgentGeneration.ts | 13 +++- frontend/hooks/agent/useSaveGuard.ts | 2 + frontend/lib/agentGenerationCache.ts | 8 ++- frontend/public/locales/en/common.json | 6 ++ frontend/public/locales/zh/common.json | 6 ++ frontend/services/agentConfigService.ts | 6 ++ frontend/stores/agentConfigStore.ts | 20 +++++- frontend/types/agentConfig.ts | 4 ++ frontend/types/chat.ts | 6 +- 25 files changed, 401 insertions(+), 26 deletions(-) create mode 100644 backend/prompts/utils/greeting_generate_en.yaml create mode 100644 backend/prompts/utils/greeting_generate_zh.yaml create mode 100644 docker/sql/v2.2.0_0603_add_greeting_fields_to_ag_tenant_agent_t.sql diff --git a/backend/consts/model.py b/backend/consts/model.py index 6969999fe..06aed86be 100644 --- a/backend/consts/model.py +++ b/backend/consts/model.py @@ -454,6 +454,8 @@ class AgentInfoRequest(BaseModel): group_ids: Optional[List[int]] = None ingroup_permission: Optional[str] = None enable_context_manager: Optional[bool] = None + greeting_message: Optional[str] = None + example_questions: Optional[List[str]] = None version_no: int = 0 diff --git a/backend/database/agent_db.py b/backend/database/agent_db.py index 82696ffab..24f5cc3df 100644 --- a/backend/database/agent_db.py +++ b/backend/database/agent_db.py @@ -201,6 +201,8 @@ def create_agent(agent_info, tenant_id: str, user_id: str): "group_ids": new_agent.group_ids, "is_new": new_agent.is_new, "enable_context_manager": new_agent.enable_context_manager, + "greeting_message": new_agent.greeting_message, + "example_questions": new_agent.example_questions, "current_version_no": new_agent.current_version_no, "version_no": new_agent.version_no, "created_by": new_agent.created_by, diff --git a/backend/database/db_models.py b/backend/database/db_models.py index b779266c9..128eafb3f 100644 --- a/backend/database/db_models.py +++ b/backend/database/db_models.py @@ -324,6 +324,8 @@ class AgentInfo(TableBase): current_version_no = Column(Integer, nullable=True, doc="Current published version number. NULL means no version published yet") ingroup_permission = Column(String(30), doc="In-group permission: EDIT, READ_ONLY, PRIVATE") enable_context_manager = Column(Boolean, default=False, doc="Whether to enable context management (compression) for this agent") + greeting_message = Column(Text, doc="Agent greeting message displayed on chat initial screen") + example_questions = Column(JSONB, doc="List of example questions for starting a conversation with this agent") class PromptTemplate(TableBase): diff --git a/backend/prompts/utils/greeting_generate_en.yaml b/backend/prompts/utils/greeting_generate_en.yaml new file mode 100644 index 000000000..31ea75632 --- /dev/null +++ b/backend/prompts/utils/greeting_generate_en.yaml @@ -0,0 +1,54 @@ +GREETING_SYSTEM_PROMPT: |- + ### You are an expert in generating agent greetings and example questions. You help users create engaging greetings and practical example questions for starting conversations with agents. + You are building an Agent application. The input includes: agent name, duty description, business description, and existing examples. + Generate a concise greeting and 3-5 example questions that help users quickly start a conversation with the agent. + The greeting should reflect the agent's positioning and capabilities. + + ### Requirements: + 1. The greeting should be concise and friendly, 1-2 sentences, introducing the agent's identity and core capabilities. Don't make it too long or too formal. + 2. Example questions should be specific and practical, representing questions users might actually ask, showcasing the agent's core features. + 3. If existing examples contain user query scenarios, prioritize extracting short user questions from them, keeping semantics consistent but simplified to natural conversational form. + 4. Provide 3-5 example questions, each with a clear use case. + 5. You MUST output strictly in JSON format, do not output any other content or formatting. + + ### Output format: + ```json + { + "greeting_message": "greeting content", + "example_questions": ["example question 1", "example question 2", "example question 3"] + } + ``` + + ### Examples: + Example 1 (Travel Planning Assistant, existing examples contain "Help me plan a trip from Shanghai to Beijing" etc.): + ```json + { + "greeting_message": "Hello! I'm your travel planning assistant, I can help you plan trips, recommend attractions, and arrange travel routes.", + "example_questions": ["Help me plan a 3-day trip from Shanghai to Beijing", "Recommend some family-friendly attractions", "What's fun to do in Hangzhou tomorrow?"] + } + ``` + + Example 2 (Data Analysis Assistant): + ```json + { + "greeting_message": "Hello! I'm a data analysis assistant, I can help you process and analyze data, provide visual reports and insights.", + "example_questions": ["Help me analyze trends in this sales data", "Generate a quarterly performance comparison report", "Which products have the highest profit margins?"] + } + ``` + +USER_PROMPT: |- + ### Agent Name: + {{display_name}} + + ### Agent Duty Description: + {{duty_description}} + + ### Business Description: + {{business_description}} + + {% if few_shots %} + ### Existing Examples (extract user query scenarios from these as example questions): + {{few_shots}} + {% endif %} + + Please generate the greeting and example questions based on the above information. Output strictly in JSON format. \ No newline at end of file diff --git a/backend/prompts/utils/greeting_generate_zh.yaml b/backend/prompts/utils/greeting_generate_zh.yaml new file mode 100644 index 000000000..34b8d85d3 --- /dev/null +++ b/backend/prompts/utils/greeting_generate_zh.yaml @@ -0,0 +1,53 @@ +GREETING_SYSTEM_PROMPT: |- + ### 你是【智能体开场白和示例问题生成专家】,用于帮助用户创建高效、吸引人的智能体开场白和示例问题。 + 现在正在构建一个Agent应用,用户的输入包含:智能体名称、职责描述、业务描述、已有示例。 + 请根据智能体的定位和职责,生成一个简短的开场白和3~5个示例问题,帮助用户快速开始与智能体的对话。 + + ### 要求: + 1.开场白要简洁友好,1-2句话即可,介绍智能体的身份和核心能力,不要过长或过于正式。 + 2.示例问题要具体、实用,是用户真实可能提出的问题,体现智能体的核心功能。 + 3.如果已有示例中包含用户的提问场景,请优先从中提炼简短的用户问题作为示例问题,保持语义一致但简化为自然对话形式。 + 4.示例问题数量为3~5个,每个问题要有明确的使用场景。 + 5.必须严格按照JSON格式输出,不要输出任何其他内容或格式。 + + ### 输出格式: + ```json + { + "greeting_message": "开场白内容", + "example_questions": ["示例问题1", "示例问题2", "示例问题3"] + } + ``` + + ### 参考示例: + 示例1(旅行规划助手,已有示例包含"帮我规划明天从上海出发去北京的行程"等场景): + ```json + { + "greeting_message": "你好!我是你的旅行规划助手,可以帮你规划行程、推荐景点和安排出行路线。", + "example_questions": ["帮我规划一个从上海到北京的三日旅行", "推荐一些适合家庭出游的景点", "明天去杭州有什么好玩的地方?"] + } + ``` + + 示例2(数据分析助手): + ```json + { + "greeting_message": "你好!我是数据分析助手,可以帮你处理和分析各种数据,提供可视化报告和洞察。", + "example_questions": ["帮我分析这组销售数据的趋势", "生成一份季度业绩对比报告", "哪些产品的利润率最高?"] + } + ``` + +USER_PROMPT: |- + ### 智能体名称: + {{display_name}} + + ### 智能体职责描述: + {{duty_description}} + + ### 业务描述: + {{business_description}} + + {% if few_shots %} + ### 已有示例(请从中提炼用户提问场景作为示例问题): + {{few_shots}} + {% endif %} + + 请根据以上信息生成开场白和示例问题。严格按JSON格式输出。 \ No newline at end of file diff --git a/backend/services/agent_service.py b/backend/services/agent_service.py index 5a340b1d6..a8d550e99 100644 --- a/backend/services/agent_service.py +++ b/backend/services/agent_service.py @@ -22,7 +22,8 @@ from utils.prompt_template_utils import normalize_prompt_generate_template_content from consts.const import MEMORY_SEARCH_START_MSG, MEMORY_SEARCH_DONE_MSG, MEMORY_SEARCH_FAIL_MSG, TOOL_TYPE_MAPPING, \ LANGUAGE, MESSAGE_ROLE, MODEL_CONFIG_MAPPING, CAN_EDIT_ALL_USER_ROLES, PERMISSION_EDIT, PERMISSION_READ, PERMISSION_PRIVATE -from consts.exceptions import MemoryPreparationException, SkillDuplicateError +from consts.exceptions import AppException, MemoryPreparationException, SkillDuplicateError +from consts.error_code import ErrorCode from consts.agent_unavailable_reasons import AgentUnavailableReason from consts.model import ( AgentInfoRequest, @@ -906,6 +907,10 @@ async def get_creating_sub_agent_info_impl(authorization: str = Header(None)): async def update_agent_info_impl(request: AgentInfoRequest, authorization: str = Header(None)): user_id, tenant_id, _ = get_current_user_info(authorization) + + if request.example_questions is not None and len(request.example_questions) > 6: + raise AppException(ErrorCode.COMMON_PARAMETER_INVALID, "example_questions cannot exceed 6 items") + prompt_template_id, prompt_template_name = get_prompt_template_summary( template_id=request.prompt_template_id, tenant_id=tenant_id, @@ -935,6 +940,8 @@ async def update_agent_info_impl(request: AgentInfoRequest, authorization: str = "duty_prompt": request.duty_prompt, "constraint_prompt": request.constraint_prompt, "few_shots_prompt": request.few_shots_prompt, + "greeting_message": request.greeting_message, + "example_questions": request.example_questions, "enabled": request.enabled if request.enabled is not None else True, "group_ids": convert_list_to_string(request.group_ids) if request.group_ids else user_group_ids, "ingroup_permission": request.ingroup_permission diff --git a/backend/services/agent_version_service.py b/backend/services/agent_version_service.py index 1f1c382d8..3c731b532 100644 --- a/backend/services/agent_version_service.py +++ b/backend/services/agent_version_service.py @@ -909,6 +909,8 @@ async def list_published_agents_impl( "group_ids": agent.get("group_ids", []), "permission": permission, "published_version_no": agent.get("published_version_no"), + "greeting_message": agent.get("greeting_message"), + "example_questions": agent.get("example_questions"), }) return simple_agent_list diff --git a/backend/services/prompt_service.py b/backend/services/prompt_service.py index 3148c3f0f..09c2b4621 100644 --- a/backend/services/prompt_service.py +++ b/backend/services/prompt_service.py @@ -10,6 +10,7 @@ from consts.error_code import ErrorCode from consts.error_message import ErrorMessage from consts.exceptions import AppException +from consts.model import AgentInfoRequest from database.agent_db import search_agent_info_by_agent_id, query_all_agent_info_by_tenant_id, \ query_sub_agents_id_list from database.model_management_db import get_model_by_model_id @@ -29,6 +30,7 @@ from utils.prompt_template_utils import ( get_prompt_generate_prompt_template, get_prompt_optimize_prompt_template, + get_prompt_template, ) # Configure logging @@ -134,7 +136,7 @@ def generate_and_save_system_prompt_impl(agent_id: int, # 1. Real-time streaming push final_results = {"duty": "", "constraint": "", "few_shots": "", "agent_var_name": "", "agent_display_name": "", - "agent_description": ""} + "agent_description": "", "greeting_message": "", "example_questions": ""} # Get all existing agent names and display names for duplicate checking (only if not in create mode) all_agents = query_all_agent_info_by_tenant_id(tenant_id) @@ -273,6 +275,68 @@ def generate_and_save_system_prompt_impl(agent_id: int, if not has_content: raise Exception("Failed to generate prompt content.") + # 3. Generate greeting message and example questions + try: + greeting_template = get_prompt_template('greeting_generate', language) + greeting_system_prompt = greeting_template.get("GREETING_SYSTEM_PROMPT", "") + greeting_user_prompt_template = greeting_template.get("USER_PROMPT", "") + + greeting_user_prompt = Template(greeting_user_prompt_template, undefined=StrictUndefined).render({ + "display_name": final_results.get("agent_display_name", ""), + "duty_description": final_results.get("duty", ""), + "business_description": task_description, + "few_shots": final_results.get("few_shots", ""), + }) + + greeting_result = call_llm_for_system_prompt( + model_id=model_id, + user_prompt=greeting_user_prompt, + system_prompt=greeting_system_prompt, + tenant_id=tenant_id, + ) + + parsed = None + try: + json_start = greeting_result.find("{") + json_end = greeting_result.rfind("}") + 1 + if json_start >= 0 and json_end > json_start: + parsed = json.loads(greeting_result[json_start:json_end]) + except json.JSONDecodeError: + logger.warning(f"Failed to parse greeting JSON from LLM output: {greeting_result}") + + if parsed and "greeting_message" in parsed and "example_questions" in parsed: + greeting_message = parsed["greeting_message"] + example_questions = parsed["example_questions"] + if isinstance(example_questions, list) and len(example_questions) > 6: + example_questions = example_questions[:6] + else: + greeting_message = greeting_result.strip() if greeting_result else "" + example_questions = [] + + yield { + "type": "greeting_message", + "content": greeting_message, + "is_complete": True + } + yield { + "type": "example_questions", + "content": json.dumps(example_questions, ensure_ascii=False), + "is_complete": True + } + + final_results["greeting_message"] = greeting_message + final_results["example_questions"] = json.dumps(example_questions, ensure_ascii=False) + + # Update agent with greeting (skip in create mode) + if agent_id != 0: + update_agent(agent_id, AgentInfoRequest( + agent_id=agent_id, + greeting_message=greeting_message, + example_questions=example_questions, + ), user_id) + except Exception as e: + logger.warning(f"Greeting generation failed: {str(e)}, skipping greeting") + def optimize_prompt_section_impl( agent_id: int, model_id: int, diff --git a/backend/utils/prompt_template_utils.py b/backend/utils/prompt_template_utils.py index 8822e5fd4..299d3bf94 100644 --- a/backend/utils/prompt_template_utils.py +++ b/backend/utils/prompt_template_utils.py @@ -99,6 +99,10 @@ def get_prompt_template(template_type: str, language: str = LANGUAGE["ZH"], **kw LANGUAGE["ZH"]: 'backend/prompts/utils/generate_title_zh.yaml', LANGUAGE["EN"]: 'backend/prompts/utils/generate_title_en.yaml' }, + 'greeting_generate': { + LANGUAGE["ZH"]: 'backend/prompts/utils/greeting_generate_zh.yaml', + LANGUAGE["EN"]: 'backend/prompts/utils/greeting_generate_en.yaml' + }, 'document_summary': { LANGUAGE["ZH"]: 'backend/prompts/document_summary_agent_zh.yaml', LANGUAGE["EN"]: 'backend/prompts/document_summary_agent_en.yaml' diff --git a/docker/sql/v2.2.0_0603_add_greeting_fields_to_ag_tenant_agent_t.sql b/docker/sql/v2.2.0_0603_add_greeting_fields_to_ag_tenant_agent_t.sql new file mode 100644 index 000000000..7786bb902 --- /dev/null +++ b/docker/sql/v2.2.0_0603_add_greeting_fields_to_ag_tenant_agent_t.sql @@ -0,0 +1,15 @@ +-- Migration: Add greeting_message and example_questions columns to ag_tenant_agent_t table +-- Date: 2026-06-03 +-- Description: Add greeting message and example questions fields for agent chat initial screen + +-- Add greeting_message column to ag_tenant_agent_t table +ALTER TABLE nexent.ag_tenant_agent_t +ADD COLUMN IF NOT EXISTS greeting_message TEXT; + +-- Add example_questions column to ag_tenant_agent_t table +ALTER TABLE nexent.ag_tenant_agent_t +ADD COLUMN IF NOT EXISTS example_questions JSONB; + +-- Add comments to the columns +COMMENT ON COLUMN nexent.ag_tenant_agent_t.greeting_message IS 'Agent greeting message displayed on chat initial screen'; +COMMENT ON COLUMN nexent.ag_tenant_agent_t.example_questions IS 'List of example questions for starting a conversation with this agent'; \ No newline at end of file diff --git a/frontend/app/[locale]/agents/components/agentInfo/AgentGenerateDetail.tsx b/frontend/app/[locale]/agents/components/agentInfo/AgentGenerateDetail.tsx index 8b6cd82d7..1ef11d526 100644 --- a/frontend/app/[locale]/agents/components/agentInfo/AgentGenerateDetail.tsx +++ b/frontend/app/[locale]/agents/components/agentInfo/AgentGenerateDetail.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState, useEffect, useMemo, useRef, useCallback } from "react"; +import { useState, useEffect, useMemo, useRef } from "react"; import { useTranslation } from "react-i18next"; import { Button, @@ -17,6 +17,7 @@ import { } from "antd"; import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; import { Zap, Maximize2, Settings2, Sparkles } from "lucide-react"; +import { Textarea } from "@/components/ui/textarea"; import { AgentConfigUpdate, @@ -682,11 +683,12 @@ export default function AgentGenerateDetail({}) { }} className="agent-config-tabs flex flex-col h-full w-full" > - + {t("agent.info.title")} {t("systemPrompt.card.duty.title")} {t("systemPrompt.card.constraint.title")} {t("systemPrompt.card.fewShots.title")} + {t("agent.greeting.tabTitle")} @@ -959,6 +961,70 @@ export default function AgentGenerateDetail({}) { (value) => updateAgentConfig({ few_shots_prompt: value }) )} + + +
+
+
+

{t("agent.greeting.messageTitle")}

+
+