nvikou's picture
Deploy TechDocs GraphRAG
da21448 verified
Raw History Blame Contribute Delete
2.16 kB
from collections.abc import Callable, Sequence
from concurrent.futures import ThreadPoolExecutor
from dataclasses import dataclass
from techdocs_graphrag.extraction import GraphExtractor
from techdocs_graphrag.ingestion import ParagraphSplitter, SourceDocument, chunk_documents
from techdocs_graphrag.ports import KnowledgeGraph, LanguageModel
ProgressCallback = Callable[[int, int], None]
@dataclass(frozen=True, slots=True)
class IndexingReport:
documents: int
chunks: int
entities: int
relations: int
class IndexingPipeline:
def __init__(
self,
*,
splitter: ParagraphSplitter,
llm: LanguageModel,
extractor: GraphExtractor,
store: KnowledgeGraph,
workers: int,
) -> None:
self._splitter = splitter
self._llm = llm
self._extractor = extractor
self._store = store
self._workers = workers
def run(
self,
documents: Sequence[SourceDocument],
on_progress: ProgressCallback | None = None,
) -> IndexingReport:
chunks = chunk_documents(documents, self._splitter)
if not chunks:
return IndexingReport(documents=len(documents), chunks=0, entities=0, relations=0)
self._store.ensure_schema()
self._store.upsert_chunks(chunks, self._llm.embed([chunk.text for chunk in chunks]))
entities = relations = 0
with ThreadPoolExecutor(max_workers=self._workers) as executor:
extractions = executor.map(self._extractor.extract, chunks)
for completed, (chunk, extraction) in enumerate(
zip(chunks, extractions, strict=True), start=1
):
self._store.upsert_extraction(chunk, extraction)
entities += len(extraction.entities)
relations += len(extraction.relations)
if on_progress:
on_progress(completed, len(chunks))
self._store.await_indexes()
return IndexingReport(
documents=len(documents),
chunks=len(chunks),
entities=entities,
relations=relations,
)