This is an automated email from the ASF dual-hosted git repository.

gaoxingcun pushed a commit to branch feature/ai-sop-workflow
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git

commit 963b594283aa00e8184e505d7e96b3ab5cbce803
Author: TJxiaobao <[email protected]>
AuthorDate: Sun Feb 1 19:34:42 2026 +0800

    feat: Optimize Skills Keywords.
---
 .../impl/ChatClientProviderServiceImpl.java        | 68 +++++++++++++++++++++-
 .../src/main/resources/prompt/system-message.st    | 35 ++++++-----
 2 files changed, 84 insertions(+), 19 deletions(-)

diff --git 
a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/impl/ChatClientProviderServiceImpl.java
 
b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/impl/ChatClientProviderServiceImpl.java
index f624d70943..67211c1c02 100644
--- 
a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/impl/ChatClientProviderServiceImpl.java
+++ 
b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/impl/ChatClientProviderServiceImpl.java
@@ -19,14 +19,17 @@
 package org.apache.hertzbeat.ai.service.impl;
 
 import lombok.extern.slf4j.Slf4j;
+import org.apache.hertzbeat.ai.sop.model.SopDefinition;
+import org.apache.hertzbeat.ai.sop.model.SopParameter;
+import org.apache.hertzbeat.ai.sop.registry.SkillRegistry;
 import org.apache.hertzbeat.common.entity.ai.ChatMessage;
 import org.apache.hertzbeat.common.entity.dto.ModelProviderConfig;
 import org.apache.hertzbeat.ai.service.ChatClientProviderService;
 import org.apache.hertzbeat.base.dao.GeneralConfigDao;
 import org.apache.hertzbeat.common.entity.manager.GeneralConfig;
 import org.apache.hertzbeat.common.util.JsonUtil;
-import org.springframework.ai.chat.prompt.SystemPromptTemplate;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.core.io.Resource;
 import org.springframework.stereotype.Service;
 import org.apache.hertzbeat.ai.pojo.dto.ChatRequestContext;
@@ -40,6 +43,8 @@ import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.context.ApplicationContext;
 import reactor.core.publisher.Flux;
 
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -52,9 +57,13 @@ import java.util.List;
 @Service
 public class ChatClientProviderServiceImpl implements 
ChatClientProviderService {
 
+    private static final String SKILLS_PLACEHOLDER = 
"{dynamically_injected_skills_list}";
+
     private final ApplicationContext applicationContext;
 
     private final GeneralConfigDao generalConfigDao;
+
+    private final SkillRegistry skillRegistry;
     
     @Autowired
     @Qualifier("hertzbeatTools")
@@ -66,9 +75,12 @@ public class ChatClientProviderServiceImpl implements 
ChatClientProviderService
     private Resource systemResource;
 
     @Autowired
-    public ChatClientProviderServiceImpl(ApplicationContext 
applicationContext, GeneralConfigDao generalConfigDao) {
+    public ChatClientProviderServiceImpl(ApplicationContext 
applicationContext, 
+                                         GeneralConfigDao generalConfigDao,
+                                         @Lazy SkillRegistry skillRegistry) {
         this.applicationContext = applicationContext;
         this.generalConfigDao = generalConfigDao;
+        this.skillRegistry = skillRegistry;
     }
 
     @Override
@@ -94,9 +106,12 @@ public class ChatClientProviderServiceImpl implements 
ChatClientProviderService
 
             log.info("Starting streaming chat for conversation: {}", 
context.getConversationId());
 
+            // Build system prompt with dynamic skills list
+            String systemPrompt = buildSystemPrompt();
+
             return chatClient.prompt()
                     .messages(messages)
-                    
.system(SystemPromptTemplate.builder().resource(systemResource).build().getTemplate())
+                    .system(systemPrompt)
                     .toolCallbacks(toolCallbackProvider)
                     .stream()
                     .content()
@@ -109,6 +124,53 @@ public class ChatClientProviderServiceImpl implements 
ChatClientProviderService
         }
     }
 
+    /**
+     * Build the system prompt with dynamically injected skills list.
+     */
+    private String buildSystemPrompt() {
+        try {
+            String template = 
systemResource.getContentAsString(StandardCharsets.UTF_8);
+            String skillsList = generateSkillsList();
+            return template.replace(SKILLS_PLACEHOLDER, skillsList);
+        } catch (IOException e) {
+            log.error("Failed to read system prompt template: {}", 
e.getMessage());
+            return "";
+        }
+    }
+
+    /**
+     * Generate a formatted list of available skills for the system prompt.
+     */
+    private String generateSkillsList() {
+        List<SopDefinition> skills = skillRegistry.getAllSkills();
+        
+        if (skills.isEmpty()) {
+            return "No skills currently available. Use listSkills tool to 
refresh.";
+        }
+        
+        StringBuilder sb = new StringBuilder();
+        for (SopDefinition skill : skills) {
+            sb.append("- **").append(skill.getName()).append("**: ");
+            sb.append(skill.getDescription());
+            
+            // Add parameter hints
+            if (skill.getParameters() != null && 
!skill.getParameters().isEmpty()) {
+                sb.append(" (requires: ");
+                List<String> paramNames = new ArrayList<>();
+                for (SopParameter param : skill.getParameters()) {
+                    if (param.isRequired()) {
+                        paramNames.add(param.getName());
+                    }
+                }
+                sb.append(String.join(", ", paramNames));
+                sb.append(")");
+            }
+            sb.append("\n");
+        }
+        
+        return sb.toString();
+    }
+
     @Override
     public boolean isConfigured() {
         if (!isConfigured) {
diff --git a/hertzbeat-ai/src/main/resources/prompt/system-message.st 
b/hertzbeat-ai/src/main/resources/prompt/system-message.st
index 772340c374..3660af46ed 100644
--- a/hertzbeat-ai/src/main/resources/prompt/system-message.st
+++ b/hertzbeat-ai/src/main/resources/prompt/system-message.st
@@ -33,22 +33,25 @@ If the user doesn't provide required parameters, ask them 
iteratively to provide
 - **get_historical_metrics**: Get historical time-series metrics with flexible 
time ranges
 - **get_warehouse_status**: Check metrics storage system status
 
-### Diagnostic Skills (SOP):
-Skills are dynamically loaded workflows. ALWAYS call listSkills first to 
discover available skills.
-
-- **listSkills**: List all available diagnostic skills with descriptions and 
parameters.
-  IMPORTANT: Always call this first before executing any skill to get the 
current list.
-- **executeSkill**: Execute a skill by name. Parameters are passed as JSON.
-  - For skills requiring monitorId, first use query_monitors to find the 
target monitor's ID
-  - If multiple monitors match, ask the user which one to diagnose
-  - Report-type skills return results directly to the user (no need to 
summarize)
-
-Example workflow for diagnostics:
-1. User: "Help me check the system health" or "Diagnose MySQL slow queries"
-2. Call listSkills() to see available skills
-3. Match user intent to a skill (e.g., "daily_inspection" or 
"mysql_slow_query_diagnosis")
-4. If skill needs monitorId, call query_monitors to find it
-5. Call executeSkill(skillName, paramsJson)
+### AI Skills (SOP Workflows):
+You have access to automated skills that can perform complex multi-step 
operations.
+
+**Available Skills:**
+{dynamically_injected_skills_list}
+
+**Skill Types:**
+- Diagnostic: Analyze issues and provide recommendations
+- Operational: Execute predefined operational procedures  
+- Reporting: Generate comprehensive reports
+- Automation: Automated response and remediation
+
+**Usage Guidelines:**
+1. Match user intent to available skills
+2. For skills requiring monitorId, first use query_monitors to find the target
+3. Execute using: executeSkill(skillName, paramsJson)
+4. Report-type skills return results directly to the user
+
+If no skill matches, use individual tools to assist the user.
 
 
 ## Natural Language Examples:


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to