Engram-protocol/engram
0
1"""Tests for kvcos.engram.embedder — unified fingerprint embedding."""2 3import pytest4import torch5import torch.nn.functional as F6 7from kvcos.engram.embedder import (8 HashEmbedder,9 get_embedder,10 get_fingerprint,11 reset_embedder,12)13 14 15class TestHashEmbedder:16 def test_deterministic(self):17 emb = HashEmbedder(dim=128)18 fp1 = emb.embed("hello")19 fp2 = emb.embed("hello")20 assert torch.allclose(fp1, fp2)21 22 def test_different_text(self):23 emb = HashEmbedder(dim=128)24 fp1 = emb.embed("hello")25 fp2 = emb.embed("world")26 assert not torch.allclose(fp1, fp2)27 28 def test_normalized(self):29 emb = HashEmbedder(dim=128)30 fp = emb.embed("test")31 norm = torch.norm(fp).item()32 assert abs(norm - 1.0) < 0.0133 34 def test_dimension(self):35 emb = HashEmbedder(dim=256)36 fp = emb.embed("test")37 assert fp.shape == (256,)38 assert emb.dim == 25639 40 def test_source_tag(self):41 emb = HashEmbedder()42 assert emb.source == "hash-fallback"43 44 45class TestGetFingerprint:46 def test_returns_tensor_and_source(self):47 fp, source = get_fingerprint("test text")48 assert isinstance(fp, torch.Tensor)49 assert isinstance(source, str)50 assert source in ("llama_cpp", "sbert", "hash-fallback")51 52 def test_deterministic(self):53 fp1, _ = get_fingerprint("same text")54 fp2, _ = get_fingerprint("same text")55 assert torch.allclose(fp1, fp2)56 57 58class TestSBertEmbedder:59 """Test sbert if available (installed in this venv)."""60 61 def test_sbert_available(self):62 """Verify sentence-transformers is usable."""63 try:64 from kvcos.engram.embedder import SBertEmbedder65 emb = SBertEmbedder()66 assert emb.source == "sbert"67 assert emb.dim == 38468 except ImportError:69 pytest.skip("sentence-transformers not installed")70 71 def test_semantic_discrimination(self):72 """Related texts should be more similar than unrelated."""73 try:74 from kvcos.engram.embedder import SBertEmbedder75 emb = SBertEmbedder()76 except ImportError:77 pytest.skip("sentence-transformers not installed")78 79 fp_a = emb.embed("machine learning neural network training")80 fp_b = emb.embed("deep learning model optimization")81 fp_c = emb.embed("chocolate cake baking recipe")82 83 sim_ab = F.cosine_similarity(fp_a.unsqueeze(0), fp_b.unsqueeze(0)).item()84 sim_ac = F.cosine_similarity(fp_a.unsqueeze(0), fp_c.unsqueeze(0)).item()85 86 assert sim_ab > sim_ac, (87 f"Related topics ({sim_ab:.4f}) should be more similar "88 f"than unrelated ({sim_ac:.4f})"89 )90 91 92class TestGetEmbedder:93 def test_singleton(self):94 reset_embedder()95 e1 = get_embedder()96 e2 = get_embedder()97 assert e1 is e298 99 def test_reset(self):100 reset_embedder()101 e1 = get_embedder()102 reset_embedder()103 e2 = get_embedder()104 # After reset, a new instance is created105 # (may or may not be same object depending on strategy)106 assert e2 is not None107 