diff --git a/crates/zclaw-growth/src/extractor.rs b/crates/zclaw-growth/src/extractor.rs index a6050a4..191d6b1 100644 --- a/crates/zclaw-growth/src/extractor.rs +++ b/crates/zclaw-growth/src/extractor.rs @@ -19,6 +19,21 @@ pub trait LlmDriverForExtraction: Send + Sync { messages: &[Message], extraction_type: MemoryType, ) -> Result>; + + /// 单次 LLM 调用提取全部类型(记忆 + 经验 + 画像信号) + /// 默认实现:退化到 3 次独立调用 + async fn extract_combined_all( + &self, + messages: &[Message], + ) -> Result { + let mut combined = crate::types::CombinedExtraction::default(); + for mt in [MemoryType::Preference, MemoryType::Knowledge, MemoryType::Experience] { + if let Ok(mems) = self.extract_memories(messages, mt).await { + combined.memories.extend(mems); + } + } + Ok(combined) + } } /// Memory Extractor - extracts memories from conversations @@ -362,6 +377,14 @@ mod tests { assert!(!result.is_empty()); } + #[tokio::test] + async fn test_extract_combined_all_default_impl() { + let driver = MockLlmDriver; + let messages = vec![Message::user("Hello")]; + let result = driver.extract_combined_all(&messages).await.unwrap(); + assert_eq!(result.memories.len(), 3); // 3 types + } + #[test] fn test_prompts_available() { assert!(!prompts::get_extraction_prompt(MemoryType::Preference).is_empty());