← Back to all articles

AI trust

Debug an AI comparison with replayable failure fixtures

A validation function, a classification table and a safe replay workflow.

AI-generated editorial illustration.

1. Capture a minimal failure fixture

Save the expected dimensions, product count and sanitized structured response before rerunning a failed comparison. Do not log API keys, raw customer supplements or full request headers. Preserve a request ID for joining operational events, and keep private payloads in access-controlled storage when genuinely necessary. A fixture should be small enough to explain the first incorrect value. Repeating a paid request until a plausible answer appears is not a diagnosis; it can hide the defect and waste the successful work from other providers.

2. Validate the structure before rendering

Validate shape, numeric type, bounds and winner range separately. Python booleans are integer subclasses, so a generic isinstance(value, int) check can accidentally accept true as a score. The fixture validator below rejects it explicitly. Real adapters should also check the number of reasons and the presence of a usable vote explanation. Keep a missing score distinct from a malformed response: a deliberate unknown may be a valid domain state, while a wrong matrix shape is a protocol failure.

import math

def validate_scores(rows, dimensions, products):
    if not isinstance(rows,list) or len(rows) != dimensions:
        raise ValueError('dimension_count')
    for row in rows:
        if not isinstance(row,list) or len(row) != products:
            raise ValueError('product_count')
        for value in row:
            if value is None:
                continue
            if type(value) not in (int,float) or not math.isfinite(value) or not 0<=value<=100:
                raise ValueError('invalid_score')
    return rows

assert validate_scores([[90,None]],1,2) == [[90,None]]
for bad in [[[True,80]], [[101,80]], [[float('nan'),80]], [[90]]]:
    try:
        validate_scores(bad,1,2)
        raise AssertionError('invalid fixture accepted')
    except ValueError:
        pass
print('malformed fixtures rejected without a model call')

3. Classify the first failing layer

Use stable categories such as identity_confirmation, product_not_found, provider_auth, provider_rate_limit, timeout, database and invalid_output. These categories are safer and easier to aggregate than unrestricted exception messages. Trace the value through identity resolution, sourced facts, rubric selection, adapter validation, aggregation and rendering. If a valid null becomes zero only in the chart, changing the prompt is the wrong fix. If the edition is wrong before scoring starts, every later calculation may be internally consistent and still answer the wrong question.

4. Turn the diagnosis into a regression case

After isolating the cause, replay the fixture with all outbound model calls blocked. Add a focused assertion for the behavior that failed, then test one successful path to avoid breaking valid results. Review whether stored reports were affected; a fixed renderer and a corrected historical dataset are different changes. Keep the incident explanation tied to observable evidence. For disagreements that the fixture cannot resolve, add a review notice rather than automatically changing scores or forcing models to agree.

Compare your options →Explore GEO ↗

All product names, logos and brands belong to their respective owners and are used for identification only. VersusSmart is an independent service and is not affiliated with, sponsored by or endorsed by these providers.