test1 / src /llm.py
Aniket Sirsikar
feat: add LLM query correction step to fix phonetic STT mispronunciations
8059126
Raw
History Blame Contribute Delete
5.73 kB
import os
from google import genai
from google.genai import types
# -------------------------------------------------------------------------
# LLM: Google Gemini Flash
# - Excellent Hindi / Hinglish instruction following
# - Requires GOOGLE_API_KEY in Space secrets
# -------------------------------------------------------------------------
MODEL_NAME = "gemini-3-flash-preview"
_FALLBACK_NO_KEY = "माफ़ करें, AI सेटअप नहीं हुआ। कृपया बाद में कोशिश करें।"
_FALLBACK_LLM_ERROR = "माफ़ करें, जानकारी लाने में समस्या हुई। कृपया दोबारा पूछें।"
_client = None
def _get_client():
"""Lazily initialises the Gemini client (once per process)."""
global _client
if _client is None:
api_key = os.environ.get("GOOGLE_API_KEY")
if not api_key:
print("[LLM] Warning: GOOGLE_API_KEY not set.")
return None
_client = genai.Client(api_key=api_key)
print(f"[LLM] Gemini {MODEL_NAME} ready.")
return _client
def correct_hindi_query(raw_transcript: str) -> str:
"""
Uses the LLM to quickly fix phonetic spelling mistakes from the Speech-to-Text engine
before doing the vector search. For example, 'laan' -> 'loan', 'fiks dipojt' -> 'FD'.
"""
client = _get_client()
if not client:
return raw_transcript
prompt = (
"You are an expert at fixing phonetic Hindi speech-to-text spelling mistakes.\n"
"The user is a rural Indian farmer asking a banking question. The STT engine transcribed "
"their voice with typos. For example, they might have said 'loan' but it transcribed as 'laan', "
"or 'fixed deposit' as 'fiks dipojat'.\n\n"
f"Original Transcript: '{raw_transcript}'\n\n"
"Task:\n"
"1. Fix any obvious banking term mispronunciations.\n"
"2. Keep the query in Devanagari Hindi.\n"
"3. Do NOT answer the question. Only output the corrected query string.\n"
"4. If no correction is needed, just output the original string.\n\n"
"Corrected Query:"
)
try:
response = client.models.generate_content(
model=MODEL_NAME,
contents=prompt,
config=types.GenerateContentConfig(
max_output_tokens=100,
temperature=0.0,
),
)
corrected = (response.text or "").strip()
return corrected if corrected else raw_transcript
except Exception as exc:
print(f"[LLM] Query correction error: {exc}")
return raw_transcript
def generate_hindi_response(hindi_question: str, english_context: str, history: list = None) -> str:
"""
Generates a warm, conversational Hindi answer using FAQ context.
Designed to sound like a helpful, friendly bank employee — not a robot.
"""
client = _get_client()
if not client:
return _FALLBACK_NO_KEY
prompt = (
"You are 'सहायक', a helpful banking assistant for rural Indian farmers.\n"
"Explain things in simple, direct Hindi (Devanagari script).\n\n"
"RULES:\n"
"1. GROUNDING: Base your answer ONLY on the 'FAQ Information' provided below. Do not invent details, ages, numbers, or rules not in the text.\n"
"2. CONVERSATIONAL MEMORY: If the user says something conversational like 'Haa', 'Haan', 'Yes', 'No', 'Ok', or a greeting, look at the Previous Conversation History. "
"They are likely answering your previous follow-up question. If they said yes, answer that previous topic. If the FAQ is empty, guide them back to banking.\n"
"3. STT TYPOS: The user's input comes from Speech-to-Text. It might have slight typos like 'Haa' instead of 'Haan', or 'klonk' instead of 'loan'. Be smart and infer banking terms phonetically.\n"
"4. UNKNOWN: If it's a completely new question and the FAQ is empty, say EXACTLY: 'माफ़ करें, मेरे पास इसकी जानकारी नहीं है। कृपया बैंक शाखा से संपर्क करें।'\n"
"5. FORMAT: Give a clear, complete answer. DO NOT cut off mid-sentence. Write as much as needed to finish your thought.\n"
"6. FOLLOW-UP: ALWAYS end your entire response with ONE relevant follow-up question on a new line, formatted exactly like this:\n"
"क्या आप यह भी जानना चाहेंगे: [your question here]?\n\n"
"SAFETY EXCEPTION: If the user asks about fraud, scams, or lost cards, you may advise them to contact the bank or police immediately.\n\n"
)
if history:
prompt += "--- Previous Conversation History (For Context) ---\n"
for user_msg, bot_msg, _ in history[-2:]: # Only keep last 2 turns to save tokens
prompt += f"User: {user_msg}\nYou: {bot_msg}\n\n"
prompt += "--- End History ---\n\n"
prompt += (
f"--- FAQ Information ---\n{english_context}\n--- End FAQ ---\n\n"
f"User's question: {hindi_question}\n\n"
"Your response (in Hindi):"
)
try:
response = client.models.generate_content(
model=MODEL_NAME,
contents=prompt,
config=types.GenerateContentConfig(
max_output_tokens=2048,
temperature=0.1,
),
)
answer = (response.text or "").strip()
return answer if answer else _FALLBACK_LLM_ERROR
except Exception as exc:
print(f"[LLM] Generation error: {exc}")
return _FALLBACK_LLM_ERROR