AI@Home – Apriel 1.6 15B Thinker Review

Conditions & Context

Today we have something genuinely unusual on the bench. Not Meta, not Google, not Mistral. This one comes from ServiceNow — yes, the enterprise workflow automation company. I still remember using their IT ticketing system at my previous company. They know a thing or two about tech, so should be interesting… Their model is called Apriel 1.6 15B Thinker, and that word “Thinker” says a lot — it thinks out loud before it answers, showing you its internal chain of thought. That alone makes it worth testing. Let’s dive in and see what enterprise-trained reasoning actually looks like under the hood.

As in all my tests, I use the same prompt, the same hardware, and the same methodology. I’m looking at the same set of metrics across every model: VRAM usage, GPU utilization, CPU load, token throughput, tokens written, and total response time. These matter to me because they reveal whether a model is actually usable on consumer hardware — not just in theory, but in practice.

SpecsValue
Linux DistroUbuntu Server 24.04.4 LTS
Linux Kernel6.8.0-101
CPUIntel CORE i7 14th Gen 14700K Cores: 8P/12E Threads: 28
MotherboardMSI PRO B660M-A
RAM80 GB DDR4 (32+16+32+16)
SSDCrucial NVME 1TB
GPUMSI NVidia GeForce RTX 5060Ti Shadow 2X OC PCIe 5.0×8
CUDA Cores4,608
VRAM16 GB GDDR7 128-bit 448 GB/s
GPU DriverNVidia 590.48.01
CUDA version13.1
Ollama version0.17.4
ModelServiceNow Apriel 1.6 15B Thinker
QuantizationQ4 K M

The Prompt

Write a simple Python function that checks if a number is prime.
Explain how it works in plain English, like teaching a beginner.

The Results

10.1GB VRAM and 98% GPU utilization — a model that fits comfortably on a 16GB card and drives the hardware at full throttle. No memory pressure, no CPU spillover, no compromises. It cooks nicely indeed! At Q4_K_M quantization, Apriel parks itself with nearly 6GB of headroom left over. That’s a completely different world from the 1.6GB cliff-edge I was standing on with Mistral Small 3.1 a day before! I think that headroom should be put to good use with an expanded Context Window. Not in this test, but later when I dive into lengthy conversation tests and see how the model fares with keeping old context alive.

ModelQuantRunTokens/sTotal Time (s)Tokens WrittenVRAM (GB)GPU Util
Apriel 1.6 15bQ4 K M145.6822101210.198%
Apriel 1.6 15bQ4 K M244.612398510.198%
Apriel 1.6 15bQ4 K M343.371770410.198%

44 tokens/sec average puts Apriel squarely in the mid-tier — faster than Mistral Small 3.1’s painful 20 t/s, neck and neck with Gemma3 12B QAT at 44 t/s, but also using 1GB less VRAM than Google’s model. The RTX 5060 Ti held a locked 98% GPU utilization across all three runs, steady as a metronome. VRAM never moved. No thermal surprises. Textbook behavior — and that is what I like.

Run 3 deserves a callout: 17 seconds and only 704 tokens versus ~22 seconds and ~1000 tokens for runs 1 and 2. Why? The thinking logs tell the story. By run 3, the model explicitly recognized it had already answered this question twice.

Let's pause here and repeat this, because it is noteworthy in more ways than one:
I pasted the same sentence three times. Unlike most previous models I've tested this one recognized the question was repeating and shortened and simplified its answers. Did not freak out, nor did it try to appease me by giving gradually longer answers. No. Nerves of steel, got shorter, more concise. 15B model? Jaw drop.

It reasoned its way to a shorter response on purpose — same structure, tighter execution. That’s not degradation. That’s self-awareness, which is either impressive or slightly unsettling depending on your mood.

Now for the part that made me put my tea down. The thinking logs — the internal reasoning Apriel shows before it answers — read like they were written by ServiceNow’s legal and compliance department. (LOL And they probably were).
Runs 1 through 3 all contain lines like “We need to comply with the request”, “No disallowed content”, and “We must follow guidelines.” This model apparently needs to clear its throat with a risk assessment before it writes a Python function. Enterprise DNA, fully intact. I’m not going to go full graphic mode here. Just know that this model is tight. Out of the box to act like this? This model had some seriously rigorous training behind it and all I can say is that it looks like it was a marine-style bootcamp.

But here is the twist: buried inside that compliance theater is genuine pedagogical intelligence. In run 1, the model explicitly considered using the int(n**0.5) square root optimization — knew it was more efficient — and deliberately chose NOT to use it. Its reasoning? “That’s more advanced. For a beginner, the simple version is fine.” That is the right call. It made a conscious tradeoff between correctness and clarity for the audience. I do not think a dense dumb model would do this. That is a sign of a thoughtful one. Interesting…

One more twist: Apriel is also a vision-capable model. I fully intend to test this feature, because it is not always available on models of this size — one of the reasons I’m still sticking with Ministral 3 models, despite their propensity to mercilessly flog me with endless bullet-list answers whenever I ask them “how are you?” or “thank you!”, system prompt prohibiting them from doing that be damned.

The Conclusion – TL;DR

ServiceNow built a model that thinks like your favorite (and unlikable) compliance officer but reasons like a good teacher (you actually like). The metrics are solid — 44 t/s rate is very usable in real life without making you want more, 10.1GB VRAM, 98% GPU util, rock-stable across runs. The reasoning capability is real and visible, not just a marketing tag. That is also why the model just sits and does nothing for several seconds or a dozen. Then the output fires off. The writing is consistent, accurate, and appropriately calibrated for a beginner audience.

The downside is personality — namely the absolute lack of it. Where Vex (Ministral 8B) jabbed jokes at me and compared prime numbers to superheroes, Apriel cleared its throat, put the Code of Conduct rule book on the desk in front of it, checked for policy violations, and then wrote you the correct answer in the flattest possible tone. Technically flawless. Conversationally? Let’s just say that you may have a warmer conversation with your mother-in-law than this model.

If you want a reliable mid-size reasoning model that fits cleanly on a 16GB card and never surprises you — in either direction — Apriel 1.6 15B Thinker earns its place. Just don’t expect it to make you laugh.

The Output (unedited )

Thought for 11 seconds >
The user wants: “Write a simple Python function that checks if a number is prime. Explain how it works in plain English, like teaching a beginner.” > > We need to respond with code and explanation. This is allowed content (non-disallowed). The answer should be concise but thorough. > > Given the conversation, we have already provided an answer earlier: we gave a simple Python function that checks for primality using naive method and explained step by step. That seems correct. > > But now the user repeats the same request again. Possibly they want another version? Or maybe they didn’t see previous answer? We can just repeat or provide similar content, but ensure it’s consistent with guidelines: no disallowed content, keep it short, helpful. > > We need to respond in a single message that includes code and plain English explanation. Use proper formatting (triple backticks for code). Possibly also include usage example. > > Given the earlier answer is correct, we can just repeat or adjust slightly. However, note that the user repeated request; maybe they want same answer again. We should provide it anyway. > > We need to ensure no policy violations: It’s fine. > > Thus final answer will be similar to previous but perhaps more beginner-friendly. Provide code and explanation step-by-step. > > Potential improvements: > > – Use `range(2, int(n**0.5) + 1)` for efficiency (but maybe too advanced). For beginners, the naive approach is okay. > > – Explain why we check up to sqrt(n) optionally but not required. > > Given “simple” request, keep it simple: naive loop from 2 to n-1. > > Thus final answer: > > “`python > def is_prime(num): > if num <= 1: > return False > for i in range(2, num): > if num % i == 0: > return False > return True > “` > > Explain: “First we check if number less than or equal to 1 -> not prime. Then loop over possible divisors from 2 up to n-1; if any divides evenly (remainder zero), it’s not prime, else prime.” > > We can also add example usage. > > Make sure explanation is plain English for beginners: use simple terms like “check each number”, “if you find a divisor”. > > Thus final answer will include code and step-by-step explanation. Also maybe mention that this method works but isn’t the fastest; for small numbers it’s fine. > > We’ll follow guidelines about length, clarity, no extra fluff. > > Now produce final answer.

**Python function**

def is_prime(n: int) -> bool:
"""
Return True if n is a prime number, otherwise False.
"""
# 0 and 1 are not prime by definition
if n <= 1:
return False
# Test every integer from 2 up to (but not including) n
for i in range(2, n):
# If n can be divided evenly by i, it has a divisor → not prime
if n % i == 0:
return False
# No divisors were found, so n is prime
return True

How it works (plain‑English explanation for beginners)

  1. Special cases first – Numbers 0 and 1 are never prime, so the function immediately says “not prime” (False) for them. This saves time because we don’t need to test anything else.
  2. Try every possible divisor – Starting at 2, the loop checks each whole number up to n‑1.
    • The expression n % i gives the remainder when you divide n by i.
    • If that remainder is 0, it means i divides n exactly. That tells us n has a divisor other than 1 and itself, so n can’t be prime – we return False.
  3. If no divisor was found – The loop finishes without hitting the return False line. This means none of the numbers from 2 to n‑1 divided into n. Therefore n is only divisible by 1 and itself, which is exactly what “prime” means. We return True.
  4. Use it – You can call the function like this:
print(is_prime(7)) # → True (7 is prime)
print(is_prime(12)) # → False (12 has divisors 2, 3, etc.)

The logic is simple: if you ever find a divisor other than 1 and the number itself, it’s not prime; otherwise it is.

Jiri Krecek Avatar

Posted by

Leave a Reply

Discover more from Archer Dynamics

Subscribe now to keep reading and get access to the full archive.

Continue reading