Contents — 26 sections
Project Overview
A context-aware assistant that converses fluently across Indian languages — understanding, remembering, and replying in the user's own tongue.
India is multilingual by default — hundreds of languages, constant code-switching between English and regional tongues, and hundreds of millions of people far more comfortable in Hindi, Tamil, Bengali or Marathi than in English. A chatbot that only works well in English shuts most of them out. This project builds a multilingual chatbot that converses fluently across Indian languages: it understands the user's language, keeps track of the conversation, and replies in the same language, so people can interact naturally in their own tongue.
Two capabilities define it. The first is genuine multilingual understanding and generation — comprehending input and producing fluent replies across many languages, including the very common case of code-switching (mixing English and a regional language, or writing a regional language in Latin script). Modern multilingual language models make this feasible in one model, rather than bolting a translator onto an English bot. The second is context awareness: a real assistant remembers what was said earlier in the conversation, so it can handle follow-ups ("and what about tomorrow?") and multi-turn tasks — the difference between a conversation and a series of disconnected queries.
The value is genuinely inclusive access — services, support and information available to people in the language they actually speak. It is honest about the hard realities of Indian-language NLP: many languages are lower-resource (less training data → weaker fluency and more errors than English), script and transliteration vary (Devanagari vs romanised Hindi), dialects and code-switching are messy, and quality is uneven across languages; and, as with any chatbot, it can be confidently wrong and needs guardrails. Built honestly — a strong multilingual model, real conversation memory, and clear-eyed about the resource gap between languages — it is both a genuinely inclusive assistant and a rich lesson in multilingual, context-aware conversational AI.
What this project does
- Converses fluently across multiple Indian languages
- Understands input and replies in the user's language
- Handles code-switching (mixed English/regional, romanised)
- Keeps conversation context across turns (memory)
- Handles follow-ups and multi-turn tasks
- Makes services accessible in people's own tongue
- Is honest about uneven quality across languages
Real-World Applications
| Setting | How it is used |
|---|---|
| Inclusive customer support | Help users in their own language. |
| Government / public services | Access to services across languages. |
| Education / information | Answering questions in regional languages. |
| Commerce / assistants | Conversational interfaces for all users. |
Deployment contexts where a build of this kind earns its keep.
Features & Capabilities
- Multilingual understanding + generation
- Code-switching / transliteration handling
- Conversation context/memory
- Language detection and matching
- Multi-turn task handling
- Guardrails for safe replies
- Honest about low-resource-language limits
Difficulty, Time & Required Skills
| Attribute | Value |
|---|---|
| Difficulty level | Advanced |
| Estimated completion time | 14–20 hours |
| Indicative build cost | Software; compute/API-dependent |
| Primary discipline | NLP & LLM |
| Reference platform | CPU/GPU workstation or server (+ LLM API optional) |
Skills you should have (or will pick up)
- Multilingual NLP (understanding + generation)
- Code-switching and transliteration handling
- Conversation state/memory management
- Language detection and response matching
- Guardrails and honest quality scoping
Bill of Materials
Every part below is commonly available from Indian and international hobby-electronics suppliers. Prices are indicative 2026 retail figures in Indian rupees and will drift — treat them as a budgeting guide, not a quotation.
| Component | Key specification | Qty | Approx. cost |
|---|---|---|---|
| Compute + LLM | CPU/GPU; a multilingual LLM (local or API) | 1 | — |
| Multilingual model | Model with strong Indian-language coverage | 1 | — |
| Language tools | Language ID, transliteration handling | 1 | — |
| Conversation store | Session memory for context | 1 | — |
Estimated total: ₹0, excluding tools, shipping and consumables.
Tools and consumables
- Soldering iron (temperature controlled, 350 °C) with 0.8 mm 60/40 or lead-free solder
- Digital multimeter — continuity, DC volts and current ranges
- Wire strippers, flush cutters and a small set of precision screwdrivers
- Heat-shrink tubing and a heat gun (or a lighter, carefully)
- A laptop with a USB port and the toolchain listed above
Hardware Specifications
This is a pure-software conversational system — no electronic hardware to specify. The "platform" is a computer plus a multilingual language model: a GPU (local model) or a hosted LLM API handles generation, and a CPU handles language detection and session management.
Memory and storage scale with concurrent conversations and retained context; a deployment adds the chat interface and a session store. Everything else is the software stack, models and libraries below.
Software Requirements & Development Environment
Reference toolchain: Python 3.11 + multilingual LLM / NLP. Anything newer normally works; anything older may lack the board definitions used here.
- Install the Arduino IDE 2.3.x (or PlatformIO if you prefer a real editor and dependency locking).
- Add
https://espressif.github.io/arduino-esp32/package_esp32_index.jsonunder File → Preferences → Additional Board Manager URLs, then install esp32 from the Boards Manager. - Set the correct port under Tools → Port. On Linux add yourself to the
dialoutgroup:sudo usermod -aG dialout $USERand log out and back in. - Open the Serial Monitor at 115200 baud — every sketch here logs its state there.
- Keep File → Preferences → Show verbose output during: compilation switched on while you are debugging build errors.
Required libraries
| Library | Why it is needed | Install |
|---|---|---|
| Python 3.11+ | Runtime for the analysis, training and service code. | sudo apt install python3 python3-venv python3-pip |
| Hugging Face Transformers 4.44+ | Pre-trained language and vision transformers with a uniform API. | pip install transformers |
| sentence-transformers 3.0+ | Sentence embeddings for semantic search and RAG retrieval. | pip install sentence-transformers |
| FastAPI + Uvicorn 0.115+ | Typed async REST API with automatic OpenAPI docs. | pip install fastapi uvicorn[standard] |
| SQLite 3.45+ | Zero-configuration embedded database for local logs. | Bundled with Python (`import sqlite3`) |
Block Diagram
The block diagram shows the functional decomposition of the system — what senses, what decides, what acts, and where the data ends up.
Circuit Diagram & Wiring
The "wiring" is the conversation data flow — user text is language-detected, combined with conversation memory, sent to a multilingual model, and the reply is returned in the user's language.
| Peripheral | Peripheral pin | Controller pin | Signal |
|---|---|---|---|
| User message | text | — | Any language |
| Language ID + memory | context | — | Lang + history |
| Multilingual LLM | generate | — | Reply |
| Response | reply | — | User's language |
Wire one row at a time and tick it off — most "it does not work" reports trace back to a single swapped pair.
Wiring explanation
- Detect the user's language (including code-switching/romanised input).
- Combine the message with conversation memory for context.
- Send to a multilingual model that understands and generates the language.
- Reply in the user's language; update the conversation memory.
- Expect uneven quality across languages — lower-resource languages are harder.
System Architecture
Read the stack from the bottom up: physical hardware, the firmware that drives it, the transport that moves data off the device, and the software a human actually looks at.
Working Principle
The case for a multilingual chatbot in India is not a nicety, it is access: a huge share of people are far more comfortable — or only comfortable — in a regional language, and constantly code-switch (Hinglish, romanised Tamil, mixed sentences). An English-only assistant simply excludes them. So the design goal is that a user can speak in their own language, naturally, and be understood and answered in it. Meeting that goal well rests on two capabilities that must both be genuine, not faked.
The first is real multilingual understanding and generation. The naïve approach — translate the user's input to English, run an English bot, translate the reply back — is brittle: it loses nuance, mangles code-switched and romanised text, and compounds errors across two translation steps. The better approach uses a multilingual language model that natively understands and generates many languages in one model, so it can handle mixed-language input, transliteration, and idiom directly. This is what makes fluent, natural conversation across languages feasible rather than clunky.
The second is context awareness, which is what separates an assistant from a stateless query box. Real conversation is multi-turn: people ask follow-ups ("and tomorrow?"), refer back ("the first option"), and carry a task across several messages. A useful chatbot therefore maintains memory of the conversation — the history (or a summary of it) that is supplied as context on each turn — so it can resolve references, keep track of the task, and respond coherently over many turns. Without this, every message is an island and the "conversation" is an illusion.
The honesty this project requires is about the uneven reality of Indian-language NLP. Languages differ enormously in resource level: English and major languages like Hindi have abundant training data and strong model quality, while many Indian languages are lower-resource, with less data and correspondingly weaker fluency and more errors — quality is genuinely uneven across languages, and it is dishonest to claim uniform excellence. Script and transliteration add friction (Hindi in Devanagari vs romanised "kya haal hai"), dialects and code-switching are messy and underrepresented in training data, and — as with any LLM chatbot — the model can be confidently wrong, so guardrails and honest handling of uncertainty are needed regardless of language. A well-built system therefore uses a strong multilingual model, maintains real conversation memory, and is transparent about which languages it serves well and where quality drops — degrading gracefully rather than pretending. Built that way, it delivers real inclusive value (natural access to information and services in people's own languages) while teaching the substance of multilingual, context-aware conversational AI, resource gaps and all.
The maths behind it
Understand + respond in-language
lang = detect(user_message) # incl. code-switching/romanised
reply = multilingual_LLM(context + user_message, target=lang)
Reply in the USER's language. One multilingual model, not a
translate→English-bot→translate bolt-on.
Context (memory) per turn
context = history (or summary) of the conversation
reply_t = LLM(context_{<t} + message_t)
update: history += (message_t, reply_t)
Enables follow-ups/references — a conversation, not islands.
Honest quality by resource level
quality(lang) ↑ with training data for that language
high-resource (English/Hindi) → strong
low-resource → weaker, more errors
Be transparent; degrade gracefully; add guardrails.
Program Flowchart
The firmware is a single cooperative loop. Nothing blocks for long, so networking, sensing and the user interface all stay responsive.
Assembly Instructions
Build on a breadboard first and only commit to solder once the whole system has run for an hour without a fault.
Set up multilingual understanding + generation
Use a strong multilingual model to understand input (including code-switching/romanised) and reply in the user's language — one model, not a translate bolt-on.
Add conversation memory
Maintain conversation history (or a rolling summary) so the bot handles follow-ups and multi-turn tasks.
Detect language and guardrail
Detect the user's language (handling romanised/mixed input), reply in it, and apply safety guardrails.
Step-by-Step Implementation Guide
Work through these in order. Each step ends in something you can observe, so a failure is always localised to the step you just finished.
Detect language, use context, reply in-language
Detect the user's language, add conversation context, and generate a reply in that language with a multilingual model.
pythonchat.pyclass Chat: def __init__(self, llm, detect): self.llm, self.detect = llm, detect self.history = [] # conversation memory def reply(self, message): lang = self.detect(message) # code-switching aware context = summarise(self.history) # context across turns prompt = (f"Reply in the user's language ({lang}); be honest if unsure.\n" f"{context}\nUser: {message}") out = self.llm.generate(prompt) # multilingual generation self.history.append((message, out)) # remember for follow-ups return outlang = self.detect(message) # code-switching awareDetecting the user's language (including mixed/romanised input) lets the bot reply in the tongue they actually used.context = summarise(self.history) # context across turnsConversation memory is supplied as context so follow-ups and references resolve — the difference between a conversation and disconnected queries.out = self.llm.generate(prompt) # multilingual generationOne multilingual model understands and generates the language directly, avoiding the brittle translate-then-English-bot approach.self.history.append((message, out)) # remember for follow-upsEach turn is remembered so the next turn has context — real multi-turn conversation.Guardrail and be transparent about quality
Apply safety guardrails to every language and be transparent where quality drops for lower-resource languages, degrading gracefully.
Complete Source Code
The listing below is complete and compiles as written — there are no elided sections. Read the annotations under each block before you upload it.
#!/usr/bin/env python3
"""
Multilingual Chatbot (context-aware)
Converses across Indian languages: detects the user's language (incl.
code-switching/romanised), keeps CONVERSATION MEMORY for follow-ups,
and replies IN THE USER'S LANGUAGE with a single multilingual model.
Quality is uneven across languages — be transparent and guardrail replies.
"""
class MultilingualChatbot:
def __init__(self, llm, detect_lang, guard):
self.llm = llm; self.detect = detect_lang; self.guard = guard
self.history = [] # conversation memory
def reply(self, message):
if not self.guard.input_ok(message):
return self.guard.refusal(self.detect(message))
lang = self.detect(message) # code-switching aware
context = self._context() # multi-turn memory
prompt = (
"You are a helpful, honest assistant. "
f"Reply in the user's language ({lang}). If unsure, say so.\n\n"
f"{context}\nUser: {message}\nAssistant:")
out = self.llm.generate(prompt) # multilingual generation
out = self.guard.output_filter(out) # safety, every language
self.history.append((message, out)) # remember the turn
return out # in the user's language
def _context(self):
# supply recent history (or a summary) so references/follow-ups work
recent = self.history[-6:]
return "\n".join(f"User: {u}\nAssistant: {a}" for u, a in recent)
if __name__ == "__main__":
bot = MultilingualChatbot(MultilingualLLM(), detect_language, Guardrails())
# bot.reply("kal ka weather kaisa hai?") # code-switched Hindi/English
# Serves high-resource languages well; lower-resource langs are weaker —
# be transparent and degrade gracefully.
Configuration & Calibration
Configuration steps
- Configure the multilingual model and supported languages.
- Configure language detection (including romanised/mixed input).
- Configure conversation memory (history/summary length).
- Configure guardrails and per-language quality expectations.
Calibration procedure
An uncalibrated sensor produces confident, precise, wrong numbers. Do this once per physical unit and record the constants.
Language coverage
Test understanding/generation per language and code-switching; map quality honestly.
Context
Verify follow-ups and references resolve using memory.
Safety
Check guardrails work across languages, not just English.
Dataset, Model & Training
Dataset
A multilingual LLM (pretrained on many languages) provides understanding/generation; Indian-language coverage and code-switching data determine quality.
Optional domain/dialogue data and transliteration resources improve specific languages.
| Dataset | Size | Licence | Use here |
|---|---|---|---|
| Multilingual LLM (pretrained) | Large | Model terms | Understanding + generation |
| Indian-language coverage | Uneven | Model terms | Per-language quality |
| Code-switch / romanised data | Scarcer | Varies | Mixed-language robustness |
| Domain dialogue data | Optional | Yours | Task/domain tuning |
Data preprocessing
- Detect language (handle romanised/mixed input); normalise script where needed.
- Assemble conversation context (history or summary) within the context window.
- Apply guardrails/safety filtering to input and output.
| Layer / stage | Shape or configuration | Purpose |
|---|---|---|
| Language ID | detect + romanised/mixed | Know the user's language |
| Memory | history / rolling summary | Context across turns |
| Multilingual model | one model, many languages | Understand + reply in-language |
| Guardrails | safety/uncertainty | Safe, honest replies |
| Quality map | per-language expectations | Transparent, graceful degradation |
Hyperparameters
| Hyperparameter | Value | Why |
|---|---|---|
| Model | strong multilingual | Indian-language coverage |
| Context length | history/summary fit | Memory vs cost |
| Temperature | moderate | Fluency vs reliability |
| Guardrails | on | Safety regardless of language |
Training process
- Primarily use a capable pretrained multilingual model; fine-tune for domain/dialogue if needed.
- Add code-switch/romanised and low-resource examples where possible.
- Evaluate per language; be transparent about quality differences.
Evaluation, Metrics & Deployment
Quality must be judged per language, not overall — the honest picture is strong for high-resource languages and weaker for low-resource ones, plus context-handling quality.
| Metric | Value | What it tells you |
|---|---|---|
| Per-language fluency | uneven (honest) | High vs low-resource |
| Context handling | multi-turn | Follow-ups/references |
| Code-switch robustness | target | Mixed/romanised input |
| Safety | guardrailed | Across all languages |
Figures from the reference training run described above — reproduce them before trusting your own changes.
Inference example
class MultilingualChat:
def __init__(self, llm, detect):
self.llm = llm; self.detect = detect
self.history = [] # conversation memory
def reply(self, message):
lang = self.detect(message) # incl. code-switching
context = summarise(self.history) # context across turns
prompt = (f"You are a helpful assistant. Reply in the user's "
f"language ({lang}). Be honest if unsure.\n"
f"Conversation so far:\n{context}\n\nUser: {message}")
out = self.llm.generate(prompt) # multilingual model
self.history.append((message, out)) # remember the turn
return out # reply in the user's language
# Quality is uneven across languages; low-resource langs are weaker.
Testing Procedure & Expected Output
Test from the bottom up. Confirm power, then each sensor in isolation, then the integrated loop — the first failing step tells you exactly where to look.
| Test | What you should see |
|---|---|
| Chat in Hindi | Fluent, in-language reply |
| Code-switch (Hinglish) | Understood; replies appropriately |
| Ask a follow-up | Uses context correctly |
| Chat in a low-resource language | Works but weaker — honest quality |
| Romanised regional input | Handled (transliteration) |
| Unsafe request | Guardrail refuses in-language |
Bench-test checklist. If a row fails, stop and fix it before moving on.
Expected output
Fluent, context-aware replies in the user's language, with honest quality across the resource spectrum.
{
"user": "kal ka weather kaisa rahega?",
"detected_language": "hi (romanised, code-switched)",
"reply": "कल मौसम साफ़ रहने की संभावना है...",
"used_context": true,
"note": "high-resource langs strong; low-resource weaker"
}
A code-switched, romanised Hindi question understood and answered fluently in Hindi, using conversation context — natural access in the user's own language, with honest expectations across languages.
Troubleshooting: Common Errors & Fixes
Performance Optimisation
- Use one strong multilingual model, not a translate bolt-on.
- Maintain conversation memory for real multi-turn dialogue.
- Handle code-switching and romanised input in detection.
- Be transparent about uneven per-language quality; guardrail all languages.
- Replace every
delay()with amillis()comparison — blocking delays are the single most common cause of dropped readings. - Sample sensors on a fixed cadence and publish on a slower one; you almost never need to transmit at the sampling rate.
- Move networking into its own FreeRTOS task so a slow DNS lookup cannot stall the control loop.
- Use
uint8_t/uint16_twhere the range allows; on an 8-bit AVR a 32-bit add costs four times as much. - Profile before optimising — print
micros()deltas around each stage and fix the slowest one first.
Safety Precautions
- The model can be confidently wrong in any language — apply guardrails across all languages, not just English.
- Be transparent about which languages are served well; do not claim uniform quality.
- Conversations may contain personal data — handle securely and lawfully.
- Provide human fallback for high-stakes interactions.
- Wear eye protection when soldering or cutting, and solder in a ventilated space — rosin flux fumes are a respiratory irritant.
- Power the circuit through a bench supply with a current limit while you are testing. A 300 mA limit turns a wiring mistake into a beep instead of a dead board.
- Disconnect power before changing any wiring. Hot-plugging a sensor onto a live bus is the fastest way to lose a controller.
Maintenance
- Improve coverage for lower-resource languages over time.
- Re-evaluate per-language quality as models improve.
- Update guardrails and language detection.
- Monitor conversations for failures and drift.
- Re-check every screw terminal and header after the first week — thermal cycling loosens connections that felt tight on day one.
- Recalibrate at the interval given in the calibration section, and keep the constants in a text file next to the firmware — not only in flash.
- Keep a short logbook of firmware versions and what changed. Six months later you will not remember why that constant is 1.083.
Future Improvements & Upgrades
A working v1 is a platform, not a finish line. These are the upgrades that add the most capability for the least rework.
- Add speech in/out for spoken multilingual interaction.
- Add RAG for grounded, domain-specific answers.
- Add more languages/dialects and better code-switching.
- Add per-language quality indicators to users.
- Design a proper PCB. Once the breadboard version has run for a month, moving to a two-layer board removes the intermittent-contact failures that dominate prototype faults.
- Add connectivity — an ESP32 and an MQTT publish turn a local gadget into something you can graph, alert on and analyse over months.
- Add persistent local storage (microSD or the on-chip flash) so a network outage does not create a hole in your data.
- Move configuration out of the source: a captive-portal setup page or a JSON config file makes the build reusable without a recompile.
- Add a battery and solar option so the unit survives a power cut and can be sited away from a socket.
- Write a small test harness that feeds synthetic sensor values through the decision logic, so you can validate thresholds without physically triggering the event.
Frequently Asked Questions
References & Learning Resources
These are the primary sources worth reading in full. Manufacturer datasheets always outrank forum posts when the two disagree.
- Multilingual NLPReference
- Code-switching (linguistics)Reference
- Low-resource languages / NLPReference
- Large language modelsReference
- Languages of IndiaReference