feat(growth,kernel,runtime): Embedding 接通 + 自学习自动化 — A线+B线 6 项实现
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

A线 Embedding 接通:
- A1: MemoryRetriever.set_embedding_client() + GrowthIntegration.configure_embedding()
  + Kernel.set_embedding_client() + viking_configure_embedding 传播到 Kernel
- A2: Skill 路由替换 new_tf_idf_only() 为 EmbeddingAdapter + LlmSkillFallback

B线 自学习自动化:
- B1: evolution_bridge.rs — candidate_to_manifest() (PromptOnly, disabled by default)
- B2: Kernel::generate_and_register_skill() 全链路 (LLM→parse→QualityGate→manifest→persist)
- B3: EvolutionMiddleware 双模式 (auto_mode 跳过注入, 留给 kernel 自动处理)
- B4: QualityGate 加固 (body ≥100字符 + 必须含标题 + 置信度上限 1.0)

验证: 934 tests PASS, 0 failures
This commit is contained in:
iven
2026-04-21 15:21:03 +08:00
parent 74ce6d4adc
commit 5b5491a08f
13 changed files with 330 additions and 8 deletions

View File

@@ -76,4 +76,77 @@ impl Kernel {
}
self.skills.execute(&zclaw_types::SkillId::new(id), &ctx, input).await
}
/// Generate a skill from an aggregated pattern and register it.
///
/// Full pipeline:
/// 1. Build LLM prompt from pattern
/// 2. Call LLM to get JSON response
/// 3. Parse response into SkillCandidate
/// 4. Validate through QualityGate (threshold 0.85 for auto-mode)
/// 5. Convert to SkillManifest (PromptOnly, disabled by default)
/// 6. Persist to disk via SkillRegistry
pub async fn generate_and_register_skill(
&self,
pattern: &zclaw_growth::pattern_aggregator::AggregatedPattern,
) -> Result<String> {
// 1. Build prompt
let prompt = zclaw_growth::skill_generator::SkillGenerator::build_prompt(pattern);
// 2. Call LLM
let request = zclaw_runtime::driver::CompletionRequest {
model: self.driver.provider().to_string(),
system: Some("你是技能设计专家,只返回 JSON 格式的技能定义。".to_string()),
messages: vec![zclaw_types::Message::user(prompt)],
max_tokens: Some(1024),
temperature: Some(0.3),
stream: false,
..Default::default()
};
let response = self.driver.complete(request).await?;
let text = response.content.iter()
.filter_map(|block| match block {
zclaw_runtime::driver::ContentBlock::Text { text } => Some(text.as_str()),
_ => None,
})
.collect::<Vec<_>>()
.join("");
// 3. Parse into SkillCandidate
let candidate = zclaw_growth::skill_generator::SkillGenerator::parse_response(
&text, pattern,
)?;
// 4. Validate through QualityGate (higher threshold for auto-generation)
let existing_triggers: Vec<String> = self.skills.list().await
.into_iter()
.flat_map(|m| m.triggers)
.collect();
let gate = zclaw_growth::quality_gate::QualityGate::new(0.85, existing_triggers);
let report = gate.validate_skill(&candidate);
if !report.passed {
return Err(zclaw_types::ZclawError::ConfigError(format!(
"QualityGate rejected: {}", report.issues.join("; ")
)));
}
// 5. Convert to SkillManifest (PromptOnly, disabled)
let manifest = super::evolution_bridge::candidate_to_manifest(&candidate);
let skill_id = manifest.id.to_string();
// 6. Persist to disk
let skills_dir = self.config.skills_dir.as_ref()
.ok_or_else(|| zclaw_types::ZclawError::InvalidInput(
"Skills directory not configured".into()
))?;
self.skills.create_skill(skills_dir, manifest).await?;
tracing::info!(
"[Kernel] Auto-generated skill '{}' (id={}) registered (disabled)",
candidate.name, skill_id
);
Ok(skill_id)
}
}