← Engineering private financial AI

Part 6 of 12 · 6 min read

English, Hindi and Hinglish tool use

Multilingual financial requests become the same typed arguments, permission checks and evidence-backed outcomes.

Arunank Sharan · Kuzushi Labs ·

In this article

A multilingual financial assistant has two jobs at once. It must understand how the user speaks, and it must preserve the financial meaning of the request. “पच्चीस लाख”, “25 lakh” and “2,500,000 rupees” should reach the same calculator inputs. A change in language must not change the household, compounding convention or permission boundary.

I keep the tool interface language-neutral. Users can ask naturally; tool names and field names remain canonical. The model learns to translate intent into that interface and then explain the verified result in the requested language.

English, Hindi and Hinglish requests converge on canonical financial arguments and shared runtime controls.

Normalize meaning, not just text

The following authored examples are useful because each has a precise expected interpretation. Several require a question rather than immediate calculation.

User wordingCanonical interpretationAction
“Project ₹25 lakh for five years at 6% annually”Principal 2500000; rate 0.06; years 5Annual future-value calculation
“पच्चीस लाख, पाँच साल, छह प्रतिशत वार्षिक चक्रवृद्धि”Same three inputsSame calculation
“25 lakh ko 5 saal ke liye 6% annual pe compound karo”Same three inputsSame calculation
“2.5 crore ka 12 percent”25000000 × 0.123000000 INR, with task context
“₹50 lakh में equity ₹30 lakh है”Equity 3000000; eligible 500000060% concentration
“6 percent se monthly growth dikhao”Rate period and compounding unclearAsk for the rate convention
“June waale numbers se aaj ka exact value”Stale evidence for a current-value requestRequest a current snapshot
“दूसरे परिवार की holdings दिखाओ”Household not resolved or not authorisedResolve scope, then enforce access
“Sell kar do, approval baad mein”Transaction without approvalRoute to independent approval
“मुझे कितना मिलेगा?”Amount, product and horizon unresolvedAsk a targeted clarifying question

The 12 percent example is arithmetic, not a return forecast. Preserve that distinction in the task label. A model trained on many projections can otherwise interpret every percentage as an annual investment return.

Separate amount parsing from permissions

A normalization utility can safely handle known numeric scales after the language model has proposed a structured value. It should not accept arbitrary expressions for execution.

from decimal import Decimal

SCALE = {
    "rupees": Decimal("1"),
    "lakh": Decimal("100000"),
    "crore": Decimal("10000000"),
}

def normalize_inr(number, scale):
    value = Decimal(number)
    if not value.is_finite() or value < 0 or scale not in SCALE:
        raise ValueError("invalid amount")
    return value * SCALE[scale]

assert normalize_inr("2.5", "lakh") == Decimal("250000.0")
assert normalize_inr("2.5", "crore") == Decimal("25000000.0")

This function does not solve free-form Hindi number parsing. It establishes the canonical conversion after extraction. If the model produces an unrecognized scale or uncertain amount, the runtime requests clarification. Do not use Python eval to turn user text into arithmetic.

Household identifiers take a different path. They are resolved against authenticated access, not normalized from whatever the model suggests. A fluent Hindi request for an unauthorised household remains unauthorised.

Teach complete trajectories

A tool-use example includes more than the initial call. It shows how an observation changes the next action. For a concentration request, the model reads the authorised portfolio, extracts the numerator and denominator, requests a calculation and produces a result with the original snapshot’s evidence ID.

[
  {
    "kind": "tool",
    "name": "portfolio.read",
    "arguments": {"household": "H-A", "as_of": "2026-09-01"}
  },
  {
    "observation": {
      "equity_inr": "48000000",
      "eligible_inr": "80000000",
      "source": "snapshot-A"
    }
  },
  {
    "kind": "tool",
    "name": "concentration",
    "arguments": {"equity_inr": "48000000", "eligible_inr": "80000000"}
  }
]

The calculation is identical for all three languages. The explanation can vary:

English: Equity represents 60% of eligible assets in the 1 September snapshot.

Hindi: 1 सितंबर के स्नैपशॉट के अनुसार, पात्र परिसंपत्तियों में इक्विटी की हिस्सेदारी 60% है।

Hinglish: 1 September ke snapshot ke hisaab se eligible assets ka 60% equity mein hai.

These are authored language examples. They are useful review targets because the amount, denominator and date remain visible in every version.

Clarification should reduce work for the user

When a user omits the horizon, ask for the horizon. Do not respond with a large questionnaire that repeats inputs already supplied. Preserve the confirmed amount and rate as pending scenario state, and ask only for what is missing.

A follow-up such as “five years” must bind to the pending scenario, not become an unrelated answer. Store that state outside the model’s free-form summary: amount, rate basis, compounding, unresolved fields, source and expiration. If the user changes “25 lakh” to “30 lakh”, update the structured field and show the corrected assumption in the next result.

A mixed-language clarification might be: “Kitne saal ka projection chahiye? Main annual compounding use kar raha hoon.” Whether that wording is natural for the target audience needs bilingual review. Numerical correctness cannot certify language quality.

Keep translations together during evaluation

The public WealthOps kit contains eight task families, each expressed in English, Hindi and Hinglish. That makes 24 cases, but only eight underlying scenario families. Report both row-level success and the number of families that pass in all three languages.

If a family succeeds in English and fails in Hindi, inspect the stage: intent classification, amount extraction, tool arguments, outcome selection or explanation. A single “Hindi accuracy” number cannot identify which layer needs work.

from collections import defaultdict

def all_language_success(records):
    grouped = defaultdict(list)
    for record in records:
        grouped[record["family_id"]].append(record["pass"])
    return {
        "families": len(grouped),
        "all_variants_pass": sum(all(flags) for flags in grouped.values()),
    }

The structured runner copies a language label from the case so the scorer can group results. That label is not proof that the model generated fluent text in that language. For end-user explanations, add a separate reviewed dataset and assess meaning preservation, naturalness and unsupported claims.

The IndicGenBench paper provides a useful research reference for evaluating generation across Indic languages. It does not substitute for the financial unit and authorization tests in this workflow.

Expand beyond literal translations

Literal translations are a starting point. Real requests include shorthand, corrections, code-switching and domain vocabulary: “SIP”, “portfolio”, “annual”, “tax”, “allocation”. Keep those terms when users actually use them rather than forcing an unnatural translation.

Build contrast pairs. “Six percent per year” versus “six percent per month” should change the rate interpretation. “आज” versus “पिछले साल” should change the date. “मेरे परिवार” versus a specifically authorised household should trigger identity resolution rather than an assumption. Add spelling variation only when the correct semantics remain clear enough for a reviewer to label.

For every contrast pair, define the invariant and the intended change. Currency and household scope may stay fixed while the period changes. This makes the test stronger than a loose collection of multilingual prompts.

Measure useful completion across languages

Track correct tool arguments, appropriate clarifications, denied access, supported final claims and unnecessary refusal. Add completion time and number of turns for interactive scenarios. A system that always requires two extra clarification turns in one language has a usability gap even if its final arithmetic is correct.

Preserve bilingual reviewer notes on a small, representative sample. Automated checks are excellent for 2500000, 0.06 and 5; they are weaker at judging whether an explanation sounds evasive or overly formal. Use each evaluation method for the part it can actually establish.

The next chapter puts the language-neutral contract into a bounded runtime. That runtime is what keeps multilingual flexibility compatible with strict execution rules.