-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathconfig.rs
More file actions
391 lines (327 loc) · 10.6 KB
/
Copy pathconfig.rs
File metadata and controls
391 lines (327 loc) · 10.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
// Copyright (c) 2026 vectorless developers
// SPDX-License-Identifier: Apache-2.0
//! Configuration types for the compile pipeline.
//!
//! This module contains all configuration types used by the compilation pipeline:
//! - [`SourceFormat`] - Document format selection
//! - [`PipelineOptions`] - Full pipeline configuration
//! - [`OptimizationConfig`] - Tree optimization settings
//! - [`ThinningConfig`] - Node merging settings
use super::summary::SummaryStrategy;
use vectorless_config::IndexerConfig;
use vectorless_document::{DocumentTree, ReasoningIndexConfig};
use vectorless_llm::throttle::ConcurrencyConfig;
use vectorless_utils::fingerprint::{Fingerprint, Fingerprinter};
use std::path::PathBuf;
/// Index mode for document processing.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SourceFormat {
/// Auto-detect format from file extension.
Auto,
/// Force Markdown format.
Markdown,
/// Force PDF format.
Pdf,
/// Custom format resolved via [`ParserRegistry`](crate::parse::ParserRegistry).
Custom(String),
}
impl Default for SourceFormat {
fn default() -> Self {
Self::Auto
}
}
/// Configuration for tree optimization.
#[derive(Debug, Clone)]
pub struct OptimizationConfig {
/// Whether optimization is enabled.
pub enabled: bool,
/// Maximum tree depth (flatten if exceeded).
pub max_depth: Option<usize>,
/// Maximum children per node (group if exceeded).
pub max_children: Option<usize>,
/// Minimum tokens for a leaf node (merge smaller ones).
pub merge_leaf_threshold: usize,
}
impl Default for OptimizationConfig {
fn default() -> Self {
Self {
enabled: true,
max_depth: None,
max_children: None,
merge_leaf_threshold: 0,
}
}
}
impl OptimizationConfig {
/// Create a new optimization config with defaults.
pub fn new() -> Self {
Self::default()
}
/// Disable optimization entirely.
pub fn disabled() -> Self {
Self {
enabled: false,
..Self::default()
}
}
/// Set maximum depth.
pub fn with_max_depth(mut self, depth: usize) -> Self {
self.max_depth = Some(depth);
self
}
/// Set maximum children per node.
pub fn with_max_children(mut self, max: usize) -> Self {
self.max_children = Some(max);
self
}
}
/// Configuration for thinning (merging small nodes).
#[derive(Debug, Clone)]
pub struct ThinningConfig {
/// Whether thinning is enabled.
pub enabled: bool,
/// Token threshold for merging.
pub threshold: usize,
/// Whether to merge child content into the parent when removing children.
/// When true, nodes below threshold absorb their children's text before removal.
/// When false, small nodes are simply discarded.
pub merge_content: bool,
}
impl Default for ThinningConfig {
fn default() -> Self {
Self {
enabled: false,
threshold: 500,
merge_content: true,
}
}
}
impl ThinningConfig {
/// Create disabled config.
pub fn disabled() -> Self {
Self::default()
}
/// Create enabled config with threshold.
pub fn enabled(threshold: usize) -> Self {
Self {
enabled: true,
threshold,
merge_content: true,
}
}
/// Set the token threshold.
pub fn with_threshold(mut self, threshold: usize) -> Self {
self.threshold = threshold;
self
}
/// Set whether to merge content.
pub fn with_merge_content(mut self, merge: bool) -> Self {
self.merge_content = merge;
self
}
}
/// Configuration for large node splitting.
#[derive(Debug, Clone)]
pub struct SplitConfig {
/// Whether splitting is enabled.
pub enabled: bool,
/// Maximum tokens per leaf node. Nodes exceeding this are split.
pub max_tokens_per_node: usize,
/// Whether to use pattern-based splitting (headings, paragraphs).
/// When false, splits at approximate byte boundaries.
pub pattern_split: bool,
}
impl Default for SplitConfig {
fn default() -> Self {
Self {
enabled: true,
max_tokens_per_node: 4000,
pattern_split: true,
}
}
}
impl SplitConfig {
/// Create disabled config.
pub fn disabled() -> Self {
Self {
enabled: false,
..Self::default()
}
}
/// Create enabled config with custom token limit.
pub fn with_max_tokens(mut self, max: usize) -> Self {
self.max_tokens_per_node = max;
self
}
/// Set whether to use pattern-based splitting.
pub fn with_pattern_split(mut self, pattern: bool) -> Self {
self.pattern_split = pattern;
self
}
}
/// Pipeline options for index execution.
#[derive(Debug, Clone)]
pub struct PipelineOptions {
/// Index mode.
pub mode: SourceFormat,
/// Whether to generate node IDs.
pub generate_ids: bool,
/// Summary generation strategy.
pub summary_strategy: SummaryStrategy,
/// Thinning configuration.
pub thinning: ThinningConfig,
/// Optimization configuration.
pub optimization: OptimizationConfig,
/// Split configuration.
pub split: SplitConfig,
/// Whether to generate document description.
pub generate_description: bool,
/// Concurrency configuration.
pub concurrency: ConcurrencyConfig,
/// Indexer configuration.
pub indexer: IndexerConfig,
/// Reasoning index configuration.
pub reasoning_index: ReasoningIndexConfig,
/// Existing tree from a previous index (for incremental updates).
/// Stages (enhance, reasoning) can reuse data from unchanged nodes.
pub existing_tree: Option<DocumentTree>,
/// Current processing version. Bumped when indexing algorithm changes
/// to force reprocessing of existing documents.
pub processing_version: u32,
/// Directory for pipeline checkpoints.
/// When set, the pipeline saves state after each stage group
/// and can resume from the last completed stage on restart.
/// When `None`, checkpointing is disabled.
pub checkpoint_dir: Option<PathBuf>,
}
impl Default for PipelineOptions {
fn default() -> Self {
Self {
mode: SourceFormat::Auto,
generate_ids: true,
summary_strategy: SummaryStrategy::full(),
thinning: ThinningConfig::default(),
optimization: OptimizationConfig::default(),
split: SplitConfig::default(),
generate_description: true,
concurrency: ConcurrencyConfig::default(),
indexer: IndexerConfig::default(),
reasoning_index: ReasoningIndexConfig::default(),
existing_tree: None,
processing_version: 1,
checkpoint_dir: None,
}
}
}
impl PipelineOptions {
/// Create new pipeline options with defaults.
pub fn new() -> Self {
Self::default()
}
/// Set the index mode.
pub fn with_mode(mut self, mode: SourceFormat) -> Self {
self.mode = mode;
self
}
/// Set whether to generate node IDs.
pub fn with_generate_ids(mut self, generate: bool) -> Self {
self.generate_ids = generate;
self
}
/// Set the summary strategy.
pub fn with_summary_strategy(mut self, strategy: SummaryStrategy) -> Self {
self.summary_strategy = strategy;
self
}
/// Set the thinning configuration.
pub fn with_thinning(mut self, thinning: ThinningConfig) -> Self {
self.thinning = thinning;
self
}
/// Set the optimization configuration.
pub fn with_optimization(mut self, optimization: OptimizationConfig) -> Self {
self.optimization = optimization;
self
}
/// Set the split configuration.
pub fn with_split(mut self, split: SplitConfig) -> Self {
self.split = split;
self
}
/// Set whether to generate document description.
pub fn with_generate_description(mut self, generate: bool) -> Self {
self.generate_description = generate;
self
}
/// Set the concurrency configuration.
pub fn with_concurrency(mut self, concurrency: ConcurrencyConfig) -> Self {
self.concurrency = concurrency;
self
}
/// Set the indexer configuration.
pub fn with_indexer(mut self, indexer: IndexerConfig) -> Self {
self.indexer = indexer;
self
}
/// Set the reasoning index configuration.
pub fn with_reasoning_index(mut self, config: ReasoningIndexConfig) -> Self {
self.reasoning_index = config;
self
}
/// Set the checkpoint directory.
///
/// When set, the pipeline saves state after each stage group
/// and can resume from the last completed stage on restart.
pub fn with_checkpoint_dir(mut self, dir: impl Into<PathBuf>) -> Self {
self.checkpoint_dir = Some(dir.into());
self
}
/// Compute a fingerprint of the pipeline configuration.
///
/// If this fingerprint changes between runs, all documents need full reprocessing
/// even if their content hasn't changed (because the processing logic is different).
pub fn logic_fingerprint(&self) -> Fingerprint {
Fingerprinter::new()
.with_str(&format!("{:?}", self.mode))
.with_bool(self.generate_ids)
.with_str(&format!("{:?}", self.summary_strategy))
.with_bool(self.generate_description)
.with_bool(self.optimization.enabled)
.with_str(&format!("{:?}", self.reasoning_index))
.into_fingerprint()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_index_mode_default() {
let mode = SourceFormat::default();
assert_eq!(mode, SourceFormat::Auto);
}
#[test]
fn test_optimization_config() {
let config = OptimizationConfig::new()
.with_max_depth(5)
.with_max_children(10);
assert!(config.enabled);
assert_eq!(config.max_depth, Some(5));
assert_eq!(config.max_children, Some(10));
}
#[test]
fn test_thinning_config() {
let config = ThinningConfig::enabled(300);
assert!(config.enabled);
assert_eq!(config.threshold, 300);
let disabled = ThinningConfig::disabled();
assert!(!disabled.enabled);
}
#[test]
fn test_pipeline_options_builder() {
let options = PipelineOptions::new()
.with_mode(SourceFormat::Markdown)
.with_generate_ids(false);
assert_eq!(options.mode, SourceFormat::Markdown);
assert!(!options.generate_ids);
}
}