Spaces:
Sleeping
Sleeping
| 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 | |