Thursday, September 3, 2026

Local LLM Research

Local LLM models racing through benchmarks toward a wall of computer code topped by a crown

Introduction

I was curious how capable a local LLM could be on the hardware I already have, so I started this project. I wanted to see what would fit on one GPU, how fast it would run, and how the models compared once I put them through the same basic tests. So I tried a bunch of them, ran the benchmark samples, and kept track of the failures too. Below are my results.

Hardware And Test Setup

  • GPU: NVIDIA RTX 6000 Ada Generation with 49,140 MiB (48 GiB) VRAM.
  • Story runs used Dynamo in dynamo:latest-vllm-local-dev with vLLM 0.25.1, one GPU, --gpu-memory-utilization 0.90, --max-model-len 32768, --max-num-batched-tokens 2048, --max-num-seqs 4, and --enforce-eager. Benchmark clients used different concurrency values, and the 70B runs used a 4K context cap and one sequence.
  • Successful models were reached through Dynamo's OpenAI-compatible POST /v1/chat/completions endpoint at the local frontend. Each model was loaded alone and stopped before the next one.
  • Story measurements are one-request eager-mode smoke tests, not tuned throughput benchmarks. Time to first token (TTFT) and tokens per second are measured at the client through Dynamo.

Working Models

The models below are ordered by measured LiveCodeBench score first, then by the broader benchmark mean. This ordering is provisional because the LiveCodeBench runs used different runtime settings and only Qwen3 0.6B has a thinking/no-thinking pair.

ModelCheckpoint and SpecsMeasured VRAM and Context CapacityBasic TestStory PerformanceQuality SignalCaveats
Qwen3-VL-30B-A3B InstructAWQ 4-bit, QuantTrio/Qwen3-VL-30B-A3B-Instruct-AWQ; 262K native context; tested text-only15.93 GiB weights; 26.39 GiB KV cache; 288,256 KV tokensAPI request passed and returned the exact requested responseNot measuredLocal LiveCodeBench 38%; Text Arena not recordedBest measured LiveCodeBench result in the historical sample. Image input was disabled.
Qwen2.5-Coder 32B InstructOfficial AWQ 4-bit, Qwen/Qwen2.5-Coder-32B-Instruct-AWQ; 32K native context18.14 GiB weights; 23.99 GiB KV cache; 98,240 KV tokensAPI request passed and returned the exact requested responseNot measuredLocal LiveCodeBench 35%Conventional instruct model; BF16 version did not fit.
OpenAI GPT-OSS 20BOfficial MXFP4; 131K native context13.8 GiB weights; 28.51 GiB KV cache; 1,167,515 KV tokensPartial: guesses 5 and 7 returned higher and correctTTFT 0.120 s; 768 output tokens; 24.465 s end to end; 31.55 tokens/sLocal LiveCodeBench 27%; Text Arena 1317 +/- 6Fastest measured story result; historical LiveCodeBench run had 44 transport errors.
DeepSeek-R1-Distill-Qwen-32BAWQ 4-bit, casperhansen/deepseek-r1-distill-qwen-32b-awq; 131K native context18.17 GiB weights; 23.96 GiB KV cache; 98,144 KV tokensPartial: guesses 5 and 7 reached correct final answersTTFT 0.088 s; 768 output tokens; 32.553 s end to end; 23.66 tokens/sLocal LiveCodeBench 25%; AIME24 72.6; MATH-500 94.3Lowest measured TTFT; long reasoning and 3 transport errors in the historical LiveCodeBench run.
Qwen3 32BOfficial AWQ 4-bit, Qwen/Qwen3-32B-AWQ; 32K native context, 131K with YaRN18.24 GiB weights; 23.92 GiB KV cache; 97,968 KV tokensAPI request passed with a 1,024-token allowanceNot measuredLocal LiveCodeBench 20%; Text Arena 1347 +/- 9Emits <think> content; historical result was not mode-controlled.
Qwen3-Coder 30B-A3B InstructAWQ 4-bit, stelterlab/Qwen3-Coder-30B-A3B-Instruct-AWQ; 262K native context15.69 GiB weights; 26.63 GiB KV cache; 290,832 KV tokensPassed exactly: higher, higher, correctTTFT 0.192 s; 548 output tokens; 35.821 s end to end; 15.38 tokens/sLocal LiveCodeBench 20%Best short deterministic smoke-test behavior; historical LiveCodeBench run had 41 transport errors.
Gemma 3 27B ITAWQ 4-bit, gaunernst/gemma-3-27b-it-int4-awq; 128K input and 8K output; tested text-only17.0 GiB weights; 25.18 GiB KV cache; 210,825 KV tokensPassed: higher, higher, correctTTFT 0.180 s; 588 output tokens; 62.274 s end to end; 9.47 tokens/sLocal LiveCodeBench 20%; Text Arena 1365 +/- 4Slowest tested model; one historical response was unparsed.
NVIDIA Nemotron 3 Nano 30B-A3BNVFP4; 262K model/configuration context; this run used 32K18.22 GiB weights; 23.98 GiB FP8 KV cache; 1,624,473 KV tokensPassed logically: higher, higher, correct; each included visible reasoning markupTTFT 0.207 s; 768 output tokens; 56.183 s end to end; 13.72 tokens/sLocal LiveCodeBench not collectedThe Ada GPU has no native FP4 compute; the LiveCodeBench run did not complete.
Qwen3.5-35B-A3BAWQ 4-bit, QuantTrio/Qwen3.5-35B-A3B-AWQ; 262K native context; tested text-only21.38 GiB weights; 20.8 GiB KV cache; 889,909 KV tokensAPI request reached the response only with a larger output allowanceNot measuredLocal LiveCodeBench 17%; Text Arena not recordedHistorical result; explicit no-thinking run still required.
Qwen3 0.6BOfficial BF16; 32K native context1.12 GiB weights; 40.59 GiB KV cache; 380,032 KV tokensNot ranked by model qualityNot measuredLiveCodeBench: 15% thinking; 8% no-thinkingSame prompts and seed, but different historical runtimes, concurrency, token limits, and no explicit no-thinking field in saved payloads.
DeepSeek-R1-Distill-Llama-70BAWQ 4-bit; 128K native context; test limited to 4K37.09 GiB weights; 5.34 GiB KV cache; 17,488 KV tokensAPI request returned an OpenAI JSON responseNot measuredLiveCodeBench not collectedFits only with a 4K request cap and one sequence.
Llama 3.3 70B InstructAWQ 4-bit; 128K native context; test limited to 4K37.09 GiB weights; 5.34 GiB KV cache; 17,488 KV tokensAPI request passed and returned the exact requested responseNot measuredLocal LiveCodeBench not collectedFits only with a 4K request cap and one sequence.

Benchmark Comparison Progress

These are 100-question samples run through Dynamo's OpenAI-compatible API with AIPerf 0.12.0 and temperature 0. Each model uses the largest practical per-model settings tested or supported by the local GPU and model mode, so completion limits and concurrency may differ. They are not full benchmark scores. The ranking below uses the arithmetic mean of MMLU-Pro, GSM8K, MATH-500, and a usable local LiveCodeBench percentage; it is a local comparison score, not an official composite benchmark. GPQA-Diamond is blocked by gated dataset access. The fixed runner used a persistent environment with AIPerf 0.12.0 and datasets 3.6.0 installed in separate steps. In these exports, AIPerf reports unparsed=100 for every GSM8K row even when correct answers were recorded, so that field is not used to interpret GSM8K results.

What The Benchmark Measures Mean

MMLU-Pro samples broad academic and professional knowledge questions, with harder questions and less reliance on simple recall than the original MMLU. GSM8K samples grade-school math word problems and checks whether the model reaches the correct numerical answer. MATH-500 samples challenging competition-style mathematics problems and checks the final answer. LiveCodeBench samples recent programming problems and runs extracted code against tests. GPQA-Diamond samples difficult graduate-level questions in subjects such as biology, physics, and chemistry, where answering usually requires expert reasoning. The simple mean is the arithmetic average of the available MMLU-Pro, GSM8K, and MATH-500 percentages; the rank orders models by that average and is not an official overall score.

For LiveCodeBench, unparsed means the grader could not extract a runnable code block from the response. A response may contain a correct idea or solution but still be unparsed when it fails the expected code format, is truncated, or includes extra text that prevents extraction. These are 100-question samples, not official full benchmark scores. Comparisons are limited because sampling, prompts, model settings, response lengths, parsing, software versions, and grader behavior can change results; the simple mean also weights the three included benchmarks equally and does not include LiveCodeBench or GPQA-Diamond.

Rank so farModelMMLU-ProGSM8KMATH-500LiveCodeBenchFour-benchmark meanLiveCodeBench - thinkingStatus
1Qwen3-VL-30B-A3B AWQ77%94%84%38%73.3%Not mode-controlled: 38% official; 22 unparsedHistorical result; mode not recorded; tested text-only
2Qwen3-Coder 30B-A3B AWQ73%94%81%36%71.0%36% official; 8 unparsed; 0 transport errors; 8,192-token capCorrected 100-question run; settings selected for best practical local result
3GPT-OSS 20B MXFP479%89%85%27%70.0%Not mode-controlled: 27% official; 21 unparsed; 44 transport errorsHistorical result; mode not recorded; GSM8K unparsed export is not meaningful
4DeepSeek-R1-Distill-Qwen-32B AWQ81%89%83%25%69.5%Not mode-controlled: 25% official; 72 unparsed; 3 transport errorsHistorical result; mode not recorded; GSM8K unparsed export is not meaningful
5Qwen3 32B AWQ81%92%84%20%69.3%Not mode-controlled: 20% official; 80 unparsedHistorical result; mode not recorded
6Qwen2.5-Coder 32B AWQ72%84%80%35%67.8%Not mode-controlled: 35% official; 2 unparsedHistorical result; mode not recorded; GSM8K unparsed export is not meaningful
7Gemma 3 27B AWQ61%83%81%20%61.3%Not mode-controlled: 20% official; 1 unparsedHistorical result; mode not recorded; GSM8K unparsed export is not meaningful
8NVIDIA Nemotron 3 Nano 30B NVFP480%90%36%Not collected68.7%Not supported: no successful LiveCodeBench runNo successful LiveCodeBench run
-Qwen3 0.6B35%76%71%15% thinking60.7%15% official; 77 unparsed; 0 transport; 28,000-token capHistorical pair; same prompts and seed, but different runtime, concurrency, token limits, and no explicit no-thinking field in the saved payloads
-Qwen3.5-35B-A3B AWQ82%91%Invalid17%Not rankedNot mode-controlled: 17% official; 68 unparsed; 0 transport; 4,096-token capExcluded: the saved MATH-500 run processed only 6 valid responses and 94 errors

Conclusions

  1. Qwen3-Coder 30B-A3B AWQ is the most dependable tested option for the short deterministic smoke test because it follows that response format cleanly and leaves substantial KV-cache capacity. In the corrected 100-question local sample it reached 36%, with 8 unparsed responses and 0 transport errors. The result is not a published-score reproduction and is not directly comparable to the earlier 20% diagnostic run because the runtime settings and transport reliability differed.
  2. GPT-OSS 20B is the fastest measured local model at 31.55 output tokens per second, but the current raw Dynamo response needs reasoning extraction.
  3. DeepSeek-R1-Distill-Qwen-32B AWQ has the strongest published reasoning signal among the tested models, but its long reasoning content reduces its suitability for short interactive responses without response parsing.
  4. Gemma 3 27B AWQ is usable in text-only mode, but was the slowest model tested and does not reliably return bare JSON without structured-output enforcement.
  5. The documented BF16 attempts from 27B through 70B exhausted the 48 GiB GPU. Quantized checkpoints made every tested model family loadable, including both 70B AWQ models, but the 70B models only leave enough capacity for a 4K request cap and one concurrent sequence.

Sources

Friday, March 27, 2026

I Sent Apple a Working iPhone 13 Pro. They Said It Was Worth $0.

I've used Apple Trade-In twice before. Both times it went fine. This time, I lost a phone worth $360-580 on the open market and got nothing back.

In March 2026, I bought two new iPhones and decided to trade in my old ones: an iPhone 13 Pro 256GB (Graphite, estimated $240) and an iPhone 13 256GB (Blue, estimated $195). I went through the usual process -- logged out of iCloud, erased the devices, and packed them into the FedEx trade-in kits Apple sent me.

Here's the first problem: Apple sent me two identical, unmarked FedEx kits. No label saying which box was for which phone. No instructions. Just two identical padded envelopes. I put the phones in and shipped them both on March 17. Both were delivered to Apple's trade-in facility in Elk Grove, CA on March 18.

Nine days later, on March 27, I got the results:

  1. iPhone 13 Pro trade-in: serial mismatch, revised refund $195
  2. iPhone 13 trade-in: serial mismatch, revised refund $0.00

Read that again. The iPhone 13 Pro box got a $195 refund -- which is the iPhone 13's value. That means Apple received the iPhone 13 in that box, correctly identified it, and paid the right amount for it. The phones simply ended up in the wrong boxes because Apple didn't label them.

So the iPhone 13 Pro was in the other box. Apple had it. They knew what it was. And instead of paying its $240 value, they gave me $0 with these reasons:

  • Incorrect product description or serial number
  • No functioning external ports
  • Data erasure unsuccessful

They identified the iPhone 13 correctly and paid $195. But when they got the iPhone 13 Pro -- a more valuable phone -- in the other box, suddenly it had "no functioning ports" and "unsuccessful data erasure"? Both phones were working and reset the same way, shipped the same day, delivered together.


So what really happened?

Maybe Apple's system is so rigid that putting phones in the wrong unmarked box -- a mistake their own packaging caused -- gives them grounds to reject the trade-in entirely and keep your phone for free. Maybe someone along the FedEx route or at the processing facility pocketed the more valuable phone, and the box swap gave them cover.

I'm not the only one this has happened to. A user on r/iphone sent in a working iPhone, got revised to $0, accidentally hit Accept just like I did, and Apple refused to reverse it. Another on r/apple had Phobio (Apple's trade-in partner) drop their phone from $370 to $0 over a disputed "cracked lens" claim. Apple's own Community forums have multiple threads asking "why did my device get $0?" The pattern is clear: working phones go in, $0 assessments come out, and there's almost nothing you can do about it.

It doesn't matter which scenario it is. Apple had both my phones, correctly identified at least one of them, and chose to pay $0 on the other.

My mistake

When I saw the $0 assessment, I was so baffled that I accidentally tapped "Accept" instead of "Reject -- ship the phone back." That was the fatal error. If I had rejected it, they would have been forced to return whatever phone they had, and I could have verified whether it was actually mine. By accepting, I gave up that right.

I also didn't take any photos or video of the phone before shipping. No proof it was working, no proof of the serial number, no proof it went into the box. Without documentation, it's my word against theirs -- and they have the phone (or whatever phone they claim is mine).




My advice to anyone thinking about using this service:

Don't. Just use eBay.

eBay gives you seller's protection, a verifiable transaction trail, and you'll get significantly more money. Right now on eBay, a used iPhone 13 Pro 256GB sells for $360-580 depending on condition and carrier -- even a "Fair" condition unlocked unit goes for $360. A refurbished one fetches $386. A phone that doesn't even have working Face ID sold for $470. Apple offered me $240 for a fully working one, then decided it was worth $0. eBay would have paid me 50-140% more than Apple's original offer, with actual buyer/seller protections backing the transaction.


But if you must use Apple Trade-In:

1. Trade in at the store.

When I picked up the new iPhones, the Genius at the Apple Store kept pushing me to trade in right there. I said no because I'd always mailed them in before. He was right. An in-store trade-in is inspected in front of you, the value is confirmed on the spot, and there's no chain of custody to worry about.

2. If you must mail it, document everything.

Before sealing the box, record a video showing:

  • The phone powered on, home screen visible
  • Settings > General > About (serial number and IMEI on screen)
  • All ports working (plug in a charge cable)
  • The phone being placed into the FedEx kit and the envelope being sealed

Keep that video until the refund posts to your account.


3. If it goes wrong, escalate -- but know what you're in for.

I'm currently trying to dispute this through Apple Support. It is a pain in the ass and incredibly time-consuming. You call, get transferred, explain the whole story again, get told someone will follow up, and then nothing happens. I don't know if anything will come of it. That's the reality: Apple's escalation process is designed to exhaust you into giving up. Do it anyway -- file the complaint, reference the trade-in order number, request the inspection report, ask for a senior advisor, mention the FTC and your state's consumer protection office. But go in with realistic expectations. The system is not built in your favor.


The bottom line

Apple Trade-In works great until it doesn't. And when it doesn't, you have almost no recourse. The process is opaque, the evaluation is done by a third party you never interact with, the packaging isn't tamper-proof, and the dispute mechanism is designed to make you give up.


I didn't lose a $240 phone. Apple's trade-in offer was $240, but the phone is worth $360-580 on eBay. That's what I actually lost -- a phone worth two to three times what Apple claimed, for a refund of zero dollars. Don't make the same mistake. Sell on eBay, trade in at the store, or at the very least, document everything before you seal that envelope.