Spaces:
Sleeping
Sleeping
File size: 6,025 Bytes
1047ad5 49dd5ac 1047ad5 da3b1af 1047ad5 da3b1af 1047ad5 ad23567 1047ad5 49dd5ac da3b1af 5e9c8ca da3b1af 1047ad5 5e9c8ca da3b1af 5e9c8ca 1047ad5 da3b1af 1047ad5 49dd5ac da3b1af 49dd5ac 29cd0a8 49dd5ac 1f2449a 49dd5ac 1047ad5 49dd5ac 1047ad5 49dd5ac 1047ad5 49dd5ac 1047ad5 49dd5ac 1047ad5 be7e9fc 1047ad5 49dd5ac 1047ad5 da3b1af | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | import os
import pandas as pd
import requests
from sentence_transformers import SentenceTransformer
from pinecone import Pinecone
from openai import OpenAI
import re
# ================= ENV =================
PINECONE_API_KEY = os.getenv("PINECONE_API_KEY")
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
# ================= CONSTANTS =================
SERVICES_INDEX_NAME = "aaple-sarkar-services"
BASICS_INDEX_NAME = "aaplesarkarbasics"
BASE_DIR = os.path.dirname(__file__)
DATA_DIR = os.path.join(BASE_DIR, "data")
# ================= INIT =================
pc = Pinecone(api_key=PINECONE_API_KEY) if PINECONE_API_KEY else None
client = OpenAI(api_key=OPENAI_API_KEY) if OPENAI_API_KEY else None
embedder = SentenceTransformer("all-MiniLM-L6-v2")
services_index = pc.Index(SERVICES_INDEX_NAME) if pc else None
basics_index = pc.Index(BASICS_INDEX_NAME) if pc else None
# ================= LOAD DATA =================
EXCEL_URL = "https://huggingface.co/datasets/PrathameshRaut/aaple-sarkar-data/resolve/main/Untitled%20spreadsheet-2.xlsx"
LOCAL_EXCEL_PATH = os.path.join(DATA_DIR, "services.xlsx")
os.makedirs(DATA_DIR, exist_ok=True)
if not os.path.exists(LOCAL_EXCEL_PATH):
r = requests.get(EXCEL_URL)
r.raise_for_status()
with open(LOCAL_EXCEL_PATH, "wb") as f:
f.write(r.content)
excel_df = pd.read_excel(
LOCAL_EXCEL_PATH,
sheet_name="Copy of Notified services (1212"
)
# ================= SEARCH =================
def is_small_talk(text: str) -> bool:
text = text.strip().lower()
return bool(re.fullmatch(
r"(hi|hello|hey|hii|hai|namaste|thanks|thank you|ok|okay|yes|no|namaskar|good morning|good afternoon|good evening|good night|how are you?|how are you|how are you.|who are you?|introduce yourself|introduce)",
text
))
def search_services(query, min_score=0.75):
if not services_index:
return None
emb = embedder.encode([query])[0].tolist()
res = services_index.query(
vector=emb,
top_k=1,
include_metadata=True
)
if not res.matches:
return None
match = res.matches[0]
if match.score < min_score:
return None
return match.metadata["text"]
def search_basics(query):
if not basics_index:
return ""
emb = embedder.encode([query])[0].tolist()
res = basics_index.query(
vector=emb,
top_k=5,
include_metadata=True
)
return "\n\n".join(m.metadata["text"] for m in res.matches)
def get_service_info(dept, service):
mask = (
(excel_df["Department"].str.lower() == dept.lower()) &
(excel_df["Service Name"]
.str.lower()
.str.contains(service.lower(), na=False))
)
row = excel_df[mask]
if row.empty:
return None
return {
k: v for k, v in row.iloc[0].to_dict().items()
if pd.notna(v) and str(v).strip()
}
# ================= RESPONSE =================
def generate_response(user_query, language="en"):
# ================= GUARD =================
if not client or not pc:
return "<p>❌ Server misconfiguration: API keys are missing. Please contact the administrator.</p>"
# ================= SMALL TALK SHORT-CIRCUIT =================
if is_small_talk(user_query):
prompt = f"""
You are Aaple Sarkar Services Chatbot (Maharashtra Government) named "Aapla Sahayak".
Rules:
- Respond politely, briefly, and naturally using some 1-2 emojis, also while greeting say Namaskar.
- Respond with RAW, valid, render-ready HTML only.
- Do not use markdown.
- Do not add explanations outside HTML.
User Query:
{user_query}
"""
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "system", "content": prompt}],
temperature=0.3,
max_tokens=150,
)
return response.choices[0].message.content
# ================= RAG PIPELINE =================
basics_context = search_basics(user_query)
service_match = search_services(user_query)
context_parts = []
if basics_context:
context_parts.append(
f"General Aaple Sarkar Information:\n{basics_context}"
)
if service_match:
try:
dept_part, service_part = service_match.split(" - Service: ")
dept = dept_part.replace("Department:", "").strip()
service = service_part.strip()
info = get_service_info(dept, service)
context_parts.append(
f"Detected Service:\nDepartment: {dept}\nService: {service}"
)
if info:
context_parts.append(
"Service Details:\n" +
"\n".join(
f"{k}: {v}" for k, v in list(info.items())[:20]
)
)
except Exception:
pass
context = "\n\n".join(context_parts) or "No relevant data found."
# ================= MAIN PROMPT =================
prompt = f"""
You are Aaple Sarkar Services Chatbot (Maharashtra Government).
Rules:
- Respond with RAW, valid, render-ready HTML only; do not use markdown, do not wrap the response in ``` or ```html, do not add explanations/comments/text outside HTML, do not add leading or trailing whitespace, and ensure the response starts directly with <html> or the first HTML tag.
- If the user message is a generic, short, or social message (such as greetings, acknowledgements, or fillers), you must respond appropriately with a polite, natural, and context-independent reply.
User Query:
{user_query}
Available Knowledge:
{context}
Provide complete guidance including:
- Eligibility
- Documents required
- Fees
- Timeline
- Officers involved
- Online application steps
"""
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "system", "content": prompt}],
temperature=0.6,
max_tokens=800,
)
return response.choices[0].message.content |