Download script.py from rita-cohere/tiny-aya-reasoning-sft-long: direct link, hf CLI and curl.
- Browser
- Download file 8.31 kB
-
https://huggingface.co/rita-cohere/tiny-aya-reasoning-sft-long/resolve/main/script.py
- Command line
-
hf download hf://rita-cohere/tiny-aya-reasoning-sft-long/script.py
-
curl -L -o script.py https://huggingface.co/rita-cohere/tiny-aya-reasoning-sft-long/resolve/main/script.py
8.31 kB
| """IOL-AI 2026 β notebook decode (prompt + force-close + T=0.6). | |
| Matches linguini-test-iolai.ipynb cells 4β5: | |
| - USER_INSTRUCTIONS (+ COT + /think) | |
| - think 2048 @ T=0.6; force <|END_THINKING|><|START_RESPONSE|> | |
| - answer 512 @ T=0.6 | |
| - marker-gated FINAL ANSWERS: parser | |
| """ | |
| from __future__ import annotations | |
| import os | |
| import subprocess | |
| import sys | |
| def _install_bundled_deps() -> None: | |
| wheels_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "wheels") | |
| if not os.path.isdir(wheels_dir): | |
| return | |
| subprocess.run( | |
| [ | |
| sys.executable, | |
| "-m", | |
| "pip", | |
| "install", | |
| "-q", | |
| "--no-index", | |
| f"--find-links={wheels_dir}", | |
| "transformers==4.56.2", | |
| ], | |
| check=True, | |
| ) | |
| _install_bundled_deps() | |
| os.environ["HF_HUB_OFFLINE"] = "1" | |
| os.environ["TRANSFORMERS_OFFLINE"] = "1" | |
| MODEL_ID = "." | |
| import json | |
| import re | |
| import pandas as pd | |
| import torch | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| SYSTEM = "" | |
| USER_INSTRUCTIONS = """You solve International Linguistics Olympiad (IOL) problems from the data you are given. | |
| You may see a task type you have never seen: follow the instruction and examples, and answer in the same form they use. | |
| What to return by task type: | |
| - translation: only the required form in the language the query asks for β do not add extra glosses or "form | meaning" unless asked | |
| - fill_blanks: only the missing form for each blank β no extra glosses | |
| - match_letters: ONLY the option letter (A, B, C, β¦), one letter per line β never copy option text, never arrows, never "A. word" | |
| - text_to_num: the number in digits only | |
| - num_to_text: the number written out in words, in the language asked | |
| - kinship / sentence matching: the full required sentence or form β NOT roman numerals (i, ii, iii) and NOT an alphabet dump | |
| - any other type: exactly what the instruction asks for, nothing else | |
| Answer in the language and form the query asks for. Do not add glosses, translations, or explanations unless the instruction requires them. | |
| Output rules: | |
| - Put answers ONLY after a line that says exactly: FINAL ANSWERS: | |
| - Never put answers before that marker. | |
| - One answer per line; exactly as many lines as items asked in the query. | |
| - Bare answers only: no numbering, no quotes, no commentary, no repeating the question. | |
| Extra hard rules: | |
| - Never refuse or apologize; always output FINAL ANSWERS: with your best guess. | |
| - For match_letters: only bare letters (A, B, C, β¦) β never dump the alphabet (A B C D E Fβ¦), never option text. | |
| - Never append tags or glosses: no "_GCY", "_NS", "form β meaning", "word - gloss", or markdown bold. | |
| - Never write an essay or explanation of how the language works under FINAL ANSWERS: β only the answer strings. | |
| - If the query asks for colour/color forms, output those forms only (one per line), not a linguistics write-up. | |
| - Emit exactly as many answer lines as items asked β no more, no fewer.""" | |
| USER_INSTRUCTIONS_COT = ( | |
| USER_INSTRUCTIONS | |
| + "\n\nThink step by step about the rules in the examples and how they apply to the query, " | |
| "then write FINAL ANSWERS: and the answer lines." | |
| ) | |
| APPEND_THINK = True | |
| THINK_BUDGET = 2048 | |
| ANSWER_BUDGET = 512 | |
| TEMPERATURE = 0.6 | |
| def build_user(context, query): | |
| instructions = USER_INSTRUCTIONS_COT if APPEND_THINK else USER_INSTRUCTIONS | |
| parts = [instructions.strip(), "", context.strip(), "", query.strip()] | |
| if APPEND_THINK: | |
| parts.append("/think") | |
| return "\n".join(parts) | |
| _SPECIAL = re.compile( | |
| r"<\|START_RESPONSE\|>|<\|END_RESPONSE\|>|" | |
| r"<\|/?END_OF_TURN_TOKEN\|>|<\|/?START_OF_TURN_TOKEN\|>|" | |
| r"<\|CHATBOT_TOKEN\|>|<\|/?START_THINKING\|>|<\|/?END_THINKING\|>|" | |
| r"<EOS_TOKEN>|<BOS_TOKEN>|<PAD>" | |
| ) | |
| _MARKER = re.compile(r"(?im)\bfinal\s+answers?\b\s*:?\s*") | |
| _TURN_NOISE = re.compile( | |
| r"<\|/?END_OF_TURN_TOKEN\|>|<\|/?START_OF_TURN_TOKEN\|>|" | |
| r"<\|CHATBOT_TOKEN\|>|<EOS_TOKEN>|<BOS_TOKEN>" | |
| ) | |
| def _lines_after(region: str) -> list[str]: | |
| answers = [] | |
| for line in region.splitlines(): | |
| line = _SPECIAL.sub("", line) | |
| line = re.sub(r"^\s*(?:\(?\d+[.)]|[-*β’])\s*", "", line).strip() | |
| if not line: | |
| if answers: | |
| break | |
| continue | |
| if re.fullmatch(r"(?i)final\s+answers?\s*:?", line): | |
| continue | |
| if answers and ( | |
| len(line) > 120 | |
| or line.lower().startswith(("however", "but the", "to solve", "### ", "**")) | |
| ): | |
| break | |
| answers.append(line) | |
| return answers | |
| def parse_answers(text: str) -> list[str]: | |
| raw = text | |
| def _from_region(region: str) -> list[str] | None: | |
| markers = list(_MARKER.finditer(region)) | |
| if not markers: | |
| return None | |
| for m in reversed(markers): | |
| answers = _lines_after(region[m.end() :]) | |
| if answers: | |
| return answers | |
| return [] | |
| region = raw | |
| if "<|END_THINKING|>" in region: | |
| region = region.rsplit("<|END_THINKING|>", 1)[-1] | |
| blocks = re.findall( | |
| r"<\|START_RESPONSE\|>(.*?)<\|END_RESPONSE\|>", region, flags=re.S | |
| ) | |
| if blocks: | |
| region = blocks[-1] | |
| found = _from_region(region) | |
| if found is not None: | |
| return found | |
| found = _from_region(raw) | |
| if found is not None: | |
| return found | |
| return [] | |
| def _build_prompt(tok, system: str, user: str): | |
| messages = [] | |
| if system.strip(): | |
| messages.append({"role": "system", "content": system}) | |
| messages.append({"role": "user", "content": user}) | |
| try: | |
| return tok.apply_chat_template( | |
| messages, | |
| add_generation_prompt=True, | |
| return_tensors="pt", | |
| return_dict=True, | |
| reasoning_options={"enabled": True}, | |
| ) | |
| except TypeError: | |
| ids = tok.apply_chat_template( | |
| messages, add_generation_prompt=True, return_tensors="pt" | |
| ) | |
| return {"input_ids": ids, "attention_mask": torch.ones_like(ids)} | |
| def generate_with_budgets(model, tok, enc): | |
| device = next(model.parameters()).device | |
| enc = {k: v.to(device) if hasattr(v, "to") else v for k, v in enc.items()} | |
| prompt_len = enc["input_ids"].shape[-1] | |
| pad_id = tok.pad_token_id or tok.eos_token_id | |
| end_ids = tok.encode("<|END_THINKING|>", add_special_tokens=False) | |
| start_ids = tok.encode("<|START_RESPONSE|>", add_special_tokens=False) | |
| out = model.generate( | |
| **enc, | |
| max_new_tokens=THINK_BUDGET, | |
| do_sample=True, | |
| temperature=TEMPERATURE, | |
| eos_token_id=tok.eos_token_id, | |
| pad_token_id=pad_id, | |
| ) | |
| gen = out[0] | |
| new_ids = gen[prompt_len:].tolist() | |
| forced = False | |
| finished = bool(new_ids) and new_ids[-1] == tok.eos_token_id | |
| if end_ids[0] not in new_ids: | |
| forced = True | |
| cont = torch.tensor( | |
| end_ids + start_ids, device=gen.device, dtype=gen.dtype | |
| ) | |
| gen = torch.cat([gen, cont], dim=0) | |
| finished = False | |
| if not finished: | |
| ids = gen.unsqueeze(0) | |
| out2 = model.generate( | |
| input_ids=ids, | |
| attention_mask=torch.ones_like(ids), | |
| max_new_tokens=ANSWER_BUDGET, | |
| do_sample=True, | |
| temperature=TEMPERATURE, | |
| eos_token_id=tok.eos_token_id, | |
| pad_token_id=pad_id, | |
| ) | |
| gen = out2[0] | |
| text = tok.decode(gen[prompt_len:], skip_special_tokens=False).strip() | |
| return _TURN_NOISE.sub("", text).strip(), forced | |
| tok = AutoTokenizer.from_pretrained(MODEL_ID) | |
| model = AutoModelForCausalLM.from_pretrained( | |
| MODEL_ID, torch_dtype=torch.float16, device_map="auto" | |
| ).eval() | |
| df = pd.read_csv("/tmp/data/test.csv", dtype=str).fillna("") | |
| rows = [] | |
| for i, r in df.iterrows(): | |
| user = build_user(r["context"], r["query"]) | |
| enc = _build_prompt(tok, SYSTEM, user) | |
| text, forced = generate_with_budgets(model, tok, enc) | |
| answers = parse_answers(text) | |
| rows.append({"id": r["id"], "pred": json.dumps(answers, ensure_ascii=False)}) | |
| pd.DataFrame(rows).to_csv("submission.csv", index=False) | |
| print(f"[{i + 1}/{len(df)}] n={len(answers)} forced={forced}", flush=True) | |
| print("wrote submission.csv", flush=True) | |