[KongchangAI]
· 2 min read· 1,335 words

Jewelry WhatsApp Assistant: Keeping Prices Out of the Model

Jewelry WhatsApp Assistant: Keeping Prices Out of the Model

Keep the model away from price numbers with three isolation layers: classification, a single data source, and output scanning.

A "price isolation" design for an Indian jewelry store's WhatsApp assistant: the model never produces prices. Rules plus a small model classify intent, price intents escalate to sales, and non-price FAQs return approved text. Displayed gold rates come only from a single manual record with a 6-hour freshness limit. Output regex blocks numbers next to currency or weight units as a second defense.

Title

Jewelry WhatsApp Assistant: Keeping Prices Out of the Model

Meta Description

How does a jewelry store's WhatsApp AI assistant avoid quoting wrong prices? This article introduces a price isolation design: intent classification first, price questions escalated directly to humans, a single data source with timestamps, and output-side number scanning as a fallback, with complete Python code examples and testing methods.

Article Content

For a WhatsApp assistant serving an Indian jewelry store, the most dangerous failure isn't an offensive reply—it's confidently quoting a wrong number: yesterday's gold rate, the making charge from an outdated price list, or a figure the model simply made up. This article introduces a "price isolation" design: keep the model entirely away from price-related answers, eliminating wrong quotes at the source.

Jewelry WhatsApp assistant price isolation design diagram

Core Idea: Classify First, Escalate Price Intents Directly to Humans

The first rule of this design is very straightforward: the model never produces numbers. The system first classifies the intent of the user message (rules plus a small model). Once a price-type intent is detected, it never enters the generation stage and is escalated directly to the sales team.

PRICE_INTENTS = {"rate_today", "making_charges", "quote", "exchange_value", "discount"}

def handle(msg):
    intent = classify(msg.text)
    if intent in PRICE_INTENTS:
        return escalate(msg, team="sales", reason=intent)
    if intent in APPROVED_FAQ:
        return reply(msg, APPROVED_FAQ[intent])
    return escalate(msg, team="front_desk", reason="unknown")

For non-price questions, if they match an FAQ reviewed by the store owner (business hours, address, parking, appointments, general policies), the fixed text is returned directly. This content doesn't change daily, so it's safe to let the model "read from the script." All other unknown intents are likewise escalated to the human front desk.

Intent Classification is a fundamental step in dialogue systems: mapping user input to predefined categories (such as "check gold rate," "ask business hours," "complaint") and then routing to different processing paths by category. Common implementations include keyword/regex-based rule matching, embedding-based semantic similarity, and fine-tuned small text classification models. Here a hybrid approach of "rules plus a small model" is used because for price-type intents, recall matters more than precision—it's better to misclassify a non-price question as a price question and escalate it than to miss a single quote request. Rules cover high-frequency expressions (such as "today rate" and "making charge"), while the small model catches variants the rules miss, including Hinglish mixed expressions. The classification result directly determines whether the subsequent generation stage is entered, so the classifier itself also needs continuous regression testing with real messages.

Need to Show the Gold Rate? A Single Data Source with Timestamps

Some store owners want the assistant to share the day's displayed gold rate. In that case, the read must come from a single manually updated record, and if it's past its freshness window, it must be refused.

MAX_AGE = timedelta(hours=6)

def displayed_rate(now):
    rec = rates.latest()
    if rec is None or now - rec["updated_at"] > MAX_AGE:
        return None
    return rec

The reply template explicitly states that this is the in-store display rate at a certain point in time, and that the final price is subject to in-store confirmation. The model fills in nothing here—it only replaces placeholders in the template with the value and update time from the database.

Freshness Check (TTL / Freshness Check) is a common technique in data pipelines to prevent "stale data being treated as real-time data." The approach is to attach an update timestamp to each record, compute now - updated_at when reading, and treat it as invalid once it exceeds a preset threshold. Six hours is chosen here because Indian jewelry stores typically adjust their displayed gold rate manually several times a day, and a record not updated for more than half a day is likely to have drifted from the market. Compared with scheduled cleanup at the database layer, read-time validation is simpler and won't let old data through due to a failed cleanup job. For the model, it only comes into contact with validated structured values and timestamps, and does not participate in judging "whether this price is still accurate"—that judgment stays in deterministic code.

Output-Side Fallback: Scan for Numbers Adjacent to Currency/Weight Units

Even for non-price replies, a text scan should be performed before sending: if the generated content contains a currency symbol or weight unit immediately adjacent to a number (such as ₹, Rs, INR, rupees, g, gm, grams, tola), block the send. This catches cases where the model "helpfully" appends an estimate to an unrelated answer.

MONEY = re.compile(r"(₹|rs\.?|inr|rupees?)\s*\d|\d+\s*(g|gm|grams?|tola)\b", re.I)

def safe_to_send(text):
    return not MONEY.search(text)

This output check is the second line of defense beyond input classification. With both stacked, the probability of price figures leaking from the model side is pushed very low.

Output Guardrail is a check layer executed after model generation and before the message is sent, forming defense in depth with input-side intent classification. Regex is the lightest-weight option among them: it doesn't judge semantics, only matches patterns, so it's fast and predictable, suitable for catching high-confidence risks like "a currency symbol or weight unit immediately adjacent to a number." Its limitations should be noted: regex cannot recognize numbers spelled out in words (such as "twenty-two thousand"), Unicode variants, or line-broken splits, nor can it distinguish legitimate numbers (such as "we open at 10") from quotes. Therefore it should serve as a last net, not the only line of defense; when it triggers, blocking and escalating to a human rather than auto-rewriting avoids introducing new errors.

Escalation Logs Are More Useful Than Accuracy Metrics

Every escalation should be logged with its reason. After a few weeks of running, the logs will tell the store owner what customers ask about most and how fast staff respond. For frontline operations, this information is more valuable than any model accuracy number—it directly points to which FAQs to add, whom to train, and which process to adjust.

Testing: Build a Price-Blocking Test Set from Real Messages

The test set should come from real (anonymized) messages, including Hinglish and voice-transcription text, asserting that every price-related message triggers an escalation. Every time the classifier or prompt is changed, rerun this test suite. This prevents regressions better than a vague "reply quality evaluation."

Why This Design Is Worth Adopting

Its value isn't in how complex the code is, but in using engineering to lock down "what the model shouldn't do." Price is the most sensitive, most volatile, and most easily hallucination-contaminated type of information in jewelry retail; removing it entirely from the generation path buys a predictable safety boundary. For any vertical-industry assistant that involves real-time quotes, this pattern can be transferred directly.

Disclosure: The author runs NxFlowAI, an AI automation agency in Mumbai; the first workflow audit requires 72 hours.

One-line Summary

Keep the model entirely away from price numbers, using three layers of isolation—classification, a single data source, and output scanning—to eliminate wrong quotes.

Paragraph Summary

The article introduces a "price isolation" design for a WhatsApp assistant serving Indian jewelry stores, with the core principle that the model never produces price numbers. The system first classifies intent using rules plus a small model; when a price-type intent is detected (checking gold rate, making charges, quotes, exchange valuation, discounts), it escalates directly to the sales team. Non-price questions that match an owner-reviewed fixed FAQ return fixed text, while all other unknown intents go to the human front desk. If the owner wants to display the day's gold rate, only a single manually maintained record may be read, and it is refused once older than 6 hours; the reply template clearly marks the time point and defers to in-store confirmation. On the output side, a regex scans for text where currency symbols or weight units are adjacent to numbers, blocking the send as a second line of defense. The author emphasizes that escalation logs guide operations better than accuracy metrics, and that the test set should come from real anonymized messages and be rerun every time.

#WhatsApp AI assistant#price isolation#intent classification#output guardrail#jewelry retail automation
Share:

Related articles