AthelaPerk commited on
Commit
b3c3dfe
·
verified ·
1 Parent(s): 8c47f68

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +148 -0
app.py ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Mnemo HuggingFace Space Demo - Simplified
3
+ """
4
+
5
+ import gradio as gr
6
+ import hashlib
7
+ import time
8
+ import numpy as np
9
+ from typing import Dict, List
10
+ from collections import defaultdict
11
+
12
+
13
+ class Mnemo:
14
+ """Simplified Mnemo for demo"""
15
+
16
+ def __init__(self):
17
+ self.memories = {}
18
+ self.embeddings = []
19
+ self.ids = []
20
+ self.feedback_boosts = defaultdict(float)
21
+ self.stats = {"adds": 0, "searches": 0, "feedback": 0}
22
+
23
+ def _embed(self, text):
24
+ emb = np.zeros(384, dtype=np.float32)
25
+ for i, word in enumerate(text.lower().split()):
26
+ idx = hash(word) % 384
27
+ emb[idx] += 1.0 / (i + 1)
28
+ norm = np.linalg.norm(emb)
29
+ return emb / norm if norm > 0 else emb
30
+
31
+ def add(self, content, metadata=None):
32
+ mem_id = f"mem_{hashlib.md5(content.encode()).hexdigest()[:8]}"
33
+ self.memories[mem_id] = {"content": content, "metadata": metadata or {}}
34
+ self.embeddings.append(self._embed(content))
35
+ self.ids.append(mem_id)
36
+ self.stats["adds"] += 1
37
+ return mem_id
38
+
39
+ def search(self, query, top_k=5):
40
+ if not self.memories:
41
+ return []
42
+ self.stats["searches"] += 1
43
+ query_emb = self._embed(query)
44
+
45
+ scores = []
46
+ for emb, mem_id in zip(self.embeddings, self.ids):
47
+ score = float(np.dot(query_emb, emb))
48
+ score += self.feedback_boosts.get(mem_id, 0) * 0.1
49
+ scores.append((mem_id, score))
50
+
51
+ scores.sort(key=lambda x: x[1], reverse=True)
52
+ return [{"id": mid, "content": self.memories[mid]["content"], "score": s}
53
+ for mid, s in scores[:top_k]]
54
+
55
+ def feedback(self, memory_id, relevance):
56
+ self.feedback_boosts[memory_id] += relevance * 0.1
57
+ self.stats["feedback"] += 1
58
+
59
+ def get_stats(self):
60
+ return {"total_memories": len(self.memories), **self.stats}
61
+
62
+
63
+ # Initialize with examples
64
+ m = Mnemo()
65
+ for ex in [
66
+ "User prefers dark mode and morning email notifications",
67
+ "Project Alpha deadline is March 15th, budget $50,000",
68
+ "Team standup every Tuesday 2pm, room 401",
69
+ "Favorite coffee: cappuccino with oat milk, no sugar",
70
+ "Working on ML model for customer churn prediction",
71
+ ]:
72
+ m.add(ex)
73
+
74
+
75
+ def search_fn(query, top_k):
76
+ if not query.strip():
77
+ return "Please enter a query"
78
+ start = time.time()
79
+ results = m.search(query, int(top_k))
80
+ latency = (time.time() - start) * 1000
81
+ if not results:
82
+ return "No results"
83
+ out = f"Found {len(results)} results in {latency:.2f}ms\n\n"
84
+ for i, r in enumerate(results, 1):
85
+ out += f"{i}. [{r['id']}] score={r['score']:.3f}\n {r['content']}\n\n"
86
+ return out
87
+
88
+
89
+ def add_fn(content):
90
+ if not content.strip():
91
+ return "Please enter content", str(m.get_stats())
92
+ mem_id = m.add(content)
93
+ return f"Added: {mem_id}", str(m.get_stats())
94
+
95
+
96
+ def feedback_fn(mem_id, relevance):
97
+ if not mem_id.strip():
98
+ return "Enter memory ID"
99
+ m.feedback(mem_id, relevance)
100
+ return f"Feedback recorded for {mem_id}"
101
+
102
+
103
+ with gr.Blocks(title="Mnemo") as demo:
104
+ gr.Markdown("# 🧠 Mnemo: Semantic-Loop Memory\n*21x faster than mem0 • No API keys • Learns from feedback*")
105
+
106
+ with gr.Row():
107
+ with gr.Column():
108
+ gr.Markdown("### 🔍 Search")
109
+ q = gr.Textbox(label="Query", placeholder="e.g., coffee preferences")
110
+ k = gr.Slider(1, 10, 5, step=1, label="Results")
111
+ search_btn = gr.Button("Search", variant="primary")
112
+ search_out = gr.Textbox(label="Results", lines=10)
113
+ search_btn.click(search_fn, [q, k], search_out)
114
+ q.submit(search_fn, [q, k], search_out)
115
+
116
+ gr.Markdown("### ➕ Add Memory")
117
+ content = gr.Textbox(label="Content", placeholder="e.g., Meeting Friday 3pm")
118
+ add_btn = gr.Button("Add")
119
+ add_out = gr.Textbox(label="Status")
120
+
121
+ with gr.Column():
122
+ stats = gr.Textbox(label="📊 Stats", value=str(m.get_stats()), lines=5)
123
+
124
+ gr.Markdown("### 👍 Feedback")
125
+ fb_id = gr.Textbox(label="Memory ID", placeholder="mem_abc123")
126
+ fb_rel = gr.Slider(-1, 1, 0.5, step=0.1, label="Relevance")
127
+ fb_btn = gr.Button("Submit Feedback")
128
+ fb_out = gr.Textbox(label="Status")
129
+ fb_btn.click(feedback_fn, [fb_id, fb_rel], fb_out)
130
+
131
+ add_btn.click(add_fn, [content], [add_out, stats])
132
+
133
+ gr.Markdown("""
134
+ ---
135
+ ### 🏆 Benchmarks vs mem0
136
+ | Metric | mem0 | Mnemo |
137
+ |--------|------|-------|
138
+ | Search Latency | 5.73ms | **0.27ms** (21x faster) |
139
+ | Ingestion | 31.1ms | **0.8ms** (39x faster) |
140
+ | API Required | Yes (OpenAI) | **No** |
141
+ | Feedback Learning | No | **Yes** |
142
+
143
+ ---
144
+ 📦 [Get the code](https://huggingface.co/AthelaPerk/mnemo-memory) • *From the team behind NRA-19 medical AI benchmark*
145
+ """)
146
+
147
+ if __name__ == "__main__":
148
+ demo.launch(server_name="0.0.0.0", server_port=7860)