Views
No views yet
title and
abstract, produced offline by
microsoft/harrier-oss-v1-270m
(a multilingual sentence-transformer, 640-dim). A built-in ItemEncoder pools
the two views into one item vector.[user | history | candidate];
a linear head emits one logit per position. sigmoid(logit) at each candidate
position is its predicted click probability.| Backbone | Qwen3-0.6B (hidden 1024, 28 layers, 16 heads) |
| Item text encoder | microsoft/harrier-oss-v1-270m (640-dim) |
item_feature_dim / user_embedding_dim | 640 / 640 |
| Item encoder | attn |
| Languages | English + Chinese |
pip install "transformers>=5.0" torch sentence-transformersharrier-oss-v1-270m,
encoded without any instruction/prompt and L2-normalized (the sentence-transformers
default). The embedding dim must equal config.item_feature_dim (640).[user | history | candidate]. The model overwrites position 0 with
user_proj(user_embedding), so position 0 is a placeholder (zeros) and
candidate_item_mask marks it 0; history is 0, candidates are 1.1import torch
2from sentence_transformers import SentenceTransformer
3from transformers import AutoModel
4
5device = "cuda" if torch.cuda.is_available() else "cpu"
6
7model = AutoModel.from_pretrained(
8 "Zetik-Dev/magrec-0.6B-en-zh", trust_remote_code=True, dtype=torch.bfloat16
9).to(device).eval()
10encoder = SentenceTransformer("microsoft/harrier-oss-v1-270m", model_kwargs={"dtype": "auto"})
11H = model.config.item_feature_dim
12
13# user profile (bullet-list style) + recent history + candidate news (title, abstract)
14profile = (
15 "- Age: 29\n"
16 "- Gender: Male\n"
17 "- Occupation: Software engineer\n"
18 "- Location: Kansas City, US\n"
19 "- Interests: NFL football (die-hard Chiefs fan), fantasy football, sports betting\n"
20 "- Reading style: Checks scores and NFL headlines every day"
21)
22
23history = [
24 ("Patrick Mahomes returns from knee injury to lead Chiefs past Vikings",
25 "Mahomes threw for three touchdowns in his first game back from a dislocated kneecap."),
26 ("Fantasy football Week 11: must-start running backs and sleepers",
27 "Our analysts break down the best waiver-wire pickups and start-sit calls."),
28 ("Chiefs' defense steps up in gritty road win over the Chargers",
29 "Kansas City forced two turnovers to hold on in a low-scoring divisional game."),
30]
31
32candidates = [
33 ("NFL power rankings: where the Chiefs land coming out of their bye week",
34 "Kansas City climbs after a statement win, while the Patriots slip a spot."),
35 ("Fantasy football waiver wire: top Week 12 pickups at every position",
36 "Streaming defenses and breakout running backs to grab before the deadline."),
37 ("Lamar Jackson's MVP case gains steam after Ravens rout the Rams",
38 "Jackson accounted for five touchdowns as Baltimore rolled on Monday night."),
39 ("Ravens sign veteran safety as playoff push heats up in the AFC",
40 "The move bolsters a secondary that has struggled with injuries down the stretch."),
41 ("Impeachment hearing: key takeaways from the day's public testimony",
42 "Diplomats testified before the House committee in a closely watched session."),
43 ("Meghan and Harry announce they will step back from royal duties",
44 "The couple said they plan to split their time between the UK and North America."),
45 ("'The Mandalorian' premiere breaks streaming records on Disney+",
46 "The Star Wars series drove a wave of sign-ups in Disney+'s opening week."),
47 ("10 cozy soup recipes to get you through the winter",
48 "Comfort-food ideas from readers, including a viral three-ingredient stew."),
49]
50
51# encode with harrier: no prompt, L2-normalized
52enc = lambda texts: encoder.encode(
53 texts, normalize_embeddings=True, convert_to_tensor=True).to(device, torch.bfloat16)
54
55hist_title = enc([t for t, _ in history])
56hist_abstract = enc([a for _, a in history])
57cand_title = enc([t for t, _ in candidates])
58cand_abstract = enc([a for _, a in candidates])
59profile_vec = enc(profile)
60
61# build [user | history | candidate]; pos0 is the user slot (placeholder zeros)
62z = torch.zeros(1, H, dtype=torch.bfloat16, device=device)
63title = torch.cat([z, hist_title, cand_title])
64abstract = torch.cat([z, hist_abstract, cand_abstract])
65cand_mask = torch.zeros(title.shape[0], dtype=torch.long, device=device) # user=0, history=0, candidate=1
66cand_mask[1 + len(history):] = 1
67
68with torch.inference_mode():
69 logits = model(
70 title_embedding=title[None], abstract_embedding=abstract[None],
71 user_embedding=profile_vec[None], candidate_item_mask=cand_mask[None],
72 )["logits"][0].float()
73
74probs = torch.sigmoid(logits[cand_mask == 1])
75for rank, j in enumerate(torch.argsort(probs, descending=True).tolist(), 1):
76 print(f"#{rank} prob={probs[j]:.4f} {candidates[j][0]}")#1 prob=0.1836 NFL power rankings: where the Chiefs land coming out of their bye week
#2 prob=0.1097 Fantasy football waiver wire: top Week 12 pickups at every position
#3 prob=0.0737 Ravens sign veteran safety as playoff push heats up in the AFC
#4 prob=0.0656 Lamar Jackson's MVP case gains steam after Ravens rout the Rams
#5 prob=0.0454 'The Mandalorian' premiere breaks streaming records on Disney+
#6 prob=0.0307 Meghan and Harry announce they will step back from royal duties
#7 prob=0.0298 10 cozy soup recipes to get you through the winter
#8 prob=0.0164 Impeachment hearing: key takeaways from the day's public testimonyforward(...) (see modeling_magrec.py) takes, per batch:| arg | shape | note |
|---|---|---|
title_embedding | [B, SL, 640] | harrier embedding of each item's title |
abstract_embedding | [B, SL, 640] | harrier embedding of each item's abstract |
user_embedding | [B, 640] | profile embedding, injected at position 0 |
candidate_item_mask | [B, SL] | 0 = user/history, 1 = candidate, -1 = padding |
{"logits": [B, SL]}; read the candidate positions (candidate_item_mask == 1).
For an offline-precomputed item tower you can instead pass item_embedding ([B, SL, 640],
the ItemEncoder output) and skip title/abstract.