refactor(skills): progressive skill loading — avoid duplicate injection
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
When SkillIndexMiddleware is active, build_system_prompt_with_skills no longer injects the full categorized skill list. Instead it only adds usage instructions, while the middleware handles the lightweight index. This reduces ~2000 tokens per request for the 75-skill system.
This commit is contained in:
@@ -229,35 +229,54 @@ impl Kernel {
|
|||||||
.map(|p| p.clone())
|
.map(|p| p.clone())
|
||||||
.unwrap_or_else(|| "You are a helpful AI assistant.".to_string());
|
.unwrap_or_else(|| "You are a helpful AI assistant.".to_string());
|
||||||
|
|
||||||
// Inject skill metadata only (progressive loading pattern from DeerFlow).
|
// Progressive skill loading (DeerFlow pattern):
|
||||||
// Full skill content is loaded on-demand via `load_skill_content` tool.
|
// If the SkillIndexMiddleware is registered in the middleware chain,
|
||||||
|
// it will inject a lightweight index at priority 200.
|
||||||
|
// We still inject a basic instruction block here for when middleware is not active.
|
||||||
|
//
|
||||||
|
// When middleware IS active, avoid duplicate injection by only keeping
|
||||||
|
// the skill-use instructions (not the full list).
|
||||||
|
let skill_index_active = {
|
||||||
|
use zclaw_runtime::tool::SkillExecutor;
|
||||||
|
!self.skill_executor.list_skill_index().is_empty()
|
||||||
|
};
|
||||||
|
|
||||||
if !skills.is_empty() {
|
if !skills.is_empty() {
|
||||||
prompt.push_str("\n\n## Available Skills\n\n");
|
if skill_index_active {
|
||||||
prompt.push_str("You have access to specialized skills. Analyze user intent and autonomously call `execute_skill` with the appropriate skill_id.\n\n");
|
// Middleware will inject the index — only add usage instructions
|
||||||
|
prompt.push_str("\n\n## Skills\n\n");
|
||||||
|
prompt.push_str("You have access to specialized skills listed in the skill index above. ");
|
||||||
|
prompt.push_str("Analyze user intent and autonomously call `skill_load` to inspect a skill, ");
|
||||||
|
prompt.push_str("then `execute_skill` with the appropriate skill_id.\n\n");
|
||||||
|
prompt.push_str("- **IMPORTANT**: Autonomously decide when to use skills based on user intent.\n");
|
||||||
|
prompt.push_str("- Do not wait for explicit skill names — recognize the need and act.\n");
|
||||||
|
prompt.push_str("- If unsure about a skill, call `skill_load` first to understand its parameters.\n");
|
||||||
|
} else {
|
||||||
|
// No middleware — inject full skill list as fallback
|
||||||
|
prompt.push_str("\n\n## Available Skills\n\n");
|
||||||
|
prompt.push_str("You have access to specialized skills. Analyze user intent and autonomously call `execute_skill` with the appropriate skill_id.\n\n");
|
||||||
|
|
||||||
// Group skills by category based on their ID patterns
|
let categories = self.categorize_skills(&skills);
|
||||||
let categories = self.categorize_skills(&skills);
|
for (category, category_skills) in categories {
|
||||||
|
prompt.push_str(&format!("### {}\n", category));
|
||||||
for (category, category_skills) in categories {
|
for skill in category_skills {
|
||||||
prompt.push_str(&format!("### {}\n", category));
|
prompt.push_str(&format!(
|
||||||
for skill in category_skills {
|
"- **{}**: {}",
|
||||||
prompt.push_str(&format!(
|
skill.id.as_str(),
|
||||||
"- **{}**: {}",
|
skill.description
|
||||||
skill.id.as_str(),
|
));
|
||||||
skill.description
|
prompt.push('\n');
|
||||||
));
|
}
|
||||||
prompt.push('\n');
|
prompt.push('\n');
|
||||||
}
|
}
|
||||||
prompt.push('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
prompt.push_str("### When to use skills:\n");
|
prompt.push_str("### When to use skills:\n");
|
||||||
prompt.push_str("- **IMPORTANT**: You should autonomously decide when to use skills based on your understanding of the user's intent.\n");
|
prompt.push_str("- **IMPORTANT**: You should autonomously decide when to use skills based on your understanding of the user's intent.\n");
|
||||||
prompt.push_str("- Do not wait for explicit skill names - recognize the need and act.\n");
|
prompt.push_str("- Do not wait for explicit skill names - recognize the need and act.\n");
|
||||||
prompt.push_str("- Match user's request to the most appropriate skill's domain.\n");
|
prompt.push_str("- Match user's request to the most appropriate skill's domain.\n\n");
|
||||||
prompt.push_str("- If multiple skills could apply, choose the most specialized one.\n\n");
|
prompt.push_str("### Example:\n");
|
||||||
prompt.push_str("### Example:\n");
|
prompt.push_str("User: \"分析腾讯财报\" → Intent: Financial analysis → Call: execute_skill(\"finance-tracker\", {...})\n");
|
||||||
prompt.push_str("User: \"分析腾讯财报\" → Intent: Financial analysis → Call: execute_skill(\"finance-tracker\", {...})\n");
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sub-agent delegation instructions (Ultra mode only)
|
// Sub-agent delegation instructions (Ultra mode only)
|
||||||
|
|||||||
Reference in New Issue
Block a user