Text Generation
Transformers
Safetensors
English
qwen2
chat
conversational
text-generation-inference
4-bit precision
awq
Instructions to use DanielTobi0/iol-ai-2026 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use DanielTobi0/iol-ai-2026 with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="DanielTobi0/iol-ai-2026") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("DanielTobi0/iol-ai-2026") model = AutoModelForCausalLM.from_pretrained("DanielTobi0/iol-ai-2026", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=40) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use DanielTobi0/iol-ai-2026 with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "DanielTobi0/iol-ai-2026" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "DanielTobi0/iol-ai-2026", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/DanielTobi0/iol-ai-2026
- SGLang
How to use DanielTobi0/iol-ai-2026 with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "DanielTobi0/iol-ai-2026" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "DanielTobi0/iol-ai-2026", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "DanielTobi0/iol-ai-2026" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "DanielTobi0/iol-ai-2026", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use DanielTobi0/iol-ai-2026 with Docker Model Runner:
docker model run hf.co/DanielTobi0/iol-ai-2026
| """IOL-AI 2026 submission script. | |
| Runs inside the competition sandbox (T4, 16 GB, no internet, 30 min limit). The | |
| submission repo is the working directory, so the model weights ship alongside this | |
| file and load from ".". The hidden test set is mounted at /tmp/data/test.csv; we | |
| write submission.csv with one row per problem id. | |
| Model: Qwen2.5-14B-Instruct-AWQ (Apache-2.0), 4-bit AWQ so it fits the T4's 16 GB. | |
| Single-pass prompt: one generation yields both the answers (FINAL ANSWERS block) and | |
| a short human-readable explanation (EXPLANATION block, for the human-eval track). | |
| """ | |
| import os | |
| # The sandbox has no network and the token is revoked before we run: force offline so | |
| # transformers/hf_hub never try to reach the Hub (which would error). | |
| os.environ["HF_HUB_OFFLINE"] = "1" | |
| os.environ["TRANSFORMERS_OFFLINE"] = "1" | |
| os.environ.setdefault("TOKENIZERS_PARALLELISM", "false") | |
| import csv | |
| import json | |
| import re | |
| import time | |
| # Heavy deps (pandas / torch / transformers) are imported lazily inside the functions | |
| # that use them, so the pure-function helpers below can be unit-tested without a GPU | |
| # or those packages installed. | |
| # ---------------------------------------------------------------------------------- | |
| # Config / timing | |
| # ---------------------------------------------------------------------------------- | |
| MODEL_ID = "." # weights ship in this repo | |
| MAX_NEW_TOKENS = 1024 # room to reason; lower = faster/safer on the time limit | |
| TEST_CSV = "/tmp/data/test.csv" | |
| OUT_CSV = "submission.csv" | |
| TIME_LIMIT = 30 * 60 # platform's TIME_LIMIT | |
| SAFETY = 150 # reserve time to always write the CSV before we're killed | |
| START = time.time() | |
| DEADLINE = START + TIME_LIMIT - SAFETY | |
| # ---------------------------------------------------------------------------------- | |
| # Prompt | |
| # ---------------------------------------------------------------------------------- | |
| SYSTEM = ( | |
| "You solve International Linguistics Olympiad problems by reasoning from the data " | |
| "you are given. Everything you need is in the problem; no outside knowledge of the " | |
| "language is required. You may meet a task type you have never seen: read the " | |
| "instruction and the examples, and answer in the same form they use. " | |
| "Common task types and what to give -- " | |
| "translation: the translated form only, in the language the task asks for; " | |
| "fill_blanks: only the missing form for each blank; " | |
| "match_letters: only the option letter (for example A, B, C); " | |
| "text_to_num: the number in digits; " | |
| "num_to_text: the number written out in words, in the language asked; " | |
| "any other type: give exactly what the instruction asks, nothing else.\n\n" | |
| "Reason step by step first. Then write a line that says exactly:\n" | |
| "FINAL ANSWERS:\n" | |
| "and below it one answer per line, in the order the items are asked -- the bare " | |
| "answer only, no numbering, no quotes, no extra text. Give your best guess for " | |
| "every item; never leave one blank.\n" | |
| "Then write a line that says exactly:\n" | |
| "EXPLANATION:\n" | |
| "and below it a SHORT explanation for a human judge (a few bullet points or a small " | |
| "table): the rule or pattern you found and the key evidence for your answers. Be " | |
| "concise and structured -- do not repeat the full reasoning." | |
| ) | |
| # ---------------------------------------------------------------------------------- | |
| # Pure-function helpers (unit-tested in test_logic.py, no GPU needed) | |
| # ---------------------------------------------------------------------------------- | |
| _ANSWERS_MARKER = re.compile(r"(?im)^\s*final\s+answers?\s*:?\s*$") | |
| _EXPL_MARKER = re.compile(r"(?im)^\s*explanation\s*:?\s*$") | |
| # Numbered items at the start of a line: "1.", "2)", "17." (translation, number tasks). | |
| _LINE_ITEM = re.compile(r"(?m)^\s*(\d+)\s*[.)]") | |
| # Parenthesized blanks anywhere on a line: "... | (1) | ..." (fill_blanks tables). | |
| _PAREN_ITEM = re.compile(r"\((\d+)\)") | |
| _LEADING_NUM = re.compile(r"^\s*\(?\d+\)?\s*[.)]\s*") | |
| def count_items(query): | |
| """Number of numbered items in the query. Handles both line-start numbering | |
| ("1." / "2)") and inline parenthesized blanks ("(1)", used by fill_blanks). Returns | |
| 0 when neither is found (e.g. matching queries whose items live in the context) so | |
| the caller falls back to trusting the model's own answer count.""" | |
| q = query or "" | |
| line_items = _LINE_ITEM.findall(q) | |
| if line_items: | |
| return len(line_items) | |
| return len(_PAREN_ITEM.findall(q)) | |
| def _clean(line): | |
| """Strip a leading '1. '/'2) '/'(3) ' and surrounding quotes/whitespace.""" | |
| line = _LEADING_NUM.sub("", line.strip()) | |
| line = line.strip().strip('"').strip("'").strip() | |
| return line | |
| def parse_answers(text): | |
| """Answers = lines after the LAST 'FINAL ANSWERS:' marker, up to 'EXPLANATION:'. | |
| Falls back to the non-empty lines of the whole text (minus the explanation) when | |
| no marker is present.""" | |
| ans_markers = list(_ANSWERS_MARKER.finditer(text)) | |
| expl_markers = list(_EXPL_MARKER.finditer(text)) | |
| expl_start = expl_markers[-1].start() if expl_markers else len(text) | |
| if ans_markers: | |
| segment = text[ans_markers[-1].end():expl_start] | |
| else: | |
| # No marker: use everything before the explanation block as a best effort. | |
| segment = text[:expl_start] | |
| out = [] | |
| for line in segment.splitlines(): | |
| cleaned = _clean(line) | |
| if cleaned: | |
| out.append(cleaned) | |
| return out | |
| def parse_explanation(text): | |
| """Explanation = text after the LAST 'EXPLANATION:' marker ('' if absent).""" | |
| expl_markers = list(_EXPL_MARKER.finditer(text)) | |
| if not expl_markers: | |
| return "" | |
| return text[expl_markers[-1].end():].strip() | |
| def align(preds, n_items): | |
| """Line up predictions with the reference by position: exactly n_items entries, | |
| padding short lists with '' and truncating long ones. When n_items is unknown | |
| (0) we keep the model's list as-is.""" | |
| if n_items <= 0: | |
| return preds | |
| return (preds + [""] * n_items)[:n_items] | |
| # ---------------------------------------------------------------------------------- | |
| # Model | |
| # ---------------------------------------------------------------------------------- | |
| def load_model(): | |
| import torch | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| tok = AutoTokenizer.from_pretrained(MODEL_ID) | |
| model = AutoModelForCausalLM.from_pretrained( | |
| MODEL_ID, torch_dtype=torch.float16, device_map="auto", | |
| ).eval() | |
| if tok.pad_token_id is None: | |
| tok.pad_token = tok.eos_token | |
| return tok, model | |
| def generate(tok, model, context, query): | |
| import torch | |
| messages = [ | |
| {"role": "system", "content": SYSTEM}, | |
| {"role": "user", "content": f"{context.strip()}\n\n{query.strip()}"}, | |
| ] | |
| # Most-robust form across transformers versions: get a bare tensor and build the | |
| # attention mask ourselves (avoids the version-dependent return_dict behaviour). | |
| input_ids = tok.apply_chat_template( | |
| messages, add_generation_prompt=True, return_tensors="pt", | |
| ).to(model.device) | |
| attn = torch.ones_like(input_ids) | |
| with torch.no_grad(): | |
| out = model.generate( | |
| input_ids=input_ids, | |
| attention_mask=attn, | |
| max_new_tokens=MAX_NEW_TOKENS, | |
| do_sample=False, # greedy -> reproducible | |
| pad_token_id=tok.pad_token_id, | |
| ) | |
| return tok.decode(out[0][input_ids.shape[-1]:], skip_special_tokens=True).strip() | |
| # ---------------------------------------------------------------------------------- | |
| # Main | |
| # ---------------------------------------------------------------------------------- | |
| def main(): | |
| import pandas as pd | |
| df = pd.read_csv(TEST_CSV, dtype=str).fillna("") | |
| print(f"loaded {len(df)} problems", flush=True) | |
| tok, model = load_model() | |
| print("model loaded", flush=True) | |
| rows = [] | |
| for i, r in df.iterrows(): | |
| n_items = count_items(r["query"]) | |
| expl = "" | |
| if time.time() > DEADLINE: | |
| # Out of time: still emit a full, positionally-aligned (blank) row so a | |
| # slow run never zeroes the whole submission via a hard timeout. | |
| preds = [] | |
| print(f"{i + 1}/{len(df)} id={r['id']} SKIPPED (deadline)", flush=True) | |
| else: | |
| try: | |
| text = generate(tok, model, r["context"], r["query"]) | |
| preds = parse_answers(text) | |
| expl = parse_explanation(text) | |
| except Exception as e: # never let one problem sink the whole run | |
| preds = [] | |
| print(f"{i + 1}/{len(df)} id={r['id']} ERROR: {e}", flush=True) | |
| else: | |
| print(f"{i + 1}/{len(df)} id={r['id']} items={n_items} " | |
| f"parsed={len(preds)}", flush=True) | |
| preds = align(preds, n_items) | |
| rows.append({ | |
| "id": r["id"], | |
| "pred": json.dumps(preds, ensure_ascii=False), | |
| "explanation": expl, | |
| }) | |
| pd.DataFrame(rows, columns=["id", "pred", "explanation"]).to_csv( | |
| OUT_CSV, index=False, quoting=csv.QUOTE_MINIMAL, | |
| ) | |
| print(f"wrote {OUT_CSV} ({len(rows)} rows) in {time.time() - START:.0f}s", flush=True) | |
| if __name__ == "__main__": | |
| main() | |