One Friday afternoon, a team pointed its production pipeline at a newly released model after reading a launch thread that called it both cheaper and better on common benchmarks. By Monday, the support queue had filled with malformed JSON and missed tool calls. The model was not broken; it was simply tuned for a different distribution than the prompts that actually reached the service. That gap is easy to close if you look at your own workload before you flip the switch.
Launch threads are not evaluations. When a name such as DeepSeek-V4-Pro-0813 or Grok 4.6 starts trending, the useful question is not whether the public benchmark table is accurate. The useful question is whether that table predicts success on your exact prompts, output shapes, and failure tolerances. A shadow test answers that question with a small amount of code and a list of representative requests.
The workflow below compares an incumbent model with a candidate on the same prompts, then records latency, token usage, and a lightweight pass or fail signal. It does not require a production rollout, and it can run on a free OpenAI-compatible endpoint so the experiment itself does not become a budget discussion. A free OpenAI-compatible endpoint from MonkeyCode can act as the baseline, and its free server option can host the runner. Disclosure: This article was prepared as part of MonkeyCode's product outreach.
Start by collecting prompts that cause real failures, such as a customer request that returned invalid JSON, a code patch with an empty diff, or a tool call that used the wrong schema. These examples are worth more than a thousand generic benchmark rows because they encode the shape of your system's errors. The harness runs each prompt twice, once through the current model and once through the candidate, then compares the results.
import asyncio, json, os, re, time
import httpx
async def call_model(client, cfg, prompt):
started = time.perf_counter()
body = {
'model': cfg['model'],
'messages': [{'role': 'user', 'content': prompt}],
'temperature': 0.0,
'max_tokens': 512,
}
url = cfg['base_url'] + '/chat/completions'
headers = {'Authorization': 'Bearer ' + os.environ.get('API_KEY', '')}
response = await client.post(url, headers=headers, json=body)
elapsed = time.perf_counter() - started
payload = response.json()
usage = payload.get('usage', {})
text = payload['choices'][0]['message']['content'] if payload.get('choices') else ''
return {
'model': cfg['model'],
'latency_s': round(elapsed, 3),
'input_tokens': usage.get('prompt_tokens', 0),
'output_tokens': usage.get('completion_tokens', 0),
'text': text,
}
def check(text, expected):
if expected.get('is_json'):
try:
json.loads(text)
return True
except Exception:
return False
if expected.get('regex'):
return re.search(expected['regex'], text, re.IGNORECASE) is not None
return True
async def run(cfg, prompt, expected):
async with httpx.AsyncClient(timeout=30) as client:
result = await call_model(client, cfg, prompt)
result['pass'] = check(result['text'], expected)
return result
async def main(path):
rows = [json.loads(line) for line in open(path) if line.strip()]
baseline = {'model': os.environ['BASELINE_MODEL'], 'base_url': os.environ['BASELINE_BASE_URL']}
candidate = {'model': os.environ['CANDIDATE_MODEL'], 'base_url': os.environ['CANDIDATE_BASE_URL']}
results = []
for row in rows:
prompt = row['prompt']
expected = row.get('expect', {})
results.append(await run(baseline, prompt, expected))
results.append(await run(candidate, prompt, expected))
print(json.dumps(results, indent=2))
if __name__ == '__main__':
asyncio.run(main(os.environ.get('PROMPT_FILE', 'prompts.jsonl')))
Create a prompt file with two representative failures. The exact model strings are placeholders, so confirm the provider's current list before you run the command.
cat > prompts.jsonl <<'EOF'
{"prompt": "Extract order id from: order #AB-1234 was placed", "expect": {"regex": "AB-1234"}}
{"prompt": "Return a JSON object with keys total and currency for 14 USD", "expect": {"is_json": true}}
EOF
export BASELINE_BASE_URL=https://your-baseline-endpoint.example/v1
export BASELINE_MODEL=your-current-model
export CANDIDATE_BASE_URL=https://candidate-endpoint.example/v1
export CANDIDATE_MODEL=deepseek-v4-pro-0813-or-grok-4.6-placeholder
export API_KEY=your_key_here
python shadow_test.py prompts.jsonl
A useful decision table keeps the comparison short. Suppose the baseline returns 48 passing results with a median latency of 1.2 seconds, while the candidate returns 44 passing results at 0.7 seconds. The candidate is genuinely faster, but it introduces four regressions in the exact failure modes you care about. That is not a reason to reject it; it is a reason to inspect the failing prompts and decide whether they are safe to retrain, route differently, or leave on the incumbent.
| Model | Pass / N | Median latency | Input tokens | Output tokens | Failure notes |
|---|---|---|---|---|---|
| baseline | 48 / 50 | 1.2s | 12,400 | 3,800 | 2 invalid JSON |
| candidate | 44 / 50 | 0.7s | 12,400 | 3,200 | 4 invalid JSON, 2 missed regex |
This harness is deliberately narrow. It does not measure long-context behavior, multi-turn tool use, retry behavior, or non-deterministic failures that appear only under load. A free endpoint also carries limits that can change without notice, so treat the baseline as a convenience rather than a production mirror. If the candidate model string is wrong or the provider renames it, the same script will fail loudly instead of silently testing the wrong model.
Teams with an existing evaluation suite or live canary traffic should not replace those systems with this script. If you already collect production pass rates and can roll back quickly, a small canary deployment will catch problems an offline dataset cannot. This shadow harness is for the earlier stage, when the only evidence you have is a trending title and a vendor's benchmark table.
The next time a model name starts trending, treat the launch post as a lead, not a lease. Collect a small set of your own failing prompts, run the harness against both models, and let the decision table tell you whether the switch is worth a canary. A free server option from MonkeyCode is one zero-cost place to keep that harness running while you collect evidence.
MonkeyCode provides free models that can run this workflow.
Top comments (0)