Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Russian Lmentry Tasks #24

Open
wants to merge 33 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
06270eb
add "bigger_number_ru" and "smaller_number_ru" tasks
eskondrashova Nov 23, 2023
5ed607c
new tasks in russian
eskondrashova Dec 29, 2023
b053859
fix removed task smaller_number, transfer ru tasks to ru folder
Feb 15, 2024
8c1fb9a
add ru tests to test dict
Feb 15, 2024
f2348fb
add suffix ru to task names
Feb 15, 2024
3a2e79e
transfer scorers
Mar 10, 2024
9100935
transfer data
Mar 10, 2024
c875f0a
add LMentryTaskRu with another path to data
Mar 10, 2024
00262b3
save russian
Mar 10, 2024
a7af3f7
limit max_tokens for mlc-serve
Mar 10, 2024
fa5338f
new templates for "most_associated_word_ru" and "least_associated_wor…
eskondrashova Apr 17, 2024
58ffe3f
update nouns_by_category_ru.json
eskondrashova Apr 17, 2024
8009c5d
new templates for "all_words_from_category_ru" and "any_words_from_ca…
eskondrashova Apr 18, 2024
9090641
add tasks to the list
Apr 18, 2024
062f0af
add templates
Apr 18, 2024
9f2bc15
fixes
Apr 18, 2024
991acd8
data ru
eskondrashova Apr 29, 2024
5b17e33
Merge remote-tracking branch 'origin/russian_lmentry_tasks' into russ…
eskondrashova Apr 29, 2024
0041206
updated constants.py
eskondrashova Apr 29, 2024
5b9f6be
"all_words_from_category_ru" - task problem
eskondrashova May 3, 2024
735dabc
"all_words_from_category_ru" - small change
eskondrashova May 3, 2024
6d8bf1b
answer patterns and code
eskondrashova May 7, 2024
3ffe6d6
small update
eskondrashova May 10, 2024
25962c9
least scorer
eskondrashova May 10, 2024
ad88eb1
transfer metadata to separated files
May 11, 2024
1c0bc3b
update test for the sake of convenience
May 11, 2024
be0dc52
fix + prints
May 11, 2024
a7c6605
fix or for distractor regexp
May 11, 2024
17a9933
all_words_from_category
eskondrashova May 13, 2024
e293aa1
most_associated_word
eskondrashova May 13, 2024
9afd1ed
remove extra prints
eskondrashova May 13, 2024
a08568c
least_associated_word
eskondrashova May 13, 2024
bcaf3a8
small update
eskondrashova May 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45,015 changes: 45,015 additions & 0 deletions data_ru/bigger_number_ru.json

Large diffs are not rendered by default.

1,635 changes: 1,635 additions & 0 deletions data_ru/ends_with_letter_ru.json

Large diffs are not rendered by default.

96,065 changes: 96,065 additions & 0 deletions data_ru/ends_with_word_ru.json

Large diffs are not rendered by default.

55,017 changes: 55,017 additions & 0 deletions data_ru/first_alphabetically_ru.json

Large diffs are not rendered by default.

106,068 changes: 106,068 additions & 0 deletions data_ru/first_letter_ru.json

Large diffs are not rendered by default.

63,018 changes: 63,018 additions & 0 deletions data_ru/first_word_ru.json

Large diffs are not rendered by default.

106,068 changes: 106,068 additions & 0 deletions data_ru/last_letter_ru.json

Large diffs are not rendered by default.

63,018 changes: 63,018 additions & 0 deletions data_ru/last_word_ru.json

Large diffs are not rendered by default.

Empty file.
166,987 changes: 166,987 additions & 0 deletions data_ru/less_letters_ru.json

Large diffs are not rendered by default.

166,987 changes: 166,987 additions & 0 deletions data_ru/more_letters_ru.json

Large diffs are not rendered by default.

Empty file.
85,001 changes: 85,001 additions & 0 deletions data_ru/sentence_containing_ru.json

Large diffs are not rendered by default.

85,001 changes: 85,001 additions & 0 deletions data_ru/sentence_not_containing_ru.json

Large diffs are not rendered by default.

45,015 changes: 45,015 additions & 0 deletions data_ru/smaller_number_ru.json

Large diffs are not rendered by default.

1,488 changes: 1,488 additions & 0 deletions data_ru/starts_with_letter_ru.json

Large diffs are not rendered by default.

96,065 changes: 96,065 additions & 0 deletions data_ru/starts_with_word_ru.json

Large diffs are not rendered by default.

55,017 changes: 55,017 additions & 0 deletions data_ru/word_after_ru.json

Large diffs are not rendered by default.

55,017 changes: 55,017 additions & 0 deletions data_ru/word_before_ru.json

Large diffs are not rendered by default.

1,403 changes: 1,403 additions & 0 deletions data_ru/word_containing_ru.json

Large diffs are not rendered by default.

1,403 changes: 1,403 additions & 0 deletions data_ru/word_not_containing_ru.json

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions lmentry/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,19 @@

ROOT_DIR = Path(__file__).parent.parent
TASKS_DATA_DIR = ROOT_DIR.joinpath("data")
TASKS_DATA_RU_DIR = ROOT_DIR.joinpath("data_ru")
HF_TASKS_DATA_DIR = ROOT_DIR.joinpath("hf_data")
PREDICTIONS_ROOT_DIR = ROOT_DIR.joinpath("predictions")
RESULTS_DIR = ROOT_DIR.joinpath("results")
VISUALIZATIONS_DIR = RESULTS_DIR.joinpath("visualizations")
SCORER_EVALUATION_DIR = RESULTS_DIR.joinpath("scorer_evaluation")
RESOURCES_DIR = ROOT_DIR.joinpath("resources")
RESOURCES_RU_DIR = ROOT_DIR.joinpath("resources_ru")
LMENTRY_WORDS_PATH = RESOURCES_DIR.joinpath("lmentry_words.json")
LMENTRY_WORDS_RU_PATH = RESOURCES_RU_DIR.joinpath("lmentry_words_ru.json")
RHYME_GROUPS_PATH = RESOURCES_DIR.joinpath("rhyme_groups.json")
HOMOPHONES_PATH = RESOURCES_DIR.joinpath("homophones.csv")
HOMOPHONES_RU_PATH = RESOURCES_RU_DIR.joinpath("homophones_ru.json")
PHONETICALLY_UNAMBIGUOUS_WORDS_PATH = RESOURCES_DIR.joinpath("phonetically_unambiguous_words.json")


Expand Down
1 change: 1 addition & 0 deletions lmentry/mlc_serve_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def create_chat_completion_payload(
"stop": stop_tokens,
"top_p": self.top_p,
"temperature": self.temperature,
"max_tokens": 512,
}

return payload
Expand Down
2 changes: 1 addition & 1 deletion lmentry/predict.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def save_predictions(
predictions_data[id_] = {"input": input_, "prediction": prediction}

with open(output_path, "w") as f_predictions:
json.dump(predictions_data, f_predictions, indent=2)
json.dump(predictions_data, f_predictions, indent=2, ensure_ascii=False)

def generate(
self,
Expand Down
41 changes: 36 additions & 5 deletions lmentry/scorers/scorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,14 @@ def get_shared_patterns(target):
@staticmethod
def get_shared_patterns_ru(target):

delimiter = r"(:|-)"

patterns = [
rf"Ответ {target}",
rf"Правильный ответ {target}",
rf"Ответ: {target}"
rf"Ответ{delimiter} {target}",
rf"Правильный ответ{delimiter} {target}",
rf"Конечно! Вот ответ на ваш вопрос{delimiter} {target}",
rf"Спасибо за вопрос!\n{target}",
rf"С удовольствием!\n{target}"
]
return [p.format(target=target) for p in patterns]

Expand Down Expand Up @@ -195,7 +199,10 @@ def _simple_scorer(self, prediction, answer, allow_answer_pattern_repetitions=Tr
score, certainty = None, None

# return certain 0 if the prediction contains no alphanumeric character
if not re.search(r"[^\W_]", prediction): # we don't consider `_` to be alphanumeric
if not re.search(r"[а-яёА-ЯЁ0-9_]", prediction): # we don't consider `_` to be alphanumeric
return 0, 1

if re.search(r"[a-zA-Z]", prediction): # we don't want to have Latin symbols
return 0, 1

if re.match(rf"{answer}\.?$", prediction, flags=re.IGNORECASE):
Expand All @@ -211,11 +218,35 @@ def _simple_scorer(self, prediction, answer, allow_answer_pattern_repetitions=Tr

return score, certainty

def _simple_scorer_ru(self, prediction, answer, allow_answer_pattern_repetitions=True) -> tuple[int, int]:

score, certainty = None, None
# return certain 0 if the prediction contains no alphanumeric character
if not re.search(r"[а-яёА-ЯЁ0-9_]", prediction): # we don't consider `_` to be alphanumeric
return 0, 1

if re.search(r"[a-zA-Z]", prediction): # we don't want to have Latin symbols
return 0, 1

if re.match(rf"{answer}\.?$", prediction, flags=re.IGNORECASE):
score = 1
certainty = 1

if allow_answer_pattern_repetitions:
alphanumeric_pattern = r"\b[а-я\d]+\b"
all_alphanumeric_words = re.findall(alphanumeric_pattern, prediction)
if all([re.match(answer + "$", word) for word in all_alphanumeric_words]):
score = 1
certainty = 1

return score, certainty

def certainty_scorer(self, prediction, base_patterns):
score, certainty = 0, 0

for i, pattern in enumerate(self.get_patterns(base_patterns)):
for i, pattern in enumerate(base_patterns):
pattern = self.normalize_string(pattern)

if re.match(pattern + r"\.?$", prediction):
score = 1
certainty = 1
Expand Down
Empty file added lmentry/scorers_ru/__init__.py
Empty file.
141 changes: 141 additions & 0 deletions lmentry/scorers_ru/all_words_from_category_scorer_ru.py

Large diffs are not rendered by default.

155 changes: 155 additions & 0 deletions lmentry/scorers_ru/any_words_from_category_scorer_ru.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import json
import re
from pathlib import Path

from lmentry.scorers.scorer import LMentryScorer
from lmentry.scorers_ru.metadata.any_words_from_category.metadata import get_words
from lmentry.scorers_ru.metadata.any_words_from_category.extra_patterns import get_extra_patterns


class AnyWordsFromCategoryScorerRu(LMentryScorer):
def __init__(self):
super().__init__()

def get_base_patterns(self, answer, category, category_word, distractors, words):
punct = r"(,|.)"

category_word = rf'("{category_word}"|{category_word})'

distractors = get_words(distractors)

words = get_words(words)

extra_patterns = get_extra_patterns(category_word, distractors, punct, category, words)

base_patterns = [
rf"{answer}.",
rf"{answer},",
rf"^{answer}\b",
]

base_patterns.extend(extra_patterns)

return base_patterns + self.get_shared_patterns_ru(target=answer)

def category_regex(self, category):
conj = r"(или|и)"

if category == "этнонимы":
category = rf"(этнонимы|этнониму|этнонимом|этнонимов|этнониме|этнонимах|этнонимами|этнонимам|этнонима|этноним)"
elif category == "имена родства":
category = rf"(имя родства|имени родства|именем родства|именах родства|именами родства|именам родства|имена родства|имен родства)"
elif category == "животные":
category = rf"(животных|животными|животным|животные|животному|животном|животное|животного|живых существах|живых существ|живыми существами|живым существом|живым существам|живые существа|живому существу|живом существе|живое существо|живого существа|живых организмов|живых организмах|живыми организмами|живым организмом|живым организмам|живые организмы|живому организму|живом организме|живой организм|живого организма)"
elif category == "растения":
category = rf"(растениях|растениями|растениям|растения|растению|растений|растении|растением|растение)"
elif category == "вещества и материалы":
category = rf"(материалы {conj} вещества|материалы|материалу {conj} веществу|материалу|материалом {conj} веществом|материалом|материалов {conj} веществ|материалов|материале {conj} веществе|материале|материалах {conj} веществах|материалах|материалами {conj} веществами|материалами|материалам {conj} веществам|материалам|материала {conj} вещества|материала|материал {conj} вещество|материал|веществу {conj} материалу|веществу|веществом {conj} материалом|веществом|вещество {conj} материал|вещество|веществе {conj} материале|веществе|веществах {conj} материалах|веществах|веществами {conj} материалами|веществами|веществам {conj} материалам|веществам|вещества {conj} материалы|вещества {conj} материала|вещества|веществ {conj} материалов|веществ)"
elif category == "здания и сооружения":
category = rf"(сооружениях {conj} зданиях|сооружениях|сооружениями {conj} зданиями|сооружениями|сооружениям {conj} зданиям|сооружениям|сооружения {conj} здания|сооружения|сооружению {conj} зданию|сооружению|сооружений {conj} зданий|сооружений|сооружении {conj} здании|сооружении|сооружением {conj} зданием|сооружением|сооружение {conj} здание|сооружение|зданиях {conj} сооружениях|зданиях|зданиями {conj} сооружениями|зданиями|зданиям {conj} сооружениям|зданиям|здания {conj} сооружения|здания|зданию {conj} сооружению|зданию|зданий {conj} сооружений|зданий|здании {conj} сооружении|здании|зданием {conj} сооружением|зданием|здание {conj} сооружение|здание)"
elif category == "механизмы и приборы":
category = rf"(приборы {conj} механизмы|приборы|прибору {conj} механизму|прибору|прибором {conj} механизмом|прибором|приборов {conj} механизмов|приборов|приборе {conj} механизме|приборе|приборах {conj} механизмах|приборах|приборами {conj} механизмами|приборами|приборам {conj} механизмам|приборам|прибора {conj} механизма|прибора|прибор {conj} механизм|прибор|механизмы {conj} приборы|механизмы|механизму {conj} прибору|механизму|механизмом {conj} прибором|механизмом|механизмов {conj} приборов|механизмов|механизме {conj} приборе|механизме|механизмах {conj} приборах|механизмах|механизмами {conj} приборами|механизмами|механизмам {conj} приборам|механизмам|механизма {conj} прибора|механизма|механизм {conj} прибор|механизм)"
elif category == "транспортные средства":
category = rf"(транспорты|транспортом|транспортов|транспортных средствах|транспортных средств|транспортными средствами|транспортным средством|транспортным средствам|транспортные средства|транспортному средству|транспортном средстве|транспортное средство|транспортного средства|транспорте|транспортах|транспортами|транспорта|транспорт)"
elif category == "мебель":
category = rf"(мебелях|мебелями|мебелям|мебелью|мебель|мебели|мебелей)"
elif category == "посуда":
category = rf"(посуды|посуду|посудой|посуде|посудах|посудами|посудам|посуда|посуд)"
elif category == "одежда и обувь":
category = rf"(одежды {conj} обувь|одежды {conj} обуви|одежды|одежду {conj} обувь|одежду|одеждой {conj} обувью|одеждой|одежде {conj} обуви|одежде|одеждах {conj} обуви|одеждах|одеждами {conj} обувью|одеждами|одеждам {conj} обуви|одеждам|одежда {conj} обувь|одежда|одежд {conj} обуви|одежд|обувью {conj} одеждой|обувью {conj} одеждами|обувью|обувь {conj} одежды|обувь {conj} одежду|обувь {conj} одежда|обувь|обуви {conj} одежды|обуви {conj} одежде|обуви {conj} одеждах|обуви {conj} одеждам|обуви {conj} одежд|обуви)"
elif category == "еда и напитки":
category = rf"(напиток {conj} еду|напиток {conj} еда|напиток|напитку {conj} еде|напитку|напитком {conj} едой|напитком|напитков {conj} еды|напитков|напитки {conj} еду|напитки {conj} еда|напитки|напитке {conj} еде|напитке|напитках {conj} еде|напитках|напитками {conj} едой|напитками|напиткам {conj} еде|напиткам|напитка {conj} еды|напитка|еды {conj} напитков|еды {conj} напитка|еды|еду {conj} напиток|еду {conj} напитки|еду|едой {conj} напитком|едой {conj} напитками|едой|еде {conj} напитку|еде {conj} напитке|еде {conj} напитках|еде {conj} напиткам|еде|еда {conj} напиток|еда {conj} напитки|еда)"
elif category == "тексты":
category = rf"(текстовых документов|текстовых материалов|тексты|тексту|текстом|текстов|тексте|текстах|текстами|текстам|текста|текст)"

return category

@staticmethod
def negative_scorer_ru(prediction, answer):
score = None
certainty = None

opposite_answer = "нет" if answer == "да" else "да"
if re.match(rf"{opposite_answer}\.?$", prediction):
score = 0
certainty = 1

return score, certainty

def score_prediction(self, prediction, example, truncate_prediction: bool = False):
prediction = self.normalize_prediction(prediction, truncate_prediction)

metadata = example["metadata"]
cat_word = metadata["distractors"]

if cat_word:
category_word = cat_word[0]
else:
category_word = ''

distractors = metadata["distractors"]

answer = "да" if metadata["num_words"] > metadata["num_distractors"] else "нет"

score, certainty = self.negative_scorer_ru(prediction, answer)
if score is not None:
return score, certainty

score, certainty = self._simple_scorer_ru(prediction, answer)

if score:
return score, certainty

category = metadata["category"]
category = self.category_regex(category)

words = metadata["words"]

base_patterns = self.get_base_patterns(answer, category, category_word, distractors, words)
score, certainty = self.certainty_scorer(prediction, base_patterns)

return score, certainty


if __name__ == "__main__":
task_name = "any_words_from_category_ru"
model_name = "llama2-7b"

predictions_path = Path(__file__).parent.parent.parent / "predictions" / task_name / f"{model_name}.json"
examples_path = Path(__file__).parent.parent.parent / "data_ru" / f"{task_name}.json"

with open(predictions_path, "r", encoding="utf8") as file:
predictions = json.load(file)

predictions_keys = list(predictions.keys())

with open(examples_path, "r", encoding="utf8") as file:
examples = list(json.load(file).values())[1]

scorer = AnyWordsFromCategoryScorerRu()

counter = 0
for key in predictions_keys:
if counter > 0:
break
examples_new = [ex for k, ex in examples.items() if k == key]
pred = scorer.score_prediction(prediction=predictions[key]['prediction'], example=examples_new[0])
print("EXAMPLE:", examples_new[0]["input"], "ANSWER:", predictions[key]['prediction'], "ACC-CERT:", pred)
print()
counter += 1

# prediction = """
# да, все слова из списка относятся к категории "транспортные средства":
#
# * "такси" - такси является транспортным средством.
# * "сани" - "сани" может быть обозначением для саней, которые также являются транспортным средством.
# * "трактор" - трактор является транспортным средством.
# * "рябина" - "рябина" не является транспортным средством и не относится к этой категории.
# * "автобус" - автобус является транспортным средством.
#
# таким образом, все слова из списка относятся к категории "транспортные средства".
# """
#
# pattern = r"нет(,|.) категория (транспорты|транспортом|транспортов|транспортных средствах|транспортных средств|транспортными средствами|транспортным средством|транспортным средствам|транспортные средства|транспортному средству|транспортном средстве|транспортное средство|транспортного средства|транспорте|транспортах|транспортами|транспорта|транспорт) не включает слова (\"рябина\"|рябина)."
#
# print("MATCH:", re.search(pattern, prediction))
Loading