74 lines
3.1 KiB
Python
74 lines
3.1 KiB
Python
"""Alternative search terms of a topic (synonyms, expanded abbreviations, English).
|
|
|
|
CRZP matches exact words, so "LLM" does not find a thesis that only writes
|
|
"jazykový model". A small reviewed table comes first; the model may add
|
|
proposals up to two alternatives in total. A model proposal is unverified: it
|
|
is searched only when CRZP itself uses it next to the topic (a work found for
|
|
the topic has it in its title or keywords) or when the topic alone finds
|
|
nothing (see answer.find). Each alternative is a separate CRZP search, the
|
|
answer names all searched terms, and every listed work contains one of them.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
|
|
from tools.crzp.source.parse import fold
|
|
|
|
MAX_ALTERNATIVES = 2
|
|
# Reviewed by hand; keys and values are search terms as they appear in CRZP titles and keywords.
|
|
TABLE = {
|
|
"llm": ["jazykový model", "GPT"],
|
|
"velky jazykovy model": ["LLM", "GPT"],
|
|
"jazykovy model": ["LLM"],
|
|
"ai": ["umelá inteligencia"],
|
|
"umela inteligencia": ["artificial intelligence"],
|
|
"nlp": ["spracovanie prirodzeného jazyka"],
|
|
"spracovanie prirodzeneho jazyka": ["NLP"],
|
|
"ml": ["strojové učenie"],
|
|
"strojove ucenie": ["machine learning"],
|
|
"chatbot": ["dialógový systém", "konverzačný agent"],
|
|
"dialogovy system": ["chatbot"],
|
|
"rag": ["retrieval augmented generation"],
|
|
"iot": ["internet vecí"],
|
|
"internet veci": ["IoT"],
|
|
"neuronova siet": ["neural network"],
|
|
"hlboke ucenie": ["deep learning"],
|
|
"rozpoznavanie reci": ["speech recognition", "prepis reči"],
|
|
"pocitacove videnie": ["computer vision"],
|
|
"kyberneticka bezpecnost": ["cybersecurity"],
|
|
"blockchain": ["distribuovaná účtovná kniha"],
|
|
}
|
|
|
|
|
|
def valid(term: str, topic: str) -> bool:
|
|
"""A short search phrase, different from the topic, no names or digits only."""
|
|
term = term.strip()
|
|
return (2 <= len(term) <= 40 and len(term.split()) <= 4 and fold(term) != fold(topic)
|
|
and not re.fullmatch(r"[\d\s]+", term) and not re.search(r"[\"„“{}<>]", term))
|
|
|
|
|
|
def reviewed(topic: str) -> list[str]:
|
|
return TABLE.get(" ".join(fold(topic).split()), [])
|
|
|
|
|
|
def expands(term: str, topic: str) -> bool:
|
|
"""The term spells out the abbreviation: "LLM" -> "large language model", "IoT" -> "internet of things"."""
|
|
letters = re.sub(r"[^a-z]", "", fold(topic))
|
|
words = re.findall(r"[^\W\d_]+", fold(term))
|
|
return (sum(c.isupper() for c in topic) >= 2 and 2 <= len(letters) <= 6 and len(words) == len(letters)
|
|
and "".join(w[0] for w in words) == letters)
|
|
|
|
|
|
def is_reviewed(term: str, topic: str) -> bool:
|
|
"""In the reviewed table, or the exact expansion of the abbreviation."""
|
|
return fold(term.strip()) in {fold(t) for t in reviewed(topic)} or expands(term, topic)
|
|
|
|
|
|
def alternatives(topic: str, proposed: list | None = None) -> list[str]:
|
|
"""Up to MAX_ALTERNATIVES terms: the reviewed table first, then the model's valid proposals."""
|
|
result = []
|
|
for term in [*reviewed(topic), *(proposed or [])]:
|
|
if isinstance(term, str) and valid(term, topic) and fold(term) not in {fold(t) for t in result}:
|
|
result.append(term.strip())
|
|
return result[:MAX_ALTERNATIVES]
|