Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -8,7 +8,8 @@ import numpy as np
|
|
8 |
from sklearn.feature_extraction.text import CountVectorizer
|
9 |
from sklearn.naive_bayes import MultinomialNB
|
10 |
import asyncio
|
11 |
-
from crewai import Agent
|
|
|
12 |
|
13 |
# Set up logging
|
14 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
@@ -35,38 +36,8 @@ Key points about Zerodha:
|
|
35 |
|
36 |
Always prioritize user safety, ethical investing practices, and transparent communication. Never provide information that could mislead users or bring disrepute to Zerodha."""
|
37 |
|
38 |
-
# Guardrail functions
|
39 |
-
|
40 |
-
return re.sub(r'[<>&\']', '', input_text)
|
41 |
-
|
42 |
-
approved_topics = ['account opening', 'trading', 'fees', 'platforms', 'funds', 'regulations', 'support']
|
43 |
-
vectorizer = CountVectorizer()
|
44 |
-
classifier = MultinomialNB()
|
45 |
-
|
46 |
-
X = vectorizer.fit_transform(approved_topics)
|
47 |
-
y = np.arange(len(approved_topics))
|
48 |
-
classifier.fit(X, y)
|
49 |
-
|
50 |
-
def is_relevant_topic(query):
|
51 |
-
query_vector = vectorizer.transform([query])
|
52 |
-
prediction = classifier.predict(query_vector)
|
53 |
-
return prediction[0] in range(len(approved_topics))
|
54 |
-
|
55 |
-
def redact_sensitive_info(text):
|
56 |
-
text = re.sub(r'\b\d{10,12}\b', '[REDACTED]', text)
|
57 |
-
text = re.sub(r'[A-Z]{5}[0-9]{4}[A-Z]', '[REDACTED]', text)
|
58 |
-
return text
|
59 |
-
|
60 |
-
def check_response_content(response):
|
61 |
-
unauthorized_patterns = [
|
62 |
-
r'\b(guarantee|assured|certain)\b.*\b(returns|profit)\b',
|
63 |
-
r'\b(buy|sell)\b.*\b(specific stocks?|shares?)\b'
|
64 |
-
]
|
65 |
-
return not any(re.search(pattern, response, re.IGNORECASE) for pattern in unauthorized_patterns)
|
66 |
-
|
67 |
-
def check_confidence(response):
|
68 |
-
uncertain_phrases = ["I'm not sure", "It's possible", "I don't have enough information"]
|
69 |
-
return not any(phrase.lower() in response.lower() for phrase in uncertain_phrases)
|
70 |
|
71 |
async def generate_response(prompt):
|
72 |
try:
|
@@ -76,18 +47,10 @@ async def generate_response(prompt):
|
|
76 |
return "I apologize, but I'm having trouble generating a response at the moment. Please try again later."
|
77 |
|
78 |
def post_process_response(response):
|
79 |
-
|
80 |
-
|
81 |
-
if not re.search(r'(Thank you|Is there anything else|Hope this helps|Let me know if you need more information)\s*$', response, re.IGNORECASE):
|
82 |
-
response += "\n\nIs there anything else I can help you with regarding Zerodha's services?"
|
83 |
-
|
84 |
-
if re.search(r'\b(invest|trade|buy|sell|market)\b', response, re.IGNORECASE):
|
85 |
-
response += "\n\nPlease note that this information is for educational purposes only and should not be considered as financial advice. Always do your own research and consider consulting with a qualified financial advisor before making investment decisions."
|
86 |
-
|
87 |
-
return response
|
88 |
|
89 |
# CrewAI setup
|
90 |
-
communication_expert_crew =
|
91 |
role='Communication Expert',
|
92 |
goal='Interpret and rephrase user queries with empathy and respect',
|
93 |
backstory="""You are an expert in communication, specializing in understanding and rephrasing queries to ensure they are interpreted in the most positive and constructive light. Your role is crucial in setting the tone for respectful and empathetic interactions.""",
|
@@ -96,7 +59,7 @@ communication_expert_crew = CrewAgent(
|
|
96 |
tools=[generate_response]
|
97 |
)
|
98 |
|
99 |
-
response_expert_crew =
|
100 |
role='Response Expert',
|
101 |
goal='Provide accurate, helpful, and emotionally intelligent responses to user queries',
|
102 |
backstory="""You are an expert in Zerodha's services and policies, with a keen ability to provide comprehensive and empathetic responses. Your role is to ensure that all user queries are addressed accurately while maintaining a respectful and supportive tone.""",
|
@@ -106,7 +69,7 @@ response_expert_crew = CrewAgent(
|
|
106 |
)
|
107 |
|
108 |
# Main function
|
109 |
-
async def zerodha_support(message, history):
|
110 |
try:
|
111 |
sanitized_message = sanitize_input(message)
|
112 |
|
@@ -133,12 +96,19 @@ async def zerodha_support(message, history):
|
|
133 |
logger.error(f"Error in CrewAI rephrasing: {e}")
|
134 |
rephrased_query = sanitized_message # Fallback to original message if rephrasing fails
|
135 |
|
136 |
-
# Generate response using
|
137 |
-
|
138 |
-
response
|
139 |
-
|
140 |
-
|
141 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
|
143 |
if not check_response_content(response):
|
144 |
response += "\n\nPlease note that I cannot provide specific investment advice or guarantee returns. For personalized guidance, please consult with a qualified financial advisor."
|
@@ -153,24 +123,98 @@ async def zerodha_support(message, history):
|
|
153 |
logger.error(f"Error in zerodha_support: {e}")
|
154 |
return "I apologize, but an error occurred while processing your request. Please try again later."
|
155 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
# Gradio interface setup
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
|
175 |
if __name__ == "__main__":
|
176 |
demo.launch()
|
|
|
8 |
from sklearn.feature_extraction.text import CountVectorizer
|
9 |
from sklearn.naive_bayes import MultinomialNB
|
10 |
import asyncio
|
11 |
+
from crewai import Agent, Task, Crew
|
12 |
+
import random
|
13 |
|
14 |
# Set up logging
|
15 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
|
|
36 |
|
37 |
Always prioritize user safety, ethical investing practices, and transparent communication. Never provide information that could mislead users or bring disrepute to Zerodha."""
|
38 |
|
39 |
+
# Guardrail functions (keep these as they were)
|
40 |
+
# ... (sanitize_input, is_relevant_topic, redact_sensitive_info, check_response_content, check_confidence)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
|
42 |
async def generate_response(prompt):
|
43 |
try:
|
|
|
47 |
return "I apologize, but I'm having trouble generating a response at the moment. Please try again later."
|
48 |
|
49 |
def post_process_response(response):
|
50 |
+
# ... (keep the existing post_process_response function)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
|
52 |
# CrewAI setup
|
53 |
+
communication_expert_crew = Agent(
|
54 |
role='Communication Expert',
|
55 |
goal='Interpret and rephrase user queries with empathy and respect',
|
56 |
backstory="""You are an expert in communication, specializing in understanding and rephrasing queries to ensure they are interpreted in the most positive and constructive light. Your role is crucial in setting the tone for respectful and empathetic interactions.""",
|
|
|
59 |
tools=[generate_response]
|
60 |
)
|
61 |
|
62 |
+
response_expert_crew = Agent(
|
63 |
role='Response Expert',
|
64 |
goal='Provide accurate, helpful, and emotionally intelligent responses to user queries',
|
65 |
backstory="""You are an expert in Zerodha's services and policies, with a keen ability to provide comprehensive and empathetic responses. Your role is to ensure that all user queries are addressed accurately while maintaining a respectful and supportive tone.""",
|
|
|
69 |
)
|
70 |
|
71 |
# Main function
|
72 |
+
async def zerodha_support(message, history, username):
|
73 |
try:
|
74 |
sanitized_message = sanitize_input(message)
|
75 |
|
|
|
96 |
logger.error(f"Error in CrewAI rephrasing: {e}")
|
97 |
rephrased_query = sanitized_message # Fallback to original message if rephrasing fails
|
98 |
|
99 |
+
# Generate response using Response Expert
|
100 |
+
response_task = Task(
|
101 |
+
description=f"Provide an accurate and helpful response to the user query: '{rephrased_query}'",
|
102 |
+
agent=response_expert_crew
|
103 |
+
)
|
104 |
+
|
105 |
+
crew = Crew(
|
106 |
+
agents=[response_expert_crew],
|
107 |
+
tasks=[response_task],
|
108 |
+
verbose=2
|
109 |
+
)
|
110 |
+
|
111 |
+
response = crew.kickoff()
|
112 |
|
113 |
if not check_response_content(response):
|
114 |
response += "\n\nPlease note that I cannot provide specific investment advice or guarantee returns. For personalized guidance, please consult with a qualified financial advisor."
|
|
|
123 |
logger.error(f"Error in zerodha_support: {e}")
|
124 |
return "I apologize, but an error occurred while processing your request. Please try again later."
|
125 |
|
126 |
+
# Custom CSS for better styling
|
127 |
+
custom_css = """
|
128 |
+
.container {
|
129 |
+
max-width: 800px;
|
130 |
+
margin: auto;
|
131 |
+
padding: 20px;
|
132 |
+
}
|
133 |
+
.title {
|
134 |
+
text-align: center;
|
135 |
+
color: #387EF5;
|
136 |
+
font-size: 32px;
|
137 |
+
margin-bottom: 20px;
|
138 |
+
}
|
139 |
+
.description {
|
140 |
+
text-align: center;
|
141 |
+
color: #555;
|
142 |
+
margin-bottom: 30px;
|
143 |
+
}
|
144 |
+
.chatbot {
|
145 |
+
border: 1px solid #ddd;
|
146 |
+
border-radius: 10px;
|
147 |
+
overflow: hidden;
|
148 |
+
}
|
149 |
+
.user-info {
|
150 |
+
background-color: #f0f0f0;
|
151 |
+
padding: 10px;
|
152 |
+
border-radius: 5px;
|
153 |
+
margin-bottom: 20px;
|
154 |
+
}
|
155 |
+
"""
|
156 |
+
|
157 |
+
# Placeholder function for user authentication (you'd implement this with your backend)
|
158 |
+
def authenticate(username, password):
|
159 |
+
# This is a mock authentication. In a real scenario, you'd verify against a database.
|
160 |
+
return username == "demo" and password == "password"
|
161 |
+
|
162 |
+
# Function to generate a random support ticket number
|
163 |
+
def generate_ticket_number():
|
164 |
+
return f"ZRD-{random.randint(100000, 999999)}"
|
165 |
+
|
166 |
# Gradio interface setup
|
167 |
+
with gr.Blocks(css=custom_css) as demo:
|
168 |
+
gr.HTML("<div class='title'>Zerodha Support Assistant</div>")
|
169 |
+
gr.HTML("<div class='description'>Ask questions about Zerodha's services, trading, account management, and more.</div>")
|
170 |
+
|
171 |
+
with gr.Tab("Login"):
|
172 |
+
username_input = gr.Textbox(label="Username")
|
173 |
+
password_input = gr.Textbox(label="Password", type="password")
|
174 |
+
login_button = gr.Button("Login")
|
175 |
+
login_message = gr.Textbox(label="Login Status", interactive=False)
|
176 |
+
|
177 |
+
with gr.Tab("Support Chat"):
|
178 |
+
with gr.Row():
|
179 |
+
with gr.Column(scale=2):
|
180 |
+
chatbot = gr.Chatbot(height=400)
|
181 |
+
message_input = gr.Textbox(label="Your Message", placeholder="Type your question here...")
|
182 |
+
submit_button = gr.Button("Send")
|
183 |
+
|
184 |
+
with gr.Column(scale=1):
|
185 |
+
with gr.Box():
|
186 |
+
gr.HTML("<div class='user-info'>")
|
187 |
+
user_display = gr.Textbox(label="Logged in as", interactive=False)
|
188 |
+
ticket_number = gr.Textbox(label="Support Ticket", value=generate_ticket_number(), interactive=False)
|
189 |
+
gr.HTML("</div>")
|
190 |
+
|
191 |
+
gr.HTML("<h4>Quick Links</h4>")
|
192 |
+
gr.HTML("<ul><li><a href='https://zerodha.com/varsity/' target='_blank'>Zerodha Varsity</a></li><li><a href='https://console.zerodha.com/' target='_blank'>Zerodha Console</a></li></ul>")
|
193 |
+
|
194 |
+
# Example queries
|
195 |
+
gr.Examples(
|
196 |
+
examples=[
|
197 |
+
"How do I open a Zerodha account?",
|
198 |
+
"What are the brokerage charges for intraday trading?",
|
199 |
+
"How can I withdraw funds from my Zerodha account?",
|
200 |
+
"What is the margin requirement for F&O trading?",
|
201 |
+
"How do I use the Kite mobile app?",
|
202 |
+
],
|
203 |
+
inputs=message_input,
|
204 |
+
)
|
205 |
+
|
206 |
+
# Login logic
|
207 |
+
def login(username, password):
|
208 |
+
if authenticate(username, password):
|
209 |
+
return "Login successful!", gr.Tabs.update(selected="Support Chat"), username
|
210 |
+
else:
|
211 |
+
return "Login failed. Please try again.", gr.Tabs.update(selected="Login"), ""
|
212 |
+
|
213 |
+
login_button.click(login, inputs=[username_input, password_input], outputs=[login_message, demo.tabs, user_display])
|
214 |
+
|
215 |
+
# Chat logic
|
216 |
+
submit_button.click(zerodha_support, inputs=[message_input, chatbot, user_display], outputs=chatbot)
|
217 |
+
message_input.submit(zerodha_support, inputs=[message_input, chatbot, user_display], outputs=chatbot)
|
218 |
|
219 |
if __name__ == "__main__":
|
220 |
demo.launch()
|