初始化项目,由ModelHub XC社区提供模型
Model: divaspoudel/iol-7162026 Source: Original Platform
This commit is contained in:
149
script.py
Normal file
149
script.py
Normal file
@@ -0,0 +1,149 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import re
|
||||
import csv
|
||||
import subprocess
|
||||
import pandas as pd
|
||||
import torch
|
||||
from transformers import AutoTokenizer, AutoModelForCausalLM
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 1. Install auto-gptq (PyPI is reachable at runtime)
|
||||
# ------------------------------------------------------------------
|
||||
try:
|
||||
import auto_gptq
|
||||
except ImportError:
|
||||
subprocess.check_call([sys.executable, "-m", "pip", "install", "-q", "auto-gptq"])
|
||||
import auto_gptq
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 2. Offline mode - no internet allowed during evaluation
|
||||
# ------------------------------------------------------------------
|
||||
os.environ["HF_HUB_OFFLINE"] = "1"
|
||||
os.environ["TRANSFORMERS_OFFLINE"] = "1"
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 3. Load model from local directory (the repo root)
|
||||
# ------------------------------------------------------------------
|
||||
MODEL_DIR = "."
|
||||
print("Loading tokenizer and model...", flush=True)
|
||||
tokenizer = AutoTokenizer.from_pretrained(MODEL_DIR, trust_remote_code=True)
|
||||
model = AutoModelForCausalLM.from_pretrained(
|
||||
MODEL_DIR,
|
||||
device_map="auto",
|
||||
trust_remote_code=True,
|
||||
torch_dtype=torch.float16,
|
||||
)
|
||||
model.eval()
|
||||
print("Model loaded.", flush=True)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 4. Helper: count numbered items in query
|
||||
# ------------------------------------------------------------------
|
||||
def count_items(query: str) -> int:
|
||||
numbers = re.findall(r'(?:^|\n)\s*(?:\d+)\.', query)
|
||||
if not numbers:
|
||||
lines = query.strip().splitlines()
|
||||
count = 0
|
||||
for ln in lines:
|
||||
if re.match(r'^\s*\d+[\.\)]', ln):
|
||||
count += 1
|
||||
return count
|
||||
return len(numbers)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 5. Parse model output to a JSON list
|
||||
# ------------------------------------------------------------------
|
||||
def extract_answers(text: str, expected_count: int) -> list:
|
||||
json_match = re.search(r'\[\s*".*?"\s*(?:,\s*".*?"\s*)*\]', text, re.DOTALL)
|
||||
if json_match:
|
||||
try:
|
||||
ans = json.loads(json_match.group())
|
||||
if isinstance(ans, list) and all(isinstance(x, str) for x in ans):
|
||||
return ans
|
||||
except:
|
||||
pass
|
||||
|
||||
lines = [ln.strip() for ln in text.splitlines() if ln.strip()]
|
||||
clean = []
|
||||
for ln in lines:
|
||||
m = re.match(r'^\s*\d+[\.\)]\s*(.*)', ln)
|
||||
if m:
|
||||
clean.append(m.group(1).strip())
|
||||
else:
|
||||
clean.append(ln)
|
||||
if len(clean) > expected_count:
|
||||
clean = clean[:expected_count]
|
||||
elif len(clean) < expected_count:
|
||||
clean += [""] * (expected_count - len(clean))
|
||||
return clean
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 6. Optional explanation generation (set to True to opt in)
|
||||
# ------------------------------------------------------------------
|
||||
EXPLAIN = False # change to True if you want to include explanations
|
||||
|
||||
def generate_explanation(context: str, query: str, answer_list: list) -> str:
|
||||
prompt = (
|
||||
f"{context}\n\n{query}\n\n"
|
||||
"My answers are: " + ", ".join(answer_list) + "\n\n"
|
||||
"Now, provide a concise explanation (max 3 bullet points) of the reasoning behind these answers. "
|
||||
"Do not repeat the answers, only the reasoning."
|
||||
)
|
||||
messages = [
|
||||
{"role": "system", "content": "You are an expert linguist. Provide a short, human-readable explanation of your reasoning for the given linguistic problem."},
|
||||
{"role": "user", "content": prompt},
|
||||
]
|
||||
ids = tokenizer.apply_chat_template(messages, add_generation_prompt=True, return_tensors="pt").to(model.device)
|
||||
with torch.no_grad():
|
||||
out = model.generate(ids, max_new_tokens=300, do_sample=False)
|
||||
expl = tokenizer.decode(out[0][ids.shape[-1]:], skip_special_tokens=True).strip()
|
||||
return expl
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 7. Main loop over test.csv
|
||||
# ------------------------------------------------------------------
|
||||
TEST_CSV = "/tmp/data/test.csv"
|
||||
df = pd.read_csv(TEST_CSV, dtype=str).fillna("")
|
||||
|
||||
rows = []
|
||||
for idx, r in df.iterrows():
|
||||
context = r["context"].strip()
|
||||
query = r["query"].strip()
|
||||
num_items = count_items(query)
|
||||
|
||||
system_msg = (
|
||||
"You solve International Linguistics Olympiad problems. "
|
||||
"Answer every numbered item in the query. "
|
||||
"Output the answers as a JSON list of strings, e.g., [\"answer1\", "answer2\"]. "
|
||||
"Do not include anything else."
|
||||
)
|
||||
user_msg = f"{context}\n\n{query}"
|
||||
|
||||
messages = [
|
||||
{"role": "system", "content": system_msg},
|
||||
{"role": "user", "content": user_msg},
|
||||
]
|
||||
ids = tokenizer.apply_chat_template(messages, add_generation_prompt=True, return_tensors="pt").to(model.device)
|
||||
|
||||
with torch.no_grad():
|
||||
outputs = model.generate(ids, max_new_tokens=512, do_sample=False)
|
||||
generated = tokenizer.decode(outputs[0][ids.shape[-1]:], skip_special_tokens=True)
|
||||
|
||||
answers = extract_answers(generated, num_items)
|
||||
print(f"Problem {r['id']}: generated {len(answers)} answers for {num_items} items", flush=True)
|
||||
|
||||
explanation = ""
|
||||
if EXPLAIN:
|
||||
explanation = generate_explanation(context, query, answers)
|
||||
|
||||
rows.append({
|
||||
"id": r["id"],
|
||||
"pred": json.dumps(answers, ensure_ascii=False),
|
||||
"explanation": explanation,
|
||||
})
|
||||
|
||||
pd.DataFrame(rows).to_csv("submission.csv", index=False)
|
||||
print("wrote submission.csv", flush=True)
|
||||
Reference in New Issue
Block a user