e4dcfc49aa
Tests / Import Check (Python 3.13) (push) Has been cancelled
Tests / Import Check (Python 3.14) (push) Has been cancelled
Tests / Python Tests (Python 3.11) (push) Has been cancelled
Tests / Python Tests (Python 3.12) (push) Has been cancelled
Tests / Python Tests (Python 3.14) (push) Has been cancelled
Tests / Test Summary (push) Has been cancelled
Tests / Lint and Format (push) Has been cancelled
Tests / Web Node Tests (push) Has been cancelled
Tests / Import Check (Python 3.11) (push) Has been cancelled
Tests / Import Check (Python 3.12) (push) Has been cancelled
Tests / Python Tests (Python 3.13) (push) Has been cancelled
180 lines
5.5 KiB
Python
180 lines
5.5 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from deeptutor.knowledge.manager import KnowledgeBaseManager
|
|
|
|
|
|
class _Signature:
|
|
def __init__(self, sig_hash: str = "active-signature") -> None:
|
|
self._hash = sig_hash
|
|
|
|
def hash(self) -> str:
|
|
return self._hash
|
|
|
|
|
|
def _patch_active_embedding(
|
|
monkeypatch: pytest.MonkeyPatch, sig_hash: str = "active-signature"
|
|
) -> None:
|
|
from deeptutor.knowledge import manager as manager_module
|
|
from deeptutor.services.rag import embedding_signature
|
|
|
|
monkeypatch.setattr(
|
|
manager_module, "_get_embedding_fingerprint", lambda: ("embed-active", 4096)
|
|
)
|
|
monkeypatch.setattr(
|
|
embedding_signature,
|
|
"signature_from_embedding_config",
|
|
lambda: _Signature(sig_hash),
|
|
)
|
|
|
|
|
|
def test_in_progress_empty_version_dir_does_not_mark_new_kb_reindex(
|
|
tmp_path: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
_patch_active_embedding(monkeypatch)
|
|
|
|
manager = KnowledgeBaseManager(base_dir=str(tmp_path))
|
|
manager.update_kb_status(
|
|
name="new-kb",
|
|
status="processing",
|
|
progress={
|
|
"stage": "processing_documents",
|
|
"message": "Embedding chunks",
|
|
"percent": 20,
|
|
},
|
|
)
|
|
|
|
# The LlamaIndex writer allocates version-N before it has persisted docstore.json.
|
|
(tmp_path / "new-kb" / "version-1").mkdir(parents=True)
|
|
|
|
reloaded = KnowledgeBaseManager(base_dir=str(tmp_path))
|
|
entry = reloaded.config["knowledge_bases"]["new-kb"]
|
|
assert entry.get("needs_reindex", False) is False
|
|
assert entry.get("embedding_mismatch", False) is False
|
|
|
|
info = reloaded.get_info("new-kb")
|
|
assert info["status"] == "processing"
|
|
assert info["statistics"]["needs_reindex"] is False
|
|
|
|
|
|
def test_ready_version_without_active_signature_marks_reindex(
|
|
tmp_path: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
_patch_active_embedding(monkeypatch, sig_hash="active-signature")
|
|
|
|
kb_dir = tmp_path / "old-kb"
|
|
version_dir = kb_dir / "version-1"
|
|
version_dir.mkdir(parents=True)
|
|
(version_dir / "docstore.json").write_text("{}", encoding="utf-8")
|
|
(version_dir / "index_store.json").write_text("{}", encoding="utf-8")
|
|
(version_dir / "meta.json").write_text(
|
|
json.dumps({"signature": "old-signature", "version": "version-1"}),
|
|
encoding="utf-8",
|
|
)
|
|
|
|
manager = KnowledgeBaseManager(base_dir=str(tmp_path))
|
|
manager.config.setdefault("knowledge_bases", {})["old-kb"] = {
|
|
"path": "old-kb",
|
|
"rag_provider": "llamaindex",
|
|
}
|
|
manager._save_config()
|
|
|
|
reloaded = KnowledgeBaseManager(base_dir=str(tmp_path))
|
|
entry = reloaded.config["knowledge_bases"]["old-kb"]
|
|
assert entry["needs_reindex"] is True
|
|
assert entry["embedding_mismatch"] is True
|
|
|
|
|
|
def test_ready_non_embedding_provider_version_does_not_mark_reindex(
|
|
tmp_path: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
_patch_active_embedding(monkeypatch, sig_hash="active-signature")
|
|
|
|
kb_dir = tmp_path / "page-kb"
|
|
version_dir = kb_dir / "version-1"
|
|
version_dir.mkdir(parents=True)
|
|
(version_dir / "pageindex_docs.json").write_text(
|
|
json.dumps({"provider": "pageindex", "docs": {"a.pdf": {"doc_id": "doc-1"}}}),
|
|
encoding="utf-8",
|
|
)
|
|
(version_dir / "meta.json").write_text(
|
|
json.dumps(
|
|
{
|
|
"provider": "pageindex",
|
|
"signature": "pageindex",
|
|
"version": "version-1",
|
|
}
|
|
),
|
|
encoding="utf-8",
|
|
)
|
|
(tmp_path / "kb_config.json").write_text(
|
|
json.dumps(
|
|
{
|
|
"knowledge_bases": {
|
|
"page-kb": {
|
|
"path": "page-kb",
|
|
"rag_provider": "pageindex",
|
|
"needs_reindex": True,
|
|
"embedding_mismatch": True,
|
|
}
|
|
}
|
|
}
|
|
),
|
|
encoding="utf-8",
|
|
)
|
|
|
|
manager = KnowledgeBaseManager(base_dir=str(tmp_path))
|
|
entry = manager.config["knowledge_bases"]["page-kb"]
|
|
assert entry["rag_provider"] == "pageindex"
|
|
assert entry.get("needs_reindex", False) is False
|
|
assert entry.get("embedding_mismatch", False) is False
|
|
assert entry["index_versions"][0]["signature"] == "pageindex"
|
|
|
|
|
|
def test_ready_status_records_last_indexed_only_when_index_changes(
|
|
tmp_path: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
_patch_active_embedding(monkeypatch)
|
|
manager = KnowledgeBaseManager(base_dir=str(tmp_path))
|
|
|
|
manager.update_kb_status(
|
|
name="kb",
|
|
status="ready",
|
|
progress={
|
|
"stage": "completed",
|
|
"timestamp": "2026-05-04T10:00:00",
|
|
"indexed_count": 2,
|
|
"index_changed": True,
|
|
"index_action": "upload",
|
|
},
|
|
)
|
|
|
|
entry = KnowledgeBaseManager(base_dir=str(tmp_path)).config["knowledge_bases"]["kb"]
|
|
assert entry["last_indexed_at"] == "2026-05-04T10:00:00"
|
|
assert entry["last_indexed_count"] == 2
|
|
assert entry["last_indexed_action"] == "upload"
|
|
|
|
manager.update_kb_status(
|
|
name="kb",
|
|
status="ready",
|
|
progress={
|
|
"stage": "completed",
|
|
"timestamp": "2026-05-04T11:00:00",
|
|
"indexed_count": 0,
|
|
"index_changed": False,
|
|
"index_action": "upload",
|
|
},
|
|
)
|
|
|
|
info = KnowledgeBaseManager(base_dir=str(tmp_path)).get_info("kb")
|
|
assert info["metadata"]["last_indexed_at"] == "2026-05-04T10:00:00"
|
|
assert info["metadata"]["last_indexed_count"] == 2
|