67 lines
3.2 KiB
Python
67 lines
3.2 KiB
Python
from brain.lookup import cosine, find_niche
|
|
|
|
# индекс: имя, родитель, синонимы, вектор
|
|
INDEX = [
|
|
{"nisha": "стоматология / имплантация", "roditel": "Медицина",
|
|
"sinonimy": ["зубной", "импланты"], "path": "n/стоматология.md", "vector": [1.0, 0.0, 0.0]},
|
|
{"nisha": "Медицина", "roditel": None, "sinonimy": ["клиника"],
|
|
"path": "n/медицина.md", "vector": [0.6, 0.6, 0.0]},
|
|
]
|
|
|
|
def fake_embed(text):
|
|
t = text.lower()
|
|
if "имплант" in t or "зуб" in t or "стоматолог" in t:
|
|
return [0.98, 0.05, 0.0]
|
|
if "медиц" in t or "клиник" in t or "маммолог" in t:
|
|
return [0.6, 0.6, 0.0]
|
|
return [0.0, 0.0, 1.0]
|
|
|
|
def test_cosine_identical():
|
|
assert cosine([1, 0], [1, 0]) == 1.0
|
|
|
|
def test_synonym_gives_niche_hit_without_embedding():
|
|
r = find_niche("импланты", INDEX, embed_fn=None) # None => если сработает embed, упадёт
|
|
assert r.kind == "niche"
|
|
assert r.entry["nisha"].startswith("стоматология")
|
|
|
|
def test_semantic_niche_hit():
|
|
r = find_niche("хочу поставить зубной протез", INDEX, embed_fn=fake_embed)
|
|
assert r.kind == "niche"
|
|
|
|
def test_domain_hit_for_unknown_subniche():
|
|
# «маммология» карточки нет, но по смыслу ближе к домену Медицина
|
|
r = find_niche("маммология", INDEX, embed_fn=fake_embed)
|
|
assert r.kind == "domain"
|
|
assert r.entry["nisha"] == "Медицина"
|
|
|
|
def test_miss_for_new_area():
|
|
r = find_niche("грузоперевозки фурами", INDEX, embed_fn=fake_embed)
|
|
assert r.kind == "miss"
|
|
|
|
def test_empty_query_is_miss_not_false_niche():
|
|
r = find_niche("", INDEX, embed_fn=None)
|
|
assert r.kind == "miss"
|
|
r2 = find_niche(" ", INDEX, embed_fn=None)
|
|
assert r2.kind == "miss"
|
|
|
|
def test_substring_synonym_no_longer_false_hits():
|
|
# «импланты» — синоним стоматологии, но «грудные импланты» — другая ниша:
|
|
# синонимный слой больше НЕ ловит по подстроке (embed_fn=None → уходит в miss, а не в стоматологию)
|
|
r = find_niche("грудные импланты", INDEX, embed_fn=None)
|
|
assert r.kind == "miss"
|
|
# «врач» ⊂ «врачебная ошибка» тоже больше не даёт ложный домен
|
|
r2 = find_niche("врачебная ошибка", INDEX, embed_fn=None)
|
|
assert r2.kind == "miss"
|
|
|
|
def test_exact_synonym_still_hits():
|
|
r = find_niche("импланты", INDEX, embed_fn=None)
|
|
assert r.kind == "niche"
|
|
|
|
def test_parent_missing_in_index_is_miss_not_leaf_as_domain():
|
|
idx = [{"nisha": "гастроэнтерология", "roditel": "НетТакогоДомена",
|
|
"sinonimy": [], "path": "n/g.md", "vector": [1.0, 0.0]}]
|
|
# cosine([0.40, 0.917], [1,0]) ≈ 0.40 — в диапазоне домена [THR_DOMAIN, THR_NICHE), но родителя нет
|
|
def emb(t): return [0.40, 0.917]
|
|
r = find_niche("что-то смежное", idx, embed_fn=emb)
|
|
assert r.kind == "miss"
|