Download source/src/vimeml/benchmarks/ajimee.py from Voltline/vimeml-tiny-ja-v1: direct link, hf CLI and curl.
- Browser
- Download file 6.57 kB
-
https://huggingface.co/Voltline/vimeml-tiny-ja-v1/resolve/main/source/src/vimeml/benchmarks/ajimee.py
- Command line
-
hf download hf://Voltline/vimeml-tiny-ja-v1/source/src/vimeml/benchmarks/ajimee.py
-
curl -L -o ajimee.py https://huggingface.co/Voltline/vimeml-tiny-ja-v1/resolve/main/source/src/vimeml/benchmarks/ajimee.py
6.57 kB
| """Convert a local AJIMEE JSON array to anco input without changing its text.""" | |
| import argparse | |
| import hashlib | |
| import json | |
| from pathlib import Path | |
| ROOT = Path(__file__).resolve().parents[3] | |
| FORMAT = "ajimee_anco_input_v1" | |
| DEVELOPMENT_FORMAT = "ime_development_anco_input_v1" | |
| SOURCE_URL = "https://github.com/azooKey/AJIMEE-Bench/tree/main/JWTD_v2/v1" | |
| def sha(data): | |
| return hashlib.sha256(data).hexdigest() | |
| def convert_items(rows): | |
| if not isinstance(rows, list) or not rows: | |
| raise ValueError("Expected a nonempty AJIMEE JSON array.") | |
| converted, mapping, seen = [], [], set() | |
| for position, row in enumerate(rows): | |
| if not isinstance(row, dict): | |
| raise ValueError(f"Row {position}: expected an object.") | |
| index = row.get("index") | |
| if type(index) not in (str, int) or (isinstance(index, str) and not index.strip()): | |
| raise ValueError(f"Row {position}: missing/invalid index.") | |
| case_id = f"ajimee:{index}" | |
| if case_id in seen: | |
| raise ValueError(f"Row {position}: duplicate index {index!r}.") | |
| seen.add(case_id) | |
| query, context, answers = row.get("input"), row.get("context_text"), row.get("expected_output") | |
| if not isinstance(query, str) or not query.strip(): | |
| raise ValueError(f"Row {position}: input must be a nonempty string.") | |
| if not isinstance(context, str): | |
| raise ValueError(f"Row {position}: context_text must be a string (empty is allowed).") | |
| if not isinstance(answers, list) or not answers or any(not isinstance(answer, str) or not answer.strip() for answer in answers): | |
| raise ValueError(f"Row {position}: expected_output must be a nonempty string array.") | |
| group = "with-context" if context else "without-context" | |
| # Preserve kana, width, punctuation, whitespace, answer order and the | |
| # full input exactly. Neither original_text nor split gold is supplied. | |
| converted.append({"query": query, "answer": list(answers), "tag": [case_id, group], | |
| "left_context": context, "right_context": None}) | |
| mapping.append({"position": position, "id": case_id, "source_index": index, | |
| "query": query, "left_context": context, "answers": list(answers), "group": group}) | |
| stats = {"cases": len(rows), "with_context": sum(bool(row["context_text"]) for row in rows), | |
| "without_context": sum(not row["context_text"] for row in rows), | |
| "multiple_acceptable_outputs": sum(len(row["expected_output"]) > 1 for row in rows), | |
| "has_split_inputs": sum(bool(row.get("splitted_input_for_limited_input_length")) for row in rows)} | |
| return converted, mapping, stats | |
| def json_bytes(value): | |
| return (json.dumps(value, ensure_ascii=False, indent=2) + "\n").encode("utf-8") | |
| def prepare(input_path, output): | |
| input_path, output = Path(input_path).resolve(), Path(output).resolve() | |
| raw = input_path.read_bytes() | |
| converted, mapping, stats = convert_items(json.loads(raw.decode("utf-8-sig"))) | |
| manifest_path = output / "manifest.json" | |
| if manifest_path.exists(): | |
| saved = json.loads(manifest_path.read_text(encoding="utf-8")) | |
| if saved.get("format") != FORMAT or saved.get("source_sha256") != sha(raw): | |
| raise ValueError("Output belongs to different input/version. Choose a new --output directory.") | |
| for name, digest in saved["files_sha256"].items(): | |
| if sha((output / name).read_bytes()) != digest: | |
| raise ValueError(f"Prepared file changed: {name}. Choose a new --output directory.") | |
| return saved["stats"] | |
| if output.exists() and any(output.iterdir()): | |
| raise ValueError("Output is not empty. Choose a new --output directory.") | |
| notice = ( | |
| "# AJIMEE-Bench provenance\n\n" | |
| f"Source: {SOURCE_URL}\n\n" | |
| "Dataset: JWTD_v2/v1, based on Japanese Wikipedia Typo Dataset v2.\n" | |
| "Upstream dataset license: CC-BY-SA 3.0. Preserve attribution and share-alike terms.\n" | |
| "License: https://creativecommons.org/licenses/by-sa/3.0/\n\n" | |
| "evaluation_items.json is the supplied local source, preserved byte for byte.\n" | |
| "Its exact upstream commit has not been verified; source SHA256 is in manifest.json.\n" | |
| "ajimee-input.json maps input/context_text/expected_output to query/left_context/answer.\n" | |
| "No text normalization, splitting, filtering or answer injection into context.\n" | |
| "original_text remains in the source snapshot and is excluded from anco input.\n" | |
| "For evaluation only; do not add these files to the training corpus.\n" | |
| ).encode("utf-8") | |
| files = {"evaluation_items.json": raw, "ajimee-input.json": json_bytes(converted), | |
| "case-map.json": json_bytes(mapping), "NOTICE.md": notice} | |
| output.mkdir(parents=True, exist_ok=True) | |
| for name, content in files.items(): | |
| path = output / name | |
| temporary = path.with_suffix(path.suffix + ".tmp") | |
| temporary.write_bytes(content) | |
| temporary.replace(path) | |
| manifest = {"format": FORMAT, "status": "complete", "source_path": str(input_path), | |
| "source_url": SOURCE_URL, "source_sha256": sha(raw), "upstream_commit_verified": False, | |
| "license": "CC-BY-SA-3.0", "stats": stats, | |
| "files_sha256": {name: sha(content) for name, content in files.items()}, | |
| "policy": "Unmodified full queries and all references; supplied left context only; right context null. Mapping positions are zero-based."} | |
| temporary = manifest_path.with_suffix(".json.tmp") | |
| temporary.write_bytes(json_bytes(manifest)) | |
| temporary.replace(manifest_path) | |
| return stats | |
| def main(argv=None): | |
| parser = argparse.ArgumentParser(description=__doc__) | |
| parser.add_argument("--input", required=True, type=Path, help="Downloaded evaluation_items.json path.") | |
| parser.add_argument("--output", type=Path, default=ROOT / "artifacts/benchmarks/ajimee-jwtd-v2-v1", | |
| help="Directory for anco input, source snapshot, case mapping and manifest.") | |
| args = parser.parse_args(argv) | |
| try: | |
| stats = prepare(args.input, args.output) | |
| except (OSError, ValueError) as error: | |
| parser.exit(2, f"Error: {error}\n") | |
| print(json.dumps(stats, ensure_ascii=False, indent=2)) | |
| print(f"Anco input: {args.output.resolve() / 'ajimee-input.json'}") | |
| print(f"Case map: {args.output.resolve() / 'case-map.json'}") | |
| if __name__ == "__main__": | |
| main() | |