retrieval
This commit is contained in:
parent
d6d02fef4d
commit
2871bc853a
@ -46,6 +46,11 @@ EVALUATION_MODES = (
|
|||||||
"hybrid",
|
"hybrid",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
VALID_SPLITS = (
|
||||||
|
"dev",
|
||||||
|
"test",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def load_questions(
|
def load_questions(
|
||||||
path: Path,
|
path: Path,
|
||||||
@ -75,6 +80,8 @@ def load_questions(
|
|||||||
dict[str, Any]
|
dict[str, Any]
|
||||||
] = []
|
] = []
|
||||||
|
|
||||||
|
seen_ids: set[str] = set()
|
||||||
|
|
||||||
for index, item in enumerate(
|
for index, item in enumerate(
|
||||||
data,
|
data,
|
||||||
start=1,
|
start=1,
|
||||||
@ -96,6 +103,10 @@ def load_questions(
|
|||||||
"question"
|
"question"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
split = item.get(
|
||||||
|
"split"
|
||||||
|
)
|
||||||
|
|
||||||
expected_documents = item.get(
|
expected_documents = item.get(
|
||||||
"expected_documents"
|
"expected_documents"
|
||||||
)
|
)
|
||||||
@ -111,6 +122,15 @@ def load_questions(
|
|||||||
f"Položka {index} nemá platné id"
|
f"Položka {index} nemá platné id"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if question_id in seen_ids:
|
||||||
|
raise ValueError(
|
||||||
|
f"Dataset obsahuje duplicitné id: {question_id}"
|
||||||
|
)
|
||||||
|
|
||||||
|
seen_ids.add(
|
||||||
|
question_id
|
||||||
|
)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
not isinstance(
|
not isinstance(
|
||||||
question,
|
question,
|
||||||
@ -122,6 +142,12 @@ def load_questions(
|
|||||||
f"{question_id}: chýba otázka"
|
f"{question_id}: chýba otázka"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if split not in VALID_SPLITS:
|
||||||
|
raise ValueError(
|
||||||
|
f"{question_id}: split musí byť "
|
||||||
|
"'dev' alebo 'test'"
|
||||||
|
)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
not isinstance(
|
not isinstance(
|
||||||
expected_documents,
|
expected_documents,
|
||||||
@ -153,6 +179,45 @@ def load_questions(
|
|||||||
return questions
|
return questions
|
||||||
|
|
||||||
|
|
||||||
|
def filter_questions_by_split(
|
||||||
|
questions: list[
|
||||||
|
dict[str, Any]
|
||||||
|
],
|
||||||
|
split: str,
|
||||||
|
) -> list[dict[str, Any]]:
|
||||||
|
if split == "all":
|
||||||
|
return questions
|
||||||
|
|
||||||
|
return [
|
||||||
|
item
|
||||||
|
for item in questions
|
||||||
|
if item.get("split") == split
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def count_splits(
|
||||||
|
questions: list[
|
||||||
|
dict[str, Any]
|
||||||
|
],
|
||||||
|
) -> dict[str, int]:
|
||||||
|
counts = {
|
||||||
|
"dev": 0,
|
||||||
|
"test": 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
for item in questions:
|
||||||
|
split = item.get(
|
||||||
|
"split"
|
||||||
|
)
|
||||||
|
|
||||||
|
if split in counts:
|
||||||
|
counts[
|
||||||
|
split
|
||||||
|
] += 1
|
||||||
|
|
||||||
|
return counts
|
||||||
|
|
||||||
|
|
||||||
def load_index_document_paths(
|
def load_index_document_paths(
|
||||||
db_file: Path,
|
db_file: Path,
|
||||||
) -> set[str]:
|
) -> set[str]:
|
||||||
@ -497,11 +562,20 @@ def evaluate_question_mode(
|
|||||||
)
|
)
|
||||||
|
|
||||||
row: dict[str, Any] = {
|
row: dict[str, Any] = {
|
||||||
"id": question["id"],
|
"id": question[
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"split": question.get(
|
||||||
|
"split"
|
||||||
|
),
|
||||||
"category": question.get(
|
"category": question.get(
|
||||||
"category",
|
"category",
|
||||||
"unknown",
|
"unknown",
|
||||||
),
|
),
|
||||||
|
"difficulty": question.get(
|
||||||
|
"difficulty",
|
||||||
|
"unknown",
|
||||||
|
),
|
||||||
"question": question[
|
"question": question[
|
||||||
"question"
|
"question"
|
||||||
],
|
],
|
||||||
@ -515,7 +589,9 @@ def evaluate_question_mode(
|
|||||||
6,
|
6,
|
||||||
),
|
),
|
||||||
"top_documents": [
|
"top_documents": [
|
||||||
item["document_path"]
|
item[
|
||||||
|
"document_path"
|
||||||
|
]
|
||||||
for item in ranked_documents
|
for item in ranked_documents
|
||||||
],
|
],
|
||||||
"top_source_urls": [
|
"top_source_urls": [
|
||||||
@ -695,11 +771,57 @@ def aggregate_by_category(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def aggregate_by_difficulty(
|
||||||
|
rows: list[
|
||||||
|
dict[str, Any]
|
||||||
|
],
|
||||||
|
) -> dict[
|
||||||
|
str,
|
||||||
|
dict[str, Any],
|
||||||
|
]:
|
||||||
|
grouped: dict[
|
||||||
|
str,
|
||||||
|
list[dict[str, Any]],
|
||||||
|
] = defaultdict(
|
||||||
|
list
|
||||||
|
)
|
||||||
|
|
||||||
|
for row in rows:
|
||||||
|
difficulty = str(
|
||||||
|
row.get(
|
||||||
|
"difficulty",
|
||||||
|
"unknown",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
grouped[
|
||||||
|
difficulty
|
||||||
|
].append(
|
||||||
|
row
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
difficulty: aggregate_metrics(
|
||||||
|
difficulty_rows
|
||||||
|
)
|
||||||
|
for (
|
||||||
|
difficulty,
|
||||||
|
difficulty_rows,
|
||||||
|
) in sorted(
|
||||||
|
grouped.items()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def print_summary(
|
def print_summary(
|
||||||
summary: dict[
|
summary: dict[
|
||||||
str,
|
str,
|
||||||
dict[str, Any],
|
dict[str, Any],
|
||||||
],
|
],
|
||||||
|
*,
|
||||||
|
split: str,
|
||||||
|
selected_count: int,
|
||||||
|
total_count: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
print()
|
print()
|
||||||
print(
|
print(
|
||||||
@ -709,6 +831,19 @@ def print_summary(
|
|||||||
"=" * 78
|
"=" * 78
|
||||||
)
|
)
|
||||||
|
|
||||||
|
print(
|
||||||
|
f"Split: {split}"
|
||||||
|
)
|
||||||
|
|
||||||
|
print(
|
||||||
|
f"Questions: "
|
||||||
|
f"{selected_count}/{total_count}"
|
||||||
|
)
|
||||||
|
|
||||||
|
print(
|
||||||
|
"-" * 78
|
||||||
|
)
|
||||||
|
|
||||||
header = (
|
header = (
|
||||||
f"{'Mode':<10}"
|
f"{'Mode':<10}"
|
||||||
f"{'Questions':>10}"
|
f"{'Questions':>10}"
|
||||||
@ -786,7 +921,9 @@ def save_csv_results(
|
|||||||
|
|
||||||
fieldnames = [
|
fieldnames = [
|
||||||
"id",
|
"id",
|
||||||
|
"split",
|
||||||
"category",
|
"category",
|
||||||
|
"difficulty",
|
||||||
"mode",
|
"mode",
|
||||||
"question",
|
"question",
|
||||||
"first_relevant_rank",
|
"first_relevant_rank",
|
||||||
@ -887,6 +1024,23 @@ def parse_args() -> argparse.Namespace:
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"--split",
|
||||||
|
choices=(
|
||||||
|
"dev",
|
||||||
|
"test",
|
||||||
|
"all",
|
||||||
|
),
|
||||||
|
default="dev",
|
||||||
|
help=(
|
||||||
|
"Časť datasetu: "
|
||||||
|
"dev = ladenie, "
|
||||||
|
"test = finálne hodnotenie, "
|
||||||
|
"all = celý dataset. "
|
||||||
|
"Predvolené je dev."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--limit",
|
"--limit",
|
||||||
type=int,
|
type=int,
|
||||||
@ -943,10 +1097,60 @@ def parse_args() -> argparse.Namespace:
|
|||||||
def main() -> None:
|
def main() -> None:
|
||||||
args = parse_args()
|
args = parse_args()
|
||||||
|
|
||||||
questions = load_questions(
|
all_questions = load_questions(
|
||||||
args.questions
|
args.questions
|
||||||
)
|
)
|
||||||
|
|
||||||
|
split_counts = count_splits(
|
||||||
|
all_questions
|
||||||
|
)
|
||||||
|
|
||||||
|
questions = (
|
||||||
|
filter_questions_by_split(
|
||||||
|
all_questions,
|
||||||
|
args.split,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if not questions:
|
||||||
|
raise RuntimeError(
|
||||||
|
f"Pre split '{args.split}' "
|
||||||
|
"sa nenašli žiadne otázky."
|
||||||
|
)
|
||||||
|
|
||||||
|
print()
|
||||||
|
print(
|
||||||
|
"Dataset"
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
"=" * 60
|
||||||
|
)
|
||||||
|
|
||||||
|
print(
|
||||||
|
f"Total: {len(all_questions)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
print(
|
||||||
|
f"Dev: {split_counts['dev']}"
|
||||||
|
)
|
||||||
|
|
||||||
|
print(
|
||||||
|
f"Test: {split_counts['test']}"
|
||||||
|
)
|
||||||
|
|
||||||
|
print(
|
||||||
|
f"Selected split: {args.split}"
|
||||||
|
)
|
||||||
|
|
||||||
|
print(
|
||||||
|
f"Selected questions: {len(questions)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
print(
|
||||||
|
"=" * 60
|
||||||
|
)
|
||||||
|
print()
|
||||||
|
|
||||||
indexed_documents = (
|
indexed_documents = (
|
||||||
load_index_document_paths(
|
load_index_document_paths(
|
||||||
args.db
|
args.db
|
||||||
@ -994,7 +1198,7 @@ def main() -> None:
|
|||||||
start=1,
|
start=1,
|
||||||
):
|
):
|
||||||
print(
|
print(
|
||||||
f"[{index:02d}/{total:02d}] "
|
f"[{index:04d}/{total:04d}] "
|
||||||
f"{question['id']}: "
|
f"{question['id']}: "
|
||||||
f"{question['question']}"
|
f"{question['question']}"
|
||||||
)
|
)
|
||||||
@ -1002,7 +1206,9 @@ def main() -> None:
|
|||||||
mode_results = (
|
mode_results = (
|
||||||
retrieve_all_modes(
|
retrieve_all_modes(
|
||||||
args.db,
|
args.db,
|
||||||
question["question"],
|
question[
|
||||||
|
"question"
|
||||||
|
],
|
||||||
limit=args.limit,
|
limit=args.limit,
|
||||||
published_only=(
|
published_only=(
|
||||||
args.published_only
|
args.published_only
|
||||||
@ -1037,11 +1243,21 @@ def main() -> None:
|
|||||||
],
|
],
|
||||||
] = {}
|
] = {}
|
||||||
|
|
||||||
|
by_difficulty: dict[
|
||||||
|
str,
|
||||||
|
dict[
|
||||||
|
str,
|
||||||
|
dict[str, Any],
|
||||||
|
],
|
||||||
|
] = {}
|
||||||
|
|
||||||
for mode in EVALUATION_MODES:
|
for mode in EVALUATION_MODES:
|
||||||
mode_rows = [
|
mode_rows = [
|
||||||
row
|
row
|
||||||
for row in evaluation_rows
|
for row in evaluation_rows
|
||||||
if row["mode"] == mode
|
if row[
|
||||||
|
"mode"
|
||||||
|
] == mode
|
||||||
]
|
]
|
||||||
|
|
||||||
summary[
|
summary[
|
||||||
@ -1056,6 +1272,12 @@ def main() -> None:
|
|||||||
mode_rows
|
mode_rows
|
||||||
)
|
)
|
||||||
|
|
||||||
|
by_difficulty[
|
||||||
|
mode
|
||||||
|
] = aggregate_by_difficulty(
|
||||||
|
mode_rows
|
||||||
|
)
|
||||||
|
|
||||||
payload = {
|
payload = {
|
||||||
"configuration": {
|
"configuration": {
|
||||||
"questions_file": str(
|
"questions_file": str(
|
||||||
@ -1064,9 +1286,25 @@ def main() -> None:
|
|||||||
"database": str(
|
"database": str(
|
||||||
args.db
|
args.db
|
||||||
),
|
),
|
||||||
"question_count": len(
|
"split": (
|
||||||
|
args.split
|
||||||
|
),
|
||||||
|
"dataset_question_count": len(
|
||||||
|
all_questions
|
||||||
|
),
|
||||||
|
"selected_question_count": len(
|
||||||
questions
|
questions
|
||||||
),
|
),
|
||||||
|
"dev_question_count": (
|
||||||
|
split_counts[
|
||||||
|
"dev"
|
||||||
|
]
|
||||||
|
),
|
||||||
|
"test_question_count": (
|
||||||
|
split_counts[
|
||||||
|
"test"
|
||||||
|
]
|
||||||
|
),
|
||||||
"limit": args.limit,
|
"limit": args.limit,
|
||||||
"published_only": (
|
"published_only": (
|
||||||
args.published_only
|
args.published_only
|
||||||
@ -1097,18 +1335,35 @@ def main() -> None:
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
"summary": summary,
|
"summary": summary,
|
||||||
"by_category": by_category,
|
"by_category": (
|
||||||
"questions": evaluation_rows,
|
by_category
|
||||||
|
),
|
||||||
|
"by_difficulty": (
|
||||||
|
by_difficulty
|
||||||
|
),
|
||||||
|
"questions": (
|
||||||
|
evaluation_rows
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filename_suffix = (
|
||||||
|
args.split
|
||||||
|
)
|
||||||
|
|
||||||
json_path = (
|
json_path = (
|
||||||
args.output_dir
|
args.output_dir
|
||||||
/ "retrieval_results.json"
|
/ (
|
||||||
|
"retrieval_results_"
|
||||||
|
f"{filename_suffix}.json"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
csv_path = (
|
csv_path = (
|
||||||
args.output_dir
|
args.output_dir
|
||||||
/ "retrieval_results.csv"
|
/ (
|
||||||
|
"retrieval_results_"
|
||||||
|
f"{filename_suffix}.csv"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
save_json_results(
|
save_json_results(
|
||||||
@ -1122,15 +1377,24 @@ def main() -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
print_summary(
|
print_summary(
|
||||||
summary
|
summary,
|
||||||
|
split=args.split,
|
||||||
|
selected_count=len(
|
||||||
|
questions
|
||||||
|
),
|
||||||
|
total_count=len(
|
||||||
|
all_questions
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
print(
|
print(
|
||||||
"Výsledky:"
|
"Výsledky:"
|
||||||
)
|
)
|
||||||
|
|
||||||
print(
|
print(
|
||||||
f" JSON: {json_path}"
|
f" JSON: {json_path}"
|
||||||
)
|
)
|
||||||
|
|
||||||
print(
|
print(
|
||||||
f" CSV: {csv_path}"
|
f" CSV: {csv_path}"
|
||||||
)
|
)
|
||||||
|
|||||||
1179
scripts/search_core.py
Normal file
1179
scripts/search_core.py
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user