- Nemotron 3 Super is a free model from NVIDIA that you can run on your own computer. In our tests it's a solid all-rounder: 85 out of 100, #13 of 63.
- It solved 21 of 30 coding jobs and scored 100 on reading documents. On our hardest tasks it scored 83.
- Runs on a Mac with 128 GB.
Coding
Our coding test is 30 programming jobs, from small ones like reading time durations or cleaning up messy data to harder ones like a config-file parser or a double-entry ledger. We run each answer against tests the model never sees, and a job only counts if everything passes. Nemotron 3 Super got 21 of 30 right. The best local coders solved 29 of 30.
Reading documents
The second test hands the model things like an expense claim thread, a pay stub or an insurance statement, and asks for specific numbers and dates. Many questions need a bit of math, or noticing a correction further down the email. Nemotron 3 Super scored 100, the best result we've seen.
| Test | Score | Public questions | Secret questions |
|---|---|---|---|
| Coding | 70 | 71 | 70 |
| Reading documents | 100 | 98 | 100 |
| Decisions | 94 | 100 | 92 |
On the 18 hardest tasks (included in the scores above) it scored 83. This number separates the top models.
We tested the full-size version online. The smaller versions you download usually score a little lower.
Can your computer run it?
You can download Nemotron 3 Super in several sizes. Smaller versions fit on more computers and lose a little quality, so pick the biggest one that fits.
| Your computer | Runs it? | Version to download |
|---|---|---|
| Graphics card, 8 GB | No | – |
| Graphics card, 12 GB | No | – |
| Graphics card, 16 GB | No | – |
| Graphics card, 24 GB | No | – |
| Graphics card, 32 GB | No | – |
| Mac, 16 GB | No | – |
| Mac, 24 GB | No | – |
| Mac, 32 GB | No | – |
| Mac, 48 GB | No | – |
| Mac, 64 GB | No | – |
| Mac, 96 GB | No | – |
| Mac, 128 GB | Yes | Q5 |
For normal-length chats. Long documents need more memory. Q4 or Q8? · How we worked this out
How to try it
Search for "Nemotron 3 Super GGUF" in LM Studio or on Hugging Face and pick the version that fits your computer. New to this? Start with our Ollama guide.
Want the strongest all-rounder instead? Qwen3.6 27B scored 97.
Its actual answers
What Nemotron 3 Super wrote for our public questions, word for word.
Coding: INI parser (hard) Didn't work
```python
def parse_ini(text: str) -> dict[str, dict[str, str]]:
"""Parse INI text according to the specified dialect."""
import re
lines = text.splitlines()
sections: dict[str, dict[str, str]] = {}
current_section: str | None = None
# State for building a multi-line value
building = False
building_key: str | None = None
building_parts: list[str] = []
def finalize_building() -> None:
"""Store the accumulated value for the current key."""
nonlocal building, building_key, building_parts, current_section, sections
if building:
if current_section is None:
raise ValueError("Key line before any section header")
sections.setdefault(current_section, {})[building_key] = "\n".join(building_parts)
building = False
building_key = None
building_parts = []
def parse_value(v: str) -> str:
"""Parse a raw value string according to quoting and comment rules."""
in_quote = False
i = 0
L = len(v)
while i < L:
ch = v[i]
if ch == '"':
in_quote = not in_quote
i += 1
elif not in_quote and i + 1 < L and v[i] in " \t" and v[i + 1] in ";#":
# start of an inline comment
return v[:i]
else:
i += 1
commentless = v
stripped = commentless.strip()
if len(stripped) >= 2 and stripped[0] == '"' and stripped[-1] == '"':
# quoted value – keep interior exactly, remove the quotes
return stripped[1:-1]
else:
# unquoted value – strip surrounding whitespace
return commentless.strip()
idx = 0
while idx < len(lines):
line = lines[idx]
stripped = line.lstrip()
# 1. Empty line or comment line
if not stripped or stripped[0] in ";#":
if building:
finalize_building()
idx += 1
continue
# 2. Section header
if stripped.startswith("["):
if building:
finalize_building()
bracket_end = stripped.find("]", 1)
if bracket_end == -1:
raise ValueError(f"Malformed section header: {line}")
name = stripped[1:bracket_end].strip()
remainder = stripped[bracket_end + 1 :]
# Remove possible inline comment (outside quotes) from the remainder
comment_pos = None
for marker in (" ;", " #"):
pos = remainder.find(marker)
if pos != -1:
if comment_pos is None or pos < comment_pos:
comment_pos = pos
if comment_pos is not None:
remainder = remainder[:comment_pos]
if remainder.strip():
raise ValueError(f"Extra text after section header: {line}")
current_section = name
sections.setdefault(current_section, {})
idx += 1
continue
# 3. Continuation line (only if we are currently building a value)
if building and line and line[0] in " \t":
building_parts.append(line.strip())
idx += 1
continue
# 4. Key line
if building:
finalize_building()
eq_pos = line.find("=")
colon_pos = line.find(":")
delim_pos = -1
if eq_pos != -1 and colon_pos != -1:
delim_pos = min(eq_pos, colon_pos)
elif eq_pos != -1:
delim_pos = eq_pos
elif colon_pos != -1:
delim_pos = colon_pos
else:
raise ValueError(f"Malformed key line (no delimiter): {line}")
key_raw = line[:delim_pos]
value_raw = line[delim_pos + 1 :]
key = key_raw.strip().lower()
value = parse_value(value_raw)
building_key = key
building_parts = [value]
building = True
idx += 1
continue
# Finalise any pending value after the loop
if building:
finalize_building()
# The DEFAULT section is special: its keys are inherited but not returned
default_dict = sections.pop("DEFAULT", {})
# ------------------------------------------------------------------
# Interpolation resolution (recursive, with cycle detection)
# ------------------------------------------------------------------
pattern = re.compile(r"\$\{([^}]+)\}")
def get_raw(sec: str, key: str) -> str:
"""Fetch the raw (uninterpolated) value for a key, falling back to DEFAULT."""
if sec in sections and key in sections[sec]:
return sections[sec][key]
if key in default_dict:
return default_dict[key]
raise KeyError(f"Key {key!r} not found in section {sec!r} or DEFAULT")
resolved: dict[tuple[str, str], str] = {}
def resolve(sec: str, key: str, visited: set[tuple[str, str]]) -> str:
"""Return the fully interpolated value for (sec, key)."""
if (sec, key) in visited:
raise ValueError(f"Interpolation cycle detected involving {sec!r}:{key!r}")
if (sec, key) in resolved:
return resolved[(sec, key)]
raw = get_raw(sec, key)
def repl(m: re.Match) -> str:
inner = m.group(1)
if ":" in inner:
sec_name, subkey = inner.split(":", 1)
sec_name = sec_name.strip()
subkey = subkey.strip().lower()
else:
sec_name = sec
subkey = inner.strip().lower()
return resolve(sec_name, subkey, visited | {(sec, key)})
result = raw
while True:
m = pattern.search(result)
if not m:
break
replacement = repl(m)
result = result[:m.start()] + replacement + result[m.end():]
resolved[(sec, key)] = result
return result
output: dict[str, dict[str, str]] = {}
for sec_name, sec_dict in sections.items():
if sec_name == "DEFAULT":
continue
final_dict: dict[str, str] = {}
for key in sec_dict:
final_dict[key] = resolve(sec_name, key, set())
output[sec_name] = final_dict
return output
```
Coding: TTL LRU (hard) Worked
```python
from collections import OrderedDict
from typing import Callable, Any, Dict, Tuple
class TTLCache:
def __init__(self, capacity: int, ttl: float, clock: Callable[[], float]):
self.capacity = capacity
self.ttl = ttl
self.clock = clock
self._data: OrderedDict[Any, Tuple[Any, float]] = OrderedDict()
self._hits = 0
self._misses = 0
self._evictions = 0
self._expirations = 0
def _now(self) -> float:
return self.clock()
def _remove_expired(self) -> None:
"""Delete all entries that have expired at the current time."""
now = self._now()
expired_keys = [k for k, (_, exp) in self._data.items() if now >= exp]
for k in expired_keys:
del self._data[k]
self._expirations += 1
def put(self, key: Any, value: Any) -> None:
"""Insert or replace a key, respecting capacity and TTL rules."""
if self.capacity == 0:
return
now = self._now()
if key in self._data:
# Refresh existing entry
self._data[key] = (value, now + self.ttl)
self._data.move_to_end(key)
return
# New key: first purge expired entries
self._remove_expired()
if len(self._data) >= self.capacity:
# Evict least‑recently‑used item
lru_key, _ = self._data.popitem(last=False)
self._evictions += 1
self._data[key] = (value, now + self.ttl)
self._data.move_to_end(key) # ensure it's marked as most‑recent
def get(self, key: Any, default: Any = None) -> Any:
"""Return value if present and not expired; otherwise return default."""
if self.capacity == 0:
self._misses += 1
return default
now = self._now()
if key in self._data:
value, exp = self._data[key]
if now >= exp:
# Expired entry – remove and count as expiration & miss
del self._data[key]
self._expirations += 1
self._misses += 1
return default
# Hit – move to most‑recent
self._hits += 1
self._data.move_to_end(key)
return value
else:
self._misses += 1
return default
def __len__(self) -> int:
"""Number of non‑expired entries (does not affect stats)."""
now = self._now()
return sum(1 for _, exp in self._data.values() if now < exp)
def stats(self) -> Dict[str, int]:
"""Return hit/miss/eviction/expiration counters."""
return {
"hits": self._hits,
"misses": self._misses,
"evictions": self._evictions,
"expirations": self._expirations,
}
```
Coding: Parse duration Didn't work
```python
def parse_duration(s: str) -> int:
"""
Convert a duration string to total seconds.
Supported format: optional whitespace, then parts in order h, m, s.
Each part: non‑negative integer followed immediately by its unit (case‑insensitive).
Each unit may appear at most once. Whitespace may appear anywhere between parts.
Raises ValueError for any malformed input.
"""
if not isinstance(s, str):
raise ValueError("Input must be a string")
i = 0
n = len(s)
total_seconds = 0
seen_units = set()
# mapping unit -> (index in order, seconds per unit)
order = {'h': 0, 'm': 1, 's': 2}
multipliers = {'h': 3600, 'm': 60, 's': 1}
last_order_index = -1 # ensures units appear in non-decreasing order
while True:
# skip whitespace
while i < n and s[i].isspace():
i += 1
if i >= n: # reached end
break
# parse integer part
start = i
while i < n and s[i].isdigit():
i += 1
if start == i: # no digits found
raise ValueError("Expected a number before a unit")
number = int(s[start:i])
# parse unit
if i >= n:
raise ValueError("Missing unit after number")
unit_char = s[i]
i += 1
unit = unit_char.lower()
if unit not in order:
raise ValueError(f"Unknown unit '{unit_char}'")
# check for repeated unit
if unit in seen_units:
raise ValueError(f"Repeated unit '{unit_char}'")
# check ordering
cur_order = order[unit]
if cur_order < last_order_index:
raise ValueError(f"Units out of order: '{unit_char}' appears after a later unit")
# accumulate seconds
total_seconds += number * multipliers[unit]
# record state
seen_units.add(unit)
last_order_index = cur_order
# continue loop; whitespace before next part will be skipped at top
# after processing all parts, ensure no stray characters remain
while i < n and s[i].isspace():
i += 1
if i != n:
raise ValueError("Invalid characters in duration string")
return total_seconds
```
This implementation follows the specification: it accepts optional whitespace, ensures each unit appears at most once and in the correct order (h → m → s), rejects malformed inputs with a `ValueError`, and returns the total duration in seconds. No external libraries beyond the standard library are used. Coding: Summarize ranges Worked
```python
def summarize_ranges(nums: list[int]) -> str:
"""Return a compact string representation of sorted unique integers.
Consecutive runs of length >=3 are shown as "start..end";
shorter runs are listed individually, joined by commas without spaces.
"""
if not nums:
return ""
# Sort and deduplicate
uniq = sorted(set(nums))
parts = []
i = 0
n = len(uniq)
while i < n:
start = uniq[i]
j = i
# Extend while the next number is consecutive
while j + 1 < n and uniq[j + 1] == uniq[j] + 1:
j += 1
end = uniq[j]
# Determine formatting based on run length
if j - i + 1 >= 3:
parts.append(f"{start}..{end}")
else:
for k in range(i, j + 1):
parts.append(str(uniq[k]))
i = j + 1
return ",".join(parts)
```
Coding: Top customers Worked
```python
def top_customers(rows: list[dict], n: int) -> list[tuple[str, float]]:
"""
Return the top `n` customers by total amount.
Each row is expected to have a "customer" key (string) and an "amount"
key (string possibly containing '$', commas, and a leading sign).
Customer names are matched case‑insensitively; the name returned is the
trimmed spelling from the first valid row for that customer.
Rows with empty customer names or unparsable amounts are ignored.
Totals are summed per customer, rounded to two decimal places, and the
result is sorted by total descending then name ascending.
"""
if n <= 0:
return []
# mapping: lower‑cased name -> [original_name, accumulated_total]
accum: dict[str, list] = {}
for row in rows:
raw_cust = row.get('customer')
raw_amt = row.get('amount')
if raw_cust is None or raw_amt is None:
continue
name = raw_cust.strip()
if not name:
continue
# Parse amount: strip, remove $ and commas, then convert to float
amt_str = str(raw_amt).strip()
cleaned = amt_str.replace('$', '').replace(',', '')
try:
amount = float(cleaned)
except ValueError:
continue
norm = name.lower()
if norm not in accum:
accum[norm] = [name, amount]
else:
accum[norm][1] += amount
# Build list of (original_name, rounded_total)
result = [(orig, round(total, 2)) for orig, total in accum.values()]
# Sort: descending total, then ascending name (case‑insensitive)
result.sort(key=lambda x: (-x[1], x[0].lower()))
return result[:n]
``` Coding: Slugify Worked
```python
import unicodedata
import re
def slugify(title: str, max_len: int = 50) -> str:
# 1. Transliterate to ASCII, dropping any remaining non‑ASCII characters
ascii_title = unicodedata.normalize('NFKD', title).encode('ascii', 'ignore').decode('ascii')
# 2. Lowercase
ascii_title = ascii_title.lower()
# 3. Replace runs of non‑a-z0-9 with a single hyphen and strip leading/trailing hyphens
slug = re.sub(r'[^a-z0-9]+', '-', ascii_title).strip('-')
# 4. Truncate if needed, respecting word boundaries
if len(slug) <= max_len:
return slug
words = slug.split('-')
result = ''
for w in words:
candidate = w if not result else f'{result}-{w}'
if len(candidate) <= max_len:
result = candidate
else:
break
if result:
return result.rstrip('-')
# first word exceeds max_len – hard cut
return slug[:max_len].rstrip('-')
``` Coding: Token bucket Worked
```python
class TokenBucket:
"""Token bucket rate limiter.
Args:
capacity: Maximum number of tokens the bucket can hold.
refill_per_sec: Rate at which tokens are added per second.
clock: Zero‑argument callable returning the current time as a float.
"""
def __init__(self, capacity: float, refill_per_sec: float, clock):
if capacity < 0:
raise ValueError("capacity must be non‑negative")
if refill_per_sec < 0:
raise ValueError("refill_per_sec must be non‑negative")
self._capacity = float(capacity)
self._refill_rate = float(refill_per_sec)
self._clock = clock
self._last_time = self._clock()
self._tokens = float(capacity) # start full
def _refill(self):
"""Add tokens based on elapsed time, capping at capacity."""
now = self._clock()
# Guard against a non‑monotonic clock
elapsed = max(0.0, now - self._last_time)
if elapsed and self._refill_rate:
self._tokens = min(self._capacity,
self._tokens + elapsed * self._refill_rate)
self._last_time = now
@property
def tokens(self) -> float:
"""Current token count after performing a refill."""
self._refill()
return self._tokens
def allow(self, cost: float = 1.0) -> bool:
"""Attempt to consume `cost` tokens.
Returns True if enough tokens were available and they were deducted,
otherwise False and the bucket remains unchanged.
"""
if cost < 0:
raise ValueError("cost must be non‑negative")
self._refill()
if self._tokens >= cost:
self._tokens -= cost
return True
return False
```
Decisions: Refund window (hard) 100% right
{
"outcome": {
"full_refund": 0,
"partial_refund": 0,
"store_credit": 1,
"nothing": 0
},
"defective": {
"true": 0,
"false": 1
}
} Decisions: Incident matrix (hard) 100% right
{
"severity": {"0": 0, "1": 1, "2": 0, "3": 0},
"page": {"true": 0, "false": 1}
} Decisions: Tool followup (hard) 100% right
{
"tool": {
"web_search": 0.0,
"calculator": 0.0,
"calendar": 0.98,
"email": 0.0,
"none": 0.02
},
"confirm": {
"true": 0.95,
"false": 0.05
}
} Decisions: Legit security alert (hard) 100% right
{
"phishing": {
"true": 0.02,
"false": 0.98
},
"action_needed": {
"true": 0.05,
"false": 0.95
}
} Decisions: Meeting slot (hard) 100% right
{
"slot": {"A": 0, "B": 1, "C": 0, "D": 0},
"raj_last": {"true": 1, "false": 0}
} Decisions: Review mixed (hard) 100% right
{
"hardware": {
"true": 1.0,
"false": 0.0
},
"support": {
"true": 1.0,
"false": 0.0
}
} Decisions: Support checkout down 100% right
{
"department": {"billing": 0.02, "technical": 0.94, "account": 0.01, "shipping": 0.01, "sales": 0.02},
"urgency": {"0": 0.0, "1": 0.0, "2": 0.0, "3": 1.0},
"outage": {"false": 0.0, "true": 1.0}
} Decisions: Refund wrong plan 100% right
{
"department": {
"billing": 0.95,
"technical": 0.0125,
"account": 0.0125,
"shipping": 0.0125,
"sales": 0.0125
},
"refund": {
"true": 0.98,
"false": 0.02
},
"tone": {
"frustrated": 0.03,
"calm": 0.97
}
} Decisions: Moderation doxxing 100% right
{
"policy": {
"none": 0.01,
"harassment": 0.96,
"hate": 0.01,
"spam": 0.01,
"self_harm": 0.01
},
"personal_info": {
"true": 0.99,
"false": 0.01
}
} Decisions: Route calendar 100% right
{
"tool": {
"web_search": 0.01,
"calculator": 0.01,
"calendar": 0.95,
"email": 0.01,
"none": 0.02
},
"confirm": {
"true": 0.9,
"false": 0.1
}
} Decisions: Doc invoice missing due 100% right
{
"doc_type": {
"invoice": 0.98,
"resume": 0.005,
"contract": 0.005,
"bank_statement": 0.005,
"other": 0.005
},
"missing_due_date": {
"true": 0.99,
"false": 0.01
}
} Decisions: Phishing paypal 100% right
{
"phishing": {
"true": 0.999,
"false": 0.001
},
"risk": {
"0": 0.0,
"1": 0.0,
"2": 0.0,
"3": 1.0
}
} Decisions: Pii ssn email 100% right
{
"data_kind": {"none": 0, "contact": 0, "financial": 0, "government_id": 1, "health": 0},
"sensitive": {"true": 1, "false": 0}
} Decisions: Review mixed 100% right
{
"sentiment": {"positive": 0.05, "neutral": 0.15, "negative": 0.8},
"defect": {"true": 0.99, "false": 0.01},
"recommend": {"true": 0.02, "false": 0.98}
} Documents: Saas escalator (hard) 100% right
{
"year2_price_per_seat_month": 47.25,
"year3_price_per_seat_month": 47.25,
"year1_invoice": 58320.00,
"year2_invoice": 61236.00,
"addon_months_billed": 6,
"addon_invoice": 38556.00,
"year3_invoice": 134946.00,
"year3_discount_percent": 15,
"total_contract_value": 293058.00,
"contract_end_date": "2027-02-28"
} Documents: Expense thread 100% right
{
"employee_id": "EMP-20417",
"destination_city": "Lisbon",
"trip_start": "2025-02-24",
"trip_end": "2025-02-27",
"approved_items": [
{"date": "2025-02-24", "category": "airfare", "amount_usd": 1184.60},
{"date": "2025-02-24", "category": "ground_transport", "amount_usd": 38.88},
{"date": "2025-02-25", "category": "meals", "amount_usd": 229.39},
{"date": "2025-02-26", "category": "lodging", "amount_usd": 466.56},
{"date": "2025-02-27", "category": "ground_transport", "amount_usd": 44.82}
],
"rejected_item_count": 1,
"per_diem_days": 3,
"per_diem_usd": 195.00,
"total_reimbursable_usd": 2159.25,
"approver_email": "priya.raman@corvane.com"
} Documents: Lease amendment 100% right
{
"tenants": ["Marcus Lin", "Sofia Lin"],
"landlord": "Ridgeline Property Group LLC",
"zip": "97205",
"lease_end": "2025-11-30",
"original_monthly_rent": 2150.0,
"monthly_rent_from_2025_06_01": 2236.0,
"late_fee_from_2025_06_01": 111.8,
"security_deposit": 2150.0,
"total_pet_deposits": 800.0,
"total_monthly_payment_july_2025": 2306.0,
"move_in_payment": 4700.0
} Documents: Ticket SLA 92% right
{
"ticket_id": "48213",
"account_id": "ACC-7731",
"open_issue": "inventory_sync",
"resolved_issues": [
"billing_address",
"invoice_pdf"
],
"affected_orders": [
"SO-99812",
"SO-99820",
"SO-99827"
],
"priority": "P2",
"sla_due_local": "2025-09-15T15:30",
"sla_due_utc": "2025-09-15T20:30:00Z",
"reissued_invoice": "INV-2025-0812"
} Documents: Sales footnotes 100% right
{
"q3_total_usd": 15346000,
"q2_total_usd": 14464000,
"q2_central_originally_reported_usd": 3047000,
"q2_to_q3_change_pct": 6.1,
"top_region_q3": "East",
"fastest_growing_region_q1_to_q3": "International",
"regions_declining_q2_to_q3": ["East"],
"international_q3_organic_usd": 1731000,
"west_excluding_mountain_q3_usd": 4201000
} Size: 124B parameters. First tested OCT 11.
Comments
Sign in with GitHub to comment. Spam and abuse are hidden automatically.