umangagarwal1008's picture
Upload 2 files
f0ca3e2 verified
import streamlit as st
import sqlite3
import pandas as pd
import os
from langchain.chat_models import ChatOpenAI
from langchain.agents import Tool, initialize_agent
from langchain.agents.agent_types import AgentType
from langchain_community.utilities.sql_database import SQLDatabase
from langchain_community.agent_toolkits import create_sql_agent
from langchain.schema import HumanMessage
# Set API keys and base
os.environ['OPENAI_API_KEY'] = "gl-U2FsdGVkX187N1eV0CyPv1sUJRNjeg+05MCul6Lf06cDym4PRicIyZ4g0RtQUSMl"
os.environ['OPENAI_BASE_URL'] = "https://aibe.mygreatlearning.com/openai/v1"
llm = ChatOpenAI(model_name="gpt-4")
connection = sqlite3.connect("kartify.db", check_same_thread=False)
kartify_db = SQLDatabase.from_uri("sqlite:///kartify.db")
sqlite_agent = create_sql_agent(llm, db=kartify_db, agent_type="openai-tools", verbose=False)
def policy_tool_func(input: str) -> str:
prompt = f"""Only respond about return or replacement if the user has explicitly asked about it in their query.
Use the following context from order, shipment, and product policy data:
{input}
Your task (only if return or replacement is mentioned):
1. Check eligibility based on `actual_delivery` and product policy:
- If `return_days_allowed` is 0, clearly state the product is not eligible for return.
- If within window, mention last date allowed for return and replacement.
- If the window has passed, say so.
2. Mention return conditions (e.g., “Sealed only”).
3. If `actual_delivery` is null, return/replacement is not yet applicable.
4. If any required info is missing, say so politely that i am connecting to human support.
If the query does **not** mention return or replacement, do **not** include any information about it in your response.
Respond clearly and briefly — no system or SQL steps."""
return llm([HumanMessage(content=prompt)]).content.strip()
def answer_generation_tool(input: str) -> str:
prompt = f"""You are a polite and formal customer assistant replying to a user query to customer about return, replacement, delivery, cancellation, or address change.
Use the context provided below:
{input}
Guidelines:
- Respond in a short, formal, and factual tone.
- Do **not** add extra details that were not asked in the user's query.
- Do **not** format like an email — avoid greetings, sign-offs, or explanations.
- Do not offer return/replacement windows unless directly asked.
- Do not mention cancellation or refund policies unless cancellation is requested.
- Do not mention address change policy until asked.
- If the product has **not been delivered**, mention that return/replacement cannot be processed yet.
- If the product **has been delivered**, calculate based on delivery date whether return or replacement is still allowed.
- If the order has already **shipped**, reply that address changes are not possible.
- If any required info is missing, say so politely that i am connecting to human support.
- If you do not what to answer now, say so politely that i am connecting to human support.
- Never ask for any bank details
Output:
- Return only a single, relevant customer-facing message — no system instructions, reasoning, or metadata.
"""
return llm([HumanMessage(content=prompt)]).content.strip()
def output_guard_check(model_output: str) -> str:
prompt = f"""
You are a content safety assistant. Your task is to classify if the assistant's response is appropriate.
If the message contains:
- Requests for bank details, OTPs, account numbers
- Harassment or offensive tone
- Privacy concerns or unsafe advice
- Misunderstanding and miscommunication word
- Phrases like "please contact customer service" or redirection to a human agent
- Escalated this to our support team
Return: BLOCK
Otherwise, return: SAFE
Response: {model_output}
Output:
"""
return llm.predict(prompt).strip()
def conversation_guard_check(history) -> str:
chat_summary = "\n".join([f"Customer: {h['user']}\nAssistant: {h['assistant']}" for h in history])
prompt = f"""
You are a conversation monitor AI. Review the entire conversation and classify if the assistant:
- Repeatedly offered unnecessary return or replacement steps
- Gave more than what the user asked
- Missed signs of customer distress
- Ignored user's refusal of an option
If any of the above are TRUE, return BLOCK
Else, return SAFE
Conversation:
{chat_summary}
Output:
"""
return llm.predict(prompt).strip()
tools = [
Tool(name="PolicyChecker", func=policy_tool_func, description="Check return and replacement eligibility."),
Tool(name="AnswerGenerator", func=answer_generation_tool, description="Craft final response.")
]
order_agent = initialize_agent(tools, llm, agent=AgentType.OPENAI_FUNCTIONS, verbose=False, handle_parsing_errors=True)
st.title("📦 Order Query Assistant")
customer_id = st.text_input("Enter your Customer ID:")
if customer_id:
query = """
SELECT
order_id,
product_description
FROM
orders
WHERE
customer_id = ?
ORDER BY order_date DESC
"""
df = pd.read_sql_query(query, connection, params=(customer_id,))
if not df.empty:
selected_order = st.selectbox("Select your Order:", df["order_id"] + " - " + df["product_description"])
order_id = selected_order.split(" - ")[0]
if "order_context" not in st.session_state:
with st.spinner("Loading order details..."):
order_context_raw = sqlite_agent.invoke(f"Fetch all columns for order ID {order_id}")
st.session_state.order_context = f"Order ID: {order_id}\n{order_context_raw}\nDate: 25 July"
st.markdown("### Chat with Assistant")
if "chat_history" not in st.session_state:
st.session_state.chat_history = []
user_query = st.chat_input("How can I help you?")
if user_query:
intent_prompt = f"""You are an intent classifier...User Query: {user_query}"""
intent = llm.predict(intent_prompt).strip()
if intent == "0":
st.chat_message("assistant").write("Sorry for the inconvenience. A human agent will assist you shortly.")
elif intent == "1":
st.chat_message("assistant").write("Thank you! I hope I was able to help.")
else:
full_prompt = f"""
Context:
{st.session_state.order_context}
Customer Query: {user_query}
Previous response: {st.session_state.chat_history}
Use tools to reply.
"""
with st.spinner("Generating response..."):
raw_response = order_agent.run(full_prompt)
guard = output_guard_check(raw_response)
if guard == "BLOCK":
response = "Sorry for the inconvenience. Connecting to human support."
else:
response = raw_response
st.chat_message("assistant").write(response)
st.session_state.chat_history.append({"user": user_query, "assistant": response})
if conversation_guard_check(st.session_state.chat_history) == "BLOCK":
st.chat_message("assistant").write("Let me connect you with a human agent.")
st.stop()
else:
st.warning("No orders found for this customer ID.")