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}]