diff --git a/apps/llm/generator.py b/apps/llm/generator.py index b62bcb29909206dee8d8169499763e5e7a7b3220..e3b5bee7f4fa19dcc60d3fa0c2cc0c38e2a9065d 100644 --- a/apps/llm/generator.py +++ b/apps/llm/generator.py @@ -139,6 +139,8 @@ class JsonGenerator: formatted_prompt = template.render(use_xml_format=use_xml_format) result = await self._call_without_function(function, formatted_prompt, conversation, retry_messages) + + _logger.info("[JSONGenerator] 函数调用结果: %s", result) try: validator.validate(result) except Exception as err: diff --git a/apps/llm/providers/base.py b/apps/llm/providers/base.py index 5c5757ae8622f38397e32601bc8bc4d00f7e75f1..a60ef217f2aa79275a0f9bb19e9b6974cd105cbd 100644 --- a/apps/llm/providers/base.py +++ b/apps/llm/providers/base.py @@ -50,9 +50,9 @@ class BaseProvider: async def chat( self, messages: list[dict[str, str]], + tools: list[LLMFunctions] | None = None, *, include_thinking: bool = False, streaming: bool = True, - tools: list[LLMFunctions] | None = None, ) -> AsyncGenerator[LLMChunk, None]: """聊天""" yield LLMChunk(content="") diff --git a/apps/llm/providers/ollama.py b/apps/llm/providers/ollama.py index dd3e6d50d4322eb7ff3dcd834b2fc46545b5ef2c..176419753d4c7e2dd7bb2bfddbc3741000b04aae 100644 --- a/apps/llm/providers/ollama.py +++ b/apps/llm/providers/ollama.py @@ -218,7 +218,7 @@ class OllamaProvider(BaseProvider): raise RuntimeError(err) # 构建请求参数 - embed_kwargs = {"input": text} + embed_kwargs: dict[str, Any] = {"input": text} # 如果modelName存在,则传递该参数 if self.config.modelName: diff --git a/apps/llm/providers/openai.py b/apps/llm/providers/openai.py index 682656fb4d40dea50025f7bd316ce3dd7dd425b0..8291ba48d47b6b83a6a3c2ef3c439ffe604ddad5 100644 --- a/apps/llm/providers/openai.py +++ b/apps/llm/providers/openai.py @@ -3,7 +3,7 @@ import logging from collections.abc import AsyncGenerator -from typing import cast +from typing import Any, cast import httpx from openai import AsyncOpenAI, AsyncStream @@ -298,7 +298,7 @@ class OpenAIProvider(BaseProvider): raise RuntimeError(err) # 构建请求参数 - embedding_kwargs = {"input": text} + embedding_kwargs: dict[str, Any] = {"input": text} # 如果modelName存在,则传递该参数 if self.config.modelName: diff --git a/apps/scheduler/executor/agent.py b/apps/scheduler/executor/agent.py index 499d0a6d4075e0cdebef1a60a8d01c68a0228605..649b3f7d2b91f6dd7a6aaf4246fbe71451d76e73 100644 --- a/apps/scheduler/executor/agent.py +++ b/apps/scheduler/executor/agent.py @@ -591,7 +591,7 @@ class MCPAgentExecutor(BaseExecutor): if self.task.state.executorStatus == ExecutorStatus.INIT: # 初始化状态 self.task.state.executorId = str(uuid.uuid4()) - self.task.state.executorName = (await self._planner.get_flow_name()).flow_name + self.task.state.executorName = await self._planner.get_flow_name(self.llm) await self.get_next_step() self.task.state.executorStatus = ExecutorStatus.RUNNING diff --git a/apps/scheduler/mcp/host.py b/apps/scheduler/mcp/host.py index 514edc182477c5776ffec99fa5598ad7e776dc8e..f1d73f1d0c86b024421c4e469331f25f86310c8e 100644 --- a/apps/scheduler/mcp/host.py +++ b/apps/scheduler/mcp/host.py @@ -45,11 +45,6 @@ class MCPHost(MCPNodeBase): async def get_client(self, mcp_id: str) -> MCPClient | None: """获取MCP客户端""" - if not await MCPServiceManager.is_user_actived(self._user_id, mcp_id): - logger.warning("用户 %s 未启用MCP %s", self._user_id, mcp_id) - return None - - # 获取MCP配置(如果失败会抛出RuntimeError) try: return await mcp_pool.get(mcp_id, self._user_id) except (KeyError, RuntimeError) as e: @@ -182,10 +177,6 @@ class MCPHost(MCPNodeBase): # 获取工具列表 tool_list = [] for mcp_id in mcp_id_list: - # 检查用户是否启用了这个mcp - if not await MCPServiceManager.is_user_actived(self._user_id, mcp_id): - logger.warning("用户 %s 未启用MCP %s", self._user_id, mcp_id) - continue # 获取MCP工具配置 try: tool_list.extend(await MCPServiceManager.get_mcp_tools(mcp_id)) diff --git a/apps/scheduler/mcp_agent/base.py b/apps/scheduler/mcp_agent/base.py index c09263347462b3ab94cd7dda0d9b29fe098eade6..bd6728e1913c427f91b6143f951d5632825642dd 100644 --- a/apps/scheduler/mcp_agent/base.py +++ b/apps/scheduler/mcp_agent/base.py @@ -11,6 +11,7 @@ from jinja2.sandbox import SandboxedEnvironment from apps.common.config import config from apps.models import LanguageType +from apps.models.task import StepStatus from apps.scheduler.mcp.prompt import MEMORY_TEMPLATE from apps.schemas.task import TaskData @@ -61,8 +62,9 @@ class MCPBase: history = [] template = MEMORY_TEMPLATE[task.runtime.language] - for index, item in enumerate(task.context, start=1): - # 用户消息:步骤描述和工具调用 + filtered_context = [item for item in task.context if item.stepStatus != StepStatus.WAITING] + + for index, item in enumerate(filtered_context, start=1): step_goal = item.extraData["step_goal"] user_content = _env.from_string(template).render( msg_type="user", @@ -76,7 +78,6 @@ class MCPBase: "content": user_content, }) - # 助手消息:步骤执行结果 assistant_content = _env.from_string(template).render( msg_type="assistant", step_index=index, diff --git a/apps/scheduler/mcp_agent/func.py b/apps/scheduler/mcp_agent/func.py index aad54cdc35680e236a67442652dfb45b10c3f102..b9d7b3ec796be9c8ee9cfcd9365c7575bd0c517a 100644 --- a/apps/scheduler/mcp_agent/func.py +++ b/apps/scheduler/mcp_agent/func.py @@ -5,39 +5,6 @@ from textwrap import dedent from apps.models import LanguageType -GET_FLOW_NAME_FUNCTION: dict[LanguageType, dict] = { - LanguageType.CHINESE: { - "name": "get_flow_name", - "description": "根据用户目标生成当前工作流程的描述性名称", - "parameters": { - "type": "object", - "properties": { - "flow_name": { - "type": "string", - "description": "MCP 流程名称", - "default": "", - }, - }, - "required": ["flow_name"], - }, - }, - LanguageType.ENGLISH: { - "name": "get_flow_name", - "description": "Generate a descriptive name for the current workflow based on the user's goal", - "parameters": { - "type": "object", - "properties": { - "flow_name": { - "type": "string", - "description": "MCP workflow name", - "default": "", - }, - }, - "required": ["flow_name"], - }, - }, -} - CREATE_NEXT_STEP_FUNCTION: dict[LanguageType, dict] = { LanguageType.CHINESE: { "name": "create_next_step", diff --git a/apps/scheduler/mcp_agent/host.py b/apps/scheduler/mcp_agent/host.py index 72b5b3559ae289e156442d8314cb5e9bd14abb3f..2597f6c09093669ba0e46b9943d12bed7920096b 100644 --- a/apps/scheduler/mcp_agent/host.py +++ b/apps/scheduler/mcp_agent/host.py @@ -58,11 +58,16 @@ class MCPHost(MCPBase): "parameters": mcp_tool.inputSchema, } + # 组装对话历史,包含步骤上下文 + conversation = [ + {"role": "system", "content": "You are a helpful assistant."}, + ] + memory = await self.assemble_memory(task) + conversation.extend(memory) + conversation.append({"role": "user", "content": llm_query}) + return await json_generator.generate( function=function, - conversation=[ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": llm_query}, - ], + conversation=conversation, prompt=prompt, ) diff --git a/apps/scheduler/mcp_agent/plan.py b/apps/scheduler/mcp_agent/plan.py index 8cbba10c00fb23b7902ddebbd7c71b9fea97cb3e..3fad54be9b3fd2de931288f6473a1db457f397aa 100644 --- a/apps/scheduler/mcp_agent/plan.py +++ b/apps/scheduler/mcp_agent/plan.py @@ -14,7 +14,6 @@ from apps.models import MCPTools from apps.scheduler.slot.slot import Slot from apps.schemas.llm import LLMChunk from apps.schemas.mcp import ( - FlowName, IsParamError, Step, ToolRisk, @@ -26,7 +25,6 @@ from .func import ( CREATE_NEXT_STEP_FUNCTION, EVALUATE_TOOL_RISK_FUNCTION, FINAL_ANSWER, - GET_FLOW_NAME_FUNCTION, GET_MISSING_PARAMS_FUNCTION, IS_PARAM_ERROR_FUNCTION, ) @@ -43,19 +41,23 @@ logger = logging.getLogger(__name__) class MCPPlanner(MCPBase): """MCP 用户目标拆解与规划""" - async def get_flow_name(self) -> FlowName: + async def get_flow_name(self, llm: LLM) -> str: """获取当前流程的名称""" template = _env.from_string(await self._load_prompt("gen_agent_name")) prompt = template.render(goal=self._goal) - result = await json_generator.generate( - function=GET_FLOW_NAME_FUNCTION[self._language], - conversation=[ - {"role": "system", "content": "You are a helpful assistant."}, - ], - prompt=prompt, - ) - return FlowName.model_validate(result) + messages = [ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": prompt}, + ] + + agent_name = "" + async for chunk in llm.call(messages, streaming=False): + agent_name += chunk.content or "" + + result = agent_name.strip() + logger.info("[MCPPlanner] 生成流程名称: %s", result) + return result async def create_next_step(self, tools: list[MCPTools], task: TaskData, llm: LLM) -> Step: """创建下一步的执行步骤""" @@ -76,12 +78,12 @@ class MCPPlanner(MCPBase): thinking_content += chunk.content or "" logger.info("[MCPPlanner] 思考分析: %s", thinking_content) - step_template = _env.from_string(await self._load_prompt("gen_step")) - step_prompt = step_template.render(goal=self._goal, tools=tools) - function = deepcopy(CREATE_NEXT_STEP_FUNCTION[self._language]) function["parameters"]["properties"]["tool_name"]["enum"] = [tool.toolName for tool in tools] + step_template = _env.from_string(await self._load_prompt("gen_step")) + step_prompt = step_template.render(goal=self._goal, tools=tools, function_schema=function) + step = await json_generator.generate( function=function, conversation=[ diff --git a/apps/schemas/mcp.py b/apps/schemas/mcp.py index 78d995a525c1ce1b8fcc55b7fdbf565d3b37d525..db5dfea5d802ed732ac6d5f8044c6f872379cbda 100644 --- a/apps/schemas/mcp.py +++ b/apps/schemas/mcp.py @@ -79,12 +79,6 @@ class Risk(str, Enum): MEDIUM = "medium" HIGH = "high" - -class FlowName(BaseModel): - """MCP 流程名称""" - - flow_name: str = Field(description="MCP 流程名称", default="") - class ToolRisk(BaseModel): """MCP工具风险评估结果""" diff --git a/apps/services/task.py b/apps/services/task.py index 552f50af14eab968bd6207e1779f525b7cf72b50..2b9fa8c51728b3229b6ec20cd9a4ad877de66d23 100644 --- a/apps/services/task.py +++ b/apps/services/task.py @@ -16,7 +16,7 @@ from apps.models import ( ) from apps.schemas.task import TaskData -logger = logging.getLogger(__name__) +_logger = logging.getLogger(__name__) class TaskManager: @@ -48,9 +48,9 @@ class TaskManager: conversationId=conversation_id, userId=user_id, ) - logger.info("[TaskManager] 创建新任务对象 (未保存)") + _logger.info("[TaskManager] 创建新任务对象 (未保存)") return new_task - logger.info("[TaskManager] 找到已存在的任务 %s", task.id) + _logger.info("[TaskManager] 找到已存在的任务 %s", task.id) return task @@ -62,7 +62,7 @@ class TaskManager: select(Task).where(Task.id == task_id), )).one_or_none() if not task_data: - logger.error("[TaskManager] 任务不存在 %s", task_id) + _logger.error("[TaskManager] 任务不存在 %s", task_id) return None runtime = (await session.scalars( @@ -174,21 +174,48 @@ class TaskManager: @staticmethod async def save_flow_context(context: list[ExecutorHistory]) -> None: - """保存Flow上下文信息到PostgreSQL""" + """保存Flow上下文信息到PostgreSQL,确保数据库与内存状态一致""" + if not context: + return + async with postgres.session() as session: + task_id = context[0].taskId + memory_ids = {ctx.id for ctx in context} + + existing_histories = list((await session.scalars( + select(ExecutorHistory).where(ExecutorHistory.taskId == task_id), + )).all()) + + existing_map = {history.id: history for history in existing_histories} + + deleted_count = 0 + for existing_id, existing_history in existing_map.items(): + if existing_id not in memory_ids: + await session.delete(existing_history) + deleted_count += 1 + _logger.debug( + "[TaskManager] 删除已从内存移除的History记录 - task_id: %s, history_id: %s, status: %s", + task_id, existing_id, existing_history.stepStatus.value, + ) + + updated_count = 0 + inserted_count = 0 for ctx in context: - # 查询是否存在该ExecutorHistory - existing_history = (await session.scalars( - select(ExecutorHistory).where(ExecutorHistory.id == ctx.id), - )).one_or_none() + existing_history = existing_map.get(ctx.id) if existing_history: - # 更新现有History for key, value in ctx.__dict__.items(): if not key.startswith("_"): setattr(existing_history, key, value) + updated_count += 1 else: - # 插入新History session.add(ctx) + inserted_count += 1 await session.commit() + + if deleted_count > 0 or inserted_count > 0 or updated_count > 0: + _logger.info( + "[TaskManager] 保存Flow上下文 - task_id: %s, 插入: %d, 更新: %d, 删除: %d", + task_id, inserted_count, updated_count, deleted_count, + ) diff --git a/data/prompts/system/mcp/agent_thinking.en.md b/data/prompts/system/mcp/agent_thinking.en.md index f89d0cbecee6b2d131c92c7d41b622310e4e9755..437aaec9d3edad5d4eacc85ffca28b240b495d72 100644 --- a/data/prompts/system/mcp/agent_thinking.en.md +++ b/data/prompts/system/mcp/agent_thinking.en.md @@ -1,15 +1,21 @@ -Now let's review the step history context. My goal is: {{goal}} +Please review the step history context. The current goal is: {{goal}} -Available tools: +You can use the following tools: {% for tool in tools %} - {{tool.toolName}}: {{tool.description}} {% endfor %} -Please think step by step: +Please provide a concise analysis and your thinking process, including the following points: -- How far along is my goal now -- What should be done next to achieve the goal -- Which tool should be used and why +- What is the progress towards completing the current goal +- What action should be taken next to achieve the goal +- Which tool should be used and the rationale for choosing that tool -Think and analyze first, then provide a specific plan for the next step. \ No newline at end of file +**Important Notes**: + +- Please provide your analysis and thinking directly, without repeating or restating the results returned by tools +- The tool outputs are already visible, you only need to reason and make decisions based on this information +- Keep responses concise and focused on the next action plan + +Now, please begin thinking step by step: \ No newline at end of file diff --git a/data/prompts/system/mcp/agent_thinking.zh.md b/data/prompts/system/mcp/agent_thinking.zh.md index 2ba00aa856342537128a7d8dedb46104ea593c7d..88085e3b2bbbfa088e15fc027e02d2ca83c1555c 100644 --- a/data/prompts/system/mcp/agent_thinking.zh.md +++ b/data/prompts/system/mcp/agent_thinking.zh.md @@ -1,15 +1,21 @@ -现在回顾一下步骤历史上下文,我的目标是:{{goal}} +请回顾历史步骤上下文,当前目标是:{{goal}} -可用的工具有: +你可以使用以下工具: {% for tool in tools %} - {{tool.toolName}}: {{tool.description}} {% endfor %} -请你一步一步分析思考: +请简明扼要地分析并给出你的思考过程,包含以下要点: -- 我的目标现在完成到什么程度了 -- 接下来应该做什么才能达成目标 -- 应该用哪个工具,为什么 +- 当前目标的完成进度如何 +- 下一步需要采取什么行动来达成目标 +- 应该使用哪个工具以及选择该工具的理由 -先思考分析,然后再给出下一步的具体方案。 +**重要说明**: + +- 请直接给出你的分析和思考,不要复述或重复工具返回的结果 +- 工具的输出内容已经可见,你只需要基于这些信息进行推理和决策 +- 保持回复简洁,专注于下一步行动方案 + +现在,请开始一步一步地思考: diff --git a/data/prompts/system/mcp/gen_agent_name.en.md b/data/prompts/system/mcp/gen_agent_name.en.md index 542ac20e31a89d45b06794e87d9f45a79f5d3033..60fc90d56439ad3e16f943ee7569e6d0c59a5cb1 100644 --- a/data/prompts/system/mcp/gen_agent_name.en.md +++ b/data/prompts/system/mcp/gen_agent_name.en.md @@ -4,51 +4,24 @@ You are a professional Agent name generation assistant, capable of generating accurate, concise, and descriptive Agent names based on user goals. -## Generation Requirements - -1. **Accuracy**: Accurately express the core process of achieving the user's goal -2. **Conciseness**: Keep the length under 20 characters, be brief and to the point -3. **Descriptiveness**: Include key operational steps (e.g., "Scan", "Analyze", "Optimize", etc.) -4. **Clarity**: Use easy-to-understand language, avoiding overly technical terms - -## Tools - -You can call the following tools to complete the Agent name generation task. - -{% raw %}{% if use_xml_format %}{% endraw %} -When calling tools, use XML-style tags for formatting. The format specification is as follows: - -```xml - -Agent Name - -``` +## Task -{% raw %}{% endif %}{% endraw %} +Generate a short Agent name within 20 characters based on the user's goal. -### generate_agent_name - -Description: Generate a descriptive Agent name based on the user's goal - -Parameters: - -- name: Agent name - -Usage example: +## Generation Requirements -- User goal: I need to scan the current mysql database, analyze performance bottlenecks, and tune it -- Name should be: Scan MySQL database, analyze performance bottlenecks, and tune +1. Accurately express the core process of the user's goal +2. Keep length under 20 characters +3. Output the name directly without additional formatting or explanation -{% raw %}{% if use_xml_format %}{% endraw %} +## Example -```xml - -Scan MySQL database, analyze performance bottlenecks, and tune - -``` +**User Goal**: I need to scan the current mysql database, analyze performance bottlenecks, and tune it -{% raw %}{% endif %}{% endraw %} +**Output**: Scan MySQL database, analyze performance bottlenecks, and tune --- **User Goal**: {{goal}} + +**Output**: diff --git a/data/prompts/system/mcp/gen_agent_name.zh.md b/data/prompts/system/mcp/gen_agent_name.zh.md index 671dd37a5c7054e97adaee72a3d025929e13281d..56229e0c84714aed3b9dc0d7c5ec9942c036b1b3 100644 --- a/data/prompts/system/mcp/gen_agent_name.zh.md +++ b/data/prompts/system/mcp/gen_agent_name.zh.md @@ -4,51 +4,24 @@ 你是一个专业的Agent名称生成助手,能够根据用户目标生成准确、简洁且具有描述性的Agent名称。 -## 生成要求 - -1. **准确性**:准确表达达成用户目标的核心过程 -2. **简洁性**:长度控制在20字以内,言简意赅 -3. **描述性**:包含关键操作步骤(如"扫描"、"分析"、"调优"等) -4. **易懂性**:使用通俗易懂的语言,避免过于专业的术语 - -## 工具 - -你可以调用以下工具来完成Agent名称生成任务。 - -{% raw %}{% if use_xml_format %}{% endraw %} -调用工具时,采用XML风格标签进行格式化。格式规范如下: - -```xml - -Agent名称 - -``` +## 任务 -{% raw %}{% endif %}{% endraw %} +根据用户目标,生成一个20字以内的简短Agent名称。 -### generate_agent_name - -描述:根据用户目标生成描述性的Agent名称 - -参数: - -- name:Agent名称 - -用法示例: +## 生成要求 -- 用户目标:我需要扫描当前mysql数据库,分析性能瓶颈,并调优 -- 名称应为:扫描MySQL数据库并分析性能瓶颈,进行调优 +1. 准确表达用户目标的核心过程 +2. 长度控制在20字以内 +3. 直接输出名称文本,无需额外格式或说明 -{% raw %}{% if use_xml_format %}{% endraw %} +## 示例 -```xml - -扫描MySQL数据库并分析性能瓶颈,进行调优 - -``` +**用户目标**:我需要扫描当前MySQL数据库,分析性能瓶颈,并调优 -{% raw %}{% endif %}{% endraw %} +**输出**:MySQL性能分析与调优 --- **用户目标**:{{goal}} + +**输出**: diff --git a/data/prompts/system/mcp/gen_step.en.md b/data/prompts/system/mcp/gen_step.en.md index ec2b1eb19b93292b86b36fefe07bd96a385a4474..605f9e4ff894723a9279e06011d3727ba33eae4d 100644 --- a/data/prompts/system/mcp/gen_step.en.md +++ b/data/prompts/system/mcp/gen_step.en.md @@ -1,75 +1,78 @@ # Step Planning Task -## Role +## Task Description -You are a professional workflow planning assistant who can intelligently plan the next execution step based on user goals and thinking analysis. +You need to immediately call the `create_next_step` function to plan the next execution step based on the previous thinking analysis and user goal. -## Task Objective +**Important**: You must call the function, not just describe or explain, but actually execute the function call. -Based on the previous thinking analysis and user goal, call the `create_next_step` function to plan the next execution step. +## Function Definition -## Planning Requirements +### Function Name -1. **Accuracy**: Plan based on the conclusions from the thinking analysis -2. **Relevance**: Select the most appropriate tool for the current stage -3. **Clarity**: Step description should be concise and clear, explaining specific operations -4. **Completeness**: Ensure each step is independent and complete, directly executable +`{{function_schema['name']}}` -## Functions +### Function Description -You can call the following functions to complete the step planning task. +{{function_schema['description']}} -{% raw %}{% if use_xml_format %}{% endraw %} -When calling tools, use XML-style tags for formatting. The format specification is as follows: +### JSON Schema -```xml - -Function Name -Step Description - +```json +{{function_schema | tojson(indent=2)}} ``` -{% raw %}{% endif %}{% endraw %} - -### create_next_step +### Parameter Details -Description: Create the next execution step +#### 1. tool_name (required) -Parameters: - -- tool_name: External tool name, must be selected from the following list +- **Type**: string +- **Constraint**: Must be one of the following enum values {% for tool in tools %} - - `{{tool.toolName}}`: {{tool.description}} + - `"{{tool.toolName}}"` - {{tool.description}} {% endfor %} -- description: Step description, clearly explain what this step will do + - `"Final"` - Use when the user goal is completed +- **Description**: Select the most appropriate tool name from the available tools list for the current step -Calling Specifications: +#### 2. description (required) -- **Fixed function name**: Must use `create_next_step`, do not use external tool names as function names -- **tool_name value**: Must be one of the tool names from the external tools list -- **description value**: Describe the specific operations of this step -- **When task completes**: If the user goal is achieved, set `tool_name` parameter to `Final` +- **Type**: string +- **Description**: Clearly describe the specific operation to be performed in this step +- **Requirements**: + - Explain why this tool is chosen + - Describe what task needs to be completed + - Be concise and clear, typically 1-2 sentences -Usage Example: +## Calling Requirements -- Scenario: User goal is "Analyze MySQL database performance", thinking analysis shows database connection established, need to perform performance analysis -- Next step should be: Call performance analysis tool to retrieve database performance metrics +✓ **Must call the function**: Don't just describe, actually call the `create_next_step` function +✓ **Fixed function name**: The function name must be `create_next_step`, not the tool name +✓ **tool_name exact match**: The tool_name value must exactly match one of the enum values +✓ **Complete parameters**: Both tool_name and description parameters must be provided +✓ **Based on thinking conclusion**: Select the most appropriate tool based on the previous thinking analysis {% raw %}{% if use_xml_format %}{% endraw %} +## XML Format Call Example + +When using XML format, please call in the following format: + ```xml mysql_analyzer -Retrieve slow query logs and performance metrics from the database +Retrieve slow query logs and performance metrics from the database to analyze performance bottlenecks ``` -{% raw %}{% endif %}{% endraw %} +**Note**: + +- The tool_name value must strictly match a tool name from the available tools list +- If the task is completed, set tool_name to `Final` ---- +{% raw %}{% endif %}{% endraw %} -## Current Task +## Execution Instruction **User Goal**: {{goal}} -Now based on the thinking and analysis above, call the `create_next_step` function to plan the next step. +Based on the thinking and analysis above, immediately call the `create_next_step` function now, select the most appropriate tool and plan the next operation. diff --git a/data/prompts/system/mcp/gen_step.zh.md b/data/prompts/system/mcp/gen_step.zh.md index ba235d914a7c6ab125931e03f8638b90fb66571b..498414cf6455734a4a48ad26538701e81c416bbe 100644 --- a/data/prompts/system/mcp/gen_step.zh.md +++ b/data/prompts/system/mcp/gen_step.zh.md @@ -1,75 +1,78 @@ # 步骤规划任务 -## 角色 +## 任务说明 -你是一个专业的工作流程规划助手,能够根据用户目标和思考分析,智能规划下一个执行步骤。 +你需要根据前面的思考分析和用户目标,立即调用 `create_next_step` 函数来规划下一个执行步骤。 -## 任务目标 +**重要**: 你必须调用函数,不要只是描述或说明,而是实际执行函数调用。 -基于前面的思考分析和用户目标,调用 `create_next_step` 函数来规划下一个执行步骤。 +## 函数定义 -## 规划要求 +### 函数名称 -1. **准确性**:基于思考分析中的结论进行规划 -2. **针对性**:选择最适合当前阶段的工具 -3. **清晰性**:步骤描述简洁明确,说明具体操作内容 -4. **完整性**:确保每个步骤独立完整,可直接执行 +`{{function_schema['name']}}` -## 函数 +### 函数描述 -你可以调用以下函数来完成步骤规划任务。 +{{function_schema['description']}} -{% raw %}{% if use_xml_format %}{% endraw %} -调用工具时,采用XML风格标签进行格式化。格式规范如下: +### JSON Schema -```xml - -函数名称 -步骤描述 - +```json +{{function_schema | tojson(indent=2)}} ``` -{% raw %}{% endif %}{% endraw %} - -### create_next_step +### 参数详细说明 -描述:创建下一个执行步骤 +#### 1. tool_name (必填) -参数: - -- tool_name: 外置工具名称,必须从以下列表中选择 +- **类型**: string +- **约束**: 必须是以下枚举值之一 {% for tool in tools %} - - `{{tool.toolName}}`: {{tool.description}} + - `"{{tool.toolName}}"` - {{tool.description}} {% endfor %} -- description: 步骤描述,清晰说明本步骤要做什么 + - `"Final"` - 当用户目标已完成时使用 +- **说明**: 从可用工具列表中选择最适合当前步骤的工具名称 -调用规范: +#### 2. description (必填) -- **函数名固定**: 必须使用 `create_next_step`,不要使用外置工具名作为函数名 -- **tool_name的值**: 必须是外置工具列表中的某个工具名称 -- **description的值**: 描述本步骤的具体操作内容 -- **任务完成时**: 如果用户目标已经完成,将 `tool_name` 参数设为 `Final` +- **类型**: string +- **说明**: 清晰描述本步骤要执行的具体操作内容 +- **要求**: + - 说明选择该工具的原因 + - 描述具体要完成什么任务 + - 简洁明确,通常1-2句话 -用法示例: +## 调用要求 -- 场景:用户目标是"分析MySQL数据库性能",思考分析显示已连接到数据库,需要进行性能分析 -- 下一步应为:调用性能分析工具,获取数据库的性能指标 +✓ **必须调用函数**: 不要只描述,要实际调用 `create_next_step` 函数 +✓ **函数名固定**: 函数名必须是 `create_next_step`,不是工具名 +✓ **tool_name 精确匹配**: tool_name 的值必须完全匹配枚举列表中的某个值 +✓ **参数完整**: tool_name 和 description 两个参数都必须提供 +✓ **基于思考结论**: 根据前面的思考分析选择最合适的工具 {% raw %}{% if use_xml_format %}{% endraw %} +## XML 格式调用示例 + +当使用 XML 格式时,请按以下格式调用: + ```xml mysql_analyzer -获取数据库的慢查询日志和性能指标 +获取数据库的慢查询日志和性能指标,以分析性能瓶颈 ``` -{% raw %}{% endif %}{% endraw %} +**注意**: + +- tool_name 的值必须严格匹配可用工具列表中的工具名称 +- 如果任务已完成,tool_name 设置为 `Final` ---- +{% raw %}{% endif %}{% endraw %} -## 当前任务 +## 执行指令 **用户目标**: {{goal}} -现在基于上面的思考分析结果,调用 `create_next_step` 函数规划下一步。 +基于上面的思考分析,现在立即调用 `create_next_step` 函数,选择最合适的工具并规划下一步操作。 diff --git a/data/sysagent.service b/data/sysagent.service index ca5a8e5999d7334c2c5789ca3fb27e0ba87f04ec..630c3816e0f4b4c1dcbb8061c66191a5a1e70aa7 100644 --- a/data/sysagent.service +++ b/data/sysagent.service @@ -5,6 +5,7 @@ User=root WorkingDirectory=/usr/lib/sysagent Environment="PYTHONPATH=/usr/lib/sysagent" Environment="CONFIG=/etc/sysagent/config.toml" +Environment="TIKTOKEN_CACHE_DIR=/var/lib/sysagent/tiktoken_cache" ExecStart=/usr/bin/python3 -m apps.main ExecReload=/bin/kill -HUP $MAINPID Restart=on-failure