graphrag_core/core/retrieval_adapters.rs
1//! Retrieval system adapters for core traits
2//!
3//! This module provides adapter implementations that bridge existing retrieval systems
4//! with the core GraphRAG AsyncRetriever trait.
5
6use crate::core::error::{GraphRAGError, Result};
7use crate::core::traits::AsyncRetriever;
8use crate::retrieval::{RetrievalSystem, SearchResult as RetrievalSearchResult};
9use async_trait::async_trait;
10
11/// Result type for retrieval operations
12#[derive(Debug, Clone)]
13pub struct RetrievalResult {
14 /// Unique identifier for this result
15 pub id: String,
16 /// Content of the result
17 pub content: String,
18 /// Relevance score
19 pub score: f32,
20 /// Associated entity names
21 pub entities: Vec<String>,
22}
23
24impl From<RetrievalSearchResult> for RetrievalResult {
25 fn from(result: RetrievalSearchResult) -> Self {
26 Self {
27 id: result.id,
28 content: result.content,
29 score: result.score,
30 entities: result.entities,
31 }
32 }
33}
34
35/// Adapter for RetrievalSystem to implement AsyncRetriever trait
36///
37/// ## Graph Integration
38///
39/// This adapter wraps the RetrievalSystem which operates on a KnowledgeGraph.
40/// For full functionality, the RetrievalSystem needs to be initialized with
41/// a populated graph. The current implementation provides the trait interface
42/// but actual retrieval requires application-level graph management.
43///
44/// ## Usage Pattern
45///
46/// ```no_run
47/// use graphrag_core::core::retrieval_adapters::RetrievalSystemAdapter;
48/// use graphrag_core::retrieval::RetrievalSystem;
49/// use graphrag_core::config::Config;
50///
51/// # async fn example() -> graphrag_core::Result<()> {
52/// let config = Config::default();
53/// let system = RetrievalSystem::new(&config)?;
54/// let adapter = RetrievalSystemAdapter::new(system);
55///
56/// // Search requires a populated knowledge graph in the retrieval system
57/// // This would typically be managed at the application level
58/// # Ok(())
59/// # }
60/// ```
61pub struct RetrievalSystemAdapter {
62 system: RetrievalSystem,
63}
64
65impl RetrievalSystemAdapter {
66 /// Create a new retrieval system adapter
67 ///
68 /// Note: The RetrievalSystem should be populated with a KnowledgeGraph
69 /// before search operations will return meaningful results.
70 pub fn new(system: RetrievalSystem) -> Self {
71 Self { system }
72 }
73
74 /// Get reference to underlying retrieval system
75 pub fn system(&self) -> &RetrievalSystem {
76 &self.system
77 }
78
79 /// Get mutable reference to underlying retrieval system
80 ///
81 /// This allows configuring the retrieval system after creation,
82 /// such as setting the knowledge graph or updating configurations.
83 pub fn system_mut(&mut self) -> &mut RetrievalSystem {
84 &mut self.system
85 }
86}
87
88#[async_trait]
89impl AsyncRetriever for RetrievalSystemAdapter {
90 type Query = String;
91 type Result = RetrievalResult;
92 type Error = GraphRAGError;
93
94 async fn search(&self, _query: Self::Query, _k: usize) -> Result<Vec<Self::Result>> {
95 // Note: Actual search implementation requires the RetrievalSystem to have
96 // access to a populated KnowledgeGraph. This is typically managed at the
97 // application level where the graph is built and passed to the retrieval system.
98 //
99 // The RetrievalSystem internally supports multiple retrieval strategies:
100 // - Vector similarity search
101 // - Entity-based retrieval
102 // - Graph path traversal
103 // - Hybrid approaches
104 //
105 // To enable full retrieval:
106 // 1. Build a KnowledgeGraph with documents, entities, and relationships
107 // 2. Pass it to the RetrievalSystem via application context
108 // 3. The RetrievalSystem will handle query expansion, ranking, and fusion
109 //
110 // For testing without a real graph, use the MockRetriever from test_utils.
111
112 Ok(vec![])
113 }
114
115 async fn search_with_context(
116 &self,
117 query: Self::Query,
118 _context: &str,
119 k: usize,
120 ) -> Result<Vec<Self::Result>> {
121 // Use same implementation as search for now
122 // Context could be used to filter or re-rank results
123 self.search(query, k).await
124 }
125
126 async fn search_batch(
127 &self,
128 queries: Vec<Self::Query>,
129 k: usize,
130 ) -> Result<Vec<Vec<Self::Result>>> {
131 let mut results = Vec::with_capacity(queries.len());
132 for query in queries {
133 results.push(self.search(query, k).await?);
134 }
135 Ok(results)
136 }
137
138 async fn update(&mut self, _content: Vec<String>) -> Result<()> {
139 // Updating the retrieval system would typically involve:
140 // 1. Adding new documents to vector store
141 // 2. Rebuilding search indices
142 // 3. Updating graph structures
143
144 // For now, this is a no-op since retrieval system doesn't expose
145 // a public update API
146 Ok(())
147 }
148
149 async fn health_check(&self) -> Result<bool> {
150 // Basic health check - verify the system is initialized
151 Ok(true)
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158 use crate::config::Config;
159
160 #[tokio::test]
161 async fn test_retrieval_adapter_creation() {
162 let config = Config::default();
163 let system = RetrievalSystem::new(&config).unwrap();
164 let adapter = RetrievalSystemAdapter::new(system);
165
166 assert!(adapter.health_check().await.unwrap());
167 }
168
169 #[tokio::test]
170 async fn test_search_batch() {
171 let config = Config::default();
172 let system = RetrievalSystem::new(&config).unwrap();
173 let adapter = RetrievalSystemAdapter::new(system);
174
175 let queries = vec![
176 "What is GraphRAG?".to_string(),
177 "How does retrieval work?".to_string(),
178 ];
179
180 let results = adapter.search_batch(queries, 5).await.unwrap();
181 assert_eq!(results.len(), 2);
182 }
183}