Neha runs categories at Dhaga & Co., a D2C fashion brand shipping roughly 48,000 orders a week. Her return rate is 31%. Of those returns, 44% land in a dropdown field marked "Other" with a free-text box underneath.
That is about 6,500 free-text entries per week. Neha can read a few hundred by hand. The other 6,200 are invisible to her. She cannot fix what she cannot see.
The question is not whether AI can help here. The question is which AI patterns actually work at this scale, and how you wire them together so the output is usable rather than just impressive.
Why one LLM call is not enough
The obvious approach is a single prompt: feed the return text to a model, ask for a category, get an answer.
It fails for three reasons.
First, classification quality varies. Some returns are obvious ("size chart wrong, ordered M but runs like XS"). Others are ambiguous ("not as expected" could be fit, colour, design, or a listing error). A single pass treats both with equal confidence and gives you no way to tell them apart.
Second, synthesis requires a different kind of reasoning than classification. Identifying that a text says "shade mismatch" is pattern recognition. Identifying that twelve different shade-mismatch returns across three vendors and four SKUs point to a specific supplier's colour calibration problem is synthesis. These are not the same cognitive task.
Third, cost compounds fast. At 6,500 rows per week, every token spent on synthesis-level reasoning during the classification step is wasted. You want cheap and fast at volume, smart and expensive only where judgment is actually required.
The solution is to chain three patterns: classify, evaluate, then route and synthesize.
The Haiku and Sonnet split
Every return text goes through claude-haiku-4-5 twice before a single Sonnet token is spent.
The first Haiku call classifies the return into one of seven categories: FIT_SIZE, QUALITY_DEFECT, COLOR_MISMATCH, EXPECTATION_GAP, DELIVERY_DAMAGE, CUSTOMER_ERROR, or UNCLEAR. It also extracts a sub-label ("runs large", "seam split", "shade darker than image") and a confidence score from 0 to 100.
If confidence is 80 or above, the classification moves forward. If it is below 80, a second Haiku call runs an evaluator pass: same return text, same classification, a different prompt asking whether the first call got it right. If the evaluator disagrees, it corrects the category. If final confidence after the second pass is still below 60, the row is flagged for Neha's manual review.
The result: Neha reviews a small, well-defined set of genuinely uncertain cases instead of reading everything. The 6,200 returns she could not reach before are now categorized. The uncertain ones are surfaced cleanly rather than buried.
Haiku costs approximately $0.0003 per classify-and-evaluate pair. At 6,500 rows per week that is under $2.
Routing before synthesis
After evaluation, route_by_category() groups results by their final category. This step looks trivial. It is not.
Synthesis quality depends on the cluster being coherent. A Sonnet prompt that receives 800 FIT_SIZE returns — all describing the same problem with different phrasing — can identify the vendor, the specific SKU, the sub-label that clusters around it, and the one action that would address the root cause. A Sonnet prompt that receives a mixed bag of 800 returns from every category produces vague output that nobody can act on.
The router is what makes the synthesizer useful. You skip it and you get summaries. You keep it and you get recommendations.
Sonnet runs once per category cluster, not once per row. Five clusters at roughly $0.006 each adds about $0.03 to the weekly cost. Total cost at Dhaga's actual scale: approximately $2.50 per week.
That number matters to the CFO. It matters to the FDE presenting it. An ML solution at the same scale would cost orders of magnitude more in infrastructure, maintenance, and retraining cycles.
What the evaluator pattern actually catches
The evaluator's job is not to second-guess good classifications. It only runs on borderline cases, and in practice it catches two things.
The first is category confusion between similar problems. FIT_SIZE and EXPECTATION_GAP look similar when a customer says "the kurta was shorter than I expected." Fit-size if the sizing is wrong relative to the chart. Expectation gap if the listing showed a different length. The initial classifier sometimes mislabels one as the other. The evaluator, reading both the classification and the original text together, catches the mismatch.
The second is UNCLEAR classifications that should not be unclear. A customer writing in Hinglish ("size toh sahi hai but kapda achha nahi laga") may produce a low-confidence classification from the first pass because the model is uncertain whether "kapda achha nahi laga" means quality defect or expectation gap. The evaluator resolves this more often than not. The rows that reach Neha as truly unclear are the ones where both passes failed to reach 60, which means they genuinely need a human eye.
Three things an FDE takes from this build
The model-cost split is a design decision, not an afterthought. Haiku for volume and Sonnet for judgment is not about saving money on a demo. It is the right architecture for any task where you have high-volume pattern recognition feeding low-volume synthesis. The choice of which model runs where determines whether the system is economically viable at production scale.
Routing is the difference between outputs and actions. A system that returns category counts is a dashboard. A system that routes by category before synthesizing returns recommended actions scoped to a specific SKU and vendor. The extra step is two lines of code. The difference in usefulness is not marginal.
The evaluator threshold is a product decision. Sixty percent final confidence as the human-review threshold is a choice, not a law. Set it higher and Neha reviews more rows with less ambiguity. Set it lower and she reviews fewer but misses more borderline misclassifications. The right threshold depends on the cost of a wrong category reaching synthesis versus the cost of Neha's time. That conversation belongs in the scoping call, not in the code.
The live tool is at dhaga-returns-intelligence on Streamlit Cloud. The source is at github.com/backend-bytes127/dhaga-returns-intelligence.