fix(search): review ambiguous topic assignments

This commit is contained in:
2026-09-14 10:31:45 +03:00
parent a1b4787930
commit 5f44981bd3
4 changed files with 2749 additions and 2732 deletions

View File

@@ -5,10 +5,13 @@ import unittest
from contextlib import closing
from pathlib import Path
from tools.build_search_topic_taxonomy import build
from tools.build_search_topic_taxonomy import build, group_for
class SearchTopicTaxonomyTest(unittest.TestCase):
def test_ambiguous_roots_are_left_for_manual_review(self):
self.assertEqual(group_for("Иностранные инвестиции"), "review_required")
def test_preserves_source_tree_counts_and_marks_unclassified_roots(self):
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary)
@@ -51,6 +54,18 @@ class SearchTopicTaxonomyTest(unittest.TestCase):
self.assertEqual(groups["review_required"]["children"][0]["grouping_status"], "manual_review")
self.assertEqual(catalog["nodes_missing_kyrgyz_label"], 2)
def test_rebuild_fails_instead_of_omitting_successful_manifest_document(self):
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary)
(root / "documents/1").mkdir(parents=True)
with closing(sqlite3.connect(root / "manifest.sqlite3")) as db:
db.execute("CREATE TABLE documents (code TEXT, state TEXT)")
db.execute("INSERT INTO documents VALUES ('1', 'success')")
db.commit()
with self.assertRaisesRegex(RuntimeError, "normalized document 1"):
build(root)
if __name__ == "__main__":
unittest.main()

View File

@@ -106,10 +106,10 @@
отношения; общие и межотраслевые вопросы.
Каталог является черновиком: группа корневой рубрики предложена по русской
подписи, неоднозначные и нераспознанные рубрики помещены в
`review_required` и отмечены `manual_review`; остальные помечены
подписи, рубрики с несколькими совпадениями правил или без совпадений помещены
в `review_required` и отмечены `manual_review`; остальные помечены
`provisional_lexical`. В корпусе 2 065 узлов и 687 вариантов корневых рубрик;
251 корневой вариант ожидает ручной классификации. Отсутствующие в источнике
328 корневых вариантов ожидают ручной классификации. Отсутствующие в источнике
кыргызские подписи оставлены пустыми: они отсутствуют у 1 524 узлов, новые
переводы не придуманы. Внутренние `source-*` ID являются
временными хешами кода источника и цепочки подписей; при `Code: null` они

File diff suppressed because it is too large Load Diff

View File

@@ -57,7 +57,7 @@ def clean(value):
def group_for(label):
text = (label or "").casefold()
matches = [code for code, pattern in RULES if re.search(pattern, text)]
return matches[0] if matches else "review_required"
return matches[0] if len(matches) == 1 else "review_required"
def node_id(path):
@@ -121,8 +121,10 @@ def build(normalized_root):
path = source_root / code / "document.json"
try:
data = json.loads(path.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError):
return code, []
except (OSError, json.JSONDecodeError) as error:
raise RuntimeError(f"cannot read normalized document {code}: {error}") from error
if not isinstance(data, dict):
raise RuntimeError(f"normalized document {code} must contain a JSON object")
return code, data.get("general_classifiers", [])
with ThreadPoolExecutor(max_workers=24) as pool: