kg: graph build, traversal queries, neo4j export - kg_ocr.graph builds a networkx graph (docs, chunks, entities, citations, co-occurrence) from chunk markdown - analyzer for summaries, top entities/citations, anomaly checks - traversal: chunks_for_entity/citation, related_entities, expand_context - export: JSON round-trip, GraphML, batched MERGE into neo4j - new CLI: ocr-pipeline kg build|stats|query|export - lazy kg_ocr imports, networkx/neo4j behind extras - dropped dead watch.py shim, added KgConfig stub - trimmed README, updated TODO
Some checks failed
tests / core (macos-latest, py3.11) (push) Has been cancelled
tests / core (macos-latest, py3.12) (push) Has been cancelled
tests / core (macos-latest, py3.13) (push) Has been cancelled
tests / core (ubuntu-latest, py3.11) (push) Has been cancelled
tests / core (ubuntu-latest, py3.12) (push) Has been cancelled
tests / core (ubuntu-latest, py3.13) (push) Has been cancelled
tests / doctor CLI smoke test (push) Has been cancelled

This commit is contained in:
2026-07-20 19:50:38 +02:00
parent 39655fc35f
commit 7503a441c2
29 changed files with 1343 additions and 160 deletions

View File

@@ -0,0 +1,54 @@
from __future__ import annotations
import sys
import types
import pytest
from kg_ocr.embeddings import create_and_index
from kg_ocr.rag import retrieve
class _FakeEmbeddings:
instances: list[_FakeEmbeddings] = []
def __init__(self, config):
self.config = config
self.indexed: list[str] | None = None
_FakeEmbeddings.instances.append(self)
def index(self, data):
self.indexed = data
def _install_fake_txtai(monkeypatch: pytest.MonkeyPatch) -> None:
fake_txtai = types.ModuleType("txtai")
fake_embeddings_mod = types.ModuleType("txtai.embeddings")
fake_embeddings_mod.Embeddings = _FakeEmbeddings # type: ignore[attr-defined]
monkeypatch.setitem(sys.modules, "txtai", fake_txtai)
monkeypatch.setitem(sys.modules, "txtai.embeddings", fake_embeddings_mod)
def test_create_and_index_config_and_data(monkeypatch: pytest.MonkeyPatch) -> None:
_install_fake_txtai(monkeypatch)
emb = create_and_index(["alpha", "beta"], model="some-model")
assert emb.config["path"] == "some-model"
assert emb.config["content"] is True
assert emb.config["hybrid"] is True
assert emb.indexed == ["alpha", "beta"]
def test_create_and_index_raises_without_txtai(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setitem(sys.modules, "txtai", None)
monkeypatch.setitem(sys.modules, "txtai.embeddings", None)
with pytest.raises(ImportError, match="txtai"):
create_and_index(["x"])
def test_retrieve_passes_through() -> None:
class FakeEmb:
def search(self, query, limit):
return [{"text": f"{query}-{i}", "score": 1.0} for i in range(limit)]
out = retrieve(FakeEmb(), "q", limit=2)
assert out == [{"text": "q-0", "score": 1.0}, {"text": "q-1", "score": 1.0}]