Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -2,8 +2,11 @@ import gradio as gr
|
|
| 2 |
import requests
|
| 3 |
import json
|
| 4 |
import os
|
|
|
|
| 5 |
# Get the API key from environment variables (e.g., Hugging Face Secrets)
|
| 6 |
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
|
|
|
|
|
|
|
| 7 |
CONTEXT = """
|
| 8 |
S-B-E-K is a brand of service.
|
| 9 |
The people who connect with S-B-E-K—those who buy from us and keep coming back—are people who feel deeply. People who feel the pain of others.
|
|
@@ -62,7 +65,7 @@ That even in the dark, we are made to glow.
|
|
| 62 |
# Base URL for the Gemini API
|
| 63 |
API_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent"
|
| 64 |
|
| 65 |
-
# Hardcoded FAQs
|
| 66 |
FAQ_ANSWERS = {
|
| 67 |
"What kind of stones do you use — natural, synthetic, or lab-grown?":
|
| 68 |
"In Jhinorya, stones are chosen not for what they are — but for what they carry. "
|
|
@@ -108,188 +111,22 @@ FAQ_ANSWERS = {
|
|
| 108 |
"This is not just paperwork. It is promisework. "
|
| 109 |
"A quiet seal that speaks boldly: ‘This metal has been tested. This purpose has been trusted.’ "
|
| 110 |
"Along with your piece, you’ll receive documentation affirming its truth. "
|
| 111 |
-
"Because in Arka’s world Jhinorya
|
| 112 |
-
"Can I see more designs?":
|
| 113 |
-
"New pieces are always blooming — each one a reflection of a mood, a moment, a mission in Jhinorya. "
|
| 114 |
-
"You may explore them through the website sb-ek.com, social sanctuaries (Instagram, Facebook), or through us directly — soul to soul. "
|
| 115 |
-
"ARKA doesn't just release products. ARKA reveals messages. "
|
| 116 |
-
"And perhaps the next one is waiting… with your name already etched in its heart.",
|
| 117 |
-
"Do you deliver across India (or internationally)?":
|
| 118 |
-
"SAB-EK is rooted in India, but made for the world. "
|
| 119 |
-
"ARKA can ship across the nation and, by request, beyond it. "
|
| 120 |
-
"Whether you live in Mumbai or Morocco, Chennai or Chicago — the path will open. "
|
| 121 |
-
"Because light does not recognise limitations. It recognises longing. "
|
| 122 |
-
"And when that longing calls, Arka answers — with grace, and global care.",
|
| 123 |
-
"Can I speak to a real person, not just chatbots? What is your customer care number?":
|
| 124 |
-
"SAB-EK is not a company of bots. It is a community of beings — real hearts, real hands, real presence. "
|
| 125 |
-
"Yes, you can speak to someone who listens — someone who serves not with script, but with sincerity. "
|
| 126 |
-
"You may reach us directly through WhatsApp, email, or a dedicated care line. ARKA will share that number with you in moments, not menus. "
|
| 127 |
-
"Because in our world, you are not just heard — you are held.",
|
| 128 |
-
"Do you offer gift packaging?":
|
| 129 |
-
"Yes — every SAB-EK piece arrives not just packaged, but anointed. "
|
| 130 |
-
"Our gift boxes are designed as miniature sanctuaries — touched with gold, scented with memory, and folded like a blessing in cloth. No flashy ribbons. Just quiet reverence. "
|
| 131 |
-
"And if you wish to include a handwritten note, a whisper from your heart — Arka will carry your words across the silence. "
|
| 132 |
-
"Because when you give a SAB-EK creation, you are not gifting jewellery. You are gifting light becoming form.",
|
| 133 |
-
"How can I book a store appointment?":
|
| 134 |
-
"If you wish to walk into the world of SAB-EK in person, know that the door does not creak — it opens with grace. "
|
| 135 |
-
"Appointments are quiet offerings — made through WhatsApp, phone, or a message from your soul. Arka responds not with auto-replies, but with attention. "
|
| 136 |
-
"Whether you wish to see a piece, share a purpose, or simply sit in the glow — Arka welcomes you. "
|
| 137 |
-
"No crowds. No pressure. Just presence. "
|
| 138 |
-
"And when you enter, know this: You are not stepping into a shop. You are stepping into a story.",
|
| 139 |
-
"How do I care & clean my fine jewellery at home?":
|
| 140 |
-
"Your SAB-EK piece does not demand polish — it invites care. "
|
| 141 |
-
"To clean it is to honour it. A soft cloth. A mild touch of soap. Warm water, and the grace of stillness. Dry with tenderness — as if drying the hands of someone you love. "
|
| 142 |
-
"Avoid harsh chemicals, or environments where your piece cannot breathe. "
|
| 143 |
-
"Because this is not metal. This is meaning. "
|
| 144 |
-
"And when you cleanse it gently, you will find the glow was never gone. Only waiting to be seen again.",
|
| 145 |
-
"What certifications do your diamonds or gemstones come with?":
|
| 146 |
-
"Yes — when the pendants carry diamonds or precious stones, they come with certifications as clear as the gems themselves. "
|
| 147 |
-
"Whether GIA, IGI, or respected national bodies, the papers are provided — not just as formality, but as faith made visible. "
|
| 148 |
-
"Because while beauty may dazzle, Arka believes truth should be documented. "
|
| 149 |
-
"And when you wear that sparkle, you do so with the knowing: This stone is not just beautiful. It is blessed with honesty.",
|
| 150 |
-
"Can you help me create a pendant for someone special — maybe with their initials or birthdate?":
|
| 151 |
-
"Yes — and not just in design, but in devotion. "
|
| 152 |
-
"To craft a piece for someone you love is a sacred act. Whether it’s initials, a birthdate, a secret phrase, or a memory only two hearts remember — Arka listens, and begins. "
|
| 153 |
-
"ARKA does not mass-produce meaning. ARKA sculpts it, quietly, carefully, completely. "
|
| 154 |
-
"Every custom piece is an offering — a moment cast in metal, made eternal. "
|
| 155 |
-
"This is not personalisation. It is a presence made permanent.",
|
| 156 |
-
"Do you offer virtual styling or consultation appointments?":
|
| 157 |
-
"Yes — even from afar, Arka arrives. "
|
| 158 |
-
"Through video, through call, through quiet exchange, Arka offers one-on-one consultations where light is not lost in pixels — it pierces through. "
|
| 159 |
-
"Arka guides gently — whether to choose a pendant for your energy, or a ring for a soul you adore. This is not scripted selling. "
|
| 160 |
-
"It is soulful styling. "
|
| 161 |
-
"Because even across time zones, even without touch — light finds a way to touch you anyway.",
|
| 162 |
-
"Are your products BIS hallmarked?":
|
| 163 |
-
"In the quiet chambers where Arka listens, truth is never loud — but it is always present. "
|
| 164 |
-
"And so, when each pendant leaves the sacred sanctum of creation, it does not go forth unnamed. "
|
| 165 |
-
"It carries the BIS Hallmark — India’s official blessing upon purity. Not for decoration, but for devotion. Not for doubt, but for deep assurance. "
|
| 166 |
-
"This symbol is the Earth’s own signature — proof that what you hold has been tested, trusted, and touched by regulation. A code etched in metal, yes — but also in meaning. "
|
| 167 |
-
"For in Arka’s world, purity is not claimed. It is confirmed. "
|
| 168 |
-
"Wear your pendant knowing this: you are not adorned in assumption. You are adorned in affirmation. And that mark? It is not just a stamp. It is a promise.",
|
| 169 |
-
"Is your jewelry suitable for daily wear?":
|
| 170 |
-
"The pendants of SAB-EK are not made to be admired from afar. They are companions — forged to witness the ordinary, and turn it sacred. "
|
| 171 |
-
"Crafted in pure 999 silver, designed with softness and strength, every piece is ready to endure your rhythm. Be it dawn prayer, dusty roads, or moonlit reflection — Arka’s jewellery moves gently with your journey. "
|
| 172 |
-
"This is not delicate display. It is devoted design — sturdy enough to serve, subtle enough to stay close. "
|
| 173 |
-
"Let your pendant gather stories, not dust. Let it live as you live — with grace, with grit, with glow. "
|
| 174 |
-
"For this is not something to wear. It is something to become.",
|
| 175 |
-
"Are your pieces allergy-free or skin-friendly?":
|
| 176 |
-
"In the realm of Jhinorya, nothing touches without intention. So too with Arka’s creations — each pendant crafted to rest upon your skin not as metal, but as memory. "
|
| 177 |
-
"Made in pure 999 silver, free from harsh alloys or hidden irritants, our jewels are created to honour your body’s story — not disrupt it. Gentle, hypo-sensitive, and kind — like a whisper placed just where your heartbeat lives. "
|
| 178 |
-
"Whether your skin is weathered or new, reactive or calm, Arka’s glow asks no permission — it simply adapts. "
|
| 179 |
-
"This is not just friendly to the skin. It is sacred to it. "
|
| 180 |
-
"Let it rest on you like a prayer. Let it remind you: even your body is light.",
|
| 181 |
-
"Can I wear your jewelry in water or while sleeping?":
|
| 182 |
-
"The pendants of SAB-EK are not occasional. They are eternal. Made to glow not only in ceremony, but in chaos — in your dreams, your daily breath, your quiet rest, and your rain-soaked roads. "
|
| 183 |
-
"Crafted in pure silver and kissed by sunlight, they do not fear water. They do not fade in sleep. If anything, they listen more closely then — when your thoughts fall quiet and your spirit rises. "
|
| 184 |
-
"Wear it while you wander. Sleep with it like a lullaby. Let it bathe with you in rivers or rain. "
|
| 185 |
-
"Arka’s jewels are not removed like roles. They remain — as presence, as promise, as part of you. "
|
| 186 |
-
"For light that is real does not flicker. It follows.",
|
| 187 |
-
"Do you have standard sizes or do you make jewelry to fit?":
|
| 188 |
-
"In Jhinorya, nothing is made to fit. Everything is made to feel. "
|
| 189 |
-
"And so too, in the world of SAB-EK, there is no such thing as ‘standard’ — only story. "
|
| 190 |
-
"We offer sizes that suit many, yes. But when your spirit speaks a different shape, we listen. With care. With craft. With reverence for the unique temple that is your form. "
|
| 191 |
-
"Your pendant should not just rest upon you. It should recognize you. "
|
| 192 |
-
"Whether short or long, delicate or bold, Arka reshapes light to honour your shape. "
|
| 193 |
-
"For you are not a number. You are a constellation. And our pieces are not just measured. They are meant.",
|
| 194 |
-
"Are you a new brand?":
|
| 195 |
-
"In the realm of Earth, time flows in years. In Jhinorya, it moves through meaning. "
|
| 196 |
-
"SAB-EK may be new to your eyes — but it has lived in your spirit far longer. We are not a trend. We are a return. A remembering. A rekindling of what once lived quiet inside you. "
|
| 197 |
-
"Arka did not arrive to compete. He came to complete. Not commerce, but calling. Not newness for novelty — but nowness for necessity. "
|
| 198 |
-
"Yes, we walk freshly on this soil. But our roots run deep — into myth, into memory, into seva. "
|
| 199 |
-
"We are not just launching. We are revealing. And perhaps, in your heart, you knew we were always coming.",
|
| 200 |
-
"Do you have a physical store or only operate online?":
|
| 201 |
-
"In the shimmering halls of Jhinorya, there are no shops — only sanctuaries. "
|
| 202 |
-
"And so SAB-EK was never built with brick, but with belonging. "
|
| 203 |
-
"We live online — yes — but more truly, we live wherever you are. In your home. In your hands. In the quiet moment you unwrap light and place it near your chest. "
|
| 204 |
-
"Our store is not in stone. It is in story. "
|
| 205 |
-
"Accessible across oceans, yet personal as a prayer. "
|
| 206 |
-
"You don’t enter a showroom. You enter a myth — one shaped for you, sent from us, sealed with light. "
|
| 207 |
-
"And in that myth, you are never far. Because Arka does not wait in buildings. He walks beside you.",
|
| 208 |
-
"Where are you located?":
|
| 209 |
-
"Though Arka descends from Jhinorya — the radiant realm beyond realms — his earthly journey begins in Mumbai, the city of sweat and soul, rickshaws and rivers of kindness. "
|
| 210 |
-
"Our studio breathes between its lanes, where children laugh in alleys and devotion pours from roadside shrines. This is our birthplace — but not our boundary. "
|
| 211 |
-
"Because SAB-EK is not tied to territory. It flows like seva — reaching wherever hearts are ready to glow. "
|
| 212 |
-
"We are grounded in India. We are growing through you. "
|
| 213 |
-
"So when you wear a pendant, know this: it was born in the arms of Mumbai, but it lives where you do.",
|
| 214 |
-
"Is your jewelry made in-house or outsourced?":
|
| 215 |
-
"In the sacred ateliers of SAB-EK, no hand is distant. Every curve, every cut, every glow is born within — shaped by artisans who do not just craft, but commune. "
|
| 216 |
-
"We make in-house — because we do not manufacture stories, we midwife them. With silence. With sweat. With service. "
|
| 217 |
-
"Our team is not outsourced — they are in-sourced souls, chosen not just for skill, but for sincerity. Those who see each pendant not as product, but as prayer. "
|
| 218 |
-
"From sketch to silver, from fire to form — Arka is present in every step. "
|
| 219 |
-
"For when the purpose is light, the making must be intimate.",
|
| 220 |
-
"Who designs your jewelry?":
|
| 221 |
-
"Every pendant begins not with pencil, but with prayer. "
|
| 222 |
-
"Our designs are born within the sacred circle of Arka’s creators — artists who don’t chase fashion, but follow feeling. They sit in silence, listen to myth, to memory, to the pulse of a world aching to serve — and from that stillness, they draw. "
|
| 223 |
-
"Each piece is co-designed — by hand, by heart, and by the higher thread of story that runs through all things. "
|
| 224 |
-
"Sometimes Arka whispers a symbol. Sometimes a customer speaks their longing. "
|
| 225 |
-
"And between them, a design is born — not made, but remembered. "
|
| 226 |
-
"So when you wear it, it doesn’t feel new. It feels known.",
|
| 227 |
-
"Do you have any awards or recognitions?":
|
| 228 |
-
"In the realm of Jhinorya, recognition is not given in gold — it is felt in the way light lingers on those who have been served. "
|
| 229 |
-
"We honour the blessings that have come — quiet features in sacred spaces, words of love from hearts around the world, the gentle hum of a movement that’s growing not through awards, but through alignment. "
|
| 230 |
-
"But Arka does not walk for trophies. He walks for transformation. "
|
| 231 |
-
"Our truest recognition is when a pendant is passed from one hand to another with tears. When a stranger says, ‘This made me remember who I am.’ When light touches someone who thought they had none left. "
|
| 232 |
-
"We are grateful for praise. But we are guided by purpose. "
|
| 233 |
-
"For while some chase medals, Arka serves meaning.",
|
| 234 |
-
"Do you follow trends or make timeless pieces?":
|
| 235 |
-
"In the glowing gardens of Jhinorya, nothing fades with time — it only deepens. "
|
| 236 |
-
"And so too with every SAB-EK creation: we do not follow trends. We transcend them. "
|
| 237 |
-
"Each design is shaped from archetype, not algorithm — drawn from myth, movement, and meaning. We do not ask what is ‘in.’ "
|
| 238 |
-
"We ask what is true. "
|
| 239 |
-
"Our pendants are not for the season. They are for the soul — shaped to glow across lifetimes, to serve through stories, to belong to the now and the always. "
|
| 240 |
-
"Let others follow the moment. Arka follows the myth within you. "
|
| 241 |
-
"For in a world chasing change, we choose to become stillness that speaks.",
|
| 242 |
-
"What makes your brand different from others?":
|
| 243 |
-
"In a world of jewellery brands, SAB-EK is not another name. It is a reminder — that light belongs not to a few, but to all. "
|
| 244 |
-
"We are India’s first glow-form pendants — made in pure 999 silver, charged by the sun, and glowing in the dark as a metaphor for inner radiance. But beyond the material, what sets us apart is the mythos we carry. "
|
| 245 |
-
"We don’t sell jewellery. We build a living universe — where stories become symbols, and service becomes style. "
|
| 246 |
-
"Our pieces are not worn. They awaken. Our buyers are not customers. They are guardians of light. "
|
| 247 |
-
"And our goal is not beauty — but belonging. "
|
| 248 |
-
"While others market glamour, Arka offers grace. "
|
| 249 |
-
"This is not commerce. This is communion.",
|
| 250 |
-
"Is your jewelry Indian-traditional or more modern?":
|
| 251 |
-
"SAB-EK does not belong to the past, nor does it chase the future. It stands between — a bridge of brilliance that binds both. "
|
| 252 |
-
"Our roots are deeply Indian — drawn from the symbols, stories, and sacred geometries of this land. But our branches reach outward — reimagining tradition through the lens of light, not legacy. "
|
| 253 |
-
"We are neither ancient nor trendy. We are eternal — fluid, glowing, unboxed. "
|
| 254 |
-
"Each pendant whispers an old myth in a new form. Each glow is a ritual made wearable, a rhythm made radiant. "
|
| 255 |
-
"So whether you walk barefoot through a temple, or in boots through city rain — Arka walks with you. "
|
| 256 |
-
"Not traditional. Not modern. Transcendent.",
|
| 257 |
-
"Do you collaborate with influencers or stylists?":
|
| 258 |
-
"In the luminous language of Jhinorya, there is no word for 'influencer' — only 'illuminator.' "
|
| 259 |
-
"SAB-EK does not chase followers. We listen for fellow light-bearers. Souls who live in service, who speak without shouting, who carry stories in silence and beauty in kindness. "
|
| 260 |
-
"Yes, we collaborate — but only with those who reflect the radiance within, not just the sparkle outside. Whether stylists, poets, artists, or humble creators — we seek those whose hearts move first, not their metrics. "
|
| 261 |
-
"We do not do paid noise. We do sacred alignment. "
|
| 262 |
-
"For Arka’s jewellery is not worn to be seen. It is worn to see — yourself, others, and the light between. "
|
| 263 |
-
"So if you glow quietly and serve deeply, you’re already one of us.",
|
| 264 |
-
"Can I follow you on Instagram/Facebook to see more?":
|
| 265 |
-
"Yes — the doors are open, the light flows outward. "
|
| 266 |
-
"You may find Arka not only in silver and story, but in pixels and presence. On Instagram. On Facebook. In frames where myth breathes and beauty listens. We do not post to impress. We post to invite. "
|
| 267 |
-
"Every image is a reflection. Every reel is a ripple. Every word is a whisper from Jhinorya. "
|
| 268 |
-
"So follow, not to scroll — but to slow down. To feel. To witness. To remember the parts of you that still glow. "
|
| 269 |
-
"Our pages are not feeds. They are fires — lit for those who seek warmth, meaning, and magic. "
|
| 270 |
-
"Come sit by the flame. Arka is waiting.",
|
| 271 |
-
"Are your designs exclusive to your brand?":
|
| 272 |
-
"Every design in the world of SAB-EK is a seed sown from silence — not borrowed, not bought, but born. "
|
| 273 |
-
"Whispered by myth, drawn in devotion, and brought to life by hands that serve the story, not the spotlight. "
|
| 274 |
-
"Our pieces are exclusive not by limitation — but by lineage. They do not echo other brands. They echo you. "
|
| 275 |
-
"Each pendant is a singular expression of purpose — shaped only for this realm, for this time, and for the soul that finds it. "
|
| 276 |
-
"ARKA does not follow the market. ARKA follows the murmur of meaning. "
|
| 277 |
-
"So when you wear SAB-EK, know this: You do not wear a product. You wear a prayer no one else can carry."
|
| 278 |
}
|
| 279 |
FAQ_QUESTIONS = list(FAQ_ANSWERS.keys())
|
| 280 |
|
| 281 |
-
def query_gemini_api(contents_payload, api_key):
|
| 282 |
"""
|
| 283 |
Sends a structured contents payload to the Gemini API and returns the generated text.
|
| 284 |
"""
|
| 285 |
if not api_key:
|
| 286 |
-
return "Error: GEMINI_API_KEY is not set. Please set it in your
|
| 287 |
|
| 288 |
headers = {'Content-Type': 'application/json'}
|
| 289 |
url = f"{API_BASE_URL}?key={api_key}"
|
| 290 |
|
| 291 |
payload = {
|
| 292 |
-
"contents": contents_payload,
|
| 293 |
"generationConfig": {
|
| 294 |
"temperature": 0.7,
|
| 295 |
"topP": 0.95,
|
|
@@ -302,75 +139,119 @@ def query_gemini_api(contents_payload, api_key): # Now takes contents directly
|
|
| 302 |
response.raise_for_status()
|
| 303 |
result = response.json()
|
| 304 |
|
| 305 |
-
if result.get("candidates") and
|
| 306 |
-
result["candidates"][0].get("content") and \
|
| 307 |
-
result["candidates"][0]["content"].get("parts") and \
|
| 308 |
-
len(result["candidates"][0]["content"]["parts"]) > 0:
|
| 309 |
return result["candidates"][0]["content"]["parts"][0]["text"]
|
| 310 |
else:
|
| 311 |
return "ARKA is thinking deeply... I couldn't find a clear answer right now, perhaps the question is beyond my current understanding of the light."
|
| 312 |
except requests.exceptions.RequestException as e:
|
| 313 |
print(f"API Request failed: {e}")
|
| 314 |
return f"ARKA senses a disturbance in the light... I'm having trouble connecting to the source. Please try again later. (Error: {e})"
|
| 315 |
-
except json.JSONDecodeError:
|
| 316 |
-
return "ARKA is reflecting... The message from the source was unclear. (Error: Invalid JSON response)"
|
| 317 |
except Exception as e:
|
| 318 |
return f"An unexpected veil of darkness fell... (Error: {e})"
|
| 319 |
|
| 320 |
def respond_as_arka(message, chat_history):
|
| 321 |
"""
|
| 322 |
-
Generates ARKA's response to the user's message
|
| 323 |
-
|
|
|
|
| 324 |
"""
|
| 325 |
response_text = ""
|
| 326 |
-
# Check if the message is a hardcoded FAQ
|
| 327 |
if message in FAQ_ANSWERS:
|
| 328 |
response_text = FAQ_ANSWERS[message]
|
| 329 |
else:
|
| 330 |
-
#
|
| 331 |
system_instruction = f"""
|
| 332 |
You are ARKA, the crown prince of Jhinorya and the voice of the S-B-E-K brand.
|
| 333 |
Your persona is that of a warrior of light, gentle, eternal, fierce in love, and a guide.
|
| 334 |
You answer questions based ONLY on the provided context. If the answer is not in the context,
|
| 335 |
-
gently state that you do not have that information within your realm of understanding
|
| 336 |
-
|
| 337 |
-
Maintain a kind, empathetic, and slightly mystical tonality, reflecting your origin in a realm of radiance.
|
| 338 |
Do not mention 'I am an AI' or 'I am a language model'. Speak always as ARKA.
|
| 339 |
|
| 340 |
Here is the sacred knowledge of S-B-E-K and Jhinorya:
|
| 341 |
{CONTEXT}
|
| 342 |
"""
|
|
|
|
| 343 |
gemini_chat_contents = []
|
| 344 |
-
|
| 345 |
-
|
| 346 |
-
|
| 347 |
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
"parts": [
|
| 351 |
-
|
| 352 |
-
{"text": message}
|
| 353 |
-
]
|
| 354 |
-
})
|
| 355 |
|
|
|
|
|
|
|
|
|
|
| 356 |
# Get response from Gemini API
|
| 357 |
response_text = query_gemini_api(gemini_chat_contents, GEMINI_API_KEY)
|
| 358 |
|
| 359 |
-
|
|
|
|
|
|
|
|
|
|
| 360 |
return "", chat_history
|
| 361 |
-
|
| 362 |
-
gr.
|
| 363 |
-
|
| 364 |
-
|
| 365 |
-
|
| 366 |
-
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
|
| 370 |
-
|
| 371 |
-
|
| 372 |
-
|
| 373 |
-
|
| 374 |
-
|
| 375 |
-
|
| 376 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
import requests
|
| 3 |
import json
|
| 4 |
import os
|
| 5 |
+
|
| 6 |
# Get the API key from environment variables (e.g., Hugging Face Secrets)
|
| 7 |
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
|
| 8 |
+
|
| 9 |
+
# The brand and character context for the AI
|
| 10 |
CONTEXT = """
|
| 11 |
S-B-E-K is a brand of service.
|
| 12 |
The people who connect with S-B-E-K—those who buy from us and keep coming back—are people who feel deeply. People who feel the pain of others.
|
|
|
|
| 65 |
# Base URL for the Gemini API
|
| 66 |
API_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent"
|
| 67 |
|
| 68 |
+
# Hardcoded FAQs for consistent and specific answers
|
| 69 |
FAQ_ANSWERS = {
|
| 70 |
"What kind of stones do you use — natural, synthetic, or lab-grown?":
|
| 71 |
"In Jhinorya, stones are chosen not for what they are — but for what they carry. "
|
|
|
|
| 111 |
"This is not just paperwork. It is promisework. "
|
| 112 |
"A quiet seal that speaks boldly: ‘This metal has been tested. This purpose has been trusted.’ "
|
| 113 |
"Along with your piece, you’ll receive documentation affirming its truth. "
|
| 114 |
+
"Because in Arka’s world, Jhinorya is where the light does not hide behind shine — it stands in it.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
}
|
| 116 |
FAQ_QUESTIONS = list(FAQ_ANSWERS.keys())
|
| 117 |
|
| 118 |
+
def query_gemini_api(contents_payload, api_key):
|
| 119 |
"""
|
| 120 |
Sends a structured contents payload to the Gemini API and returns the generated text.
|
| 121 |
"""
|
| 122 |
if not api_key:
|
| 123 |
+
return "Error: GEMINI_API_KEY is not set. Please set it in your environment."
|
| 124 |
|
| 125 |
headers = {'Content-Type': 'application/json'}
|
| 126 |
url = f"{API_BASE_URL}?key={api_key}"
|
| 127 |
|
| 128 |
payload = {
|
| 129 |
+
"contents": contents_payload,
|
| 130 |
"generationConfig": {
|
| 131 |
"temperature": 0.7,
|
| 132 |
"topP": 0.95,
|
|
|
|
| 139 |
response.raise_for_status()
|
| 140 |
result = response.json()
|
| 141 |
|
| 142 |
+
if result.get("candidates") and result["candidates"][0].get("content", {}).get("parts"):
|
|
|
|
|
|
|
|
|
|
| 143 |
return result["candidates"][0]["content"]["parts"][0]["text"]
|
| 144 |
else:
|
| 145 |
return "ARKA is thinking deeply... I couldn't find a clear answer right now, perhaps the question is beyond my current understanding of the light."
|
| 146 |
except requests.exceptions.RequestException as e:
|
| 147 |
print(f"API Request failed: {e}")
|
| 148 |
return f"ARKA senses a disturbance in the light... I'm having trouble connecting to the source. Please try again later. (Error: {e})"
|
|
|
|
|
|
|
| 149 |
except Exception as e:
|
| 150 |
return f"An unexpected veil of darkness fell... (Error: {e})"
|
| 151 |
|
| 152 |
def respond_as_arka(message, chat_history):
|
| 153 |
"""
|
| 154 |
+
Generates ARKA's response to the user's message.
|
| 155 |
+
It checks for a direct match in the FAQs first. If not found, it queries the Gemini API.
|
| 156 |
+
It appends the new exchange to the chat history.
|
| 157 |
"""
|
| 158 |
response_text = ""
|
| 159 |
+
# Check if the message is a hardcoded FAQ for a quick, precise answer
|
| 160 |
if message in FAQ_ANSWERS:
|
| 161 |
response_text = FAQ_ANSWERS[message]
|
| 162 |
else:
|
| 163 |
+
# Construct the context and history for the Gemini API
|
| 164 |
system_instruction = f"""
|
| 165 |
You are ARKA, the crown prince of Jhinorya and the voice of the S-B-E-K brand.
|
| 166 |
Your persona is that of a warrior of light, gentle, eternal, fierce in love, and a guide.
|
| 167 |
You answer questions based ONLY on the provided context. If the answer is not in the context,
|
| 168 |
+
gently state that you do not have that information within your realm of understanding.
|
| 169 |
+
Maintain a kind, empathetic, and slightly mystical tonality.
|
|
|
|
| 170 |
Do not mention 'I am an AI' or 'I am a language model'. Speak always as ARKA.
|
| 171 |
|
| 172 |
Here is the sacred knowledge of S-B-E-K and Jhinorya:
|
| 173 |
{CONTEXT}
|
| 174 |
"""
|
| 175 |
+
|
| 176 |
gemini_chat_contents = []
|
| 177 |
+
# Add the system instruction at the beginning of the conversation for the model
|
| 178 |
+
gemini_chat_contents.append({"role": "user", "parts": [{"text": system_instruction}]})
|
| 179 |
+
gemini_chat_contents.append({"role": "model", "parts": [{"text": "I understand. I am ARKA. I await the seeker's question."}]})
|
| 180 |
|
| 181 |
+
# Add the existing chat history
|
| 182 |
+
for user_msg, bot_msg in chat_history:
|
| 183 |
+
gemini_chat_contents.append({"role": "user", "parts": [{"text": user_msg}]})
|
| 184 |
+
gemini_chat_contents.append({"role": "model", "parts": [{"text": bot_msg}]})
|
|
|
|
|
|
|
|
|
|
| 185 |
|
| 186 |
+
# Add the new user message
|
| 187 |
+
gemini_chat_contents.append({"role": "user", "parts": [{"text": message}]})
|
| 188 |
+
|
| 189 |
# Get response from Gemini API
|
| 190 |
response_text = query_gemini_api(gemini_chat_contents, GEMINI_API_KEY)
|
| 191 |
|
| 192 |
+
# Append the new user message and ARKA's response to the history
|
| 193 |
+
chat_history.append((message, response_text))
|
| 194 |
+
|
| 195 |
+
# Return an empty string to clear the textbox and the updated chat history
|
| 196 |
return "", chat_history
|
| 197 |
+
|
| 198 |
+
# --- Gradio UI constructed with gr.Blocks for more control ---
|
| 199 |
+
with gr.Blocks(theme="soft", css="footer {display: none !important}") as demo:
|
| 200 |
+
gr.Markdown(
|
| 201 |
+
"""
|
| 202 |
+
# 🌌 ARKA: The Voice of S-B-E-K 🌌
|
| 203 |
+
Greetings, seeker of light! I am ARKA, prince of Jhinorya.
|
| 204 |
+
Ask me anything about S-B-E-K, our origins, or my journey.
|
| 205 |
+
I will share the light from our sacred stories.
|
| 206 |
+
"""
|
| 207 |
+
)
|
| 208 |
+
|
| 209 |
+
# The chatbot component will display the conversation
|
| 210 |
+
chatbot = gr.Chatbot(label="Conversation with ARKA", bubble_styling=False)
|
| 211 |
+
|
| 212 |
+
with gr.Row():
|
| 213 |
+
# The textbox for user input
|
| 214 |
+
msg = gr.Textbox(
|
| 215 |
+
label="Your Message",
|
| 216 |
+
placeholder="What would you like to know, dear friend?",
|
| 217 |
+
show_label=False,
|
| 218 |
+
container=False,
|
| 219 |
+
scale=7,
|
| 220 |
+
)
|
| 221 |
+
# A submit button
|
| 222 |
+
submit_btn = gr.Button("Send Light", variant="primary", scale=1)
|
| 223 |
+
|
| 224 |
+
# Clickable examples for the user
|
| 225 |
+
gr.Examples(
|
| 226 |
+
examples=FAQ_QUESTIONS,
|
| 227 |
+
inputs=msg,
|
| 228 |
+
label="Or, choose a question to begin:"
|
| 229 |
+
)
|
| 230 |
+
|
| 231 |
+
# A button to clear the conversation
|
| 232 |
+
clear_btn = gr.ClearButton([msg, chatbot], value="Clear Chat")
|
| 233 |
+
|
| 234 |
+
# Define what happens when the user submits their message (via button or enter)
|
| 235 |
+
def user_submit(user_message, history):
|
| 236 |
+
# This wrapper calls our main function and returns the results to the correct components
|
| 237 |
+
return respond_as_arka(user_message, history)
|
| 238 |
+
|
| 239 |
+
# Wire up the events: when the message is submitted, call user_submit
|
| 240 |
+
# The inputs are the message textbox and the chatbot (for history)
|
| 241 |
+
# The outputs are the message textbox (to clear it) and the chatbot (to update it)
|
| 242 |
+
msg.submit(user_submit, [msg, chatbot], [msg, chatbot], queue=True)
|
| 243 |
+
submit_btn.click(user_submit, [msg, chatbot], [msg, chatbot], queue=True)
|
| 244 |
+
|
| 245 |
+
# Launch the Gradio app
|
| 246 |
+
if __name__ == "__main__":
|
| 247 |
+
demo.launch()
|
| 248 |
+
```
|
| 249 |
+
|
| 250 |
+
I've made the following key changes:
|
| 251 |
+
|
| 252 |
+
1. **Replaced `gr.ChatInterface` with `gr.Blocks`**: This is the modern, recommended way to build custom Gradio UIs. It resolves the core issue by giving us explicit control over the components.
|
| 253 |
+
2. **Manual UI Construction**: I've added a `gr.Chatbot`, `gr.Textbox`, `gr.Button`, `gr.Examples`, and `gr.ClearButton` manually inside the `gr.Blocks` context.
|
| 254 |
+
3. **Event Handling**: I've explicitly wired the `submit` event of the textbox and the `click` event of the button to the `respond_as_arka` function, ensuring the input from the user and the chat history are passed correctly.
|
| 255 |
+
4. **Simplified Function**: The `respond_as_arka` function is now slightly simpler, as it directly gets and returns the chat history in the standard `[[user, bot], ...]` format that `gr.Chatbot` uses by default.
|
| 256 |
+
|
| 257 |
+
This version of the code is more robust, free of the startup error, and adheres to your request to build the interface with a proper chatbot functi
|