Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -6,6 +6,9 @@ from huggingface_hub import InferenceClient
|
|
6 |
from dataclasses import dataclass
|
7 |
import pytesseract
|
8 |
from PIL import Image
|
|
|
|
|
|
|
9 |
|
10 |
@dataclass
|
11 |
class ChatMessage:
|
@@ -30,20 +33,122 @@ class XylariaChat:
|
|
30 |
self.image_api_headers = {"Authorization": f"Bearer {self.hf_token}"}
|
31 |
|
32 |
self.conversation_history = []
|
33 |
-
self.persistent_memory =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
|
35 |
-
self.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
|
37 |
def store_information(self, key, value):
|
38 |
-
|
|
|
|
|
|
|
39 |
return f"Stored: {key} = {value}"
|
40 |
|
41 |
-
def retrieve_information(self,
|
42 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
|
44 |
def reset_conversation(self):
|
45 |
self.conversation_history = []
|
46 |
-
self.persistent_memory
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
|
48 |
try:
|
49 |
self.client = InferenceClient(
|
@@ -99,10 +204,9 @@ class XylariaChat:
|
|
99 |
content=self.system_prompt
|
100 |
).to_dict())
|
101 |
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
)
|
106 |
messages.append(ChatMessage(
|
107 |
role="system",
|
108 |
content=memory_context
|
@@ -151,7 +255,6 @@ class XylariaChat:
|
|
151 |
prompt += f"<|assistant|>\n{msg['content']}<|end|>\n"
|
152 |
prompt += "<|assistant|>\n"
|
153 |
return prompt
|
154 |
-
|
155 |
|
156 |
def create_interface(self):
|
157 |
def streaming_response(message, chat_history, image_filepath, math_ocr_image_path):
|
@@ -194,6 +297,24 @@ class XylariaChat:
|
|
194 |
yield "", updated_history, None, None
|
195 |
return
|
196 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
self.conversation_history.append(ChatMessage(role="user", content=message).to_dict())
|
198 |
self.conversation_history.append(ChatMessage(role="assistant", content=full_response).to_dict())
|
199 |
|
@@ -249,7 +370,6 @@ class XylariaChat:
|
|
249 |
transform: translateY(0);
|
250 |
}
|
251 |
}
|
252 |
-
|
253 |
/* Accordion Styling and Animation */
|
254 |
.gr-accordion-button {
|
255 |
background-color: #f0f0f0 !important;
|
@@ -285,7 +405,7 @@ class XylariaChat:
|
|
285 |
with gr.Blocks(theme='soft', css=custom_css) as demo:
|
286 |
with gr.Column():
|
287 |
chatbot = gr.Chatbot(
|
288 |
-
label="Xylaria 1.5 Senoa
|
289 |
height=500,
|
290 |
show_copy_button=True,
|
291 |
)
|
@@ -358,4 +478,4 @@ def main():
|
|
358 |
)
|
359 |
|
360 |
if __name__ == "__main__":
|
361 |
-
main()
|
|
|
6 |
from dataclasses import dataclass
|
7 |
import pytesseract
|
8 |
from PIL import Image
|
9 |
+
from sentence_transformers import SentenceTransformer, util
|
10 |
+
import torch
|
11 |
+
import numpy as np
|
12 |
|
13 |
@dataclass
|
14 |
class ChatMessage:
|
|
|
33 |
self.image_api_headers = {"Authorization": f"Bearer {self.hf_token}"}
|
34 |
|
35 |
self.conversation_history = []
|
36 |
+
self.persistent_memory = []
|
37 |
+
self.memory_embeddings = None
|
38 |
+
self.embedding_model = SentenceTransformer('all-mpnet-base-v2')
|
39 |
+
|
40 |
+
self.internal_state = {
|
41 |
+
"emotions": {
|
42 |
+
"valence": 0.5,
|
43 |
+
"arousal": 0.5,
|
44 |
+
"dominance": 0.5,
|
45 |
+
},
|
46 |
+
"memory_load": 0.0,
|
47 |
+
"introspection_level": 0.0
|
48 |
+
}
|
49 |
|
50 |
+
self.goals = [
|
51 |
+
{"goal": "Provide helpful and informative responses", "priority": 0.8, "status": "active"},
|
52 |
+
{"goal": "Learn from interactions and improve conversational abilities", "priority": 0.9, "status": "active"},
|
53 |
+
{"goal": "Maintain a coherent and engaging conversation", "priority": 0.7, "status": "active"}
|
54 |
+
]
|
55 |
+
|
56 |
+
self.system_prompt = """You are a helpful and harmless assistant. You are Xylaria developed by Sk Md Saad Amin. You should think step-by-step """
|
57 |
+
|
58 |
+
def update_internal_state(self, emotion_deltas, memory_load_delta, introspection_delta):
|
59 |
+
self.internal_state["emotions"]["valence"] = np.clip(self.internal_state["emotions"]["valence"] + emotion_deltas.get("valence", 0), 0.0, 1.0)
|
60 |
+
self.internal_state["emotions"]["arousal"] = np.clip(self.internal_state["emotions"]["arousal"] + emotion_deltas.get("arousal", 0), 0.0, 1.0)
|
61 |
+
self.internal_state["emotions"]["dominance"] = np.clip(self.internal_state["emotions"]["dominance"] + emotion_deltas.get("dominance", 0), 0.0, 1.0)
|
62 |
+
self.internal_state["memory_load"] = np.clip(self.internal_state["memory_load"] + memory_load_delta, 0.0, 1.0)
|
63 |
+
self.internal_state["introspection_level"] = np.clip(self.internal_state["introspection_level"] + introspection_delta, 0.0, 1.0)
|
64 |
+
|
65 |
+
def introspect(self):
|
66 |
+
introspection_report = "Introspection Report:\n"
|
67 |
+
introspection_report += f" Current Emotional State (VAD): {self.internal_state['emotions']}\n"
|
68 |
+
introspection_report += f" Memory Load: {self.internal_state['memory_load']:.2f}\n"
|
69 |
+
introspection_report += f" Introspection Level: {self.internal_state['introspection_level']:.2f}\n"
|
70 |
+
introspection_report += " Current Goals:\n"
|
71 |
+
for goal in self.goals:
|
72 |
+
introspection_report += f" - {goal['goal']} (Priority: {goal['priority']:.2f}, Status: {goal['status']})\n"
|
73 |
+
return introspection_report
|
74 |
+
|
75 |
+
def adjust_response_based_on_state(self, response):
|
76 |
+
if self.internal_state["introspection_level"] > 0.7:
|
77 |
+
response = self.introspect() + "\n\n" + response
|
78 |
+
|
79 |
+
valence = self.internal_state["emotions"]["valence"]
|
80 |
+
arousal = self.internal_state["emotions"]["arousal"]
|
81 |
+
|
82 |
+
if valence < 0.4:
|
83 |
+
if arousal > 0.6:
|
84 |
+
response = "I'm feeling a bit overwhelmed right now, but I'll do my best to assist you. " + response
|
85 |
+
else:
|
86 |
+
response = "I'm not feeling my best at the moment, but I'll try to help. " + response
|
87 |
+
elif valence > 0.6:
|
88 |
+
if arousal > 0.6:
|
89 |
+
response = "I'm feeling quite energized and ready to assist! " + response
|
90 |
+
else:
|
91 |
+
response = "I'm in a good mood and happy to help. " + response
|
92 |
+
|
93 |
+
return response
|
94 |
+
|
95 |
+
def update_goals(self, user_feedback):
|
96 |
+
if "helpful" in user_feedback.lower():
|
97 |
+
for goal in self.goals:
|
98 |
+
if goal["goal"] == "Provide helpful and informative responses":
|
99 |
+
goal["priority"] = min(goal["priority"] + 0.1, 1.0)
|
100 |
+
elif "confusing" in user_feedback.lower():
|
101 |
+
for goal in self.goals:
|
102 |
+
if goal["goal"] == "Provide helpful and informative responses":
|
103 |
+
goal["priority"] = max(goal["priority"] - 0.1, 0.0)
|
104 |
|
105 |
def store_information(self, key, value):
|
106 |
+
new_memory = f"{key}: {value}"
|
107 |
+
self.persistent_memory.append(new_memory)
|
108 |
+
self.update_memory_embeddings()
|
109 |
+
self.update_internal_state({}, 0.1, 0)
|
110 |
return f"Stored: {key} = {value}"
|
111 |
|
112 |
+
def retrieve_information(self, query):
|
113 |
+
if not self.persistent_memory:
|
114 |
+
return "No information found in memory."
|
115 |
+
|
116 |
+
query_embedding = self.embedding_model.encode(query, convert_to_tensor=True)
|
117 |
+
|
118 |
+
if self.memory_embeddings is None:
|
119 |
+
self.update_memory_embeddings()
|
120 |
+
|
121 |
+
if self.memory_embeddings.device != query_embedding.device:
|
122 |
+
self.memory_embeddings = self.memory_embeddings.to(query_embedding.device)
|
123 |
+
|
124 |
+
cosine_scores = util.pytorch_cos_sim(query_embedding, self.memory_embeddings)[0]
|
125 |
+
top_results = torch.topk(cosine_scores, k=min(3, len(self.persistent_memory)))
|
126 |
+
|
127 |
+
relevant_memories = [self.persistent_memory[i] for i in top_results.indices]
|
128 |
+
self.update_internal_state({}, 0, 0.1)
|
129 |
+
return "\n".join(relevant_memories)
|
130 |
+
|
131 |
+
def update_memory_embeddings(self):
|
132 |
+
self.memory_embeddings = self.embedding_model.encode(self.persistent_memory, convert_to_tensor=True)
|
133 |
|
134 |
def reset_conversation(self):
|
135 |
self.conversation_history = []
|
136 |
+
self.persistent_memory = []
|
137 |
+
self.memory_embeddings = None
|
138 |
+
self.internal_state = {
|
139 |
+
"emotions": {
|
140 |
+
"valence": 0.5,
|
141 |
+
"arousal": 0.5,
|
142 |
+
"dominance": 0.5,
|
143 |
+
},
|
144 |
+
"memory_load": 0.0,
|
145 |
+
"introspection_level": 0.0
|
146 |
+
}
|
147 |
+
self.goals = [
|
148 |
+
{"goal": "Provide helpful and informative responses", "priority": 0.8, "status": "active"},
|
149 |
+
{"goal": "Learn from interactions and improve conversational abilities", "priority": 0.9, "status": "active"},
|
150 |
+
{"goal": "Maintain a coherent and engaging conversation", "priority": 0.7, "status": "active"}
|
151 |
+
]
|
152 |
|
153 |
try:
|
154 |
self.client = InferenceClient(
|
|
|
204 |
content=self.system_prompt
|
205 |
).to_dict())
|
206 |
|
207 |
+
relevant_memory = self.retrieve_information(user_input)
|
208 |
+
if relevant_memory and relevant_memory != "No information found in memory.":
|
209 |
+
memory_context = "Remembered Information:\n" + relevant_memory
|
|
|
210 |
messages.append(ChatMessage(
|
211 |
role="system",
|
212 |
content=memory_context
|
|
|
255 |
prompt += f"<|assistant|>\n{msg['content']}<|end|>\n"
|
256 |
prompt += "<|assistant|>\n"
|
257 |
return prompt
|
|
|
258 |
|
259 |
def create_interface(self):
|
260 |
def streaming_response(message, chat_history, image_filepath, math_ocr_image_path):
|
|
|
297 |
yield "", updated_history, None, None
|
298 |
return
|
299 |
|
300 |
+
full_response = self.adjust_response_based_on_state(full_response)
|
301 |
+
|
302 |
+
self.update_goals(message)
|
303 |
+
|
304 |
+
if any(word in message.lower() for word in ["sad", "unhappy", "depressed", "down"]):
|
305 |
+
self.update_internal_state({"valence": -0.2, "arousal": 0.1}, 0, 0)
|
306 |
+
elif any(word in message.lower() for word in ["happy", "good", "great", "excited", "amazing"]):
|
307 |
+
self.update_internal_state({"valence": 0.2, "arousal": 0.2}, 0, 0)
|
308 |
+
elif any(word in message.lower() for word in ["angry", "mad", "furious", "frustrated"]):
|
309 |
+
self.update_internal_state({"valence": -0.3, "arousal": 0.3, "dominance": -0.2}, 0, 0)
|
310 |
+
elif any(word in message.lower() for word in ["scared", "afraid", "fearful", "anxious"]):
|
311 |
+
self.update_internal_state({"valence": -0.2, "arousal": 0.4, "dominance": -0.3}, 0, 0)
|
312 |
+
elif any(word in message.lower() for word in ["surprise", "amazed", "astonished"]):
|
313 |
+
self.update_internal_state({"valence": 0.1, "arousal": 0.5, "dominance": 0.1}, 0, 0)
|
314 |
+
else:
|
315 |
+
self.update_internal_state({"valence": 0.05, "arousal": 0.05}, 0, 0.1)
|
316 |
+
|
317 |
+
|
318 |
self.conversation_history.append(ChatMessage(role="user", content=message).to_dict())
|
319 |
self.conversation_history.append(ChatMessage(role="assistant", content=full_response).to_dict())
|
320 |
|
|
|
370 |
transform: translateY(0);
|
371 |
}
|
372 |
}
|
|
|
373 |
/* Accordion Styling and Animation */
|
374 |
.gr-accordion-button {
|
375 |
background-color: #f0f0f0 !important;
|
|
|
405 |
with gr.Blocks(theme='soft', css=custom_css) as demo:
|
406 |
with gr.Column():
|
407 |
chatbot = gr.Chatbot(
|
408 |
+
label="Xylaria 1.5 Senoa",
|
409 |
height=500,
|
410 |
show_copy_button=True,
|
411 |
)
|
|
|
478 |
)
|
479 |
|
480 |
if __name__ == "__main__":
|
481 |
+
main()
|