Files
markbaseengine/compare_e4b_logits.py
T
MarkBase Admin ac75faa0cc
CI / build-and-test (push) Has been cancelled
Initial commit: E4B-MarkBase model integration with passing tests
- E4B-MarkBase model (42 layers, 4.4GB) loaded successfully
- All Phase 1-6 tests passed (model loading, forward pass, vision/audio towers, token generation, performance)
- All stress tests passed (5/5 in 127.6s)
  - Concurrent inference
  - Memory stress (67.5 tok/s, 0 NaN)
  - Continuous generation
  - Batch processing
  - Long-running stability
- Swift Metal inference engine with multimodal support
2026-06-23 18:12:35 +08:00

84 lines
2.6 KiB
Python

#!/usr/bin/env python3
"""
Compare logits from original E4B model vs our Swift implementation.
Uses transformers library since MLX doesn't support Gemma-4 yet.
"""
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
import json
import numpy as np
# Load original E4B model from HuggingFace
model_path = "google/gemma-4-4b-it"
print("Loading original E4B model from HuggingFace...")
print("This may take a moment to download...")
try:
tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoModelForCausalLM.from_pretrained(
model_path,
device_map="auto",
torch_dtype=torch.bfloat16
)
print("Model loaded successfully!")
except Exception as e:
print(f"Error loading model: {e}")
print("\nFalling back to checking config from converted model...")
# Check config from converted model
conv_path = "/Users/accusys/MarkBase12B/models/E4B-MarkBase/config.json"
with open(conv_path) as f:
cfg = json.load(f)
print("\nConverted model config:")
for key in ["hidden_size", "num_hidden_layers", "vocab_size",
"num_attention_heads", "num_key_value_heads",
"hidden_size_per_layer_input"]:
print(f" {key}: {cfg.get('text_config', {}).get(key, cfg.get(key))}")
exit(1)
# Get BOS token
bos_token_id = tokenizer.bos_token_id if tokenizer.bos_token_id else 2
print(f"\nBOS token ID: {bos_token_id}")
# Run forward pass for position 0
input_ids = torch.tensor([[bos_token_id]])
print(f"Input IDs: {input_ids}")
with torch.no_grad():
outputs = model(input_ids)
logits = outputs.logits[0, 0].float().numpy() # [vocab_size]
print(f"\nLogits shape: {logits.shape}")
print(f"Logits range: min={logits.min():.2f}, max={logits.max():.2f}")
# Get top 10 tokens
top_indices = np.argsort(logits)[-10:][::-1]
print("\nTop 10 tokens (position 0, BOS):")
for i, idx in enumerate(top_indices):
token = tokenizer.decode([idx])
print(f" {i+1}. token {idx} '{token}': {logits[idx]:.2f}")
# Test with actual prompt
prompt = "<start_of_turn>user\nThe capital of France is<end_of_turn>\n<start_of_turn>model\n"
print(f"\nTesting prompt: '{prompt[:50]}...'")
# Tokenize
inputs = tokenizer(prompt, return_tensors="pt")
print(f"Tokens: {inputs['input_ids'][0][:20].tolist()}...")
# Generate
print("\nGenerating response...")
with torch.no_grad():
outputs = model.generate(
**inputs,
max_new_tokens=30,
do_sample=True,
temperature=1.0,
top_k=40
)
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(f"Response: '{response}'")