Views
No views yet
aisingapore/Llama-SEA-LION-v3.5-8B-R. The LoRA adapters have been merged into the base model for simpler deployment.aisingapore/Llama-SEA-LION-v3.5-8B-Rmodeling.py and the weights for the pooling/projection heads.1import torch
2import torch.nn.functional as F
3from transformers import AutoModelForCausalLM, AutoTokenizer
4from huggingface_hub import hf_hub_download
5import importlib.util
6
7# --- 1. Setup and Load Components ---
8device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
9repo_id = "evoreign/sea-lion-8b-mrl-embedding-merged"
10
11# --- 2. Dynamically Load Custom Classes ---
12print("Downloading custom modeling code...")
13modeling_path = hf_hub_download(repo_id=repo_id, filename="modeling.py")
14spec = importlib.util.spec_from_file_location("modeling", modeling_path)
15modeling = importlib.util.module_from_spec(spec)
16spec.loader.exec_module(modeling)
17LatentAttentionPooling = modeling.LatentAttentionPooling
18MatryoshkaProjection = modeling.MatryoshkaProjection
19print("Custom classes loaded successfully.")
20
21# --- 3. Load Merged Model ---
22print("Loading the full merged model (this may take time and memory)...")
23# No PeftModel needed, we load directly from the repo ID.
24model = AutoModelForCausalLM.from_pretrained(
25 repo_id,
26 torch_dtype=torch.float16, # Use float16 for memory efficiency
27 device_map="auto",
28 trust_remote_code=True
29)
30tokenizer = AutoTokenizer.from_pretrained(repo_id)
31
32# --- 4. Load Custom Pooling and Projection Heads ---
33HIDDEN_SIZE = model.config.hidden_size
34MAX_DIM = 4096
35
36print("Loading custom pooling and projection heads...")
37pooler = LatentAttentionPooling(hidden_size=HIDDEN_SIZE).to(device).to(torch.float16)
38projection = MatryoshkaProjection(hidden_size=HIDDEN_SIZE, max_embed_dim=MAX_DIM).to(device).to(torch.float16)
39
40pooler_path = hf_hub_download(repo_id=repo_id, filename="pooler.pt")
41projection_path = hf_hub_download(repo_id=repo_id, filename="projection.pt")
42
43pooler.load_state_dict(torch.load(pooler_path, map_location=device))
44projection.load_state_dict(torch.load(projection_path, map_location=device))
45
46model.eval()
47pooler.eval()
48projection.eval()
49
50# --- 5. Create the Inference Function ---
51def embed_texts_mrl(texts, out_dim=None):
52 with torch.no_grad():
53 inputs = tokenizer(
54 texts, return_tensors="pt", padding=True, truncation=True, max_length=4096
55 ).to(device)
56 # Use model() directly as it's not a PeftModel
57 out = model(**inputs, output_hidden_states=True)
58 hidden = out.hidden_states[-1]
59 mask = inputs.attention_mask
60 pooled = pooler(hidden, attention_mask=mask)
61 z_max = projection(pooled)
62 z = z_max[:, :out_dim] if out_dim else z_max
63 return F.normalize(z, p=2, dim=1)
64
65# --- 6. Example Usage ---
66my_texts = ["Contoh kalimat untuk di-embed.", "Another sentence to embed."]
67emb_256 = embed_texts_mrl(my_texts, out_dim=256)
68print("Sliced embedding shape:", emb_256.shape)
69# Expected output: torch.Size([2, 256])query, positive, hard_negative).