Reality123b commited on
Commit
d95e3f7
·
verified ·
1 Parent(s): bf2bb14

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +107 -192
app.py CHANGED
@@ -1,129 +1,52 @@
1
  import os
2
  import gradio as gr
3
  from huggingface_hub import InferenceClient
4
- import firebase_admin
5
- from firebase_admin import credentials, firestore, auth
6
- import uuid
7
- import tempfile
8
- import json
9
 
10
  class XylariaChat:
11
  def __init__(self):
12
- # Securely load HuggingFace and Firebase tokens from environment variables
13
- self.hf_token = os.environ.get("HF_TOKEN")
14
- firebase_cred_json = os.environ.get("FIREBASE_SERVICE_ACCOUNT")
15
-
16
- # Optional: Add more robust error handling for missing environment variables
17
  if not self.hf_token:
18
- print("Warning: HuggingFace token not found. Some functionality may be limited.")
19
-
20
- # Firebase initialization
21
- self.db = None
22
- if firebase_cred_json:
23
- try:
24
- # Convert the JSON string to a temporary credentials file
25
- with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.json') as temp_cred_file:
26
- # Add error handling for JSON parsing
27
- try:
28
- firebase_creds = json.loads(firebase_cred_json)
29
- json.dump(firebase_creds, temp_cred_file)
30
- temp_cred_file.close()
31
-
32
- firebase_cred = credentials.Certificate(temp_cred_file.name)
33
- firebase_admin.initialize_app(firebase_cred)
34
- self.db = firestore.client()
35
- except json.JSONDecodeError:
36
- print("Error: Invalid Firebase credentials JSON")
37
-
38
- # Remove the temporary credentials file
39
- os.unlink(temp_cred_file.name)
40
- except Exception as e:
41
- print(f"Firebase initialization error: {e}")
42
 
43
- # Initialize the inference client (only if token is available)
44
- self.client = None
45
- if self.hf_token:
46
- try:
47
- self.client = InferenceClient(
48
- model="Qwen/QwQ-32B-Preview",
49
- api_key=self.hf_token
50
- )
51
- except Exception as e:
52
- print(f"Inference client initialization error: {e}")
53
 
54
- # Initialize conversation history
55
  self.conversation_history = []
56
-
57
- def signup(self, username, email, password):
58
- """User signup method"""
59
- if not self.db:
60
- return "Firebase is not initialized. Signup unavailable."
61
 
62
- try:
63
- # Create user in Firebase Authentication
64
- user = auth.create_user(
65
- email=email,
66
- password=password,
67
- display_name=username
68
- )
69
-
70
- # Store additional user info in Firestore
71
- user_ref = self.db.collection('users').document(user.uid)
72
- user_ref.set({
73
- 'username': username,
74
- 'email': email,
75
- 'created_at': firestore.SERVER_TIMESTAMP
76
- })
77
-
78
- return f"Successfully created account for {username}"
79
- except Exception as e:
80
- return f"Signup error: {str(e)}"
81
 
82
- def login(self, email, password):
83
- """User login method"""
84
- if not self.db:
85
- return "Firebase is not initialized. Login unavailable."
86
-
87
- try:
88
- # Authenticate user with Firebase
89
- user = auth.get_user_by_email(email)
90
-
91
- # In a real-world scenario, you'd use Firebase Auth's sign-in method
92
- # This is a simplified version for demonstration
93
- return f"Login successful for {user.display_name}"
94
- except Exception as e:
95
- return f"Login error: {str(e)}"
96
 
97
- def save_message(self, user_id, message, sender):
98
- """Save message to Firestore"""
99
- if not self.db:
100
- return
101
-
102
- try:
103
- messages_ref = self.db.collection('conversations').document(user_id)
104
- messages_ref.collection('messages').add({
105
- 'text': message,
106
- 'sender': sender,
107
- 'timestamp': firestore.SERVER_TIMESTAMP
108
- })
109
- except Exception as e:
110
- print(f"Error saving message: {e}")
111
 
112
- def get_response(self, user_input, chat_history):
113
- # Check if client is initialized
114
- if not self.client:
115
- return "AI response is currently unavailable."
116
-
117
- # Prepare messages with conversation context
118
  messages = [
119
- {"role": "system", "content": """You are Xylaria 1.4 Senoa, an AI assistant developed by SK MD Saad Amin.
120
- - You're NOT MADE BY OPENAI OR ANY OTHER INSTITUTION
121
- - Be friendly and chatty, use emoji sometimes."""},
122
- *[{"role": "user" if msg[0] else "assistant", "content": msg[1]} for msg in chat_history]
123
  ]
124
 
125
- # Add current user input
126
- messages.append({"role": "user", "content": user_input})
 
 
 
 
127
 
128
  # Generate response with streaming
129
  try:
@@ -141,36 +64,11 @@ class XylariaChat:
141
  return f"Error generating response: {str(e)}"
142
 
143
  def create_interface(self):
144
- # Dynamic CSS for OS theme detection
145
- custom_css = """
146
- /* OS Theme Detection */
147
- @media (prefers-color-scheme: dark) {
148
- .gradio-container {
149
- background-color: #121212;
150
- color: #ffffff;
151
- }
152
- }
153
-
154
- @media (prefers-color-scheme: light) {
155
- .gradio-container {
156
- font-family: 'Inter', sans-serif;
157
- background-color: #f3f4f6;
158
- color: #1f2937;
159
- }
160
- }
161
- """
162
-
163
  def streaming_response(message, chat_history):
164
- # Unique user ID (in a real app, you'd use actual user authentication)
165
- user_id = str(uuid.uuid4())
166
-
167
- # Save user message to Firestore
168
- self.save_message(user_id, message, 'user')
169
 
170
- # Get AI response stream
171
- response_stream = self.get_response(message, chat_history)
172
-
173
- # If it's an error or string, return immediately
174
  if isinstance(response_stream, str):
175
  return "", chat_history + [[message, response_stream]]
176
 
@@ -179,74 +77,68 @@ class XylariaChat:
179
  updated_history = chat_history + [[message, ""]]
180
 
181
  # Streaming output
182
- try:
183
- for chunk in response_stream:
184
- if chunk.choices[0].delta.content:
185
- chunk_content = chunk.choices[0].delta.content
186
- full_response += chunk_content
187
-
188
- # Update the last message in chat history with partial response
189
- updated_history[-1][1] = full_response
190
- yield "", updated_history
191
- except Exception as e:
192
- return "", updated_history + [["", f"Error in response: {str(e)}"]]
193
 
194
- # Save bot message to Firestore
195
- self.save_message(user_id, full_response, 'bot')
 
 
 
 
 
196
 
197
- return "", updated_history
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
 
199
  with gr.Blocks(theme='soft', css=custom_css) as demo:
200
- # Authentication Tab
201
- with gr.Tabs():
202
- with gr.TabItem("Login"):
203
- with gr.Column():
204
- login_email = gr.Textbox(label="Email")
205
- login_password = gr.Textbox(label="Password", type="password")
206
- login_btn = gr.Button("Login")
207
- login_output = gr.Textbox(label="Login Status")
208
-
209
- with gr.TabItem("Signup"):
210
- with gr.Column():
211
- signup_username = gr.Textbox(label="Username")
212
- signup_email = gr.Textbox(label="Email")
213
- signup_password = gr.Textbox(label="Password", type="password")
214
- signup_btn = gr.Button("Sign Up")
215
- signup_output = gr.Textbox(label="Signup Status")
216
-
217
- # Chat Interface
218
- with gr.Column(scale=1):
219
  chatbot = gr.Chatbot(
220
  label="Xylaria 1.4 Senoa",
221
  height=500,
222
- show_copy_button=True,
223
- type="messages" # Added to resolve deprecation warning
224
  )
225
 
226
- # Input row with minimalist design
227
  with gr.Row():
228
  txt = gr.Textbox(
229
  show_label=False,
230
  placeholder="Type your message...",
 
231
  scale=4
232
  )
233
  btn = gr.Button("Send", scale=1)
234
 
235
- # Clear conversation button
236
  clear = gr.Button("Clear Conversation")
237
-
238
- # Authentication Event Handlers
239
- login_btn.click(
240
- fn=self.login,
241
- inputs=[login_email, login_password],
242
- outputs=[login_output]
243
- )
244
-
245
- signup_btn.click(
246
- fn=self.signup,
247
- inputs=[signup_username, signup_email, signup_password],
248
- outputs=[signup_output]
249
- )
250
 
251
  # Submit functionality with streaming
252
  btn.click(
@@ -259,10 +151,33 @@ class XylariaChat:
259
  inputs=[txt, chatbot],
260
  outputs=[txt, chatbot]
261
  )
262
- clear.click(lambda: None, None, chatbot)
263
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  return demo
265
 
266
- # Note: Actual launch should be done with proper environment variable setup
267
- xylaria_chat = XylariaChat()
268
- xylaria_chat.create_interface().launch(share=True)
 
 
 
 
 
 
 
 
 
1
  import os
2
  import gradio as gr
3
  from huggingface_hub import InferenceClient
 
 
 
 
 
4
 
5
  class XylariaChat:
6
  def __init__(self):
7
+ # Securely load HuggingFace token
8
+ self.hf_token = os.getenv("HF_TOKEN")
 
 
 
9
  if not self.hf_token:
10
+ raise ValueError("HuggingFace token not found in environment variables")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
+ # Initialize the inference client
13
+ self.client = InferenceClient(
14
+ model="Qwen/QwQ-32B-Preview",
15
+ api_key=self.hf_token
16
+ )
 
 
 
 
 
17
 
18
+ # Initialize conversation history and persistent memory
19
  self.conversation_history = []
20
+ self.persistent_memory = {}
 
 
 
 
21
 
22
+ # System prompt with more detailed instructions
23
+ self.system_prompt = """You are Xylaria 1.4 Senoa, an AI assistant developed by SK MD Saad Amin.
24
+ -Youre NOT MADE BY OPENAI OR ANY OTHER INSTITUITON
25
+ - respond to image quires with the link of the image
26
+ - be as friendly and chatty as possible, use emoji sometimes. """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
+ def store_information(self, key, value):
29
+ """Store important information in persistent memory"""
30
+ self.persistent_memory[key] = value
 
 
 
 
 
 
 
 
 
 
 
31
 
32
+ def retrieve_information(self, key):
33
+ """Retrieve information from persistent memory"""
34
+ return self.persistent_memory.get(key)
 
 
 
 
 
 
 
 
 
 
 
35
 
36
+ def get_response(self, user_input):
37
+ # Prepare messages with conversation context and persistent memory
 
 
 
 
38
  messages = [
39
+ {"role": "system", "content": self.system_prompt},
40
+ *self.conversation_history,
41
+ {"role": "user", "content": user_input}
 
42
  ]
43
 
44
+ # Add persistent memory context if available
45
+ if self.persistent_memory:
46
+ memory_context = "Remembered Information:\n" + "\n".join(
47
+ [f"{k}: {v}" for k, v in self.persistent_memory.items()]
48
+ )
49
+ messages.insert(1, {"role": "system", "content": memory_context})
50
 
51
  # Generate response with streaming
52
  try:
 
64
  return f"Error generating response: {str(e)}"
65
 
66
  def create_interface(self):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  def streaming_response(message, chat_history):
68
+ # Clear input textbox
69
+ response_stream = self.get_response(message)
 
 
 
70
 
71
+ # If it's an error, return immediately
 
 
 
72
  if isinstance(response_stream, str):
73
  return "", chat_history + [[message, response_stream]]
74
 
 
77
  updated_history = chat_history + [[message, ""]]
78
 
79
  # Streaming output
80
+ for chunk in response_stream:
81
+ if chunk.choices[0].delta.content:
82
+ chunk_content = chunk.choices[0].delta.content
83
+ full_response += chunk_content
84
+
85
+ # Update the last message in chat history with partial response
86
+ updated_history[-1][1] = full_response
87
+ yield "", updated_history
 
 
 
88
 
89
+ # Update conversation history
90
+ self.conversation_history.append(
91
+ {"role": "user", "content": message}
92
+ )
93
+ self.conversation_history.append(
94
+ {"role": "assistant", "content": full_response}
95
+ )
96
 
97
+ # Limit conversation history to prevent token overflow
98
+ if len(self.conversation_history) > 10:
99
+ self.conversation_history = self.conversation_history[-10:]
100
+
101
+ # Custom CSS for Inter font
102
+ custom_css = """
103
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
104
+
105
+ body, .gradio-container {
106
+ font-family: 'Inter', sans-serif !important;
107
+ }
108
+
109
+ .chatbot-container .message {
110
+ font-family: 'Inter', sans-serif !important;
111
+ }
112
+
113
+ .gradio-container input,
114
+ .gradio-container textarea,
115
+ .gradio-container button {
116
+ font-family: 'Inter', sans-serif !important;
117
+ }
118
+ """
119
 
120
  with gr.Blocks(theme='soft', css=custom_css) as demo:
121
+ # Chat interface with improved styling
122
+ with gr.Column():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  chatbot = gr.Chatbot(
124
  label="Xylaria 1.4 Senoa",
125
  height=500,
126
+ show_copy_button=True
 
127
  )
128
 
129
+ # Input row with improved layout
130
  with gr.Row():
131
  txt = gr.Textbox(
132
  show_label=False,
133
  placeholder="Type your message...",
134
+ container=False,
135
  scale=4
136
  )
137
  btn = gr.Button("Send", scale=1)
138
 
139
+ # Clear history and memory buttons
140
  clear = gr.Button("Clear Conversation")
141
+ clear_memory = gr.Button("Clear Memory")
 
 
 
 
 
 
 
 
 
 
 
 
142
 
143
  # Submit functionality with streaming
144
  btn.click(
 
151
  inputs=[txt, chatbot],
152
  outputs=[txt, chatbot]
153
  )
154
+
155
+ # Clear conversation history
156
+ clear.click(
157
+ fn=lambda: None,
158
+ inputs=None,
159
+ outputs=[chatbot],
160
+ queue=False
161
+ )
162
+
163
+ # Clear persistent memory
164
+ clear_memory.click(
165
+ fn=lambda: None,
166
+ inputs=None,
167
+ outputs=[],
168
+ queue=False
169
+ )
170
+
171
  return demo
172
 
173
+ # Launch the interface
174
+ def main():
175
+ chat = XylariaChat()
176
+ interface = chat.create_interface()
177
+ interface.launch(
178
+ share=True, # Optional: create a public link
179
+ debug=True # Show detailed errors
180
+ )
181
+
182
+ if __name__ == "__main__":
183
+ main()