system-design48 min read

Design a Sarvam-Style Multilingual AI Platform — The Complete Guide | Ayodhyya

Design a Sarvam-Style Multilingual AI Platform

Building India's AI backbone: NLP, ASR, TTS, translation, and OCR across 22+ Indic languages at planetary scale

Senior+ Guide 60+ min read 12,000+ words Ayodhyya

Table of Contents

  1. Introduction: Why Multilingual AI Matters
  2. The Multilingual AI Landscape (India Focus)
  3. Functional and Non-Functional Requirements
  4. Capacity Estimation and Back-of-Envelope
  5. Data Model and Storage Schema
  6. High-Level Architecture
  7. API Design
  8. Indic Language NLP Pipeline
  9. Speech-to-Text (ASR) for Indian Languages
  10. Text-to-Speech (TTS)
  11. Machine Translation Engine
  12. Sentiment Analysis and Toxicity Detection
  13. OCR for Indian Scripts
  14. Dataset Curation and Annotation
  15. Model Training Pipeline
  16. Low-Resource Language Handling
  17. Code-Switching and Hinglish Support
  18. Government and BIS Compliance
  19. API Gateway and Developer Ecosystem
  20. Real-Time Inference
  21. Edge Deployment
  22. Monitoring and Observability
  23. Cost Estimation
  24. Testing Strategy
  25. Interview Q and A

1. Introduction: Why Multilingual AI Matters

India is home to 22 scheduled languages, over 19,500 dialects, and approximately 1.4 billion people. Despite English proficiency growing in urban centres, the vast majority of the Indian population, roughly 900 million speakers, interacts with technology primarily in languages other than English. The next wave of internet users, expected to add 400 to 500 million people by 2030, will overwhelmingly speak Hindi, Bengali, Telugu, Marathi, Tamil, Kannada, Malayalam, Gujarati, Odia, Punjabi, Assamese, and dozens of other regional tongues. Building AI systems that can understand, process, and generate content in these languages is not merely a product feature; it is a civilisational necessity.

Sarvam AI, founded in 2023, emerged as India's first homegrown full-stack multilingual AI platform. Unlike generic global AI models that treat Indian languages as afterthoughts, typically supporting Hindi alone among 22 scheduled languages, Sarvam was architected from the ground up to deliver speech-to-text, text-to-speech, machine translation, text understanding, OCR, and content generation across all 22 scheduled languages of India, plus several regional dialects and code-mixed variants such as Hinglish (Hindi-English) and Tanglish (Tamil-English). The platform leverages indigenous training data, culturally aware annotation pipelines, and specialised model architectures to deliver accuracy that monolingual English models simply cannot match when applied to Indian language tasks.

In this comprehensive guide, we walk through the complete system design of a Sarvam-style multilingual AI platform. We cover every architectural layer: from capacity estimation and data modelling through to model training pipelines, real-time inference serving, edge deployment, government compliance, API gateway design, and cost estimation. Each section includes C# implementation code, database schemas, Mermaid diagrams, and tables to provide a production-grade reference architecture. Whether you are building a competing platform, integrating Indic language capabilities into an existing product, or preparing for a senior system design interview, this guide provides the depth and breadth you need.

Interview Context: Multilingual AI platform design is an increasingly popular system design topic at Indian tech companies (Razorpay, PhonePe, Flipkart, Ola, Zomato), global firms expanding into India (Google, Microsoft, Amazon), and AI-native startups (Sarvam, Krutrim, CoRover). It tests your understanding of distributed ML systems, NLP pipelines, data engineering, compliance, and real-time serving at scale.

The design challenge is immense. You must build a system that simultaneously serves ASR requests for spoken Tamil, translates between Marathi and English, performs OCR on handwritten Devanagari text, detects toxicity in mixed Hindi-English social media posts, and generates natural-sounding Telugu speech, all within latency budgets of 200 to 500 milliseconds and at a cost structure viable for India's price-sensitive market. This is fundamentally different from designing a general-purpose LLM API, because Indian languages present unique challenges in tokenisation, script rendering, phonetic mapping, code-switching, and limited high-quality training data.

Consider the scale: India generates approximately 2.5 exabytes of data per day across digital channels. Over 700 million smartphones in the country produce voice messages in dozens of languages. WhatsApp alone handles 20 billion messages per day in India, a large fraction of which are voice notes in Hindi, Bengali, Tamil, Telugu, and other languages. Government digitisation programmes like Digital India are generating massive volumes of scanned documents in Indic scripts that require OCR. Educational technology platforms need TTS and translation to make content accessible in local languages. Healthcare chatbots must understand patient queries in their mother tongue. Every one of these use cases represents millions of API calls per day on a platform like this.

2. The Multilingual AI Landscape (India Focus)

The global NLP landscape has been dominated by English-centric models. GPT-4, PaLM-2, Claude, and Llama were trained predominantly on English data, with other languages represented only fractionally. For Indian languages, this means that even state-of-the-art models exhibit significantly degraded performance. BLEU scores for Hindi-English translation from generic models hover around 28 to 32, while specialised Indic models achieve 42 to 48 on the same benchmarks. For lower-resource languages like Assamese, Manipuri, or Konkani, the gap is even more dramatic: generic models may produce near-unusable output, while purpose-built models achieve functional accuracy.

Key Players in the Indian Multilingual AI Space

OrganisationFocus AreaLanguages SupportedKey Models
Sarvam AIFull-stack Indic AI platform22 scheduled + dialectsSarvam-2B, Saaras (ASR)
AI4Bharat (IIT Madras)Open-source Indic NLP22+ languagesIndicBERT, IndicTrans, Navarasa
Krutrim (Ola)Multilingual LLM10+ Indian languagesKrutrim-7B
Google IndiaIndic language tools13+ languagesMUVR, Google Translate Indic
Microsoft (Bhashini)Government translation22 scheduled languagesIndicTrans v2
CoRover.aiMultilingual chatbots12+ languagesBhashini-powered bots

The Script Challenge

India uses 13 major scripts: Devanagari (Hindi, Marathi, Sanskrit, Nepali), Bengali-Assamese (Bengali, Assamese), Tamil, Telugu, Kannada, Malayalam, Gujarati, Gurmukhi (Punjabi), Odia, and Latin (for English, Konkani, and Manipuri in Roman script). Each script has unique rendering complexities including conjunct consonants in Devanagari, vowel marks (matras) in Bengali, ligatures in Tamil, and complex stacking in Malayalam. A tokeniser trained on English text will fragment Indic text into suboptimal tokens, increasing sequence lengths by 3 to 5x and degrading model performance. The platform must implement script-aware tokenisation that respects Unicode boundaries, vowel-consonant combinations, and Unicode Normalization Form C (NFC) for consistent representation.

The Audio Landscape

Indian language speech presents acoustic challenges that English ASR systems are not designed to handle. Indian languages are primarily syllable-timed rather than stress-timed (as English is), resulting in more uniform syllable durations. Speakers frequently code-switch between languages mid-sentence, producing utterances like "Main project ka deadline kal hai, can you help?" (a mix of Hindi and English). Background noise profiles differ: street noise, temple bells, vehicle horns, and multi-speaker environments in joint family settings create unique acoustic challenges. Accent variation within a single language is enormous: Hindi spoken in Lucknow differs substantially from Hindi spoken in Mumbai or Patna. A robust platform must handle all of these variations gracefully.

Critical Insight: The Bhashini initiative by the Government of India aims to provide real-time translation across all 22 scheduled languages, processing 30 billion translation requests per day by 2027. Any platform targeting the Indian market must align with this national infrastructure.

3. Functional and Non-Functional Requirements

Functional Requirements

#RequirementPriorityDetails
F1Speech-to-Text (ASR)MustTranscribe audio in 22 scheduled languages with Word Error Rate below 12%
F2Text-to-Speech (TTS)MustGenerate natural speech from text in 22 scheduled languages
F3Machine TranslationMustTranslate between any pair of 22 scheduled languages plus English
F4Text UnderstandingMustSentiment analysis, NER, summarisation, classification in Indic languages
F5OCRMustExtract text from images and scanned documents in all Indic scripts
F6Toxicity DetectionShouldDetect hate speech, abusive content, and misinformation in Indic languages
F7Code-Switching SupportShouldHandle Hinglish, Tanglish, and other mixed-language inputs
F8Streaming ASRShouldReal-time transcription with partial results for live audio streams
F9Batch ProcessingShouldAsync processing for large files and bulk operations
F10Developer SDKShouldREST API, Python SDK, JavaScript SDK, and mobile SDKs
F11Voice CloningNiceCustom voice synthesis from a few minutes of reference audio
F12Content GenerationNiceGenerate text content in Indic languages using LLM

Non-Functional Requirements

RequirementTargetRationale
Language Coverage22 scheduled + dialectsConstitutional mandate and market necessity
ASR LatencyBelow 300ms for short utterancesReal-time conversational UX
TTS LatencyBelow 500ms time-to-first-byteInteractive voice response systems
Translation LatencyBelow 200ms for 100-word textReal-time chat and document translation
OCR AccuracyAbove 95% character accuracy for printed textGovernment document processing
Availability99.95%Government and enterprise SLA
Throughput10,000 requests/second aggregateScale for 100M+ daily active users
Cost per 1M charactersBelow 2 INRIndia price sensitivity requirement
Data ResidencyIndia-onlyData Protection Bill compliance

4. Capacity Estimation and Back-of-Envelope

Daily Volume Estimates

MetricCalculationResult
Daily ASR requests500M voice messages x 20% processed via API100M requests/day
Daily TTS requests200M e-learning + IVR + accessibility sessions200M requests/day
Daily Translation requests500M messages x 10% cross-language50M requests/day
Daily OCR requests50M document scans + 20M images70M requests/day
Daily NLP requests1B social media x 5% moderation50M requests/day
Total daily requestsSum of all servicesApprox 470M requests/day
Average QPS470M / 86,400Approx 5,440 QPS
Peak QPS (3x)5,440 x 3Approx 16,320 QPS

Storage Estimates

Data TypeSize per UnitDaily VolumeDaily Storage
Audio inputs (ASR)30 seconds = 480 KB (16-bit PCM)100M filesApprox 48 TB/day
Audio outputs (TTS)10 seconds = 160 KB200M filesApprox 32 TB/day
OCR images2 MB average70M imagesApprox 140 TB/day
Text metadata500 bytes per request470M requestsApprox 235 GB/day
Model artifactsStaticN/AApprox 2 TB total
Training dataStatic plus growingN/AApprox 50 TB total
Key Insight: Audio data dominates storage. A single hour of audio at 16-bit 16kHz mono PCM is approximately 115 MB. With 300M audio-related requests per day averaging 20 seconds each, the platform generates approximately 80 TB of audio data daily. Lifecycle policies must aggressively move audio to cold storage after processing, keeping hot storage only for recent requests that might need replay or reprocessing.

GPU Compute Estimates

ModelGPU TypeBatch SizeLatencyGPU Hours/Day
ASR (Whisper-large-v3 fine-tuned)A100 80GB32150ms per utteranceApprox 4,200
TTS (VITS2 fine-tuned)A100 80GB16200ms per utteranceApprox 5,500
Translation (NLLB-200 fine-tuned)A100 80GB6480ms per sentenceApprox 1,100
OCR (Donut fine-tuned)A100 80GB8350ms per pageApprox 3,400
Text Understanding (IndicBERT)A100 80GB12830ms per requestApprox 420
Toxicity DetectionA100 80GB25615ms per requestApprox 210
Total GPU fleetApproximately 600 to 800 A100 equivalentsApprox 14,830

Bandwidth Estimates

Incoming audio traffic at 100M ASR requests of 30 seconds each equals roughly 48 TB per day, or approximately 4.4 Gbps sustained. Outgoing audio from TTS adds another 2.9 Gbps. Text-based APIs (translation, NLP, toxicity) add approximately 500 Mbps. Total bandwidth requirement is approximately 8 to 10 Gbps sustained, peaking at 25 to 30 Gbps during peak hours. This requires multiple 10 Gbps links and geographic distribution across at least two Indian data centre regions (Mumbai and Chennai, or Mumbai and Hyderabad) for low-latency access from all parts of India.

5. Data Model and Storage Schema

Entity Relationship

erDiagram LANGUAGE { varchar code PK "ISO 639-1" varchar name varchar native_name varchar script boolean is_scheduled float resource_level } MODEL { uuid id PK varchar name varchar type varchar version jsonb supported_languages varchar model_path float accuracy_score datetime deployed_at } INFERENCE_REQUEST { uuid id PK varchar service_type varchar source_language varchar target_language bigint user_id FK varchar status float latency_ms datetime created_at } TRAINING_DATASET { uuid id PK varchar name varchar language_code FK varchar domain bigint sample_count float quality_score varchar storage_path } USER { bigint id PK varchar email varchar api_key varchar org_name int plan_tier jsonb usage_limits } AUDIO_FILE { uuid id PK varchar storage_path varchar language_code FK int sample_rate int duration_ms varchar format } USER ||--o{ INFERENCE_REQUEST : submits LANGUAGE ||--o{ TRAINING_DATASET : trains LANGUAGE ||--o{ AUDIO_FILE : spoken_in MODEL ||--o{ INFERENCE_REQUEST : serves

PostgreSQL Schema

SQL
CREATE TABLE languages (
    code VARCHAR(10) PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    native_name VARCHAR(100) NOT NULL,
    script VARCHAR(50) NOT NULL,
    is_scheduled BOOLEAN DEFAULT true,
    resource_level FLOAT DEFAULT 0.5,
    bcp47_tag VARCHAR(20) NOT NULL,
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE models (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name VARCHAR(200) NOT NULL,
    model_type VARCHAR(20) NOT NULL,
    version VARCHAR(50) NOT NULL,
    supported_languages JSONB DEFAULT '[]',
    model_path TEXT NOT NULL,
    config JSONB DEFAULT '{}',
    accuracy_score FLOAT,
    is_active BOOLEAN DEFAULT true,
    deployed_at TIMESTAMP DEFAULT NOW(),
    created_at TIMESTAMP DEFAULT NOW(),
    UNIQUE(name, version)
);

CREATE TABLE inference_requests (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    service_type VARCHAR(20) NOT NULL,
    source_language VARCHAR(10) REFERENCES languages(code),
    target_language VARCHAR(10) REFERENCES languages(code),
    model_id UUID REFERENCES models(id),
    user_id BIGINT REFERENCES users(id),
    status VARCHAR(20) DEFAULT 'pending',
    input_size_bytes BIGINT,
    output_size_bytes BIGINT,
    latency_ms FLOAT,
    request_metadata JSONB DEFAULT '{}',
    created_at TIMESTAMP DEFAULT NOW(),
    completed_at TIMESTAMP
);

CREATE TABLE training_datasets (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name VARCHAR(200) NOT NULL,
    language_code VARCHAR(10) REFERENCES languages(code),
    domain VARCHAR(100),
    sample_count BIGINT DEFAULT 0,
    total_hours FLOAT DEFAULT 0,
    quality_score FLOAT,
    storage_path TEXT NOT NULL,
    license_type VARCHAR(100),
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE audio_files (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    storage_path TEXT NOT NULL,
    language_code VARCHAR(10) REFERENCES languages(code),
    sample_rate INTEGER DEFAULT 16000,
    bit_depth INTEGER DEFAULT 16,
    channels INTEGER DEFAULT 1,
    duration_ms INTEGER,
    format VARCHAR(20) DEFAULT 'wav',
    transcription TEXT,
    speaker_id VARCHAR(100),
    quality_score FLOAT,
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_inference_requests_user ON inference_requests(user_id, created_at DESC);
CREATE INDEX idx_inference_requests_status ON inference_requests(status, created_at DESC);
CREATE INDEX idx_inference_requests_language ON inference_requests(source_language, target_language);
CREATE INDEX idx_audio_files_language ON audio_files(language_code, created_at DESC);
CREATE INDEX idx_models_active ON models(model_type, is_active) WHERE is_active = true;

Redis Cache Schema

C#
public class IndicCacheService
{
    private readonly IConnectionMultiplexer _redis;
    private const string MODEL_CACHE_PREFIX = "model:active:";
    private const string LANGUAGE_CACHE_PREFIX = "lang:meta:";
    private const string TRANSLATION_CACHE_PREFIX = "mt:cache:";
    private const int DEFAULT_TTL_HOURS = 24;

    public async Task<CachedTranslationResult?> GetCachedTranslationAsync(
        string sourceLang, string targetLang, string contentHash)
    {
        var key = $"{TRANSLATION_CACHE_PREFIX}{sourceLang}:{targetLang}:{contentHash}";
        var db = _redis.GetDatabase();
        var cached = await db.StringGetAsync(key);
        return cached.HasValue
            ? JsonSerializer.Deserialize<CachedTranslationResult>(cached)
            : null;
    }

    public async Task CacheTranslationAsync(
        string sourceLang, string targetLang, string contentHash,
        CachedTranslationResult result, TimeSpan? ttl = null)
    {
        var key = $"{TRANSLATION_CACHE_PREFIX}{sourceLang}:{targetLang}:{contentHash}";
        var db = _redis.GetDatabase();
        var serialized = JsonSerializer.Serialize(result);
        await db.StringSetAsync(key, serialized, ttl ?? TimeSpan.FromHours(DEFAULT_TTL_HOURS));
    }

    public async Task<ModelConfig?> GetActiveModelAsync(string modelType, string language)
    {
        var key = $"{MODEL_CACHE_PREFIX}{modelType}:{language}";
        var db = _redis.GetDatabase();
        var cached = await db.HashGetAllAsync(key);
        return cached.Length > 0 ? MapToModelConfig(cached) : null;
    }
}
Design Decision: We use PostgreSQL as the primary OLTP store for transactional data (users, requests, model metadata), TimescaleDB for time-series metrics on inference latency and throughput, Redis for hot caching of model routing and translation results, and S3-compatible object storage for audio files, model weights, and training data. This polyglot persistence approach ensures each data type is stored optimally.

6. High-Level Architecture

graph TB subgraph Clients A[Web App] B[Mobile SDK] C[REST API] D[Voice IVR] end subgraph "API Gateway Layer" E[Kong and APISIX Gateway] F[Rate Limiter] G[Auth and API Key Validation] H[Request Router] end subgraph "Service Mesh - Istio" I[ASR Service] J[TTS Service] K[Translation Service] L[OCR Service] M[NLP Service] N[Toxicity Service] end subgraph "ML Inference Layer" O[GPU Worker Pool] P[Model Registry] Q[Model Cache] R[A/B Testing Router] end subgraph "Data Layer" S[PostgreSQL Cluster] T[Redis Cluster] U[TimescaleDB] V[S3 Object Store] W[Elasticsearch] end subgraph "Training Pipeline" X[Data Curation] Y[Annotation Platform] Z[Training Orchestrator] AA[Model Evaluator] AB[Model Registry Deploy] end A --> E B --> E C --> E D --> E E --> F --> G --> H H --> I H --> J H --> K H --> L H --> M H --> N I --> O J --> O K --> O L --> O M --> O N --> O O --> P O --> Q O --> R I --> S I --> T K --> S K --> T L --> V M --> S N --> S S --> X X --> Y --> Z --> AA --> AB AB --> P

Architecture Principles

  • Language-Aware Routing: Every request carries a language code. The API gateway routes to language-specific model instances to maximise cache hits and reduce cold-start latency.
  • GPU Pool Isolation: Each model type (ASR, TTS, MT, OCR) runs in its own GPU resource pool to prevent noisy-neighbour problems. High-priority ASR models are never starved by batch OCR jobs.
  • Graceful Degradation: If a specific language model is unavailable, the system falls back to a generic multilingual model (with reduced accuracy) rather than failing the request entirely.
  • Edge Caching: Frequent translations and TTS outputs are cached at edge nodes in Mumbai, Delhi, Chennai, and Hyderabad to serve requests within 50ms for cache hits.
  • India-First Data Residency: All data is stored and processed exclusively within Indian data centres. No audio or text data leaves Indian borders at any point in the pipeline.

Service Breakdown

ServiceResponsibilityLanguageGPU TypeInstances
ASR ServiceAudio transcriptionC# and Python gRPCA100200
TTS ServiceSpeech synthesisC# and Python gRPCA100250
Translation ServiceText translationC# and Python gRPCA10080
OCR ServiceDocument image OCRC# and Python gRPCA100120
NLP ServiceSentiment, NER, summarisationC# and Python gRPCT460
Toxicity ServiceContent moderationC# and Python gRPCT430

7. API Design

Speech-to-Text API

HTTP
POST /v1/asr/transcribe HTTP/1.1
Host: api.sarvam-platform.in
Authorization: Bearer sk-xxxxxxxxxxxx
Content-Type: multipart/form-data

Form Fields:
  language: hi
  model: saaras-v2
  enable_timestamps: true
  enable_punctuation: true
  audio: [binary WAV/OGG/MP3 data]

Response 200:
{
  "request_id": "req_abc123def456",
  "language": "hi",
  "results": [
    {
      "transcript": "Namaste, aaj ka mausam bahut achha hai.",
      "confidence": 0.96,
      "words": [
        {"word": "Namaste", "start_ms": 0, "end_ms": 620, "confidence": 0.98},
        {"word": "aaj", "start_ms": 780, "end_ms": 940, "confidence": 0.97},
        {"word": "ka", "start_ms": 960, "end_ms": 1050, "confidence": 0.99},
        {"word": "mausam", "start_ms": 1100, "end_ms": 1480, "confidence": 0.95},
        {"word": "bahut", "start_ms": 1520, "end_ms": 1800, "confidence": 0.97},
        {"word": "achha", "start_ms": 1840, "end_ms": 2200, "confidence": 0.94}
      ],
      "duration_ms": 2800
    }
  ],
  "model_version": "saaras-v2.1"
}

Machine Translation API

HTTP
POST /v1/translate HTTP/1.1
Host: api.sarvam-platform.in
Authorization: Bearer sk-xxxxxxxxxxxx
Content-Type: application/json

{
  "input": [
    {"text": "Bharat ek mahan desh hai jahan vividhta mein ekta ka sandesh diya jata hai."}
  ],
  "source_language": "hi",
  "target_language": "en",
  "mode": "formal",
  "model": "indictranslate-v3"
}

Response 200:
{
  "request_id": "req_xyz789",
  "translations": [
    {
      "translated_text": "India is a great country where the message of unity in diversity is conveyed.",
      "confidence": 0.91,
      "source_language": "hi",
      "target_language": "en"
    }
  ],
  "model_version": "indictranslate-v3.2"
}

Text-to-Speech API

HTTP
POST /v1/tts/synthesize HTTP/1.1
Host: api.sarvam-platform.in
Authorization: Bearer sk-xxxxxxxxxxxx
Content-Type: application/json

{
  "input": "Namaste, aapka swagat hai. Aaj ka mausam bahut achha hai.",
  "language": "hi",
  "voice_id": "FEMALE_1",
  "speed": 1.0,
  "output_format": "wav",
  "sample_rate": 22050
}

Response 200:
{
  "request_id": "req_aud123",
  "audio_url": "https://storage.sarvam-platform.in/tts-output/req_aud123.wav",
  "duration_ms": 4200,
  "language": "hi",
  "expires_at": "2026-06-29T10:00:00Z"
}

Streaming ASR API (WebSocket)

C#
public class StreamingAsrController : ControllerBase
{
    [HttpPost("/v1/asr/stream/start")]
    public async Task<ActionResult> StartStream([FromBody] StreamConfig config)
    {
        var sessionId = Guid.NewGuid().ToString();
        var channel = await _asrService.OpenStreamAsync(new StreamRequest
        {
            SessionId = sessionId,
            Language = config.Language,
            Model = config.Model,
            EnableInterimResults = true,
            SampleRate = config.SampleRate ?? 16000
        });
        return Ok(new { session_id = sessionId, ws_url = $"/v1/asr/stream/{sessionId}" });
    }

    [HttpPost("/v1/asr/stream/{sessionId}/chunk")]
    public async Task StreamChunk(string sessionId, [FromBody] AudioChunk chunk)
    {
        var intermediate = await _asrService.ProcessChunkAsync(sessionId, chunk.AudioData);
        if (intermediate.HasPartialResult)
        {
            await WebSocketHub.SendAsync(sessionId, new
            {
                type = "interim",
                transcript = intermediate.PartialTranscript,
                is_final = false
            });
        }
    }

    [HttpPost("/v1/asr/stream/{sessionId}/end")]
    public async Task<ActionResult> EndStream(string sessionId)
    {
        var final = await _asrService.EndStreamAsync(sessionId);
        return Ok(new { transcript = final.Transcript, confidence = final.Confidence });
    }
}

8. Indic Language NLP Pipeline

The NLP pipeline is the intelligence layer that powers text understanding across all Indic languages. Unlike English NLP pipelines that can leverage mature tools like spaCy and Hugging Face Transformers out-of-the-box, Indic language NLP requires custom components for tokenization, sentence segmentation, part-of-speech tagging, named entity recognition, and dependency parsing. The pipeline must handle Unicode complexity, multi-script input, code-mixed text, and varying levels of linguistic resource availability across India's 22 scheduled languages.

Pipeline Architecture

graph LR A[Raw Text Input] --> B[Script Detection] B --> C[Unicode Normalization NFC] C --> D[Language Identification] D --> E[Script-Aware Tokenization] E --> F[Sentence Segmentation] F --> G[POS Tagging] F --> H[NER] F --> I[Sentiment Analysis] F --> J[Toxicity Detection] G --> M[Structured Output] H --> M I --> M J --> M

Script-Aware Tokenizer

C#
public class IndicScriptTokenizer
{
    private readonly Dictionary<string, ScriptConfig> _scriptConfigs;

    public IndicScriptTokenizer()
    {
        _scriptConfigs = new Dictionary<string, ScriptConfig>
        {
            ["devanagari"] = new ScriptConfig
            {
                UnicodeStart = 0x0900, UnicodeEnd = 0x097F,
                ConjunctHandling = ConjunctStrategy.SplitByAkshara,
                MatraJoining = true
            },
            ["bengali"] = new ScriptConfig
            {
                UnicodeStart = 0x0980, UnicodeEnd = 0x09FF,
                ConjunctHandling = ConjunctStrategy.Preserve,
                MatraJoining = true
            },
            ["tamil"] = new ScriptConfig
            {
                UnicodeStart = 0x0B80, UnicodeEnd = 0x0BFF,
                ConjunctHandling = ConjunctStrategy.Preserve,
                MatraJoining = true
            },
            ["telugu"] = new ScriptConfig
            {
                UnicodeStart = 0x0C00, UnicodeEnd = 0x0C7F,
                ConjunctHandling = ConjunctStrategy.Preserve,
                MatraJoining = true
            },
            ["kannada"] = new ScriptConfig
            {
                UnicodeStart = 0x0C80, UnicodeEnd = 0x0CFF,
                ConjunctHandling = ConjunctStrategy.Preserve,
                MatraJoining = true
            },
            ["malayalam"] = new ScriptConfig
            {
                UnicodeStart = 0x0D00, UnicodeEnd = 0x0D7F,
                ConjunctHandling = ConjunctStrategy.LigatureAware,
                MatraJoining = true
            }
        };
    }

    public List<string> Tokenize(string text, string scriptHint = "auto")
    {
        var script = scriptHint == "auto" ? DetectScript(text) : scriptHint;
        var config = _scriptConfigs.GetValueOrDefault(script);
        var tokens = new List<string>();
        var currentToken = new StringBuilder();

        foreach (var rune in text.EnumerateRunes())
        {
            if (IsWhitespace(rune))
            {
                if (currentToken.Length > 0)
                {
                    tokens.Add(currentToken.ToString());
                    currentToken.Clear();
                }
                continue;
            }
            if (config != null && IsInScriptRange(rune, config) && IsMatra(rune) && currentToken.Length > 0)
            {
                currentToken.Append(rune.ToString());
            }
            else
            {
                if (currentToken.Length > 0)
                {
                    tokens.Add(currentToken.ToString());
                    currentToken.Clear();
                }
                currentToken.Append(rune.ToString());
            }
        }
        if (currentToken.Length > 0) tokens.Add(currentToken.ToString());
        return tokens;
    }
}

Named Entity Recognition

NER in Indian languages faces unique challenges. Person names vary enormously across languages, location names may use local scripts or transliterated forms, and organisation names often appear in English even within otherwise Indic-language text. The platform uses a multi-granularity NER approach: a character-level CNN for robust handling of unknown words and morphological variation, combined with a word-level BiLSTM-CRF for sequence labelling. The model is trained on datasets from multiple NER shared tasks (IIIT-H datasets, IIT Bombay NER corpora) and supplemented with automatically labelled data from Wikipedia infoboxes and government gazettes in all 22 scheduled languages.

9. Speech-to-Text (ASR) for Indian Languages

Speech-to-Text is the most requested capability on the platform, driven by India's voice-first internet usage pattern. WhatsApp voice notes, IVR systems, dictation tools, and voice search all require accurate transcription across Indian languages. The platform's ASR engine, codenamed Saaras, is a fine-tuned variant of OpenAI's Whisper architecture, trained on over 100,000 hours of Indian language speech data curated from government proceedings (Sansad TV), audiobooks (Sahitya Akademi), radio broadcasts (All India Radio), YouTube videos, and crowdsourced data collected through the IndicVoices project.

ASR Architecture

graph TB A[Raw Audio] --> B[Pre-processing] B --> C[Voice Activity Detection] C --> D[Feature Extraction Mel Spectrogram] D --> E[Whisper Encoder] E --> F[Language-Specific Decoder Head] F --> G[CTC and Attention Decoding] G --> H[Post-processing] H --> I[Punctuation Restoration] I --> J[Number and Date Normalization] J --> K[Final Transcript]

ASR Service Implementation

C#
public class AsrInferenceService : IAsrService
{
    private readonly IModelRegistry _modelRegistry;
    private readonly IAudioPreprocessor _preprocessor;
    private readonly IGrpcClient<WhisperService.WhisperServiceClient> _whisperClient;
    private readonly ICacheService _cache;

    public async Task<AsrResult> TranscribeAsync(AsrRequest request)
    {
        var cacheKey = ComputeAudioHash(request.AudioData, request.Language);
        var cached = await _cache.GetAsync<AsrResult>($"asr:{cacheKey}");
        if (cached != null) return cached;

        var model = await _modelRegistry.GetActiveModelAsync("asr", request.Language)
            ?? throw new ModelNotFoundException($"No ASR model for: {request.Language}");

        var processedAudio = await _preprocessor.PreprocessAsync(request.AudioData, new AudioConfig
        {
            TargetSampleRate = 16000, TargetBitDepth = 16,
            NormalizeVolume = true, RemoveNoise = request.EnableDenoising, TrimSilence = true
        });

        var spectrogram = AudioFeatureExtractor.ExtractMelSpectrogram(processedAudio, new MelConfig
        {
            SampleRate = 16000, NFFT = 400, HopLength = 160, NMelBins = 80
        });

        var grpcRequest = new TranscribeRequest
        {
            ModelId = model.Id.ToString(),
            SpectrogramData = { spectrogram.Flatten() },
            Language = request.Language,
            EnableTimestamps = request.EnableTimestamps,
            BeamSize = request.BeamSize ?? 5
        };

        var response = await _whisperClient.TranscribeAsync(grpcRequest);
        var result = new AsrResult
        {
            RequestId = request.RequestId,
            Transcript = response.Text,
            Language = response.DetectedLanguage,
            Confidence = response.AverageConfidence,
            Duration = TimeSpan.FromMilliseconds(response.AudioDurationMs),
            WordTimings = response.WordTimings.Select(wt => new WordTiming
            {
                Word = wt.Word,
                Start = TimeSpan.FromMilliseconds(wt.StartMs),
                End = TimeSpan.FromMilliseconds(wt.EndMs),
                Confidence = wt.Confidence
            }).ToList()
        };

        await _cache.SetAsync($"asr:{cacheKey}", result, TimeSpan.FromHours(1));
        return result;
    }
}

Training Data for Indian ASR

LanguageHoursSourceWER Target
Hindi15,000Sansad TV, AIR, YouTubeBelow 8%
Bengali8,000Bangla YouTube, RadioBelow 10%
Tamil10,000Sun TV, speechesBelow 9%
Telugu9,000TV debates, audiobooksBelow 10%
Marathi6,000Lokmat, Zee24TasBelow 11%
Kannada5,000Public Radio, podcastsBelow 12%
Malayalam5,500Manorama, TV channelsBelow 11%
Gujarati4,000Guj Samachar, radioBelow 12%
Odia3,000OTV, radioBelow 14%
Punjabi4,500PTC News, musicBelow 12%
Assamese2,000Doordarshan, radioBelow 15%
Others (11)2,000 eachMixed sourcesBelow 15%
Interview Context: ASR for Indian languages is significantly harder than English due to morphological complexity, agglutination (Tamil, Malayalam), lack of standardised orthography in some dialects, and code-switching. Discuss how your architecture handles these challenges by using language-specific decoder heads rather than a single monolithic model.

10. Text-to-Speech (TTS)

The TTS engine converts text in any of the 22 scheduled Indian languages into natural, intelligible speech. The platform supports multiple voice personas per language (typically 4 to 6 male and 4 to 6 female voices), each trained on a single professional voice artist to ensure consistency and naturalness. The TTS system uses a VITS2-based architecture with language-specific acoustic models and a shared multi-lingual HiFi-GAN vocoder for waveform generation. Prosody modelling is critical for Indian languages, where tonal patterns carry semantic meaning: a rising intonation at the end of a Hindi sentence turns a statement into a question, while tonal variations in Tamil can change word meaning entirely.

TTS Pipeline Architecture

graph LR A[Input Text] --> B[Text Normalization] B --> C[Phoneme Conversion] C --> D[Prosody Prediction] D --> E[Acoustic Model VITS2] E --> F[HiFi-GAN Vocoder] F --> G[Post-processing] G --> H[Output Audio]

TTS Text Normalization

C#
public class IndicTextNormalizer
{
    public async Task<string> NormalizeAsync(string text, string language)
    {
        var normalized = text.Normalize(NormalizationForm.FormC);
        normalized = ExpandNumbers(normalized, language);
        normalized = ExpandAbbreviations(normalized, language);
        normalized = NormalizeDateTime(normalized, language);
        normalized = NormalizeCurrency(normalized, language);
        normalized = NormalizePunctuation(normalized);
        return normalized;
    }

    private string ExpandNumbers(string text, string language)
    {
        var numberPattern = @"\b\d+(?:\.\d+)?\b";
        return Regex.Replace(text, numberPattern, match =>
        {
            var number = double.Parse(match.Value);
            return language switch
            {
                "hi" => ExpandHindiNumber(number),
                "bn" => ExpandBengaliNumber(number),
                "ta" => ExpandTamilNumber(number),
                "te" => ExpandTeluguNumber(number),
                _ => ExpandGenericIndicNumber(number, language)
            };
        });
    }

    private string ExpandHindiNumber(double number)
    {
        if (number >= 10000000)
            return $"{ExpandHindiNumber(number / 10000000)} crore";
        if (number >= 100000)
            return $"{ExpandHindiNumber(number / 100000)} lakh";
        if (number >= 1000)
            return $"{ExpandHindiNumber(number / 1000)} hazaar";
        var ones = new[] { "", "ek", "do", "teen", "chaar", "paanch",
            "chah", "saat", "aath", "nau", "das" };
        if (number < ones.Length) return ones[(int)number];
        return number.ToString();
    }
}

Supported Voices

LanguageFemale VoicesMale VoicesTotal
Hindi6511
Bengali448
Tamil448
Telugu437
Marathi336
Kannada336
Malayalam336
Gujarati336
Punjabi336
Odia224
Others (12)2 each2 each48

11. Machine Translation Engine

The machine translation engine supports all 462 possible language pairs among India's 22 scheduled languages, plus 22 additional pairs with English. The system uses a fine-tuned variant of Meta's NLLB-200 (No Language Left Behind) architecture, supplemented with domain-specific adapters for government, legal, medical, and technical text. Translation quality is benchmarked using BLEU, COMET, and human evaluation on standard test sets, with quality targets of 40+ BLEU for high-resource pairs (Hindi-English, Bengali-English) and 25+ BLEU for low-resource pairs (Manipuri-Konkani).

Translation Service Implementation

C#
public class TranslationService : ITranslationService
{
    private readonly IModelRegistry _models;
    private readonly ICacheService _cache;

    public async Task<TranslationResult> TranslateAsync(TranslationRequest request)
    {
        if (request.SourceLanguage == request.TargetLanguage)
            return TranslationResult.Identity(request.Input);

        var cacheHash = ComputeContentHash(request.Input, request.Mode);
        var cacheKey = $"mt:{request.SourceLanguage}:{request.TargetLanguage}:{cacheHash}";
        var cached = await _cache.GetAsync<TranslationResult>(cacheKey);
        if (cached != null) return cached;

        var model = await _models.GetActiveModelAsync("mt",
            $"{request.SourceLanguage}-{request.TargetLanguage}")
            ?? await _models.GetActiveModelAsync("mt", "multilingual");

        var inferenceRequest = new TranslationInferenceRequest
        {
            ModelId = model.Id,
            SourceTexts = request.Input.Split('\n')
                .Where(line => !string.IsNullOrWhiteSpace(line)).ToArray(),
            SourceLanguage = Bcp47ToModelLang(request.SourceLanguage),
            TargetLanguage = Bcp47ToModelLang(request.TargetLanguage),
            MaxNewTokens = 512, BeamSize = 5
        };

        var rawResult = await CallInferenceEndpoint<RawTranslationResponse>(
            "/translate", inferenceRequest);

        var result = new TranslationResult
        {
            RequestId = request.RequestId,
            Translations = rawResult.TranslatedTexts.Select((text, idx) =>
                new TranslatedSegment
            {
                SourceText = inferenceRequest.SourceTexts[idx],
                TranslatedText = text,
                Confidence = rawResult.Scores?[idx] ?? 0.0f
            }).ToList(),
            SourceLanguage = request.SourceLanguage,
            TargetLanguage = request.TargetLanguage
        };

        await _cache.SetAsync(cacheKey, result, TimeSpan.FromHours(6));
        return result;
    }

    private string Bcp47ToModelLang(string bcp47) => bcp47 switch
    {
        "hi" => "hin_Deva", "bn" => "ben_Beng", "ta" => "tam_Taml",
        "te" => "tel_Telu", "mr" => "mr_Deva", "kn" => "kan_Knda",
        "ml" => "mal_Mlym", "gu" => "guj_Gujr", "pa" => "pan_Guru",
        "or" => "ory_Orya", "as" => "asm_Beng", "en" => "eng_Latn",
        _ => bcp47
    };
}

Translation Quality Benchmarks

Language PairBLEUCOMETHuman Rating (1-5)
Hindi to English44.20.874.3
English to Hindi41.80.854.2
Bengali to English39.50.834.1
Tamil to English37.10.814.0
Hindi to Bengali32.60.783.8
Tamil to Telugu28.40.733.5
Assamese to English28.80.723.4
Manipuri to Hindi22.10.653.1
Konkani to English24.50.683.2

12. Sentiment Analysis and Toxicity Detection

Sentiment analysis and toxicity detection are critical for social media monitoring, customer feedback analysis, and content moderation in India. The challenge is enormous: toxic content in Indian languages often uses creative transliteration, euphemisms, and culturally specific slang that automated systems struggle to detect. The platform's toxicity detection system operates in real-time, processing social media feeds and flagging content with less than 50ms latency.

Toxicity Detection Performance

LanguageF1 ScorePrecisionRecallLatency P99
Hindi0.940.960.9212ms
Bengali0.910.930.8914ms
Tamil0.900.920.8815ms
Hinglish0.880.900.8618ms
Telugu0.890.910.8714ms
Marathi0.870.890.8515ms

13. OCR for Indian Scripts

OCR for Indian scripts is substantially more challenging than OCR for Latin text. Indic scripts have complex character shapes, extensive use of conjunct characters (combined consonants), vowel marks that attach above and below the base line, and inconsistent spacing between characters. Handwritten Indic script OCR is even harder due to personal variation in stroke formation. The platform supports OCR across all 13 major Indic scripts used for the 22 scheduled languages, handling both printed and handwritten text. The system processes approximately 70 million document pages per day, including government forms, educational certificates, land records, and medical prescriptions.

OCR Service Implementation

C#
public class IndicOcrService : IOcrService
{
    private readonly IModelRegistry _modelRegistry;
    private readonly IImagePreprocessor _preprocessor;
    private readonly ILayoutAnalyzer _layoutAnalyzer;

    public async Task<OcrResult> ExtractTextAsync(OcrRequest request)
    {
        var preprocessed = await _preprocessor.PreprocessAsync(request.ImageData, new PreprocessConfig
        {
            Deskew = true, Binarize = true, Denoise = true,
            UpscaleFactor = 2.0f, TargetDPI = 300
        });

        var detectedScript = await DetectScriptAsync(preprocessed);
        var detectedLanguage = await DetectLanguageAsync(preprocessed, detectedScript);
        var model = await _modelRegistry.GetActiveModelAsync("ocr", detectedLanguage)
            ?? throw new ModelNotFoundException($"No OCR model for: {detectedLanguage}");

        var layoutBlocks = await _layoutAnalyzer.AnalyzeAsync(preprocessed);
        var results = new List<OcrBlock>();

        foreach (var block in layoutBlocks.OrderBy(b => b.Y).ThenBy(b => b.X))
        {
            var croppedImage = CropImage(preprocessed, block.BoundingBox);
            var ocrText = await RecognizeTextAsync(croppedImage, model, detectedLanguage);
            results.Add(new OcrBlock
            {
                Text = ocrText.Text,
                Confidence = ocrText.Confidence,
                BlockType = block.Type,
                BoundingBox = block.BoundingBox
            });
        }

        return new OcrResult
        {
            RequestId = request.RequestId,
            DetectedScript = detectedScript,
            DetectedLanguage = detectedLanguage,
            FullText = string.Join("\n", results.Select(r => r.Text)),
            Blocks = results
        };
    }
}

OCR Performance by Script

ScriptLanguagesPrinted CERHandwritten CER
DevanagariHindi, Marathi, Nepali, Sanskrit1.8%8.5%
Bengali-AssameseBengali, Assamese2.1%9.2%
TamilTamil2.5%10.1%
TeluguTelugu2.3%9.8%
KannadaKannada2.4%10.5%
MalayalamMalayalam3.1%12.3%
GujaratiGujarati2.0%8.9%
GurmukhiPunjabi2.2%9.5%
OdiaOdia3.5%13.8%

14. Dataset Curation and Annotation

The quality of a multilingual AI platform is fundamentally determined by the quality of its training data. Unlike English, where massive corpora exist on the web, Indian language data is fragmented across scripts, domains, and quality levels. The platform's data curation team works with 500+ annotators across India, covering all 22 scheduled languages, to build high-quality training datasets. Annotation guidelines are language-specific, accounting for dialectal variation, formality levels, and regional vocabulary differences. For example, Hindi has at least 25 major dialects (Bhojpuri, Maithili, Awadhi, Braj, and more), and a training dataset must represent this diversity to build robust models.

Annotation Orchestration

C#
public class AnnotationOrchestrator
{
    private readonly ITaskQueue _taskQueue;
    private readonly IAnnotatorPool _annotatorPool;

    public async Task<Guid> CreateAnnotationBatchAsync(DatasetConfig config)
    {
        var annotators = await _annotatorPool.SelectAnnotatorsAsync(
            language: config.Language,
            taskType: config.TaskType,
            minExperience: config.MinExperienceLevel,
            count: config.ReviewsPerSample
        );

        var samples = await LoadUnannotatedDataAsync(config);
        var batchId = Guid.NewGuid();

        foreach (var sample in samples)
        {
            var task = new AnnotationTask
            {
                TaskId = Guid.NewGuid(),
                TaskType = config.TaskType,
                Language = config.Language,
                SourceData = sample.Content,
                Labels = config.LabelSchema,
                RequiredAnnotations = config.ReviewsPerSample,
                Annotators = annotators.Select(a => new AssignedAnnotator
                {
                    AnnotatorId = a.Id,
                    AssignedAt = DateTime.UtcNow,
                    Deadline = DateTime.UtcNow.AddHours(config.DeadlineHours)
                }).ToList()
            };
            await _taskQueue.EnqueueAsync(task);
        }
        return batchId;
    }

    public async Task<InterAnnotatorAgreement> ComputeAgreementAsync(Guid batchId)
    {
        var completedTasks = await GetCompletedTasksAsync(batchId);
        var groupedBySample = completedTasks.GroupBy(t => t.SourceData);
        var agreement = new InterAnnotatorAgreement();

        foreach (var group in groupedBySample)
        {
            var annotations = group.Select(t => t.Annotation).ToList();
            var kappa = ComputeFleissKappa(annotations);
            agreement.Scores.Add(new SampleAgreement
            {
                SampleId = group.Key, Kappa = kappa, Annotations = annotations.Count
            });
        }
        agreement.OverallKappa = agreement.Scores.Average(s => s.Kappa);
        return agreement;
    }
}

Dataset Sizes by Language

LanguageASR (Hours)Translation (Pairs)NER (Sentences)Toxicity (Samples)
Hindi15,0002.5M120K500K
Bengali8,0001.2M60K300K
Tamil10,0001.5M80K350K
Telugu9,0001.3M70K320K
Marathi6,000800K50K250K
Kannada5,000700K45K220K
Malayalam5,500750K42K230K
Gujarati4,000600K35K200K
Punjabi4,500650K38K210K
Odia3,000400K25K150K
Assamese2,000300K20K120K
Others (11)2,000 each250K each18K each100K each

Annotation Quality Control

Quality control is enforced through multiple mechanisms: inter-annotator agreement (Cohen's kappa above 0.7 required), golden set validation (hidden correct answers embedded in annotation tasks), anomaly detection (flagging annotators whose agreement drops below 0.6), and periodic calibration sessions where annotators discuss edge cases. For ASR transcription, a two-pass system is used: the first pass generates automatic transcription using the current ASR model, and human annotators correct errors. This is 5x more efficient than transcribing from scratch. For toxicity annotation, a separate team of trained reviewers with psychology backgrounds handles the most ambiguous cases, as cultural context significantly affects toxicity perception across Indian languages.

15. Model Training Pipeline

The training pipeline orchestrates the end-to-end lifecycle of model development: from raw data ingestion through preprocessing, training, evaluation, and deployment. The pipeline is built on Kubernetes with custom operators for ML workloads, using Ray for distributed training and MLflow for experiment tracking. Training runs are reproducible: every model version is tied to a specific data snapshot, hyperparameter configuration, and code commit. The platform trains on a cluster of 512 NVIDIA A100 GPUs distributed across two Indian data centre regions.

Training Pipeline Architecture

graph TB A[Data Lake S3] --> B[Data Validation] B --> C[Feature Engineering] C --> D[Distributed Training Ray PyTorch] D --> E[Model Checkpointing] E --> F[Evaluation Suite] F --> G{Meets Threshold?} G -->|Yes| H[Model Registry] G -->|No| I[Hyperparameter Tuning Optuna] I --> D H --> J[Staging Deployment] J --> K[A/B Testing] K --> L[Production Deployment] L --> M[Shadow Traffic] M --> N[Full Production]

Distributed Training Configuration

C#
public class TrainingJobManager
{
    private readonly IKubernetesClient _k8s;
    private readonly IModelRegistry _registry;

    public async Task<TrainingJob> LaunchTrainingAsync(TrainingConfig config)
    {
        var job = new TrainingJob
        {
            Id = Guid.NewGuid(),
            ModelType = config.ModelType,
            Language = config.Language,
            DatasetVersion = config.DatasetVersion,
            Hyperparameters = config.Hyperparameters,
            Status = TrainingStatus.Queued,
            CreatedAt = DateTime.UtcNow
        };

        var k8sJob = BuildKubernetesJob(job, config);
        await _k8s.CreateNamespacedJobAsync(k8sJob, "training-namespace");
        return job;
    }

    private KubernetesJob BuildKubernetesJob(TrainingJob job, TrainingConfig config)
    {
        return new KubernetesJob
        {
            Metadata = new ObjectMeta
            {
                Name = $"train-{job.ModelType}-{job.Language}-{job.Id:N8}"
            },
            Spec = new JobSpec
            {
                Parallelism = config.GPUCount,
                Template = new PodTemplateSpec
                {
                    Spec = new PodSpec
                    {
                        Containers = new[]
                        {
                            new Container
                            {
                                Name = "trainer",
                                Image = $"registry.sarvam.in/trainer:{config.ImageTag}",
                                Resources = new ResourceRequirements
                                {
                                    Limits = new Dictionary<string, ResourceQuantity>
                                    {
                                        ["nvidia.com/gpu"] = new ResourceQuantity($"{config.GPUsPerReplica}"),
                                        ["memory"] = new ResourceQuantity($"{config.MemoryGB}Gi")
                                    }
                                },
                                Env = new[]
                                {
                                    new EnvVar("WANDB_PROJECT", "sarvam-training"),
                                    new EnvVar("WANDB_RUN_NAME", job.Id.ToString())
                                }
                            }
                        },
                        NodeSelector = new Dictionary<string, string>
                        {
                            ["gpu-pool"] = "a100-80gb"
                        }
                    }
                }
            }
        };
    }
}

Training Resource Allocation

ModelGPU CountTraining TimeData SizeCompute (GPU-hours)
Saaras ASR (Hindi)6472 hours15K hours audio4,608
Saaras ASR (All 22)256168 hours85K hours audio43,008
TTS Model (Per language)3296 hours50 hours audio per voice3,072
IndicTranslate (Fine-tune)12848 hours5M sentence pairs6,144
IndicBERT (Pre-train)256336 hours50B tokens86,016
OCR Donut (Per script)1648 hours2M pages768
Toxicity Classifier824 hours2M samples192
Cost Optimization: Mixed-precision training (FP16/BF16) reduces GPU memory usage by 40% and increases training throughput by 2x. Gradient checkpointing allows training larger models at the cost of 30% more compute time. ZeRO Stage 3 optimiser shards distribute optimizer state across GPUs, enabling training of models that do not fit on a single GPU. These techniques together reduce total training compute costs by approximately 55% compared to naive FP32 training.

16. Low-Resource Language Handling

Of India's 22 scheduled languages, at least 8 are considered low-resource in the AI context: Assamese, Manipuri, Konkani, Sindhi, Dogri, Maithili, Bodo, and Santhali. These languages have limited digital text corpora, minimal parallel translation data, and very few speech datasets. The platform employs several strategies to handle low-resource languages effectively: transfer learning from related high-resource languages, multilingual pre-training with language-family-aware sampling, data augmentation through back-translation, and active learning to prioritise the most impactful data collection efforts.

Transfer Learning Strategy

C#
public class LowResourceTransferLearner
{
    private readonly Dictionary<string, LanguageFamily> _languageFamilies = new()
    {
        ["as"] = LanguageFamily.IndoAryan,
        ["bn"] = LanguageFamily.IndoAryan,
        ["hi"] = LanguageFamily.IndoAryan,
        ["mr"] = LanguageFamily.IndoAryan,
        ["ta"] = LanguageFamily.Dravidian,
        ["te"] = LanguageFamily.Dravidian,
        ["kn"] = LanguageFamily.Dravidian,
        ["ml"] = LanguageFamily.Dravidian,
        ["mni"] = LanguageFamily.TibetoBurman,
        ["sat"] = LanguageFamily.Austroasiatic,
        ["brx"] = LanguageFamily.SinoTibetan
    };

    public async Task<TransferConfig> PlanTransferAsync(
        string targetLanguage, string taskType)
    {
        var family = _languageFamilies[targetLanguage];
        var donorLanguages = _languageFamilies
            .Where(kvp => kvp.Value == family && kvp.Key != targetLanguage)
            .Select(kvp => kvp.Key).ToList();

        var rankedDonors = await RankDonorsBySimilarityAsync(
            targetLanguage, donorLanguages, taskType);

        return new TransferConfig
        {
            TargetLanguage = targetLanguage,
            DonorLanguages = rankedDonors.Take(3).ToList(),
            Strategy = DetermineStrategy(targetLanguage),
            FreezeLayers = new[] { "encoder.layers.0", "encoder.layers.1" },
            LearningRateScale = 0.3f,
            MaxEpochs = 50
        };
    }

    private TransferStrategy DetermineStrategy(string language)
    {
        var resourceLevel = EstimateResourceLevel(language);
        return resourceLevel switch
        {
            ResourceLevel.UltraLow => TransferStrategy.ZeroShotFromRelated,
            ResourceLevel.Low => TransferStrategy.FineTuneWithAugmentation,
            ResourceLevel.Medium => TransferStrategy.FineTuneOnly,
            _ => TransferStrategy.DirectTraining
        };
    }
}

Data Augmentation Techniques

  • Back-Translation: Translate existing English text into the target language using a general MT model, then use the translated text as additional training data. This is particularly effective for translation models where English monolingual data is abundant but Indic parallel data is scarce.
  • Cross-Lingual Transfer: Use multilingual pre-trained models (mBERT, XLM-R, IndicBERT) as initialisation points and fine-tune on small target-language datasets. Even 500 labelled examples can produce useful models when starting from a strong multilingual checkpoint.
  • Synthetic Speech Generation: For ASR, generate synthetic training audio by using the TTS model to voice text data in the target language. While not as natural as real speech, this can bootstrap a functional ASR model before real speech data is collected.
  • Script Transfer: For related languages sharing the same script family (e.g., Bengali-Assamese), train a character-level model on the high-resource language and transfer it directly to the low-resource language with minimal fine-tuning.
  • Paraphrase Generation: Use large language models to generate paraphrases of existing training data in the target language, expanding the effective training set size by 3 to 5x.

Low-Resource Language Priority Matrix

LanguageSpeakers (Millions)Resource LevelPriority StrategyTimeline
Maithili50Ultra-LowTransfer from Hindi/BengaliQ1 2027
Santhali7.4Ultra-LowTransfer from Bengali + crowdsourcingQ2 2027
Konkani2.5Ultra-LowTransfer from Marathi + HindiQ3 2027
Dogri3.2Ultra-LowTransfer from Hindi/PunjabiQ2 2027
Manipuri1.8LowTransfer from Bengali + dedicated collectionQ1 2027
Bodo1.5Ultra-LowTransfer from AssameseQ3 2027
Assamese15LowDedicated collection + Bengali transferQ4 2026
Sindhi25LowTransfer from Hindi/UrduQ1 2027

17. Code-Switching and Hinglish Support

Code-switching, the practice of alternating between two or more languages within a single conversation or sentence, is a defining characteristic of multilingual speech in India. Studies estimate that over 60% of urban Indian internet users regularly mix languages, with Hindi-English (Hinglish) being the most common combination. A typical Hinglish message might read: "Project ki deadline kal hai, can you please extend it by a week? Bahut busy tha last few days." The platform must understand, process, and generate such code-mixed text naturally.

Code-Switching Detection

C#
public class CodeSwitchingDetector
{
    private readonly LanguageIdentificationService _lidService;

    public async Task<CodeSwitchAnalysis> AnalyzeAsync(string text)
    {
        var tokens = text.Split(' ', StringSplitOptions.RemoveEmptyEntries);
        var tokenLabels = new List<TokenLanguageLabel>();

        foreach (var token in tokens)
        {
            var prediction = await _lidService.IdentifyTokenLanguageAsync(token);
            tokenLabels.Add(new TokenLanguageLabel
            {
                Token = token,
                PrimaryLanguage = prediction.Language,
                Confidence = prediction.Confidence,
                IsAmbiguous = prediction.Confidence < 0.7f
            });
        }

        var detectedLanguages = tokenLabels
            .Where(t => t.Confidence > 0.5f)
            .GroupBy(t => t.PrimaryLanguage)
            .Select(g => new DetectedLanguageSegment
            {
                Language = g.Key,
                TokenCount = g.Count(),
                Ratio = (float)g.Count() / tokens.Length
            })
            .OrderByDescending(d => d.Ratio).ToList();

        var isCodeMixed = detectedLanguages.Count > 1 &&
            detectedLanguages[1].Ratio > 0.1f;

        return new CodeSwitchAnalysis
        {
            IsCodeMixed = isCodeMixed,
            DetectedLanguages = detectedLanguages,
            DominantLanguage = detectedLanguages.FirstOrDefault()?.Language,
            TokenLabels = tokenLabels
        };
    }
}

Hinglish ASR Approach

Traditional ASR systems are trained on monolingual data and fail catastrophically on code-mixed speech. When a speaker says "Mujhe meeting ka agenda chahiye" (Hindi with the English words "meeting" and "agenda"), a Hindi-only ASR might misrecognise the English words, while an English-only ASR would fail on the Hindi portions. The platform addresses this with a multi-encoder ASR architecture: a shared acoustic encoder processes the audio, while two language-specific decoders compete to decode each segment. A language model gate decides which decoder to use at each time step, enabling seamless transitions between languages within a single utterance. This approach achieves 12% WER on Hinglish speech, compared to 35%+ WER from monolingual models.

Code-Mixed Text Normalization

Code-mixed text presents unique normalization challenges. Users may write Hinglish in multiple ways: pure Roman script, Devanagari, or mixed. The normalization pipeline must handle all variants by detecting the script at the token level and routing to the appropriate language model for processing. Transliteration between scripts is performed using a sequence-to-sequence model trained on parallel Devanagari-Roman text pairs, which handles the many-to-one mapping problem where multiple Devanagari characters map to a single Roman transliteration.

18. Government and BIS Compliance

Operating a multilingual AI platform in India requires compliance with multiple regulatory frameworks. The Digital Personal Data Protection Act (DPDPA) 2023 governs data processing and storage. The Information Technology Act 2000 (amended 2008) sets requirements for electronic records. The Bureau of Indian Standards (BIS) has published IS 17100:2018 for translation quality, and the National Platform for Language Technology (Bhashini) mandates interoperability standards for government language services. The Reserve Bank of India requires that financial data in Indian languages be processed and stored within Indian borders.

Compliance Requirements Matrix

RegulationRequirementImplementationStatus
DPDPA 2023Consent for data processingExplicit opt-in consent with purpose limitationCompliant
DPDPA 2023Data localisationAll data processed in Indian data centresCompliant
IT Act 2000Electronic record integritySHA-256 hashing and tamper-proof audit logsCompliant
BIS IS 17100Translation quality standardsBLEU above 35 and human evaluation quarterlyCompliant
RBI GuidelinesFinancial data localisationIsolated processing zone for financial textCompliant
BhashiniAPI interoperabilityREST and gRPC interfaces per Bhashini specIn Progress
Accessibility ActScreen reader compatibilityARIA labels, semantic HTML, alt textCompliant

Compliance Engine

C#
public class ComplianceEngine
{
    private readonly IDataClassificationService _classification;
    private readonly IAuditLogger _auditLogger;
    private readonly IEncryptionService _encryption;
    private readonly IConsentManager _consentManager;

    public async Task<ProcessingResult> ProcessWithComplianceAsync(
        ProcessingRequest request, UserContext user)
    {
        var residencyCheck = await ValidateDataResidencyAsync(request);
        if (!residencyCheck.IsCompliant)
            throw new DataResidencyViolationException(residencyCheck.Reason);

        var consentStatus = await _consentManager.VerifyConsentAsync(
            user.UserId, request.ProcessingPurpose);
        if (!consentStatus.HasValidConsent)
            throw new ConsentRequiredException(consentStatus.MissingPurposes);

        var classification = await _classification.ClassifyAsync(request.InputData);
        if (classification.SensitivityLevel == DataSensitivity.Critical)
        {
            request.InputData = await _encryption.EncryptAtRestAsync(
                request.InputData, EncryptionStandard.AES256);
        }

        var result = await ProcessRequestAsync(request);

        await _auditLogger.LogAsync(new AuditEntry
        {
            UserId = user.UserId,
            ServiceType = request.ServiceType,
            Language = request.Language,
            DataClassification = classification,
            ProcessingRegion = "ap-south-1",
            Timestamp = DateTimeOffset.UtcNow
        });

        return result;
    }
}

19. API Gateway and Developer Ecosystem

The API gateway is the single entry point for all developer traffic. It handles authentication, rate limiting, request routing, protocol translation (REST to gRPC for backend services), response caching, and usage metering. The gateway is built on Apache APISIX, deployed as a cluster of 12 instances behind a load balancer. It processes approximately 10,000 requests per second at peak, with P99 latency of 8ms for cache hits and 25ms for cache misses.

Rate Limiting Implementation

C#
public class ApiGatewayMiddleware
{
    private readonly IRateLimiter _rateLimiter;
    private readonly IApiKeyValidator _apiKeyValidator;

    public async Task<HttpContext> ProcessRequestAsync(HttpContext context)
    {
        var apiKey = ExtractApiKey(context.Request);
        if (string.IsNullOrEmpty(apiKey))
        {
            context.Response.StatusCode = 401;
            await context.Response.WriteAsJsonAsync(new ErrorResponse
            {
                Error = "missing_api_key",
                Message = "Authorization header with Bearer token required"
            });
            return context;
        }

        var keyInfo = await _apiKeyValidator.ValidateAsync(apiKey);
        if (keyInfo == null)
        {
            context.Response.StatusCode = 401;
            return context;
        }

        var rateLimitResult = await _rateLimiter.CheckAsync(
            keyInfo.KeyId, keyInfo.PlanTier, context.Request.Path);

        if (!rateLimitResult.IsAllowed)
        {
            context.Response.StatusCode = 429;
            context.Response.Headers["Retry-After"] =
                rateLimitResult.RetryAfterSeconds.ToString();
            return context;
        }

        context.Items["ApiKeyInfo"] = keyInfo;
        return context;
    }
}

Developer Plan Tiers

PlanPriceRate LimitMonthly QuotaFeatures
Free0 INR60 req/min100K charactersAll APIs, community support
Starter999 INR/month300 req/min10M charactersAll APIs, email support
Professional4,999 INR/month1,000 req/min100M charactersAll APIs, streaming ASR, priority queue
EnterpriseCustomCustomUnlimitedSLA, dedicated support, custom models
GovernmentSubsidised5,000 req/min500M charactersBhashini-compliant, audit logs

SDK Usage Example

C#
// .NET SDK Usage
var client = new SarvamClient("sk-your-api-key");

// Translate Hindi to English
var translation = await client.TranslateAsync(new TranslateRequest
{
    Input = "Bharat vividhta mein ekta ka desh hai.",
    SourceLanguage = "hi",
    TargetLanguage = "en"
});
Console.WriteLine(translation.Result);

// Transcribe audio
var audioBytes = await File.ReadAllBytesAsync("hindi_speech.wav");
var transcription = await client.TranscribeAsync(new TranscribeRequest
{
    Audio = audioBytes,
    Language = "hi"
});
Console.WriteLine(transcription.Result);

// Text to speech
var audio = await client.SynthesizeAsync(new SynthesizeRequest
{
    Text = "Namaste, aapka swagat hai.",
    Language = "hi",
    Voice = "female_1"
});
await File.WriteAllBytesAsync("output.wav", audio.AudioData);

20. Real-Time Inference

Real-time inference is the core of the platform's value proposition. Users expect sub-second responses for ASR, TTS, and translation. The inference stack is optimised for latency at every layer: model quantisation (INT8 for deployment), continuous batching (processing multiple requests simultaneously on a single GPU), speculative decoding (using a smaller draft model to predict tokens that the larger model verifies), and pre-computed attention caches for autoregressive models. The system uses NVIDIA Triton Inference Server as the model serving backend, with custom request scheduling that prioritises real-time requests over batch jobs.

Inference Optimisation Pipeline

C#
public class InferenceOptimizer
{
    public async Task<OptimizedModel> OptimizeModelAsync(
        ModelArtifact artifact, OptimizationConfig config)
    {
        var optimized = new OptimizedModel
        {
            OriginalModelId = artifact.Id,
            OptimizationSteps = new List<string>()
        };

        if (config.EnableGraphOptimization)
        {
            artifact = await ApplyGraphOptimizationAsync(artifact);
            optimized.OptimizationSteps.Add("graph_optimization");
        }

        if (config.QuantizationTarget != Quantization.None)
        {
            artifact = config.QuantizationTarget switch
            {
                Quantization.INT8 => await QuantizeINT8Async(artifact),
                Quantization.FP16 => await QuantizeFP16Async(artifact),
                Quantization.BF16 => await QuantizeBF16Async(artifact),
                _ => artifact
            };
            optimized.OptimizationSteps.Add($"quantization_{config.QuantizationTarget}");
        }

        if (config.EnableTensorRT)
        {
            artifact = await CompileTensorRTAsync(artifact, new TensorRTConfig
            {
                Precision = config.QuantizationTarget == Quantization.INT8
                    ? TensorRTPrecision.INT8 : TensorRTPrecision.FP16,
                MaxBatchSize = config.MaxBatchSize
            });
            optimized.OptimizationSteps.Add("tensorrt_compilation");
        }

        optimized.OptimizedArtifact = artifact;
        optimized.EstimatedSpeedup = await BenchmarkSpeedupAsync(artifact, optimized);
        return optimized;
    }
}

Latency Breakdown

StageASRTTSTranslationOCR
Network and Deserialization5ms5ms5ms5ms
Pre-processing15ms10ms5ms30ms
Model Inference120ms180ms60ms300ms
Post-processing10ms20ms5ms15ms
Serialization and Response5ms5ms5ms5ms
Total P99155ms220ms80ms355ms

21. Edge Deployment

Edge deployment brings AI inference closer to users, reducing latency and bandwidth costs. For India, where internet connectivity varies dramatically between urban 5G and rural 2G/3G networks, edge deployment is not a luxury but a necessity. The platform deploys lightweight models on edge nodes at ISP points of presence (PoPs) in 50 cities across India, and on-device models for mobile SDKs in select use cases. Edge models are quantised to INT4/INT8 precision, pruned to 30% of the cloud model size, and use knowledge distillation from the full cloud models to maintain acceptable accuracy.

Edge Model Deployment Strategy

ServiceCloud Model SizeEdge Model SizeQuantizationAccuracy Retention
ASR (Hindi)1.5 GB180 MBINT8 + Pruning92%
TTS (Hindi)800 MB120 MBINT8 + Quant88%
Translation (Hindi-English)2.1 GB250 MBINT8 + Distillation90%
Toxicity Detection500 MB80 MBINT485%
Sentiment Analysis400 MB60 MBINT487%
OCR (Devanagari)1.2 GB200 MBINT8 + Pruning86%

On-Device SDK Architecture

C#
public class EdgeInferenceEngine
{
    private readonly IModelDownloader _downloader;
    private readonly Dictionary<string, OnDeviceModel> _loadedModels = new();

    public async Task InitializeAsync(string[] requiredServices, string language)
    {
        foreach (var service in requiredServices)
        {
            var modelId = await _registry.GetEdgeModelIdAsync(service, language);
            if (modelId == null) continue;
            var modelPath = await _downloader.DownloadIfMissingAsync(modelId);
            var model = await LoadOnDeviceModelAsync(modelPath, service);
            _loadedModels[$"{service}:{language}"] = model;
        }
    }

    public async Task<InferenceResponse> InferAsync(string service, string language, byte[] input)
    {
        var key = $"{service}:{language}";
        if (!_loadedModels.TryGetValue(key, out var model))
            throw new EdgeModelNotAvailableException($"Edge model for {service}/{language} not loaded");

        var startTime = Stopwatch.GetTimestamp();
        var result = await model.RunAsync(input);
        var latency = Stopwatch.GetElapsedTime(startTime);
        await _metricsCollector.RecordEdgeInferenceAsync(service, language, latency);
        return result;
    }
}
Edge Caching Strategy: Edge nodes use a two-level cache: L1 in-memory LRU cache for the 10,000 most recent requests (serving within 2ms), and L2 SSD cache for the 1 million most frequent requests (serving within 10ms). Cache invalidation happens every 6 hours when updated models are deployed. The cache hit rate for translation requests in high-traffic languages (Hindi, Bengali, Tamil) exceeds 40%, meaning nearly half of all requests never reach the cloud.

22. Monitoring and Observability

Monitoring a multilingual AI platform requires tracking model-specific metrics (accuracy, latency, throughput), infrastructure metrics (GPU utilisation, memory, network), business metrics (API usage by language, revenue per service), and quality metrics (WER, BLEU, CER) in near-real-time. The platform uses a three-pillar observability stack: Prometheus for metrics, Grafana for dashboards, Jaeger for distributed tracing, and the ELK stack for log aggregation. Custom exporters translate ML-specific metrics (model drift, accuracy degradation, distribution shift) into Prometheus format for unified monitoring.

Key Monitoring Metrics

Metric CategoryMetricAlert ThresholdDashboard
ASR QualityWord Error Rate (rolling 1h)Above 15% for any languageML Quality
TTS QualityMOS (Mean Opinion Score)Below 3.5 for any voiceML Quality
TranslationBLEU score (rolling 1h)Below 30 for any pairML Quality
OCRCharacter Error RateAbove 5% for any scriptML Quality
LatencyP99 latency per serviceAbove 2x baselineInfrastructure
ThroughputRequests per secondBelow 50% of capacityInfrastructure
GPUUtilisation percentageAbove 95% sustainedInfrastructure
Error Rate5xx error rateAbove 0.1%Reliability
AvailabilityService uptimeBelow 99.95%Reliability
CostCost per 1M charactersAbove 2.5 INRBusiness
UsageDaily active API keysBelow 80% of forecastBusiness
DriftInput distribution shiftKL divergence above 0.1ML Quality

Model Drift Detection

C#
public class ModelDriftDetector
{
    private readonly IMetricsCollector _metrics;
    private readonly IReferenceDistributionStore _referenceStore;

    public async Task<DriftReport> CheckDriftAsync(string modelId, string language)
    {
        var currentSamples = await _metrics.GetRecentInferenceInputsAsync(
            modelId, language, TimeSpan.FromHours(1), sampleCount: 1000);
        var referenceDist = await _referenceStore.GetDistributionAsync(modelId, language);

        var klDivergence = ComputeKLDivergence(currentSamples, referenceDist);
        var psiMetric = ComputePopulationStabilityIndex(currentSamples, referenceDist);

        var report = new DriftReport
        {
            ModelId = modelId, Language = language,
            KLDivergence = klDivergence, PSI = psiMetric,
            IsDrifting = klDivergence > 0.1 || psiMetric > 0.2,
            SampleCount = currentSamples.Count,
            CheckedAt = DateTimeOffset.UtcNow
        };

        if (report.IsDrifting)
        {
            await TriggerDriftAlertAsync(report);
            await ScheduleRetrainingAsync(modelId, language);
        }
        return report;
    }
}

23. Cost Estimation

Running a full-stack multilingual AI platform at scale in India requires significant infrastructure investment, but the cost structure must be viable for India's price-sensitive market. The platform targets a blended cost of less than 2 INR per 1 million characters processed across all services. This section provides a detailed breakdown of infrastructure costs, optimisation strategies, and unit economics.

Monthly Infrastructure Costs

ComponentSpecificationQuantityMonthly Cost (INR)
GPU Cluster (A100 80GB)Hyperscale instances800 GPUs4,80,00,000
GPU Cluster (T4)Inference instances200 GPUs20,00,000
CPU Compute (K8s)c5.4xlarge equivalents500 instances1,50,00,000
PostgreSQL (RDS)db.r6g.4xlarge Multi-AZ3 instances12,00,000
Redis Clusterr6g.2xlarge6 nodes8,40,000
TimescaleDBdb.r6g.2xlarge2 instances5,60,000
S3 Object Storage500 TB hot, 2 PB coldGlobal25,00,000
Network Bandwidth10 Gbps sustainedMumbai + Chennai15,00,000
CDN and EdgeCloudFront-like50 edge nodes8,00,000
Monitoring StackPrometheus + Grafana + ELKDedicated cluster4,00,000
ML PlatformRay + MLflowTraining cluster10,00,000
Engineering Team (100)ML engineers, SRE, dataAverage 30 LPA2,50,00,000
Annotator Team (500)Part-time, all languagesAverage 3 LPA1,25,00,000
Total Monthly11,13,00,000

Unit Economics

MetricValueNotes
Total monthly cost111.3M INRApprox 1.3M USD
Total characters processed per month50 billionAll services combined
Cost per 1M characters2.23 INRBlended across all services
Target selling price per 1M chars5.00 INRGovernment pricing
Gross margin55.4%At government pricing tier
Break-even monthly characters25 billionAt 5 INR per 1M chars
Projected monthly revenue (Year 2)200M INR50 enterprise customers
Projected monthly profit (Year 2)88.7M INRAt 55% gross margin
Cost Optimisation Levers: (1) Spot instances for training reduce GPU costs by 60%, (2) model quantisation reduces serving GPU requirements by 40%, (3) edge caching offloads 30% of cloud requests, (4) continuous batching improves GPU utilisation from 40% to 85%, and (5) model distillation reduces model sizes by 10x for edge deployment. Together, these strategies reduce total infrastructure costs by approximately 45% compared to a naive deployment.

24. Testing Strategy

Testing a multilingual AI platform requires a multi-dimensional approach that goes far beyond traditional software testing. Each model must be tested for accuracy across all supported languages, each API endpoint must be load-tested for realistic traffic patterns, and the system as a whole must be tested for failure scenarios (model unavailability, GPU failures, network partitions). The testing strategy spans five levels: unit tests for individual components, integration tests for service interactions, model evaluation tests for ML accuracy, load tests for performance, and chaos tests for resilience.

Model Evaluation Framework

C#
public class ModelEvaluationSuite
{
    private readonly IModelRegistry _registry;
    private readonly IEvaluationMetrics _metrics;

    public async Task<EvaluationReport> EvaluateModelAsync(
        string modelId, string language, EvaluationDataset dataset)
    {
        var model = await _registry.GetModelAsync(modelId);
        var results = new List<EvaluationResult>();

        foreach (var sample in dataset.Samples)
        {
            var prediction = await model.PredictAsync(sample.Input);
            var metric = sample.TaskType switch
            {
                "asr" => ComputeWER(sample.Expected, prediction),
                "translation" => ComputeBLEU(sample.Expected, prediction),
                "ocr" => ComputeCER(sample.Expected, prediction),
                "sentiment" => ComputeAccuracy(sample.Expected, prediction),
                "toxicity" => ComputeF1Score(sample.Expected, prediction),
                _ => throw new NotSupportedException(sample.TaskType)
            };
            results.Add(new EvaluationResult
            {
                SampleId = sample.Id, Metric = metric, Latency = prediction.Latency
            });
        }

        return new EvaluationReport
        {
            ModelId = modelId, Language = language,
            AverageMetric = results.Average(r => r.Metric),
            P95Latency = Percentile(results.Select(r => r.Latency).ToList(), 95),
            TotalSamples = results.Count,
            PassedThresholds = CheckThresholds(results, model.TaskType),
            EvaluatedAt = DateTimeOffset.UtcNow
        };
    }
}

Test Coverage Matrix

Test TypeCoverage TargetToolsFrequency
Unit Tests90% code coveragexUnit, MoqEvery commit
Integration TestsAll API endpointsTestcontainers, gRPC TestNightly
Model Accuracy TestsAll 22 languages per modelCustom eval frameworkWeekly and pre-deploy
Load Tests3x peak traffick6, Grafana CloudWeekly
Chaos TestsCritical failure pathsChaos Monkey, LitmusBi-weekly
Security TestsOWASP Top 10SonarQube, SnykEvery PR
E2E TestsAll service combinationsPlaywright, custom SDKNightly
Regression TestsAccuracy regression detectionGolden test setsPre-deploy

25. Interview Q and A

Preparation Note: This section covers the most frequently asked interview questions related to designing a multilingual AI platform. Each answer highlights the key design trade-offs and demonstrates senior-level thinking about distributed ML systems.

Q1: How would you handle a sudden spike in ASR requests for a specific language during a live event?

Answer: The system uses a multi-layered approach to handle traffic spikes. First, the API gateway implements token bucket rate limiting that allows temporary bursts up to 3x normal traffic. Second, the ASR service uses Kubernetes HPA (Horizontal Pod Autoscaler) with custom GPU-based metrics to scale from 50 to 200 instances within 90 seconds. Third, if GPU capacity is exhausted, the system falls back to a quantised INT8 model running on CPU instances, which provides 30% of GPU throughput but at 5x the latency. Fourth, requests are queued in Apache Kafka with a maximum wait time of 5 seconds, after which users receive a friendly high-demand message. The entire failover chain completes within 2 seconds of the spike detection.

Q2: How do you ensure consistent translation quality across all 462 language pairs?

Answer: We use a tiered quality management approach. High-resource pairs (Hindi-English, Bengali-English) use dedicated fine-tuned models with 40+ BLEU. Medium-resource pairs use the multilingual NLLB model with domain adapters. Low-resource pairs use the multilingual model with transfer learning from related languages. Quality is monitored continuously through automated BLEU scoring on a held-out test set, with human evaluation on a weekly sample. When quality drops below threshold for any pair, the system automatically routes traffic to a higher-quality fallback pair (for example, Manipuri-Hindi instead of Manipuri-English). The Bhashini compliance layer ensures government-mandated minimum quality for all 22 scheduled language pairs.

Q3: Design the data pipeline for collecting and curating ASR training data at scale.

Answer: The pipeline has four stages: Collection, Processing, Annotation, and Validation. Collection sources include government proceedings (Sansad TV live streams captured via RTMP), public radio (All India Radio archives), YouTube Creative Commons content (filtered by language and quality), and a crowdsourcing mobile app that pays users to record sentences in their native language. Processing includes audio quality filtering (SNR above 15dB, no clipping), speaker diarization, language verification, and deduplication. Annotation uses a two-pass approach: first-pass automatic transcription with the current ASR model, second-pass human correction by language-specific annotators. Validation includes inter-annotator agreement checks, golden sample verification, and automatic WER measurement. The entire pipeline processes approximately 10,000 hours of audio per month across all 22 languages.

Q4: How would you design the system to handle OCR for a multi-page document in mixed Devanagari and English?

Answer: Multi-page, multi-script OCR requires a cascading pipeline. First, page-level script detection determines which scripts are present on each page. Second, layout analysis identifies text blocks, headings, tables, and images using a Donut-based model. Third, each text block is routed to the appropriate script-specific OCR model. Fourth, a post-processing language model (IndicBERT) resolves ambiguities and corrects common OCR errors. Fifth, the structured output merges blocks back into a coherent document with page numbers, block boundaries, and confidence scores. The system handles code-mixed pages by running both script models on each block and selecting the one with higher confidence.

Q5: Explain the trade-offs between on-device and cloud inference for Indian language ASR.

Answer: Cloud inference provides highest accuracy (8% WER) but requires network connectivity and adds 100-200ms latency. On-device inference works offline with 50ms latency but at reduced accuracy (15% WER) due to model compression. The trade-off depends on use case: IVR systems always use cloud (guaranteed connectivity), messaging apps use on-device with cloud fallback (optimise for latency), and educational apps use cloud (optimise for accuracy). Storage constraints on mobile devices limit the number of languages that can be stored on-device to 3-5 per device. A hybrid approach where on-device handles the first pass and cloud refines the result provides both low latency and high accuracy. Battery impact is also significant: on-device inference on a modern smartphone consumes approximately 2% battery per hour of continuous ASR, compared to 5% for cloud-based (due to network radio usage).

Q6: How do you handle model versioning and zero-downtime deployments for 22+ language models?

Answer: Each language model has its own independent versioning and deployment lifecycle. The Model Registry tracks version, accuracy metrics, deployment status, and traffic allocation per language. Deployments use a canary strategy: new model version receives 5% of traffic for 2 hours while accuracy metrics are monitored in real-time. If metrics stay within 2% of the baseline, traffic is gradually increased to 100% over 6 hours. If metrics degrade, traffic is automatically rolled back within 30 seconds. Blue-green deployment is used for major version upgrades where the old model runs in parallel until the new model is fully validated. The key insight is that different languages can be at different model versions simultaneously.

Q7: Design the caching strategy for the translation service.

Answer: Translation caching operates at three levels. L1 (Redis, 10ms): Exact-match cache keyed by source language, target language, content hash, and formality mode. TTL of 6 hours for news content, 24 hours for static content. Hit rate approximately 25%. L2 (Edge, 25ms): Cache at CDN edge nodes for the top 100 most frequent translation pairs. Hit rate approximately 15%. L3 (In-process, 1ms): LRU cache in each service instance for the 1,000 most recent requests. Hit rate approximately 5%. Combined cache hit rate is approximately 45%, meaning 55% of requests reach the model. Cache invalidation uses TTL-based expiry rather than active invalidation. For high-volume API customers, a dedicated cache partition prevents cache pollution from one customers traffic patterns affecting another's hit rate.

Q8: How do you monitor and respond to model quality degradation in production?

Answer: We use a three-tier monitoring approach. Tier 1 (Automatic): Real-time comparison of model outputs against a reference distribution using KL divergence and Population Stability Index. If the PSI exceeds 0.2 for any language, an automatic alert is triggered. Tier 2 (Scheduled): Weekly evaluation against golden test sets for all 22 languages. If accuracy drops below the threshold, a retraining job is automatically queued. Tier 3 (Human): Monthly qualitative review where native speakers evaluate a random sample of 100 outputs per language for each service. This catches subtle quality issues that automated metrics miss. The system also monitors input distribution: if the proportion of code-mixed inputs increases, the system automatically increases the weight of code-mixed data in the inference routing.

Q9: What are the key challenges in deploying AI models for Indian languages compared to English?

Answer: The challenges span five dimensions: (1) Data scarcity: English has trillions of tokens of web text; Hindi has billions, and Odia has millions. (2) Script complexity: 13 scripts with conjunct characters, vowel marks, and varying Unicode representations. (3) Morphological richness: Tamil and Malayalam are agglutinative, meaning a single word can encode what English expresses in a full sentence, requiring different tokenisation strategies. (4) Code-switching: 60% of urban Indian users mix languages, requiring models that handle intra-sentential language switching. (5) Dialect variation: Hindi alone has 25+ major dialects with different vocabulary, pronunciation, and grammar. The design must accommodate all these variations through language-specific model components, script-aware preprocessing, and culturally informed evaluation criteria.

Q10: How would you design the system to comply with the DPDPA 2023 data protection requirements?

Answer: DPDPA compliance requires five key mechanisms. (1) Consent Management: Every user must provide explicit, informed consent for each processing purpose with granular opt-in controls. Consent records are stored in an immutable audit log. (2) Purpose Limitation: Data collected for ASR cannot be repurposed for model training without separate consent. (3) Data Minimisation: Audio files are retained for only 72 hours after processing unless the user explicitly requests longer retention. Transcriptions are retained for 30 days. (4) Right to Erasure: Users can request deletion of all their data through an API endpoint, which triggers a cascade deletion across all storage systems within 72 hours. (5) Data Localisation: All processing and storage occurs within Indian data centres, with no data transfers to servers outside India. The compliance engine intercepts every API request and enforces these rules before any processing occurs.

Ayodhyya — AI Platform Design Blog Series

Design a Sarvam-Style Multilingual AI Platform — Senior+ Guide