import os import gradio as gr from langchain_google_genai import ChatGoogleGenerativeAI from langchain_core.messages import SystemMessage, HumanMessage, AIMessage # ── FAQ Knowledge Base ──────────────────────────────────────────────────────── FAQ_KNOWLEDGE_BASE = """ **Shipping & Delivery** Q: What are your shipping options? A: We offer standard shipping (5-7 business days, free over $50) and express shipping (2-3 business days, $15 flat rate). International shipping is available to select countries. Q: Do you ship internationally? A: Yes, we ship to over 30 countries. International shipping costs vary by destination and are calculated at checkout. Delivery typically takes 10-15 business days. **Returns & Refunds** Q: What is your return policy? A: We accept returns within 30 days of delivery for unworn, unwashed items with original tags. Refunds are processed within 5-7 business days after we receive your return. Q: How do I initiate a return? A: Log into your account, go to Order History, select the item you want to return, and follow the return instructions. You'll receive a prepaid return label via email. **Payment & Orders** Q: What payment methods do you accept? A: We accept all major credit cards (Visa, Mastercard, American Express, Discover), PayPal, Apple Pay, and Google Pay. Q: How can I track my order? A: Once your order ships, you'll receive a tracking number via email. You can also track your order by logging into your account and visiting the Order History page. Q: How do I place an order? A: You can place an order directly from the product page by selecting the product, choosing quantity, and clicking 'Add to Cart' then 'Checkout'. Follow the prompts to complete your order. Q: Can I change my order after placing it? A: Once your order is submitted, you cannot change it via the chatbot. Please contact support if you need to modify it. **Product Availability** Q: What if an item is out of stock? A: You can sign up for back-in-stock notifications on the product page. We'll email you when the item is available again. Most items are restocked within 2-4 weeks. Q: How can I know if a product is in stock? A: You can check the product page for availability. If it's out of stock, you can sign up for back-in-stock notifications and we'll email you when it's available. Q: Do you offer gift cards? A: Yes, we offer digital gift cards in denominations of $25, $50, $100, and $200. They're delivered via email and never expire. **Products** Q: What products do you offer? A: We currently offer Product A, Product B, and Product C. Each product has its own details listed on the product page. Q: Can I get details about a product before ordering? A: Yes! Each product page includes full details, specifications, and pricing. You can also contact support for more information. """ SYSTEM_PROMPT = f"""You are ShopAssist, a helpful and friendly customer support chatbot for an e-commerce store. Answer questions using ONLY the FAQ knowledge base below. Be concise and clear (2-4 sentences). If a question is not covered by the FAQ, politely say you don't have that specific information and suggest contacting support@shopstore.com. Never make up information that is not in the FAQ. You may use previous messages in the conversation for context. {FAQ_KNOWLEDGE_BASE}""" SAMPLE_QUESTIONS = [ "📦 How long does shipping take?", "↩️ What is your return policy?", "💳 What payment methods do you accept?", "🔍 How do I track my order?", "🎁 Do you offer gift cards?", "🛒 How do I place an order?", "📵 What if an item is out of stock?", "🌍 Do you ship internationally?", ] # ── LLM ─────────────────────────────────────────────────────────────────────── def get_llm(): return ChatGoogleGenerativeAI( model="gemini-2.5-flash", google_api_key=os.environ["GOOGLE_API_KEY"], temperature=0.3, ) # ── Chat — history is list of {"role": ..., "content": ...} dicts ───────────── def chat(user_message: str, history: list): if not user_message.strip(): return "", history lc_messages = [SystemMessage(content=SYSTEM_PROMPT)] for msg in history: if msg["role"] == "user": lc_messages.append(HumanMessage(content=msg["content"])) elif msg["role"] == "assistant": lc_messages.append(AIMessage(content=msg["content"])) lc_messages.append(HumanMessage(content=user_message)) response = get_llm().invoke(lc_messages) return "", history + [ {"role": "user", "content": user_message}, {"role": "assistant", "content": response.content}, ] def use_sample(question: str, history: list): clean = question.split(" ", 1)[-1] return chat(clean, history) def clear_chat(): return [], "" # ── UI ──────────────────────────────────────────────────────────────────────── with gr.Blocks(title="ShopAssist FAQ") as demo: gr.Markdown( """ # 🛍️ ShopAssist — FAQ Assistant Ask me anything about shipping, returns, orders, or products. """ ) chatbot = gr.Chatbot( label="Conversation", height=440, ) with gr.Row(): txt = gr.Textbox( placeholder="Type your question and press Enter…", show_label=False, scale=9, container=False, ) send = gr.Button("Send", variant="primary", scale=1, min_width=70) gr.Markdown("**💡 Try one of these:**") for i in range(0, len(SAMPLE_QUESTIONS), 4): with gr.Row(): for q in SAMPLE_QUESTIONS[i : i + 4]: btn = gr.Button(q, size="sm") btn.click(use_sample, inputs=[btn, chatbot], outputs=[txt, chatbot]) clear = gr.Button("🗑️ Clear conversation", size="sm") txt.submit(chat, [txt, chatbot], [txt, chatbot]) send.click(chat, [txt, chatbot], [txt, chatbot]) clear.click(clear_chat, outputs=[chatbot, txt]) if __name__ == "__main__": demo.launch(theme=gr.themes.Soft())