1"""Sliding window chunking strategy."""
2
3from __future__ import annotations
4
5from typing import Any
6
7from lexigram.ai.rag.chunking.base import AbstractChunker
8from lexigram.ai.rag.chunking.types import Chunk
9
10
11class SlidingWindowChunker(AbstractChunker):
12 """Sliding window chunking with configurable stride.
13
14 Creates overlapping chunks by sliding a window across the text.
15
16 Example:
17 >>> chunker = SlidingWindowChunker(window_size=500, stride=250)
18 >>> chunks = chunker.chunk("Long document...")
19 """
20
21 def __init__(self, window_size: int = 1000, stride: int = 500):
22 """Initialize sliding window chunker.
23
24 Args:
25 window_size: Size of each window in characters
26 stride: Step size for sliding (stride < window_size creates overlap)
27 """
28 self.window_size = window_size
29 self.stride = stride
30
31 if stride <= 0:
32 msg = "Stride must be positive"
33 raise ValueError(msg)
34 if stride > window_size:
35 msg = "Stride should not exceed window_size"
36 raise ValueError(msg)
37
38 def chunk(self, text: str, metadata: dict[str, Any] | None = None) -> list[Chunk]:
39 """Split text using sliding window.
40
41 Args:
42 text: Text to chunk
43 metadata: Optional metadata
44
45 Returns:
46 List of chunks
47 """
48 if not text:
49 return []
50
51 chunks: list[Chunk] = []
52 chunk_index = 0
53
54 for start in range(0, len(text), self.stride):
55 end = min(start + self.window_size, len(text))
56 chunk_text = text[start:end]
57
58 if chunk_text.strip():
59 chunks.append(
60 Chunk(
61 text=chunk_text,
62 start_index=start,
63 end_index=end,
64 chunk_index=chunk_index,
65 metadata=metadata,
66 ),
67 )
68 chunk_index += 1
69
70 # Stop if we've reached the end
71 if end >= len(text):
72 break
73
74 return chunks