msrh-zindi-magic / data_builders /build_fewshot_train.py
MagicCard's picture
Docs
028081c
Raw
History Blame Contribute Delete
3.2 kB
"""Build train JSON with top-3 AfriE5-similar same-subset (Q,A) demos prepended.
Source: msrh_rag_train_afrie5_TV_k3.json (36501 rows = Train+Val).
Per row: find top-3 same-subset OTHER (Q,A) pairs, exclude self by ID.
"""
import os, json, time, pathlib
os.environ["HF_HOME"] = "/mnt/msrh/Magic_submission/hf_cache"
os.environ.setdefault("CUDA_VISIBLE_DEVICES", "4")
import numpy as np
import pandas as pd
from sentence_transformers import SentenceTransformer
WORK = pathlib.Path("/mnt/msrh/Magic_submission")
TRAIN_CSV = WORK/"data/Train.csv"
VAL_CSV = WORK/"data/Val.csv"
SRC_JSON = WORK/"LF/data/msrh_rag_train_afrie5_TV_k3.json"
OUT_JSON = WORK/"LF/data/msrh_rag_train_afrie5_TV_k3_fewshot.json"
train = pd.read_csv(TRAIN_CSV).reset_index(drop=True)
val = pd.read_csv(VAL_CSV).reset_index(drop=True)
tv_pool = pd.concat([train, val], ignore_index=True)
print(f"TV pool size: {len(tv_pool)}")
MODEL = "/mnt/msrh/Magic_submission/hub/AfriE5-Large-instruct"
print(f"[{time.strftime('%H:%M:%S')}] loading {MODEL}")
model = SentenceTransformer(MODEL, device="cuda", trust_remote_code=True)
QUERY_INST = "Instruct: Given a maternal/sexual/reproductive health question, retrieve relevant passages that answer the question\nQuery: "
K = 3
demos_by_id = {} # ID -> [(Q, A), ...]
for subset in sorted(tv_pool["subset"].unique()):
pool_sub = tv_pool[tv_pool["subset"] == subset].reset_index(drop=True)
print(f"[{time.strftime('%H:%M:%S')}] subset={subset} n={len(pool_sub)}")
pool_emb = model.encode([QUERY_INST + str(q) for q in pool_sub["input"]],
batch_size=32, normalize_embeddings=True,
show_progress_bar=False, convert_to_numpy=True)
sims = pool_emb @ pool_emb.T
np.fill_diagonal(sims, -1.0)
top_idx = np.argsort(-sims, axis=1)[:, :K]
for i, row in pool_sub.iterrows():
demos_by_id[row["ID"]] = [
(str(pool_sub.iloc[int(j)]["input"]), str(pool_sub.iloc[int(j)]["output"]))
for j in top_idx[i]
]
print(f"[{time.strftime('%H:%M:%S')}] demos built for {len(demos_by_id)} rows")
# The source train JSON has rows in the same order as tv_pool (train then val per build script)
n_inj = 0
n_skip = 0
with open(SRC_JSON) as fin, open(OUT_JSON, "w") as fout:
for i, ln in enumerate(fin):
r = json.loads(ln)
pool_row = tv_pool.iloc[i]
dem = demos_by_id.get(pool_row["ID"], [])
if dem:
content = r["messages"][0]["content"]
idx = content.find("Context 1:")
if idx > 0:
before = content[:idx].rstrip()
after = content[idx:]
ex_block = "\n\n".join([f"Example {k+1}:\nQ: {q}\nA: {a}" for k, (q, a) in enumerate(dem)])
new_content = f"{before}\n\nFew-shot examples (similar questions from training):\n{ex_block}\n\n{after}"
r["messages"][0]["content"] = new_content
n_inj += 1
else:
n_skip += 1
else:
n_skip += 1
fout.write(json.dumps(r, ensure_ascii=False) + "\n")
print(f"\nInjected demos in {n_inj} rows, skipped {n_skip}")
print(f"wrote {OUT_JSON}")