51 lines
1.5 KiB
Python
51 lines
1.5 KiB
Python
from typing import ClassVar
|
|
|
|
import tiktoken
|
|
from docling.chunking import HybridChunker # type: ignore
|
|
from docling_core.transforms.chunker.tokenizer.openai import OpenAITokenizer
|
|
from docling_core.types.doc.document import DoclingDocument
|
|
|
|
from haiku.rag.config import Config
|
|
|
|
|
|
class Chunker:
|
|
"""A class that chunks text into smaller pieces for embedding and retrieval.
|
|
|
|
Uses docling's structure-aware chunking to create semantically meaningful chunks
|
|
that respect document boundaries.
|
|
|
|
Args:
|
|
chunk_size: The maximum size of a chunk in tokens.
|
|
"""
|
|
|
|
encoder: ClassVar[tiktoken.Encoding] = tiktoken.encoding_for_model("gpt-4o")
|
|
|
|
def __init__(
|
|
self,
|
|
chunk_size: int = Config.CHUNK_SIZE,
|
|
):
|
|
self.chunk_size = chunk_size
|
|
tokenizer = OpenAITokenizer(
|
|
tokenizer=tiktoken.encoding_for_model("gpt-4o"), max_tokens=chunk_size
|
|
)
|
|
|
|
self.chunker = HybridChunker(tokenizer=tokenizer) # type: ignore
|
|
|
|
async def chunk(self, document: DoclingDocument) -> list[str]:
|
|
"""Split the document into chunks using docling's structure-aware chunking.
|
|
|
|
Args:
|
|
document: The DoclingDocument to be split into chunks.
|
|
|
|
Returns:
|
|
A list of text chunks with semantic boundaries.
|
|
"""
|
|
if document is None:
|
|
return []
|
|
|
|
# Chunk using docling's hybrid chunker
|
|
chunks = list(self.chunker.chunk(document))
|
|
return [self.chunker.contextualize(chunk) for chunk in chunks]
|
|
|
|
|
|
chunker = Chunker()
|