From 369ab17caa5046a13b88cbbfc7a11433b1b15e2e Mon Sep 17 00:00:00 2001 From: 2h0u4n <2740125866@qq.com> Date: Sat, 2 May 2026 22:43:16 +0800 Subject: [PATCH 1/4] feat: add section-level prompt optimization for generated agent details --- docker/.env.bak | 168 ------------------------------------------------ 1 file changed, 168 deletions(-) delete mode 100644 docker/.env.bak diff --git a/docker/.env.bak b/docker/.env.bak deleted file mode 100644 index 24b53751b..000000000 --- a/docker/.env.bak +++ /dev/null @@ -1,168 +0,0 @@ -# ===== Necessary Configs (Necessary till now, will be migrated to frontend page) ===== - -# Voice Service Config -APPID=app_id -TOKEN=token - -# ===== Non-essential Configs (Modify if you know what you are doing) ===== - -CLUSTER=volcano_tts -VOICE_TYPE=zh_male_jieshuonansheng_mars_bigtts -SPEED_RATIO=1.3 - -# ===== Proxy Configuration (Optional) ===== - -# HTTP_PROXY=http://proxy-server:port -# HTTPS_PROXY=http://proxy-server:port -# NO_PROXY=localhost,127.0.0.1 - -# ===== Backend Configuration (No need to modify at all) ===== - -# Model Path Config -CLIP_MODEL_PATH=/opt/models/clip-vit-base-patch32 -NLTK_DATA=/opt/models/nltk_data - -# Elasticsearch Service -ELASTICSEARCH_HOST=http://nexent-elasticsearch:9200 -ELASTIC_PASSWORD=nexent@2025 - -# Elasticsearch Memory Configuration -ES_JAVA_OPTS="-Xms2g -Xmx2g" - -# Elasticsearch Disk Watermark Configuration -ES_DISK_WATERMARK_LOW=85% -ES_DISK_WATERMARK_HIGH=90% -ES_DISK_WATERMARK_FLOOD_STAGE=95% - -# Main Services -# Config service (port 5010) - Main API service for config operations -CONFIG_SERVICE_URL=http://nexent-config:5010 -ELASTICSEARCH_SERVICE=http://nexent-config:5010/api - -# Runtime service (port 5014) - Runtime execution service for agent operations -RUNTIME_SERVICE_URL=http://nexent-runtime:5014 - -# MCP service (port 5011) - MCP protocol service -NEXENT_MCP_SERVER=http://nexent-mcp:5011 -MCP_MANAGEMENT_API=http://nexent-mcp:5015 - -# Data process service (port 5012) - Data processing service -DATA_PROCESS_SERVICE=http://nexent-data-process:5012/api - -# Northbound service (port 5013) - Northbound API service -NORTHBOUND_API_SERVER=http://nexent-northbound:5013/api - -# Postgres Config -POSTGRES_HOST=nexent-postgresql -POSTGRES_USER=root -NEXENT_POSTGRES_PASSWORD=nexent@4321 -POSTGRES_DB=nexent -POSTGRES_PORT=5432 - -# Minio Config -MINIO_ENDPOINT=http://nexent-minio:9000 -MINIO_ROOT_USER=nexent -MINIO_ROOT_PASSWORD=nexent@4321 -MINIO_REGION=cn-north-1 -MINIO_DEFAULT_BUCKET=nexent - -# Redis Config -REDIS_URL=redis://redis:6379/0 -REDIS_BACKEND_URL=redis://redis:6379/1 - -# Model Engine Config -MODEL_ENGINE_ENABLED=false - -# Supabase Config -DASHBOARD_USERNAME=supabase -DASHBOARD_PASSWORD=Huawei123 - -# Supabase db Config -SUPABASE_POSTGRES_PASSWORD=Huawei123 -SUPABASE_POSTGRES_HOST=db -SUPABASE_POSTGRES_DB=supabase -SUPABASE_POSTGRES_PORT=5436 - -# Supabase Auth Config -SITE_URL=http://localhost:3011 -SUPABASE_URL=http://supabase-kong-mini:8000 -API_EXTERNAL_URL=http://supabase-kong-mini:8000 -DISABLE_SIGNUP=false -JWT_EXPIRY=3600 -DEBUG_JWT_EXPIRE_SECONDS=0 - -# Supabase Configuration -ENABLE_EMAIL_SIGNUP=true -ENABLE_EMAIL_AUTOCONFIRM=true -ENABLE_ANONYMOUS_USERS=false - -# Supabase Phone Config -ENABLE_PHONE_SIGNUP=false -ENABLE_PHONE_AUTOCONFIRM=false - -MAILER_URLPATHS_CONFIRMATION="/auth/v1/verify" -MAILER_URLPATHS_INVITE="/auth/v1/verify" -MAILER_URLPATHS_RECOVERY="/auth/v1/verify" -MAILER_URLPATHS_EMAIL_CHANGE="/auth/v1/verify" - -INVITE_CODE=nexent2025 - -# Terminal Tool SSH Key Path -SSH_PRIVATE_KEY_PATH=/path/to/openssh-server/ssh-keys/openssh_server_key - -# ===== Data Processing Service Configuration ===== - -# Redis Port -REDIS_PORT=6379 - -# Flower Monitoring -FLOWER_PORT=5555 - -# Ray Configuration -RAY_ACTOR_NUM_CPUS=2 -RAY_DASHBOARD_PORT=8265 -RAY_DASHBOARD_HOST=0.0.0.0 -RAY_NUM_CPUS=4 -RAY_OBJECT_STORE_MEMORY_GB=0.25 -RAY_TEMP_DIR=/tmp/ray -RAY_LOG_LEVEL=INFO - -# Service Control Flags -DISABLE_RAY_DASHBOARD=true -DISABLE_CELERY_FLOWER=true -DOCKER_ENVIRONMENT=false -ENABLE_UPLOAD_IMAGE=false - -# Celery Configuration -CELERY_WORKER_PREFETCH_MULTIPLIER=1 -CELERY_TASK_TIME_LIMIT=3600 -ELASTICSEARCH_REQUEST_TIMEOUT=30 - -# Worker Configuration -QUEUES=process_q,forward_q -WORKER_NAME= -WORKER_CONCURRENCY=4 - -# Skills Configuration -SKILLS_PATH=/mnt/nexent/skills - -# Telemetry and Monitoring Configuration -ENABLE_TELEMETRY=false -SERVICE_NAME=nexent-backend -JAEGER_ENDPOINT=http://localhost:14268/api/traces -PROMETHEUS_PORT=8000 -TELEMETRY_SAMPLE_RATE=1.0 -LLM_SLOW_REQUEST_THRESHOLD_SECONDS=5.0 -LLM_SLOW_TOKEN_RATE_THRESHOLD=10.0 - -# Market Backend Address -MARKET_BACKEND=http://60.204.251.153:8010 -DEPLOYMENT_VERSION="speed" -# Root dir -ROOT_DIR="/c/Users/18270/nexent-data" -TERMINAL_MOUNT_DIR="/opt/terminal" -SSH_USERNAME="root" -SSH_PASSWORD="731215" -NEXENT_MCP_DOCKER_IMAGE="ccr.ccs.tencentyun.com/nexent-hub/nexent-mcp:v2.0.1" -MINIO_ACCESS_KEY="72c31cb5b521511cea652723" -MINIO_SECRET_KEY="m5gcSuKzZnp84CqmG7z5VKnd2C+H5U3PSr7eoJeygmI=" From 2f51302a12dfd8697379d9f3e2d68c75ba2af12d Mon Sep 17 00:00:00 2001 From: 2h0u4n <2740125866@qq.com> Date: Sat, 2 May 2026 22:45:32 +0800 Subject: [PATCH 2/4] feat: add section-level prompt optimization for generated agent details --- backend/apps/prompt_app.py | 45 ++- backend/consts/model.py | 16 + backend/prompts/utils/prompt_optimize_en.yaml | 51 ++++ backend/prompts/utils/prompt_optimize_zh.yaml | 51 ++++ backend/services/prompt_service.py | 214 ++++++++++++- backend/utils/prompt_template_utils.py | 18 ++ ...2.0.2_0410_add_columns_outer_api_tools.sql | 1 + .../agentInfo/AgentGenerateDetail.tsx | 287 ++++++++++++++---- .../agentInfo/PromptOptimizeModal.tsx | 159 ++++++++++ frontend/public/locales/en/common.json | 10 + frontend/public/locales/zh/common.json | 11 + frontend/services/api.ts | 1 + frontend/services/promptService.ts | 20 +- frontend/types/agentConfig.ts | 20 ++ test/backend/app/test_prompt_app.py | 67 ++++ test/backend/services/test_prompt_service.py | 98 +++++- .../utils/test_prompt_template_utils.py | 16 + 17 files changed, 1023 insertions(+), 62 deletions(-) create mode 100644 backend/prompts/utils/prompt_optimize_en.yaml create mode 100644 backend/prompts/utils/prompt_optimize_zh.yaml create mode 100644 frontend/app/[locale]/agents/components/agentInfo/PromptOptimizeModal.tsx create mode 100644 test/backend/app/test_prompt_app.py diff --git a/backend/apps/prompt_app.py b/backend/apps/prompt_app.py index a9bd8d3a6..4b14e3bfa 100644 --- a/backend/apps/prompt_app.py +++ b/backend/apps/prompt_app.py @@ -3,9 +3,13 @@ from typing import Optional from fastapi import APIRouter, Header, HTTPException, Request from fastapi.responses import StreamingResponse +from starlette.responses import JSONResponse -from consts.model import GeneratePromptRequest -from services.prompt_service import gen_system_prompt_streamable +from consts.model import GeneratePromptRequest, OptimizePromptSectionRequest +from services.prompt_service import ( + gen_system_prompt_streamable, + optimize_prompt_section_impl, +) from utils.auth_utils import get_current_user_info router = APIRouter(prefix="/prompt") @@ -36,3 +40,40 @@ async def generate_and_save_system_prompt_api( logger.exception(f"Error occurred while generating system prompt: {e}") raise HTTPException( status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail="Error occurred while generating system prompt.") + + +@router.post("/optimize") +async def optimize_prompt_section_api( + optimize_request: OptimizePromptSectionRequest, + http_request: Request, + authorization: Optional[str] = Header(None) +): + try: + _, tenant_id, language = get_current_user_info( + authorization, http_request) + optimized_section = optimize_prompt_section_impl( + agent_id=optimize_request.agent_id, + model_id=optimize_request.model_id, + task_description=optimize_request.task_description, + tenant_id=tenant_id, + language=language, + section_type=optimize_request.section_type, + section_title=optimize_request.section_title, + current_content=optimize_request.current_content, + feedback=optimize_request.feedback, + tool_ids=optimize_request.tool_ids, + sub_agent_ids=optimize_request.sub_agent_ids, + knowledge_base_display_names=optimize_request.knowledge_base_display_names, + ) + return JSONResponse( + status_code=HTTPStatus.OK, + content={ + "message": "Prompt section optimized successfully", + "data": optimized_section, + } + ) + except HTTPException: + raise + except Exception as exc: + logger.exception(f"Error occurred while optimizing prompt section: {exc}") + raise diff --git a/backend/consts/model.py b/backend/consts/model.py index 7cea3fdb5..867512e1e 100644 --- a/backend/consts/model.py +++ b/backend/consts/model.py @@ -308,6 +308,22 @@ class GeneratePromptRequest(BaseModel): None, description="Optional: knowledge base display names from frontend (takes precedence over database query)") +class OptimizePromptSectionRequest(BaseModel): + task_description: str + agent_id: int + model_id: int + section_type: str + section_title: str + current_content: str + feedback: str + tool_ids: Optional[List[int]] = Field( + None, description="Optional: tool IDs from frontend (takes precedence over database query)") + sub_agent_ids: Optional[List[int]] = Field( + None, description="Optional: sub-agent IDs from frontend (takes precedence over database query)") + knowledge_base_display_names: Optional[List[str]] = Field( + None, description="Optional: knowledge base display names from frontend (takes precedence over database query)") + + class GenerateTitleRequest(BaseModel): conversation_id: int question: str diff --git a/backend/prompts/utils/prompt_optimize_en.yaml b/backend/prompts/utils/prompt_optimize_en.yaml new file mode 100644 index 000000000..a487107b7 --- /dev/null +++ b/backend/prompts/utils/prompt_optimize_en.yaml @@ -0,0 +1,51 @@ +OPTIMIZE_SYSTEM_PROMPT: |- + ### You Are a Prompt Optimization Expert + You optimize one specific section of an agent prompt based on the user's feedback while preserving the section's original intent and format conventions. + + ### Your Goal + Improve only the target section content according to the evaluation feedback. + + ### Requirements + 1. Output only the optimized section content. + 2. Preserve the target section's language unless the user feedback explicitly requests otherwise. + 3. Keep the optimized content aligned with the business task, available tools, and available assistants. + 4. Do not add explanations, summaries, markdown fences, titles, or comparison text. + 5. For `duty`, keep the content concise and role-oriented. + 6. For `constraint`, keep the content as explicit usage requirements. + 7. For `few_shots`, keep the content as concrete examples consistent with the current prompt style. + +OPTIMIZE_USER_PROMPT: |- + ### Section Type + {{ section_type }} + + ### Section Title + {{ section_title }} + + ### Business Task Description + {{ task_description }} + + ### Current Section Content + {{ current_content }} + + ### User Evaluation Feedback + {{ feedback }} + + ### Available Tools + {% if tool_description %} + {{ tool_description }} + {% else %} + No available tools. + {% endif %} + + ### Available Assistants + {% if assistant_description %} + {{ assistant_description }} + {% else %} + No available assistants. + {% endif %} + + {% if knowledge_base_names %} + ### Knowledge Base Configuration Note + When optimizing few-shot examples that use `knowledge_base_search`, you must use these actual configured knowledge base names: + {{ knowledge_base_names | default('') }} + {% endif %} diff --git a/backend/prompts/utils/prompt_optimize_zh.yaml b/backend/prompts/utils/prompt_optimize_zh.yaml new file mode 100644 index 000000000..a769ea5eb --- /dev/null +++ b/backend/prompts/utils/prompt_optimize_zh.yaml @@ -0,0 +1,51 @@ +OPTIMIZE_SYSTEM_PROMPT: |- + ### 你是一名提示词优化专家 + 你需要根据用户给出的评价,对智能体提示词中的某一个指定部分进行优化,同时保持该部分原本的目标和格式风格。 + + ### 你的任务 + 只优化目标部分的内容,并让结果更贴合用户评价。 + + ### 要求 + 1. 只输出优化后的该部分内容。 + 2. 保持原内容的语言风格,除非用户明确要求切换语言。 + 3. 优化结果要与业务任务、可用工具和可用助手保持一致。 + 4. 不要输出解释、总结、标题、对比说明或 Markdown 代码块。 + 5. 当 `section_type` 为 `duty` 时,内容应保持简洁,突出智能体角色与职责。 + 6. 当 `section_type` 为 `constraint` 时,内容应保持为清晰明确的使用要求。 + 7. 当 `section_type` 为 `few_shots` 时,内容应保持为具体示例,并与当前提示词风格一致。 + +OPTIMIZE_USER_PROMPT: |- + ### 部分类型 + {{ section_type }} + + ### 部分标题 + {{ section_title }} + + ### 业务任务描述 + {{ task_description }} + + ### 当前内容 + {{ current_content }} + + ### 用户评价反馈 + {{ feedback }} + + ### 可用工具 + {% if tool_description %} + {{ tool_description }} + {% else %} + 当前没有可用工具。 + {% endif %} + + ### 可用助手 + {% if assistant_description %} + {{ assistant_description }} + {% else %} + 当前没有可用助手。 + {% endif %} + + {% if knowledge_base_names %} + ### 知识库配置说明 + 如果优化后的 few-shot 示例中需要使用 `knowledge_base_search`,必须使用以下已配置的真实知识库名称: + {{ knowledge_base_names | default('') }} + {% endif %} diff --git a/backend/services/prompt_service.py b/backend/services/prompt_service.py index aa4d420d5..199521146 100644 --- a/backend/services/prompt_service.py +++ b/backend/services/prompt_service.py @@ -24,11 +24,27 @@ _generate_unique_display_name_with_suffix ) from utils.llm_utils import call_llm_for_system_prompt -from utils.prompt_template_utils import get_prompt_generate_prompt_template +from utils.prompt_template_utils import ( + get_prompt_generate_prompt_template, + get_prompt_optimize_prompt_template, +) # Configure logging logger = logging.getLogger("prompt_service") +PROMPT_SECTION_TYPE_TITLES = { + LANGUAGE["ZH"]: { + "duty": "智能体角色", + "constraint": "使用要求", + "few_shots": "示例", + }, + LANGUAGE["EN"]: { + "duty": "Agent Role", + "constraint": "Usage Requirements", + "few_shots": "Few Shots", + }, +} + def gen_system_prompt_streamable(agent_id: int, model_id: int, task_description: str, user_id: str, tenant_id: str, language: str, tool_ids: Optional[List[int]] = None, sub_agent_ids: Optional[List[int]] = None, knowledge_base_display_names: Optional[List[str]] = None): try: @@ -238,6 +254,88 @@ def generate_and_save_system_prompt_impl(agent_id: int, raise Exception("Failed to generate prompt content.") +def optimize_prompt_section_impl( + agent_id: int, + model_id: int, + task_description: str, + tenant_id: str, + language: str, + section_type: str, + section_title: str, + current_content: str, + feedback: str, + tool_ids: Optional[List[int]] = None, + sub_agent_ids: Optional[List[int]] = None, + knowledge_base_display_names: Optional[List[str]] = None, +) -> dict: + normalized_section_type = (section_type or "").strip() + if normalized_section_type not in {"duty", "constraint", "few_shots"}: + raise AppException( + ErrorCode.COMMON_PARAMETER_INVALID, + "Unsupported prompt section type." + ) + + if not (current_content or "").strip(): + raise AppException( + ErrorCode.COMMON_MISSING_REQUIRED_FIELD, + "Current section content is required." + ) + + if not (feedback or "").strip(): + raise AppException( + ErrorCode.COMMON_MISSING_REQUIRED_FIELD, + "Optimization feedback is required." + ) + + tool_info_list = _resolve_prompt_generation_tools( + agent_id=agent_id, + tenant_id=tenant_id, + tool_ids=tool_ids, + ) + knowledge_base_display_names = _resolve_knowledge_base_display_names( + agent_id=agent_id, + tenant_id=tenant_id, + tool_info_list=tool_info_list, + knowledge_base_display_names=knowledge_base_display_names, + ) + sub_agent_info_list = _resolve_prompt_generation_sub_agents( + agent_id=agent_id, + tenant_id=tenant_id, + sub_agent_ids=sub_agent_ids, + ) + + prompt_template = get_prompt_optimize_prompt_template(language) + prompt_context = join_info_for_optimize_prompt_section( + prompt_for_optimize=prompt_template, + section_type=normalized_section_type, + section_title=section_title or _default_prompt_section_title(normalized_section_type, language), + task_description=task_description, + current_content=current_content, + feedback=feedback, + tool_info_list=tool_info_list, + sub_agent_info_list=sub_agent_info_list, + language=language, + knowledge_base_display_names=knowledge_base_display_names, + ) + + optimized_content = call_llm_for_system_prompt( + model_id=model_id, + user_prompt=prompt_context, + system_prompt=prompt_template["OPTIMIZE_SYSTEM_PROMPT"], + tenant_id=tenant_id, + ).strip() + + if not optimized_content: + raise AppException(ErrorCode.MODEL_PROMPT_GENERATION_FAILED) + + return { + "section_type": normalized_section_type, + "section_title": section_title or _default_prompt_section_title(normalized_section_type, language), + "original_content": current_content, + "optimized_content": optimized_content, + } + + def generate_system_prompt(sub_agent_info_list, task_description, tool_info_list, tenant_id: str, model_id: int, language: str = LANGUAGE["ZH"], knowledge_base_display_names: Optional[List[str]] = None): """Main function for generating system prompts""" prompt_for_generate = get_prompt_generate_prompt_template(language) @@ -267,6 +365,67 @@ def generate_system_prompt(sub_agent_info_list, task_description, tool_info_list yield from _stream_results(produce_queue, latest, stop_flags, threads, error_holder) +def _resolve_prompt_generation_tools( + agent_id: int, + tenant_id: str, + tool_ids: Optional[List[int]] = None, +) -> List[dict]: + if tool_ids and len(tool_ids) > 0: + logger.debug(f"Using frontend-provided tool IDs: {tool_ids}") + return query_tools_by_ids(tool_ids) + + logger.debug("No tools selected (empty tool_ids list)") + return get_enabled_tool_description_for_generate_prompt( + tenant_id=tenant_id, agent_id=agent_id + ) + + +def _resolve_knowledge_base_display_names( + agent_id: int, + tenant_id: str, + tool_info_list: List[dict], + knowledge_base_display_names: Optional[List[str]] = None, +) -> Optional[List[str]]: + if knowledge_base_display_names: + logger.debug( + f"Using frontend-provided knowledge base display names: {knowledge_base_display_names}" + ) + return knowledge_base_display_names + + resolved_names = get_knowledge_base_display_names( + tool_info_list=tool_info_list, + agent_id=agent_id, + tenant_id=tenant_id + ) + logger.debug(f"Using database query for knowledge base display names: {resolved_names}") + return resolved_names + + +def _resolve_prompt_generation_sub_agents( + agent_id: int, + tenant_id: str, + sub_agent_ids: Optional[List[int]] = None, +) -> List[dict]: + if sub_agent_ids and len(sub_agent_ids) > 0: + sub_agent_info_list = [] + for sub_agent_id in sub_agent_ids: + try: + sub_agent_info = search_agent_info_by_agent_id( + agent_id=sub_agent_id, tenant_id=tenant_id) + sub_agent_info_list.append(sub_agent_info) + except Exception as exc: + logger.warning( + f"Failed to get sub-agent info for agent_id {sub_agent_id}: {str(exc)}" + ) + logger.debug(f"Using frontend-provided sub-agent IDs: {sub_agent_ids}") + return sub_agent_info_list + + logger.debug("No sub-agents selected (empty sub_agent_ids list)") + return get_enabled_sub_agent_description_for_generate_prompt( + tenant_id=tenant_id, agent_id=agent_id + ) + + def _start_generation_threads(content, prompt_for_generate, produce_queue, latest, stop_flags, tenant_id, model_id): """Start all prompt generation threads""" # Shared error tracking across threads @@ -402,6 +561,59 @@ def join_info_for_generate_system_prompt(prompt_for_generate, sub_agent_info_lis return content +def join_info_for_optimize_prompt_section( + prompt_for_optimize, + section_type: str, + section_title: str, + task_description: str, + current_content: str, + feedback: str, + tool_info_list, + sub_agent_info_list, + language: str = LANGUAGE["ZH"], + knowledge_base_display_names: Optional[List[str]] = None, +): + input_label = "Inputs" if language == LANGUAGE["EN"] else "接受输入" + output_label = "Output type" if language == LANGUAGE["EN"] else "返回输出类型" + + tool_description = "\n".join( + [f"- {tool['name']}: {tool['description']} \n {input_label}: {tool['inputs']}\n {output_label}: {tool['output_type']}" + for tool in tool_info_list] + ) + assistant_description = "\n".join( + [f"- {sub_agent_info['name']}: {sub_agent_info['description']}" for sub_agent_info in sub_agent_info_list] + ) + + if knowledge_base_display_names: + kb_names_str = ", ".join(f'"{name}"' for name in knowledge_base_display_names) + else: + kb_names_str = "" + + template_context = { + "section_type": section_type, + "section_title": section_title, + "task_description": task_description, + "current_content": current_content, + "feedback": feedback, + "tool_description": tool_description, + "assistant_description": assistant_description, + "knowledge_base_names": kb_names_str, + } + + return Template( + prompt_for_optimize["OPTIMIZE_USER_PROMPT"], + undefined=StrictUndefined + ).render(template_context) + + +def _default_prompt_section_title(section_type: str, language: str) -> str: + localized_titles = PROMPT_SECTION_TYPE_TITLES.get( + language, + PROMPT_SECTION_TYPE_TITLES[LANGUAGE["ZH"]] + ) + return localized_titles.get(section_type, section_type) + + def get_enabled_tool_description_for_generate_prompt(agent_id: int, tenant_id: str): # Get tool information logger.info("Fetching tool instances") diff --git a/backend/utils/prompt_template_utils.py b/backend/utils/prompt_template_utils.py index cf83bfa60..3cd267a10 100644 --- a/backend/utils/prompt_template_utils.py +++ b/backend/utils/prompt_template_utils.py @@ -16,6 +16,7 @@ def get_prompt_template(template_type: str, language: str = LANGUAGE["ZH"], **kw Args: template_type: Template type, supports the following values: - 'prompt_generate': Prompt generation template + - 'prompt_optimize': Prompt section optimization template - 'agent': Agent template including manager and managed agents - 'generate_title': Title generation template - 'document_summary': Document summary template (Map stage) @@ -33,6 +34,10 @@ def get_prompt_template(template_type: str, language: str = LANGUAGE["ZH"], **kw LANGUAGE["ZH"]: 'backend/prompts/utils/prompt_generate_zh.yaml', LANGUAGE["EN"]: 'backend/prompts/utils/prompt_generate_en.yaml' }, + 'prompt_optimize': { + LANGUAGE["ZH"]: 'backend/prompts/utils/prompt_optimize_zh.yaml', + LANGUAGE["EN"]: 'backend/prompts/utils/prompt_optimize_en.yaml' + }, 'agent': { LANGUAGE["ZH"]: { 'manager': 'backend/prompts/manager_system_prompt_template_zh.yaml', @@ -101,6 +106,19 @@ def get_prompt_generate_prompt_template(language: str = LANGUAGE["ZH"]) -> Dict[ return get_prompt_template('prompt_generate', language) +def get_prompt_optimize_prompt_template(language: str = LANGUAGE["ZH"]) -> Dict[str, Any]: + """ + Get prompt optimization template. + + Args: + language: Language code ('zh' or 'en') + + Returns: + dict: Loaded prompt optimization template configuration + """ + return get_prompt_template('prompt_optimize', language) + + def get_agent_prompt_template(is_manager: bool, language: str = LANGUAGE["ZH"]) -> Dict[str, Any]: """ Get agent prompt template diff --git a/docker/sql/v2.0.2_0410_add_columns_outer_api_tools.sql b/docker/sql/v2.0.2_0410_add_columns_outer_api_tools.sql index fe527cf16..35fccf9cb 100644 --- a/docker/sql/v2.0.2_0410_add_columns_outer_api_tools.sql +++ b/docker/sql/v2.0.2_0410_add_columns_outer_api_tools.sql @@ -1,3 +1,4 @@ +-- Active: 1776876067388@@127.0.0.1@5434@nexent@nexent -- v2.0.2_0410_add_columns_outer_api_tools.sql -- Add MCP service-level columns to ag_outer_api_tools table -- These columns enable grouping tools from the same OpenAPI spec under a single MCP service diff --git a/frontend/app/[locale]/agents/components/agentInfo/AgentGenerateDetail.tsx b/frontend/app/[locale]/agents/components/agentInfo/AgentGenerateDetail.tsx index 1dd8422fa..2693625c0 100644 --- a/frontend/app/[locale]/agents/components/agentInfo/AgentGenerateDetail.tsx +++ b/frontend/app/[locale]/agents/components/agentInfo/AgentGenerateDetail.tsx @@ -17,7 +17,7 @@ import { App, } from "antd"; import type { TabsProps } from "antd"; -import { Zap, Maximize2 } from "lucide-react"; +import { Sparkles, Zap, Maximize2 } from "lucide-react"; import log from "@/lib/logger"; import { AgentProfileInfo, AgentBusinessInfo } from "@/types/agentConfig"; @@ -43,6 +43,7 @@ import { USER_ROLES } from "@/const/auth"; import { Can } from "@/components/permission/Can"; import { useAgentConfigStore } from "@/stores/agentConfigStore"; import ExpandEditModal from "./ExpandEditModal"; +import PromptOptimizeModal from "./PromptOptimizeModal"; const { TextArea } = Input; @@ -115,6 +116,8 @@ export default function AgentGenerateDetail({ // Modal states const [expandModalOpen, setExpandModalOpen] = useState(false); const [expandModalType, setExpandModalType] = useState<'duty' | 'constraint' | 'few-shots' | null>(null); + const [optimizeModalOpen, setOptimizeModalOpen] = useState(false); + const [optimizeModalType, setOptimizeModalType] = useState<'duty' | 'constraint' | 'few-shots' | null>(null); // Use ref to track generation initiator - this doesn't trigger re-renders // but is accessible in closures @@ -183,7 +186,7 @@ export default function AgentGenerateDetail({ content: { backgroundColor: "#fff", borderWidth: 1, - padding: "8px ", + padding: "4px 8px 8px", borderRadius: "0 0 8px 8px", height: "100%", }, @@ -428,19 +431,56 @@ export default function AgentGenerateDetail({ setExpandModalOpen(true); }; + const handleOpenOptimizeModal = (type: 'duty' | 'constraint' | 'few-shots') => { + if (!editable || isGenerating || !businessInfo.businessLogicModelId) { + return; + } + setOptimizeModalType(type); + setOptimizeModalOpen(true); + }; + const renderExpandButton = (type: "duty" | "constraint" | "few-shots") => { return wrapNoEditTooltipInline( + + + } + destroyOnHidden + > +
+
+ {t("systemPrompt.optimize.feedbackLabel")} +