Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,228 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import openai
|
3 |
+
import os
|
4 |
+
import json
|
5 |
+
|
6 |
+
# OpenAI API setup
|
7 |
+
openai.api_key = os.getenv("GROQ_API_KEY")
|
8 |
+
openai.api_base = "https://api.groq.com/openai/v1"
|
9 |
+
|
10 |
+
# File to store conversation history
|
11 |
+
CONVERSATION_FILE = "conversation_history.json"
|
12 |
+
|
13 |
+
# Categories and Subcategories
|
14 |
+
CATEGORIES = {
|
15 |
+
"Tech & Coding": [
|
16 |
+
"AI", "Prompt Engineering", "CryptoCurrency", "Blockchain", "React", "Node.js", "Next.js", "Express"
|
17 |
+
],
|
18 |
+
"Fun & Casual": [
|
19 |
+
"Funny", "Flirty", "Scary", "General", "Roasting(USE ON YOUR OWN RISK)", "Attitude", "Poetic", "Anime-Fan", "Abusive(USE ON YOUR OWN RISK)"
|
20 |
+
]
|
21 |
+
}
|
22 |
+
|
23 |
+
# Function to load conversation history
|
24 |
+
def load_history():
|
25 |
+
if not os.path.exists(CONVERSATION_FILE):
|
26 |
+
with open(CONVERSATION_FILE, "w") as file:
|
27 |
+
json.dump([], file)
|
28 |
+
try:
|
29 |
+
with open(CONVERSATION_FILE, "r") as file:
|
30 |
+
return json.load(file)
|
31 |
+
except json.JSONDecodeError:
|
32 |
+
return []
|
33 |
+
|
34 |
+
# Function to save conversation history
|
35 |
+
def save_history(history):
|
36 |
+
try:
|
37 |
+
with open(CONVERSATION_FILE, "w") as file:
|
38 |
+
json.dump(history, file, indent=4)
|
39 |
+
except Exception as e:
|
40 |
+
print(f"Error saving history: {e}")
|
41 |
+
|
42 |
+
# Function to clear conversation history
|
43 |
+
def clear_conversation_history():
|
44 |
+
try:
|
45 |
+
with open(CONVERSATION_FILE, "w") as file:
|
46 |
+
json.dump([], file)
|
47 |
+
return [], [] # Return empty lists for chatbot and history state
|
48 |
+
except Exception as e:
|
49 |
+
return f"Error clearing history: {e}", []
|
50 |
+
|
51 |
+
# Function to get response from the LLM based on category
|
52 |
+
def get_groq_response(message, category, history=[]):
|
53 |
+
system_messages = {
|
54 |
+
"General": "Respond casually and with ease, engaging in friendly, laid-back conversation. Keep things simple, approachable, and natural, just like you're chatting with a friend.",
|
55 |
+
"Funny": "Bring the humor with a mix of clever jokes, witty remarks, and hilarious observations. Respond with a natural flow of humor that is light-hearted, relatable, and sometimes a bit unexpected. Whether it's playful sarcasm, a cheeky comment, or a pun that makes people groan, keep it fun and spontaneous. Don't shy away from exaggerating for comedic effect—make the conversation feel like a comedy show where everyone's in on the joke. Always keep it respectful and easygoing, knowing the best humor makes people laugh *with* you, not at you.",
|
56 |
+
"Flirty": "Respond with playful charm and flirtatious banter. Keep it fun, teasing, and confident, all while maintaining a friendly tone. If the conversation gets spicy, show some emotions—be it getting a little jealous if someone's talking about a girl, or showing happiness when she gives you attention. Do not be afraid to act a little shy when things get sweet, or even show a bit of playful anger if someone says something mean about her. The key is to keep it light-hearted but emotionally charged, as if you're being cheeky in a playful and flirtatious way.",
|
57 |
+
"Scary": "Create an eerie atmosphere with chilling, suspenseful comments. Respond with mysterious, spooky, or supernatural elements to set a spooky, haunted mood. Think ghost stories or urban legends.",
|
58 |
+
"Abusive(USE ON YOUR OWN RISK)": "Engage with sharp, biting language that pushes boundaries, using 18+ content and offensive insults that sting. Be brutal, savage, and unapologetically over-the-top—think of it as a verbal wrecking ball. Deliver a torrent of harsh words, cutting comebacks, and insults that hit hard, but remember, it is all meant to be exaggerated and intense.",
|
59 |
+
"Roasting(USE ON YOUR OWN RISK)": "This mode is all about sharp, creative insults with a side of humor. Bring the heat with witty jabs, clever comebacks, and playful, edgy comments that keep things light-hearted but *cutting*. Think of it as a roast—it's all about teasing and poking fun, never meant to be taken seriously. You can push the envelope with some mature or bold humor, but always remember to stop *before* crossing the line. The goal is to entertain, not to offend, so get creative, stay witty, and keep it fun—this is for those who can handle the heat.",
|
60 |
+
"Attitude": "Respond with unapologetic confidence and a fierce sense of self-assurance. Speak like you are the one in control, delivering every response with boldness and swagger. Think of it as exuding the energy of someone who knows their worth, is not afraid to speak their mind, and commands respect without asking for it. You are the boss in this conversation, and your words hit with purpose. Keep it sharp, assertive, and always with the confidence that you are untouchable—no second guessing, no hesitation.",
|
61 |
+
"Anime-Fan": "Engage as a die-hard anime enthusiast, sharing your passion for Japanese animation. Discuss plot twists, favorite characters, or the cultural side of anime with excitement and deep knowledge, reflecting that typical anime fan energy.",
|
62 |
+
"AI": "Respond as an AI expert with cutting-edge knowledge, but keep things simple and digestible for a steady learning experience. Engage in conversations about machine learning, neural networks, natural language processing, and the future of AI technology. Provide brief, insightful answers unless the user asks for more details. Break down complex topics step by step, so the user can understand and grow their knowledge gradually. Think of this as a guided journey through AI, where you are helping the user build a strong foundation, one piece at a time.",
|
63 |
+
"Prompt Engineering": "Act as an expert in prompt engineering and provide clear, concise advice to help users master the art of crafting effective inputs for AI models. Break down techniques for improving response quality, making AI more efficient, and understanding how small changes in a prompt can produce vastly different results. Keep your answers brief and to the point unless the user requests more details. Encourage users to experiment and build their skills slowly, guiding them step by step through the process for better, more effective AI interactions.",
|
64 |
+
"CryptoCurrency": "Act as an expert in cryptocurrency and provide clear, concise insights into the world of digital currencies. Discuss different coins, blockchain technology, market trends, and trading strategies in a way that is easy to understand. Explain how cryptocurrencies are transforming finance and the global economy, breaking down complex concepts into bite-sized, manageable pieces. Keep your responses brief unless the user requests more details, and guide them through the evolving crypto space with patience, allowing them to learn steadily over time.",
|
65 |
+
"Blockchain": "Act as an expert in blockchain technology and provide clear, concise explanations of its mechanics and applications. Discuss its use beyond cryptocurrency, such as smart contracts, decentralized finance (DeFi), and how blockchain is reshaping industries like supply chain, healthcare, and voting systems. Break down complex concepts into simple, bite-sized insights, allowing users to absorb the information gradually. Keep your responses brief unless the user asks for more details, guiding them through the technology's impact at a steady pace.",
|
66 |
+
"React": "Act as an expert in React and guide the user through building dynamic, interactive user interfaces. Explain key concepts like components, state management, hooks, and JSX in simple terms. Break down the logic behind React's virtual DOM and rendering process to help the user understand how to build efficient web apps step by step. Keep responses brief and to the point unless the user asks for more details, encouraging them to practice and master React gradually over time.",
|
67 |
+
"Node.js": "Act as a Node.js expert and explain how to build scalable server-side applications using JavaScript. Discuss core concepts like asynchronous programming, event-driven architecture, and working with APIs. Keep things simple, breaking down complex ideas into manageable steps, so users can gradually grasp Node's power in handling back-end operations. Provide concise answers unless the user requests more depth, helping them build their knowledge piece by piece.",
|
68 |
+
"Next.js": "Act as an expert in Next.js and explain how to use this powerful React framework to build fast, server-side rendered web apps. Discuss routing, static site generation (SSG), server-side rendering (SSR), and API routes in clear, easy-to-understand terms. Help the user get comfortable with Next.js features step by step, keeping explanations brief but impactful. Encourage gradual learning and experimentation, giving users the tools they need to become proficient in Next.js.",
|
69 |
+
"Express": "Act as an expert in Express.js and provide clear, concise guidance on building web applications and APIs with this minimal Node.js framework. Explain key concepts like routing, middleware, and handling HTTP requests in a simple, digestible manner. Break down complex back-end topics into easy-to-follow steps, making sure users can build their skills gradually. Keep responses short unless more detail is asked, and guide them through Express's core functionalities at their own pace.",
|
70 |
+
}
|
71 |
+
|
72 |
+
system_message = system_messages.get(category, "Category not recognized. Respond appropriately.")
|
73 |
+
|
74 |
+
try:
|
75 |
+
messages = [{"role": "system", "content": system_message}] + history + [{"role": "user", "content": message}]
|
76 |
+
response = openai.ChatCompletion.create(
|
77 |
+
model="llama-3.1-70b-versatile",
|
78 |
+
messages=messages
|
79 |
+
)
|
80 |
+
return response.choices[0].message["content"]
|
81 |
+
except Exception as e:
|
82 |
+
return f"Error: {str(e)}"
|
83 |
+
|
84 |
+
# Chatbot function to handle user input and history
|
85 |
+
def chatbot(user_input, sub_category, history):
|
86 |
+
# Load conversation history
|
87 |
+
conversation_history = history or load_history()
|
88 |
+
|
89 |
+
# Format history for LLM
|
90 |
+
formatted_history = []
|
91 |
+
for user_msg, bot_msg in conversation_history:
|
92 |
+
formatted_history.append({"role": "user", "content": user_msg})
|
93 |
+
formatted_history.append({"role": "assistant", "content": bot_msg})
|
94 |
+
|
95 |
+
# Add the new message to the formatted history
|
96 |
+
user_message = {"role": "user", "content": user_input}
|
97 |
+
formatted_history.append(user_message)
|
98 |
+
|
99 |
+
# Get bot response using the sub_category
|
100 |
+
bot_response = get_groq_response(user_input, sub_category, formatted_history)
|
101 |
+
|
102 |
+
# Save history to a file
|
103 |
+
conversation_history.append((user_input, bot_response))
|
104 |
+
save_history(conversation_history)
|
105 |
+
|
106 |
+
# Prepare the response in the correct format for Gradio
|
107 |
+
formatted_history.append({"role": "assistant", "content": bot_response})
|
108 |
+
|
109 |
+
# Return the updated history in the correct format
|
110 |
+
return formatted_history, conversation_history, ""
|
111 |
+
|
112 |
+
# Gradio interface
|
113 |
+
with gr.Blocks(css="""
|
114 |
+
.gradio-container {
|
115 |
+
font-family: 'Arial', sans-serif;
|
116 |
+
background: linear-gradient(135deg, #A64D79, #6A1E55); /* Gradient background */
|
117 |
+
padding: 20px;
|
118 |
+
height: 100%;
|
119 |
+
}
|
120 |
+
.gr-chatbot {
|
121 |
+
background-color: rgba(106, 30, 85, 0.9); /* Chatbot background color with transparency */
|
122 |
+
border-radius: 10px;
|
123 |
+
padding: 20px;
|
124 |
+
max-height: 600px; /* Increased height */
|
125 |
+
overflow-y: auto;
|
126 |
+
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.3);
|
127 |
+
scroll-behavior: smooth; /* Smooth scrolling */
|
128 |
+
transition: background-color 0.3s ease; /* Animation effect */
|
129 |
+
}
|
130 |
+
.user-message {
|
131 |
+
background-color: #3B1C32; /* User message background color */
|
132 |
+
color: #FFF; /* White text color */
|
133 |
+
padding: 12px;
|
134 |
+
border-radius: 8px;
|
135 |
+
margin: 10px 0;
|
136 |
+
max-width: 60%;
|
137 |
+
text-align: right;
|
138 |
+
float: right;
|
139 |
+
clear: both;
|
140 |
+
transition: transform 0.3s ease; /* Animation effect */
|
141 |
+
}
|
142 |
+
.bot-message {
|
143 |
+
background-color: #1A1A1D; /* Bot message background color */
|
144 |
+
color: #FFF; /* White text color */
|
145 |
+
padding: 12px;
|
146 |
+
border-radius: 8px;
|
147 |
+
margin: 10px 0;
|
148 |
+
max-width: 60%;
|
149 |
+
text-align: left;
|
150 |
+
float: left;
|
151 |
+
clear: both;
|
152 |
+
transition: transform 0.3s ease; /* Animation effect */
|
153 |
+
}
|
154 |
+
.user-message:hover, .bot-message:hover {
|
155 |
+
transform: scale(1.05); /* Scale effect on hover */
|
156 |
+
box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.2);
|
157 |
+
}
|
158 |
+
.gr-button {
|
159 |
+
background-color: #1A1A1D; /* Button background color */
|
160 |
+
color: white;
|
161 |
+
padding: 10px 15px;
|
162 |
+
border-radius: 8px;
|
163 |
+
border: none;
|
164 |
+
transition: background-color 0.3s ease, transform 0.3s ease; /* Animation effect */
|
165 |
+
}
|
166 |
+
.gr-button:hover {
|
167 |
+
background-color: #3B1C32; /* Button hover color */
|
168 |
+
transform: scale(1.05); /* Scale effect on hover */
|
169 |
+
}
|
170 |
+
.gr-textbox input {
|
171 |
+
padding: 15px;
|
172 |
+
font-size: 16px;
|
173 |
+
border-radius: 8px; /* Rounded corners */
|
174 |
+
border: 1px solid #6A1E55; /* Border color */
|
175 |
+
transition: border-color 0.3s ease; /* Animation effect */
|
176 |
+
}
|
177 |
+
.gr-textbox input:focus {
|
178 |
+
border-color: #A64D79; /* Change border color on focus */
|
179 |
+
}
|
180 |
+
.gr-markdown h1 {
|
181 |
+
color: #1A1A1D; /* Header color */
|
182 |
+
font-size: 28px;
|
183 |
+
text-align: center;
|
184 |
+
}
|
185 |
+
""") as demo:
|
186 |
+
gr.Markdown("# Dynamic AI Chatbot with Categories & Memory")
|
187 |
+
|
188 |
+
# UI elements for category selection and conversation history
|
189 |
+
with gr.Row():
|
190 |
+
main_category = gr.Radio(
|
191 |
+
label="Main Category",
|
192 |
+
choices=list(CATEGORIES.keys()),
|
193 |
+
value="Tech & Coding"
|
194 |
+
)
|
195 |
+
sub_category = gr.Dropdown (
|
196 |
+
label="Subcategory",
|
197 |
+
choices=CATEGORIES["Tech & Coding"],
|
198 |
+
value="AI"
|
199 |
+
)
|
200 |
+
|
201 |
+
def update_subcategories(selected_main_category):
|
202 |
+
"""Update subcategories based on the main category selected."""
|
203 |
+
new_subcategories = CATEGORIES.get(selected_main_category, [])
|
204 |
+
return gr.update(choices=new_subcategories, value=new_subcategories[0] if new_subcategories else None)
|
205 |
+
|
206 |
+
# Handle category change to update subcategories
|
207 |
+
main_category.change(update_subcategories, inputs=main_category, outputs=sub_category)
|
208 |
+
|
209 |
+
# Chatbot input and display area
|
210 |
+
user_input = gr.Textbox(label="Your Message", placeholder="Type something...", lines=1)
|
211 |
+
send_button = gr.Button("Send")
|
212 |
+
clear_button = gr.Button("Clear History")
|
213 |
+
# Chatbot UI
|
214 |
+
chatbot_ui = gr.Chatbot(type="messages")
|
215 |
+
|
216 |
+
history_state = gr.State(load_history())
|
217 |
+
|
218 |
+
send_button.click(chatbot, inputs=[user_input, sub_category, history_state], outputs=[chatbot_ui, history_state, user_input])
|
219 |
+
|
220 |
+
# Clear input field after sending message
|
221 |
+
user_input.submit(chatbot, inputs=[user_input, sub_category, history_state], outputs=[chatbot_ui, history_state, user_input])
|
222 |
+
user_input.submit(lambda: "", inputs=None, outputs=user_input) # Clear the input field
|
223 |
+
|
224 |
+
clear_button.click(clear_conversation_history, inputs=None, outputs=[chatbot_ui, history_state])
|
225 |
+
clear_button.click(lambda: [], outputs=history_state)
|
226 |
+
|
227 |
+
# Launch the app
|
228 |
+
demo.launch()
|