xtristan's picture
Release OpenJudgement-4B-Preview
eb2384f
Raw History Blame Contribute Delete
3.45 kB
"""Pure-Python request contract and probability conversion."""
import json, math
def text(value):
return value if isinstance(value,str) else json.dumps(value,ensure_ascii=False,sort_keys=True,separators=(',',':'))
def normalize_question(q):
if not isinstance(q,dict): raise ValueError('Each question must be an object.')
kind=q.get('type'); instruction=q.get('instructions')
if kind not in ('choice','score','noul'): raise ValueError('type must be choice, score, or noul')
if instruction is None or not text(instruction).strip(): raise ValueError('instructions must be nonempty')
instruction=text(instruction)
criteria=q.get('criteria')
if kind=='noul':
if criteria is not None:
if not isinstance(criteria,dict) or set(criteria)!={'true','false'}: raise ValueError('Noul criteria must contain true and false.')
instruction+='\nTrue means: '+text(criteria['true'])+'\nFalse means: '+text(criteria['false'])
return kind,instruction,[''],['true']
if kind=='choice':
if not isinstance(criteria,dict) or not 2<=len(criteria)<=255: raise ValueError('Choice needs 2–255 named criteria.')
if any(not isinstance(k,str) or not k.strip() for k in criteria): raise ValueError('Choice keys must be nonempty strings.')
keys=list(criteria)
candidates=[k if v is None else text(v) for k,v in criteria.items()]
else:
if not isinstance(criteria,list) or not 2<=len(criteria)<=10: raise ValueError('Score needs 2–10 ordered criteria.')
candidates=[text(c) for c in criteria];keys=[str(i) for i in range(len(criteria))]
if kind=='score' and len(set(candidates))!=len(candidates): raise ValueError('Score criteria descriptions must be distinct.')
return kind,instruction,candidates,keys
def hypothesis(kind,instruction,candidate):
return instruction if kind=='noul' else instruction+'\nCandidate answer: '+candidate
def softmax(values):
m=max(values);ex=[math.exp(x-m) for x in values];s=sum(ex)
return [v/s for v in ex]
def probabilities(logits,kind,temperature=1.,bias=0.):
if not math.isfinite(temperature) or temperature<=0: raise ValueError('temperature must be positive and finite')
if not logits or any(not math.isfinite(x) for x in logits): raise ValueError('Nonfinite or empty logits')
if kind=='noul':
x=logits[0]/temperature+bias
p=1/(1+math.exp(-x)) if x>=0 else math.exp(x)/(1+math.exp(x))
return [1-p,p]
return softmax([x/temperature for x in logits])
def answer(kind,keys,candidates,probs):
if kind=='noul':return {'type':'noul','noul':probs[1],'stats':{}}
entropy=-sum(p*math.log(p) for p in probs if p>0)
confidence=max(0.,min(1.,(len(probs)*max(probs)-1)/(len(probs)-1) if kind=='choice' else 1-entropy/math.log(len(probs))))
result={'type':kind,'probabilities':dict(zip(keys,probs)),'confidence':round(confidence,2),'stats':{}}
if kind=='choice':result['choice']=keys[max(range(len(probs)),key=probs.__getitem__)]
else:
result['score']=round(sum(i*p for i,p in enumerate(probs)),2)
result['legend']=dict(zip(keys,candidates))
return result
def record_hypothesis(record,index):
candidate=record["candidates"][index]
if record["kind"]=="choice":
key=record["keys"][index]
if key!=candidate:candidate=key+": "+candidate
return hypothesis(record["kind"],record["instructions"],candidate)