cascade_agent/knowledge/
mod.rs1pub mod embeddings;
4pub mod vectordb;
5
6use std::sync::Arc;
7
8use async_trait::async_trait;
9use serde_json::{Map, Value};
10
11use crate::config::KnowledgeSettings;
12use crate::error::Result;
13use crate::tools::knowledge_tool::{KnowledgeHit, KnowledgeProvider};
14
15use embeddings::Embedder;
16use vectordb::{KnowledgeEntry, SearchResult, VectorStore};
17
18#[derive(Debug)]
24pub struct KnowledgeBase {
25 store: VectorStore,
26 config: KnowledgeSettings,
27}
28
29impl KnowledgeBase {
30 pub async fn new(config: &KnowledgeSettings) -> Result<Self> {
34 let model_name = config.embedding_model.clone();
36 let embedder = tokio::task::spawn_blocking(move || Embedder::new(&model_name))
37 .await
38 .map_err(|e| {
39 crate::error::AgentError::KnowledgeError(format!("Embedder init panicked: {}", e))
40 })??;
41
42 let embedder = Arc::new(embedder);
43 let store = VectorStore::new(&config.db_path, embedder, &config.default_collection).await?;
44
45 store.create_collection(&config.default_collection).await?;
47
48 Ok(Self {
49 store,
50 config: config.clone(),
51 })
52 }
53
54 pub async fn query_existing(&self, query: &str) -> Result<Vec<SearchResult>> {
56 let limit = self.config.max_results;
57 self.store
58 .search(&self.config.default_collection, query, limit)
59 .await
60 }
61
62 pub async fn store_results(
64 &self,
65 collection: &str,
66 entries: Vec<KnowledgeEntry>,
67 ) -> Result<()> {
68 self.store.insert(collection, entries).await
69 }
70
71 pub async fn create_collection(&self, name: &str) -> Result<()> {
73 self.store.create_collection(name).await
74 }
75
76 pub async fn list_collections(&self) -> Result<Vec<String>> {
78 self.store.list_collections().await
79 }
80}
81
82#[async_trait]
87impl KnowledgeProvider for KnowledgeBase {
88 async fn query(
89 &self,
90 query: &str,
91 collection: &str,
92 limit: usize,
93 ) -> std::result::Result<Vec<KnowledgeHit>, String> {
94 let results = self
95 .store
96 .search(collection, query, limit)
97 .await
98 .map_err(|e| format!("Knowledge query failed: {}", e))?;
99
100 let hits: Vec<KnowledgeHit> = results
101 .into_iter()
102 .filter(|r| {
103 r.score >= self.config.similarity_threshold
105 })
106 .map(|r| KnowledgeHit {
107 text: r.text,
108 score: r.score,
109 metadata: if r.metadata.is_null() {
110 None
111 } else if let Value::Object(map) = r.metadata {
112 Some(map)
113 } else {
114 let mut map = Map::new();
115 map.insert("value".into(), r.metadata);
116 Some(map)
117 },
118 })
119 .collect();
120
121 Ok(hits)
122 }
123}