graphrag_core/query/
planner.rs1use crate::core::Result;
2use crate::ollama::OllamaClient;
3use serde::{Deserialize, Serialize};
4
5pub struct QueryPlanner {
7 client: OllamaClient,
8}
9
10#[derive(Debug, Serialize, Deserialize)]
11struct DecompositionResponse {
12 sub_queries: Vec<String>,
13}
14
15impl QueryPlanner {
16 pub fn new(client: OllamaClient) -> Self {
18 Self { client }
19 }
20
21 pub async fn decompose(&self, query: &str) -> Result<Vec<String>> {
23 let prompt = format!(
24 "You are an expert query planner for a RAG system. \
25 Your task is to decompose the following complex user query into a list of simple, independent sub-queries \
26 that can be answered using vector search. \
27 \
28 Return ONLY a raw JSON object with a single key 'sub_queries' containing the list of strings. \
29 Do not include any explanation, markdown formatting, or preamble. \
30 \
31 Query: '{}' \
32 \
33 JSON Response:",
34 query
35 );
36
37 let response_text = self.client.generate(&prompt).await?;
38
39 let cleaned_json = response_text
41 .trim()
42 .trim_start_matches("```json")
43 .trim_start_matches("```")
44 .trim_end_matches("```")
45 .trim();
46
47 let response: DecompositionResponse = serde_json::from_str(cleaned_json).map_err(|e| {
49 crate::core::GraphRAGError::Generation {
50 message: format!(
51 "Failed to parse planner response: {}. Text: {}",
52 e, cleaned_json
53 ),
54 }
55 })?;
56
57 Ok(response.sub_queries)
58 }
59}