| """人格预测 v2 - 单模型多头""" | |
| import json, numpy as np, torch, torch.nn as nn | |
| EMBEDDING_DIM, VEC_DIM = 768, 64 | |
| TRUNK = [256, 128, 64] | |
| HEADS = { | |
| "ocean": (["开放性","尽责性","外向性","宜人性","神经质"], 10), | |
| "four": (["力量型","活泼型","完美型","和平型"], 100), | |
| "color": (["红","蓝","黄","绿"], 100), | |
| "mbti": (["E","I","S","N","T","F","J","P"], 100), | |
| "enneagram": ([f"type_{i}" for i in range(1,10)], 100), | |
| } | |
| class PersonalityModel(nn.Module): | |
| def __init__(self): | |
| super().__init__() | |
| layers=[]; prev=EMBEDDING_DIM | |
| for h in TRUNK: layers+=[nn.Linear(prev,h),nn.BatchNorm1d(h),nn.ReLU(),nn.Dropout(0.2)]; prev=h | |
| self.trunk=nn.Sequential(*layers) | |
| self.heads=nn.ModuleDict({n:nn.Sequential(nn.Linear(VEC_DIM,len(d)),nn.Sigmoid()) for n,(d,_) in HEADS.items()}) | |
| def forward(self,x): | |
| v=self.trunk(x); return {n:h(v) for n,h in self.heads.items()}, v | |
| class PersonalityPredictor: | |
| def __init__(self, model_dir=".", device=None): | |
| self.device=device or ("cuda"if torch.cuda.is_available()else"cpu") | |
| from sentence_transformers import SentenceTransformer | |
| self.enc=SentenceTransformer("shibing624/text2vec-base-chinese",device=self.device) | |
| self.model=PersonalityModel().to(self.device) | |
| ckpt=torch.load(f"{model_dir}/personality_model.pt",map_location=self.device) | |
| self.model.load_state_dict(ckpt["state_dict"]); self.model.eval() | |
| def predict(self, text): | |
| emb=self.enc.encode([text],normalize_embeddings=True) | |
| x=torch.tensor(emb,dtype=torch.float32).to(self.device) | |
| with torch.no_grad(): out,vec=self.model(x) | |
| result={} | |
| for n,(dims,scale) in HEADS.items(): | |
| s=out[n].cpu().numpy()[0]; r={} | |
| for i,d in enumerate(dims): r[d]=round(float(s[i])*scale,1) | |
| if n in("four","color"): | |
| r["_primary"]=dims[int(np.argmax(s))] | |
| elif n=="mbti": | |
| e,i_,s_,n_,t,f,j,p=s | |
| r["_mbti"]=("E"if e>i_ else"I")+("S"if s_>n_ else"N")+("T"if t>f else"F")+("J"if j>p else"P") | |
| elif n=="enneagram": | |
| idx=int(np.argmax(s)); names=["完美型","助人型","成就型","自我型","理智型","疑惑型","活跃型","领袖型","和平型"] | |
| r["_primary"]=f"{idx+1}号·{names[idx]}" | |
| result[n]=r | |
| result["vector"]=vec.cpu().numpy()[0].tolist() | |
| return result | |
| if __name__=="__main__": | |
| p=PersonalityPredictor() | |
| for t in ["曹操性格奸诈多疑、雄才大略,善于用人却心狠手辣", | |
| "此人极其暴躁冲动,一言不合就动手打人,毫无耐心"]: | |
| r=p.predict(t); print(f"\n{t[:30]}...") | |
| print(f" OCEAN:{r['ocean']} 四型:{r['four'].get('_primary')} MBTI:{r['mbti'].get('_mbti')}") | |