Audit & optimization
I find where AI truly creates value, and cut the bill on what's already running.
Adopting AI without a strategy is expensive both ways: missed opportunities, and token bills that spiral. And before we even talk about the model, I check the state of your data: scattered, incomplete or out of date, it sinks the best project. I audit your processes AND your data, put numbers on the profitable cases, and optimize what's already running: often 30 to 70% lower costs, at the same quality.
Key facts
-30 to -70%
on your AI bill, at the same quality
Step 0
the state of your data, checked before we code
48h
for a first audit readout
Audit & optimization
What I build
AI audit & strategy
Your processes put under the microscope to find the use cases with real ROI, and honestly rule out the ones that aren't worth it.
Audit · Quantified use cases · ROI roadmap
Cost optimization
Model selection, caching, prompt architecture, batching: the LLM bill goes down without losing quality.
30 to 70% less · Caching · Batching · Model selection
Data readiness
Before building anything, I look at your data where it lives: is it complete, up to date, gathered, usable? Building AI on data that isn't ready is building on sand. I tell you what's blocking and where to start, without a big pointless overhaul.
Data readiness · Data quality · Feasibility
The promise
AI at the right price, where it pays off.
Demonstration
Breaking a support call into token line items
A business software vendor runs a support assistant in production. The bill keeps climbing, nobody knows what one answer costs, and next year's budget is decided soon.
Invented caseThis case is not an engagement. It is invented end to end, and the code below is the real code that would run it.
HumanThe bill keeps climbing
The assistant has answered well since it went live. The monthly bill keeps climbing and nobody knows why. What does one answer cost?
The agentInspect a real turn
An aggregated bill does not say where the volume comes from. So I inspect a real turn, the seventh of a live conversation, and separate what changes at every turn from what does not. That second block is the replayed context.
Tool callThe inspection call
{ "tool": "inspect_call", "conversation": "conv-8412", "turn": 7, "break_down": true, "line_items": [ "system_prompt", "product_catalog", "response_examples", "conversation_history", "customer_question" ], "compare_with_turn": 6 }The inspection runs on a production call, not one built for the demo.
Tool responseThe reading for that turn
{ "conversation": "conv-8412", "turn": 7, "tokens_sent": 17740, "line_items": { "system_prompt": 1180, "product_catalog": 9400, "response_examples": 2600, "conversation_history": 4350, "customer_question": 210 }, "fingerprints_identical_to_turn_6": [ "system_prompt", "product_catalog", "response_examples" ], "replayed_context": 13180, "cache_read_tokens": 0, "cache_control_present": false, "calls_observed": 1, "calls_required": 200, "bill_estimate": "refused, sample of a single call" }The reading refuses to price a bill from a single call: the guard in the code requires the series.
Tool callThe replayed request
{ "tool": "replay_call", "conversation": "conv-8412", "turn": 7, "blocks": [ { "line_item": "system_prompt", "cache_control": "ephemeral" }, { "line_item": "response_examples", "cache_control": "ephemeral" }, { "line_item": "product_catalog", "mode": "retrieved_excerpts", "records": 3 }, { "line_item": "conversation_history", "turns_kept": 3 }, { "line_item": "customer_question" } ], "measure": [ "tokens_sent", "cache_read_tokens", "similarity_to_original_answer" ] }The cached prefix must stay identical byte for byte, or the cache read never fires.
AnswerVolume by line item
The inspected turn sends 17,740 tokens: 1,180 of system prompt, 9,400 of catalog, 2,600 of examples, 4,350 of history, 210 of question. Three line items carry the same fingerprint as the previous turn and weigh 13,180 tokens, resent in full, with no cache. The replayed request marks those blocks for the cache, cuts the catalog to three records and the history to three turns. Its measurement comes with the series, and no figure lands before that: the token price stays the one in your contract.
Breaking a call into token line items, with its sample guard
"""Token line item reading for a support assistant running in production."""
from collections import Counter
MINIMUM_CALLS = 200
STABLE_LINE_ITEMS = ("system_prompt", "product_catalog", "response_examples")
class SampleTooSmall(Exception):
"""A reading drawn from a handful of calls is contradicted by the first spike."""
def inspect_call(call):
line_items, fingerprints = Counter(), {}
for block in call["blocks"]:
line_items[block["line_item"]] += block["tokens"]
fingerprints[block["line_item"]] = block["fingerprint"]
return line_items, fingerprints
def replay_call(call, plan):
kept = {block["line_item"]: block for block in plan}
blocks = [dict(b, **kept[b["line_item"]]) for b in call["blocks"] if b["line_item"] in kept]
return dict(call, blocks=blocks)
def replayed_context(line_items, fingerprints, previous):
stable = [item for item in line_items if item in STABLE_LINE_ITEMS]
return sum(line_items[i] for i in stable if previous.get(i) == fingerprints[i])
def report(calls, minimum=MINIMUM_CALLS):
if len(calls) < minimum:
raise SampleTooSmall(
"sample too small: {} of the {} calls required".format(len(calls), minimum)
)
total, replayed, cache_read = Counter(), 0, 0
conversation, previous = None, {}
for call in sorted(calls, key=lambda c: (c["conversation"], c["turn"])):
# Replayed context is counted inside one conversation, never across two.
if call["conversation"] != conversation:
conversation, previous = call["conversation"], {}
line_items, fingerprints = inspect_call(call)
total.update(line_items)
replayed += replayed_context(line_items, fingerprints, previous)
cache_read += call.get("cache_read_tokens", 0)
previous = fingerprints
sent = sum(total.values())
return {
"calls": len(calls),
"tokens_sent": sent,
"tokens_per_answer": sent // len(calls),
"replayed_context": replayed,
"cache_read_tokens": cache_read,
"line_items": dict(total.most_common()),
}
def bill(reading, input_price, cache_read_price):
# Prices come from the contract in force, never from the code.
full = reading["tokens_sent"] - reading["cache_read_tokens"]
return full * input_price + reading["cache_read_tokens"] * cache_read_priceUntil someone breaks down a real call, an AI budget is not steered; it is endured.
Audit & optimization
Before / after
An AI project launched on messy data
You know whether your data holds up, before the first line of code
AI everywhere except where it pays off
A roadmap prioritized by return on investment
Audit & optimization
The stack
Token audit
Prompt engineering
Caching
Batching
Observability
Evaluation
Audit & optimization
Straight answers
What does an AI audit include?
An inventory of your processes, AI use cases quantified by ROI, the traps flagged early (data, costs, compliance) and a prioritized roadmap. First readout within 48 hours, full report within days.
How do you cut an LLM bill by 30 to 70%?
Caching answers and stable context, the right model for each task, leaner prompts, batching bulk jobs. I first measure where the tokens go, then pull the levers in order of payoff.
What if the audit concludes AI is useless for me?
I tell you, and you save yourself a failed project. It happens. An honest no after a few days of audit beats a letdown after months of building.
Does the audit commit me to anything afterwards?
No. The report and the roadmap are yours: you can build with me, in-house, or with someone else. The audit stands on its own.
What if my data isn't ready?
It's the most common case, and there's nothing shameful about it. The audit says it plainly: what's usable right away, what needs cleaning up or gathering first, and the shortest path to get there. We don't build on sand. And your data stays with you at every step.
Read on this topic
Contact
Ready to go from demo to production?
Reply within 24 hours · first conversation free, no strings attached.