File size: 1,963 Bytes
0e38be0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# SkillJev inference: OpenJev 4B (Qwen3.5 NLI) backbone + LoRA + 3 linear heads.
import json, torch, torch.nn as nn
from transformers import AutoTokenizer, AutoModelForSequenceClassification
from peft import PeftModel
from huggingface_hub import snapshot_download
G=["lang_core","api_design","data_storage","system_design","cloud_devops","reliability_obs","security","testing_quality","frontend","leadership"]
E=["supported","partial","contradicted","insufficient"]; P=["0","1","2","3","4","5","unknown"]
T={"g":0.5,"e":2.4,"p":2.8}  # temperature scaling fit on dev
d=snapshot_download("niko0xdev/skilljev")
tok=AutoTokenizer.from_pretrained("AlexWortega/openjev",subfolder="qwen3.5-4b-nli-v5"); tok.padding_side="right"
tok.pad_token=tok.pad_token or tok.eos_token
full=AutoModelForSequenceClassification.from_pretrained("AlexWortega/openjev",subfolder="qwen3.5-4b-nli-v5",dtype=torch.bfloat16)
H=full.score.in_features; bb=PeftModel.from_pretrained(full.base_model,d).eval().to("cuda")
heads=nn.ModuleDict({"g":nn.Linear(H,len(G)),"e":nn.Linear(H,len(E)),"p":nn.Linear(H,len(P))})
heads.load_state_dict(torch.load(f"{d}/heads.pt",map_location="cpu")); heads.to("cuda").eval()
@torch.no_grad()
def predict(requirement, evidence):  # evidence: list of (source_type, section, text)
    ev="\n".join(f"[{s}/{c}] {t}" for s,c,t in evidence) or "(no evidence)"
    x=tok(f"Requirement: {requirement}\nEvidence:\n{ev}",truncation=True,max_length=192,return_tensors="pt").to("cuda")
    z=bb(**x).last_hidden_state[0,-1].float(); out={}
    for k,lab,name in [("g",G,"skill_group"),("e",E,"evidence"),("p",P,"proficiency")]:
        pr=(heads[k](z)/T[k]).softmax(-1); i=int(pr.argmax()); out[name]={"label":lab[i],"confidence":round(float(pr[i]),3)}
    return out
if __name__=="__main__":
    print(json.dumps(predict("Strong PostgreSQL skills",[("cv","experience","Partitioned a 3TB PostgreSQL table and tuned indexes, cutting queries from 40s to 1s.")]),indent=1))