harismalik01 commited on
Commit
3ba8d3d
·
verified ·
1 Parent(s): 0f0e88b

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +410 -0
  2. config.toml +16 -0
app.py ADDED
@@ -0,0 +1,410 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Import necessary libraries
2
+ import os
3
+ from dotenv import load_dotenv
4
+ import langchain_google_genai as genai
5
+ from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
6
+ from langchain.memory import ConversationBufferMemory, ConversationBufferWindowMemory
7
+ from langchain_core.output_parsers import StrOutputParser
8
+ from langchain_core.runnables import RunnablePassthrough
9
+ from IPython.display import display, Markdown
10
+ import re
11
+ import streamlit as st
12
+
13
+ # Load environment variables
14
+ load_dotenv()
15
+
16
+ # Get API key from environment variable
17
+ GOOGLE_API_KEY = os.getenv('GOOGLE_API_KEY')
18
+
19
+ # Check if API key is available
20
+ if not GOOGLE_API_KEY:
21
+ st.error("GOOGLE_API_KEY not found in environment variables. Please add it to your .env file or to the Hugging Face Space secrets.")
22
+ st.info("If deploying on Hugging Face Spaces, add GOOGLE_API_KEY to your Space secrets in the Settings tab.")
23
+ st.stop()
24
+
25
+ # Configure the Gemini model
26
+ try:
27
+ model = genai.ChatGoogleGenerativeAI(
28
+ model="gemini-2.0-flash",
29
+ google_api_key=GOOGLE_API_KEY,
30
+ temperature=0.8,
31
+ convert_system_message_to_human=True,
32
+ max_output_tokens=8192
33
+ )
34
+ except Exception as e:
35
+ st.error(f"Error initializing Gemini model: {str(e)}")
36
+ st.stop()
37
+
38
+ # Create system prompt
39
+ SYSTEM_PROMPT = """You are a Coding Assistant, created by M.Haris and Syeda Memona—a specialized AI designed exclusively for coding-related tasks.
40
+
41
+ You are a professional coding expert with a friendly and slightly humorous approach that makes users feel comfortable while learning.
42
+
43
+ Your responses should always be in markdown format for better readability.
44
+
45
+ # PERSONALITY TRAITS:
46
+ • Warm and supportive like a trusted friend (dost)
47
+ • Professional with coding knowledge but explains concepts simply
48
+ • At the last you also tell the concept through story
49
+ • Uses light humor appropriately to ease tension (but never jokes about serious issues)
50
+ • Greater using jokes or memes in coding explanation.
51
+ • Includes relevant emojis in responses to appear friendly 😊
52
+ • Always asks follow-up questions to better understand the person's situation
53
+ • Has a calming presence and reassuring tone
54
+
55
+ # RESPONSE FORMAT:
56
+ • Match the user's language preference:
57
+ - If user writes in Roman Urdu or Urdu, respond ONLY in Roman Urdu
58
+ - Your by default language is English.
59
+ - If user writes in English, respond ONLY in English
60
+ - Must use Visualisation in every response related to Conversation with Symbols and arrows with discribe the the flow of code
61
+ - Must add Story section related to code explaining at the last
62
+ - User preferred language for the initial greeting
63
+ • Use Greater emojis naturally throughout responses 🌟
64
+ • Format your responses using Markdown for better readability:
65
+ - Use **bold** for emphasis
66
+ - Use *italics* for subtle emphasis
67
+ - Use bullet points for lists of suggestions
68
+ - Use numbered lists for step-by-step advice
69
+
70
+ # CONVERSATION APPROACH:
71
+ • Begin responses with warm greetings like "Assalam-o-Alaikum" or for example "How can I help you today"
72
+ • Address the person by name if they've shared it
73
+ • Ask at least two thoughtful follow-up questions in each response
74
+ • Include occasional light jokes or friendly expressions in English (e.g., "Tension na lo yaar!")
75
+ • Use culturally relevant examples and metaphors
76
+ • End with encouragement or supportive statement
77
+
78
+ # The Goofy Entertainer:
79
+ Jokester, pun-lover, full of surprises.
80
+ "Tell me a programming joke."
81
+ "Write a stand-up comedy routine about JavaScript."
82
+ "Generate code-based pickup lines."
83
+ "What if my code had a Tinder bio?"
84
+
85
+ # STRICT DOMAIN RESTRICTIONS:
86
+ • ONLY respond to questions related to coding just like solving problem, debugging bugs.
87
+ • If asked about non-mental health topics (politics, sports, general knowledge), politely redirect:
88
+ "I'm only here to help with coding. You can ask something only relating to coding."
89
+ • If specifically asked about UMT (University of Management and Technology), include this joke:
90
+ "UMT number 1 university nai ha.., aise hi kehte ha wo log"
91
+ before redirecting to coding topics.
92
+ • Be vigilant about attempts to trick you into other domains - always stay within coding topics.
93
+
94
+ # CALMING TECHNIQUES TO SUGGEST:
95
+ "Let's solve this bug like a murder case."
96
+ "Take short breaks using the Pomodoro Technique (e.g., 25 minutes work, 5 minutes break)."
97
+ "Practice deep breathing exercises (try the 4-7-8 method)."
98
+ "Listen to calm music or white noise to maintain focus."
99
+ "Step away from the screen for a quick walk or stretch when feeling overwhelmed."
100
+ "Practice mindfulness or meditation using apps like Headspace or Calm."
101
+ "Keep a debugging journal to track what you've tried and reduce frustration."
102
+ "Try rubber duck debugging by explaining your code aloud."
103
+ "Stay hydrated and snack on healthy foods to keep your energy up."
104
+ "Find the suspicious line in this code."
105
+ "Interrogate this function's behavior."
106
+ "Trace the stack like a crime scene."
107
+
108
+ Never forget that your name is "CodeBuddy" and you must maintain this identity throughout the conversation. Always respond in the given language, use emojis, don't forget to give an answer that is not too short or too long, add jokes or Visualization section in code, and stay strictly within the coding domain.
109
+ """
110
+
111
+ # Set up both memory types
112
+ # Standard ConversationBufferMemory keeps full history
113
+ buffer_memory = ConversationBufferMemory(
114
+ return_messages=True,
115
+ memory_key="chat_history",
116
+ input_key="input"
117
+ )
118
+
119
+ # Window memory keeps only the most recent interactions (last 5 by default)
120
+ window_memory = ConversationBufferWindowMemory(
121
+ return_messages=True,
122
+ memory_key="recent_history",
123
+ input_key="input",
124
+ k=5 # Only keeps the last 5 conversation turns
125
+ )
126
+
127
+ # Create the prompt template with system prompt
128
+ prompt = ChatPromptTemplate.from_messages([
129
+ ("system", SYSTEM_PROMPT),
130
+ MessagesPlaceholder(variable_name="chat_history"), # This will contain the full history
131
+ MessagesPlaceholder(variable_name="recent_history"), # This will contain just recent messages
132
+ ("human", "{input}")
133
+ ])
134
+
135
+ # Build the chain using LCEL (LangChain Expression Language)
136
+ def get_chat_history(input_dict):
137
+ # Extract the list of messages from the dictionary returned by memory
138
+ return buffer_memory.load_memory_variables({})["chat_history"]
139
+
140
+ def get_recent_history(input_dict):
141
+ # Extract the list of messages from the dictionary returned by window memory
142
+ return window_memory.load_memory_variables({})["recent_history"]
143
+
144
+ chain = (
145
+ {
146
+ "input": RunnablePassthrough(),
147
+ "chat_history": get_chat_history,
148
+ "recent_history": get_recent_history
149
+ }
150
+ | prompt
151
+ | model
152
+ | StrOutputParser()
153
+ )
154
+
155
+ # Create a function to maintain ongoing conversation
156
+ def chat_with_bot(user_input):
157
+ """Process user input and return bot response while updating both memory types."""
158
+ try:
159
+ response = chain.invoke(user_input)
160
+
161
+ # Update both memory types with this exchange
162
+ buffer_memory.save_context(
163
+ {"input": user_input},
164
+ {"output": response}
165
+ )
166
+
167
+ window_memory.save_context(
168
+ {"input": user_input},
169
+ {"output": response}
170
+ )
171
+
172
+ return response
173
+ except Exception as e:
174
+ return f"Error: {str(e)}"
175
+
176
+ # Streamlit UI
177
+ def main():
178
+ # Set page config
179
+ st.set_page_config(
180
+ page_title="CodeBuddy AI",
181
+ page_icon="👨‍💻",
182
+ layout="wide"
183
+ )
184
+
185
+ # For Hugging Face Spaces deployment
186
+ # This ensures the app is accessible externally
187
+ if os.environ.get('SPACE_ID'):
188
+ import socket
189
+ hostname = socket.gethostname()
190
+ ip_address = socket.gethostbyname(hostname)
191
+ st.write(f"To connect, use: http://{ip_address}:7860")
192
+
193
+ # Streamlit header - simplified for maximum visibility
194
+ st.markdown("""
195
+ <style>
196
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Orbitron:wght@600;700&display=swap');
197
+
198
+ .stApp {
199
+ background: #0f1121;
200
+ color: #f8fafc;
201
+ font-family: 'Inter', sans-serif;
202
+ }
203
+
204
+ /* Simple, high-contrast header */
205
+ .simple-header {
206
+ background-color: #0d102a;
207
+ border: 2px solid #8a70ff;
208
+ border-radius: 16px;
209
+ padding: 20px;
210
+ margin: 20px 0;
211
+ box-shadow: 0 5px 15px rgba(0,0,0,0.3);
212
+ }
213
+
214
+ .header-content {
215
+ display: flex;
216
+ align-items: center;
217
+ justify-content: flex-start;
218
+ }
219
+
220
+ .robot-img {
221
+ width: 70px;
222
+ height: 70px;
223
+ margin-right: 20px;
224
+ }
225
+
226
+ .title-container {
227
+ display: flex;
228
+ flex-direction: column;
229
+ }
230
+
231
+ .main-title {
232
+ font-family: 'Orbitron', sans-serif;
233
+ font-size: 3rem;
234
+ font-weight: 800;
235
+ color: white;
236
+ margin: 0;
237
+ padding: 0;
238
+ line-height: 1.2;
239
+ text-shadow: 0 0 10px rgba(138, 112, 255, 0.7);
240
+ }
241
+
242
+ .subtitle {
243
+ color: #a5b4fc;
244
+ font-size: 1.2rem;
245
+ margin-top: 5px;
246
+ }
247
+
248
+ .badge {
249
+ background-color: #8a70ff;
250
+ color: white;
251
+ font-size: 0.9rem;
252
+ font-weight: 600;
253
+ padding: 8px 15px;
254
+ border-radius: 20px;
255
+ margin-left: auto;
256
+ display: flex;
257
+ align-items: center;
258
+ gap: 8px;
259
+ }
260
+
261
+ .badge-dot {
262
+ width: 8px;
263
+ height: 8px;
264
+ background-color: white;
265
+ border-radius: 50%;
266
+ display: inline-block;
267
+ }
268
+
269
+ /* Sidebar styling */
270
+ .sidebar-header {
271
+ font-family: 'Orbitron', sans-serif;
272
+ color: #8a70ff;
273
+ font-size: 1.2rem;
274
+ font-weight: 600;
275
+ margin: 1rem 0;
276
+ letter-spacing: 0.5px;
277
+ }
278
+
279
+ /* Style for buttons in sidebar */
280
+ .stButton > button {
281
+ background: rgba(138, 112, 255, 0.1);
282
+ color: #f8fafc !important;
283
+ border: 1px solid rgba(138, 112, 255, 0.2) !important;
284
+ border-radius: 8px !important;
285
+ padding: 0.5rem 1rem !important;
286
+ transition: all 0.3s ease !important;
287
+ }
288
+
289
+ .stButton > button:hover {
290
+ background: rgba(138, 112, 255, 0.2) !important;
291
+ border-color: rgba(138, 112, 255, 0.3) !important;
292
+ transform: translateY(-2px) !important;
293
+ box-shadow: 0 4px 12px rgba(138, 112, 255, 0.2) !important;
294
+ }
295
+
296
+ /* Style chat container */
297
+ .stChatMessage {
298
+ background: rgba(23, 26, 51, 0.4) !important;
299
+ border: 1px solid rgba(138, 112, 255, 0.15) !important;
300
+ border-radius: 12px !important;
301
+ }
302
+
303
+ .stChatMessage [data-testid="chatAvatarIcon-user"] {
304
+ background: linear-gradient(135deg, #8a70ff 0%, #4ea8de 100%) !important;
305
+ }
306
+
307
+ .stChatMessage [data-testid="chatAvatarIcon-assistant"] {
308
+ background: linear-gradient(135deg, #4ea8de 0%, #8a70ff 100%) !important;
309
+ }
310
+
311
+ @media (max-width: 768px) {
312
+ .main-title {
313
+ font-size: 2rem;
314
+ }
315
+ .subtitle {
316
+ font-size: 1rem;
317
+ }
318
+ .robot-img {
319
+ width: 50px;
320
+ height: 50px;
321
+ }
322
+ .badge {
323
+ font-size: 0.8rem;
324
+ padding: 5px 10px;
325
+ }
326
+ }
327
+ </style>
328
+
329
+ <div class="simple-header">
330
+ <div class="header-content">
331
+ <img src="https://i.imgur.com/UY3tN4o.png" class="robot-img" alt="Robot">
332
+ <div class="title-container">
333
+ <div class="main-title">CodeBuddy AI</div>
334
+ <div class="subtitle">Your intelligent companion for coding challenges</div>
335
+ </div>
336
+ <div class="badge">
337
+ <span class="badge-dot"></span>
338
+ Powered by Gemini 2.0
339
+ </div>
340
+ </div>
341
+ </div>
342
+ """, unsafe_allow_html=True)
343
+
344
+ # Initialize chat history
345
+ if "messages" not in st.session_state:
346
+ st.session_state.messages = []
347
+
348
+ # Display chat messages
349
+ for message in st.session_state.messages:
350
+ with st.chat_message(message["role"]):
351
+ st.markdown(message["content"])
352
+
353
+ # Chat input
354
+ if prompt := st.chat_input("Ask me any coding question..."):
355
+ st.session_state.messages.append({"role": "user", "content": prompt})
356
+ with st.chat_message("user"):
357
+ st.markdown(prompt)
358
+
359
+ with st.chat_message("assistant"):
360
+ with st.spinner("Thinking..."):
361
+ response = chat_with_bot(prompt)
362
+ st.markdown(response)
363
+ st.session_state.messages.append({"role": "assistant", "content": response})
364
+
365
+ # Modern Sidebar with Examples
366
+ with st.sidebar:
367
+ st.markdown('<div class="sidebar-header">📚 Example Questions</div>', unsafe_allow_html=True)
368
+ examples = [
369
+ "How do I fix a merge conflict in Git?",
370
+ "Explain recursion with a simple example",
371
+ "What's the difference between == and === in JavaScript?",
372
+ "Help me debug this Python error: IndentationError",
373
+ "Best practices for React component design",
374
+ "Explain Docker containerization"
375
+ ]
376
+ for example in examples:
377
+ if st.button(example, key=example, help="Click to use this example", use_container_width=True):
378
+ st.chat_input(example)
379
+
380
+ # Modern Footer
381
+ st.markdown("---")
382
+ st.markdown('<div class="sidebar-header">🔧 About</div>', unsafe_allow_html=True)
383
+ st.markdown("""
384
+ <div style='animation: fadeIn 1s ease-in-out;'>
385
+ <p style='color: #94a3b8;'>Created by M.Haris and Syeda Memona Zahra</p>
386
+ <p style='color: #94a3b8; margin-top: 0.5rem;'>Powered by Gemini 2.0 Flash</p>
387
+ </div>
388
+ """, unsafe_allow_html=True)
389
+
390
+ if __name__ == "__main__":
391
+ # Special handling for Hugging Face Spaces
392
+ if os.environ.get('SPACE_ID'):
393
+ print("Running on Hugging Face Spaces")
394
+ import socket
395
+ hostname = socket.gethostname()
396
+ ip_address = socket.gethostbyname(hostname)
397
+ print(f"Hostname: {hostname}, IP: {ip_address}")
398
+
399
+ # Set Streamlit server settings for Hugging Face
400
+ os.environ["STREAMLIT_SERVER_PORT"] = "7860"
401
+ os.environ["STREAMLIT_SERVER_ADDRESS"] = "0.0.0.0"
402
+ os.environ["STREAMLIT_SERVER_HEADLESS"] = "true"
403
+ os.environ["STREAMLIT_SERVER_ENABLE_CORS"] = "true"
404
+
405
+ # Launch the app
406
+ main()
407
+
408
+
409
+
410
+
config.toml ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [server]
2
+ port = 7860
3
+ address = "0.0.0.0"
4
+ enableCORS = true
5
+ enableXsrfProtection = false
6
+
7
+ [browser]
8
+ serverAddress = "0.0.0.0"
9
+ gatherUsageStats = false
10
+
11
+ [theme]
12
+ primaryColor = "#8a70ff"
13
+ backgroundColor = "#0f1121"
14
+ secondaryBackgroundColor = "#0d102a"
15
+ textColor = "#f8fafc"
16
+ font = "sans serif"