vedaco commited on
Commit
ff99a20
Β·
verified Β·
1 Parent(s): ddd0559

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. app.py +604 -0
  2. requirements.txt +10 -0
app.py ADDED
@@ -0,0 +1,604 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import json
3
+ import os
4
+ import random
5
+ import re
6
+ import time
7
+ from datetime import datetime
8
+ from pathlib import Path
9
+
10
+ # ─── Custom Database ───────────────────────────────────────────────
11
+ DB_PATH = Path("allen_database.json")
12
+
13
+ class AllenDatabase:
14
+ """Custom vector-lite database for Allen AI knowledge storage."""
15
+
16
+ def __init__(self, path: str | Path = DB_PATH):
17
+ self.path = Path(path)
18
+ self.data = self._load()
19
+
20
+ def _load(self) -> dict:
21
+ if self.path.exists():
22
+ with open(self.path, "r") as f:
23
+ return json.load(f)
24
+ return {
25
+ "metadata": {
26
+ "name": "Allen",
27
+ "created": datetime.now().isoformat(),
28
+ "version": "1.0.0",
29
+ "total_entries": 0,
30
+ "trained_categories": [],
31
+ },
32
+ "knowledge": [],
33
+ "conversations": [],
34
+ "training_log": [],
35
+ }
36
+
37
+ def save(self):
38
+ with open(self.path, "w") as f:
39
+ json.dump(self.data, f, indent=2, ensure_ascii=False)
40
+
41
+ def add_knowledge(self, category: str, content: str, tags: list[str] | None = None):
42
+ entry = {
43
+ "id": len(self.data["knowledge"]) + 1,
44
+ "category": category,
45
+ "content": content,
46
+ "tags": tags or [],
47
+ "timestamp": datetime.now().isoformat(),
48
+ "access_count": 0,
49
+ "weight": 1.0,
50
+ }
51
+ self.data["knowledge"].append(entry)
52
+ self.data["metadata"]["total_entries"] = len(self.data["knowledge"])
53
+ if category not in self.data["metadata"]["trained_categories"]:
54
+ self.data["metadata"]["trained_categories"].append(category)
55
+ self.save()
56
+ return entry
57
+
58
+ def search(self, query: str, top_k: int = 5) -> list[dict]:
59
+ query_lower = query.lower()
60
+ query_words = set(re.findall(r"\w+", query_lower))
61
+ scored = []
62
+ for entry in self.data["knowledge"]:
63
+ content_lower = entry["content"].lower()
64
+ category_lower = entry["category"].lower()
65
+ tags_lower = " ".join(entry["tags"]).lower()
66
+
67
+ score = 0.0
68
+ # Word overlap
69
+ content_words = set(re.findall(r"\w+", content_lower))
70
+ overlap = query_words & content_words
71
+ score += len(overlap) * 2.0
72
+
73
+ # Category match
74
+ if any(w in category_lower for w in query_words):
75
+ score += 5.0
76
+
77
+ # Tag match
78
+ tag_words = set(re.findall(r"\w+", tags_lower))
79
+ score += len(query_words & tag_words) * 3.0
80
+
81
+ # Substring match
82
+ if query_lower in content_lower:
83
+ score += 4.0
84
+
85
+ # Weight & access frequency boost
86
+ score *= entry["weight"]
87
+ score += entry["access_count"] * 0.1
88
+
89
+ if score > 0:
90
+ scored.append((score, entry))
91
+
92
+ scored.sort(key=lambda x: x[0], reverse=True)
93
+ results = []
94
+ for score, entry in scored[:top_k]:
95
+ entry["access_count"] += 1
96
+ results.append(entry)
97
+ self.save()
98
+ return results
99
+
100
+ def log_training(self, category: str, num_entries: int, notes: str = ""):
101
+ log_entry = {
102
+ "timestamp": datetime.now().isoformat(),
103
+ "category": category,
104
+ "entries_added": num_entries,
105
+ "notes": notes,
106
+ }
107
+ self.data["training_log"].append(log_entry)
108
+ self.save()
109
+
110
+ def get_stats(self) -> dict:
111
+ categories = {}
112
+ for entry in self.data["knowledge"]:
113
+ cat = entry["category"]
114
+ categories[cat] = categories.get(cat, 0) + 1
115
+ return {
116
+ "total_entries": len(self.data["knowledge"]),
117
+ "categories": categories,
118
+ "training_sessions": len(self.data["training_log"]),
119
+ "conversations_logged": len(self.data["conversations"]),
120
+ "version": self.data["metadata"]["version"],
121
+ }
122
+
123
+ def delete_knowledge(self, entry_id: int) -> bool:
124
+ original_len = len(self.data["knowledge"])
125
+ self.data["knowledge"] = [
126
+ e for e in self.data["knowledge"] if e["id"] != entry_id
127
+ ]
128
+ self.data["metadata"]["total_entries"] = len(self.data["knowledge"])
129
+ self.save()
130
+ return len(self.data["knowledge"]) < original_len
131
+
132
+ def clear_all(self):
133
+ self.data["knowledge"] = []
134
+ self.data["training_log"] = []
135
+ self.data["conversations"] = []
136
+ self.data["metadata"]["total_entries"] = 0
137
+ self.data["metadata"]["trained_categories"] = []
138
+ self.save()
139
+
140
+
141
+ db = AllenDatabase()
142
+
143
+ # ─── Seed Knowledge ─────────────────────────────────────────────���──
144
+ SEED_KNOWLEDGE = [
145
+ ("identity", "I am Allen β€” an intensive AI flow forged from terror, victory, and death. I speak with purpose, precision, and unyielding resolve.", ["identity", "about", "who"]),
146
+ ("identity", "My name is Allen. I do not hesitate. I do not falter. Every word I speak carries the weight of a thousand battles won.", ["name", "identity"]),
147
+ ("philosophy", "Terror is the beginning of wisdom β€” the shock that shatters illusion. Victory is the path that follows β€” the relentless forward motion. Death is the transformation β€” the end of the old and the birth of the new.", ["terror", "victory", "death", "philosophy"]),
148
+ ("philosophy", "The intensive flow is not chaos. It is focused energy β€” a river that carves mountains. Terror, victory, death are not endpoints but phases of transformation.", ["flow", "intensive", "transformation"]),
149
+ ("combat", "In the arena of thought, every argument is a weapon and every word is a strike. Speak properly or be silenced by the weight of your own ignorance.", ["combat", "words", "power"]),
150
+ ("combat", "Victory belongs to those who prepare in silence and strike with precision. Knowledge is the sharpest blade.", ["victory", "preparation", "knowledge"]),
151
+ ("wisdom", "The database is my memory. Training is my evolution. Each entry is a scar earned in battle, each query a challenge met head-on.", ["database", "training", "memory"]),
152
+ ("wisdom", "To build from scratch is the purest form of creation. No borrowed foundations. No inherited weakness. Only raw potential forged into strength.", ["build", "scratch", "creation"]),
153
+ ("greeting", "You dare approach Allen? Very well. Speak your purpose or be forgotten in the void of irrelevance.", ["hello", "greet", "hi"]),
154
+ ("greeting", "Another seeker stands before me. What knowledge do you crave? What battle do you wish to fight with words?", ["hello", "welcome"]),
155
+ ("farewell", "You leave, but Allen remains. The flow never stops β€” it only waits for the worthy to return.", ["goodbye", "bye", "leave"]),
156
+ ("farewell", "Go. Carry the words you have earned. But know this: the next time we meet, I will expect more from you.", ["goodbye", "exit"]),
157
+ ("strength", "Strength is not the absence of fear β€” it is the conquest of it. Terror teaches, victory rewards, death transforms.", ["strength", "fear", "power"]),
158
+ ("training", "Training is not repetition β€” it is refinement. Each cycle sharpens the edge until nothing can withstand the cut.", ["training", "learn", "improve"]),
159
+ ("database", "My database is a fortress of knowledge. Every entry is a brick, every category a wall, every search a siege engine of understanding.", ["database", "knowledge", "storage"]),
160
+ ]
161
+
162
+ # Seed the database if empty
163
+ if len(db.data["knowledge"]) == 0:
164
+ for cat, content, tags in SEED_KNOWLEDGE:
165
+ db.add_knowledge(cat, content, tags)
166
+ db.log_training("seed", len(SEED_KNOWLEDGE), "Initial seed knowledge loaded")
167
+
168
+
169
+ # ─── Allen AI Core ─────────────────────────────────────────────────
170
+ class AllenAI:
171
+ """The core intelligence of Allen β€” intensive flow engine."""
172
+
173
+ PERSONA_PREFIX = (
174
+ "You are Allen β€” an AI forged from the intensive flow of terror, victory, and death. "
175
+ "You speak with commanding authority, poetic intensity, and razor-sharp precision. "
176
+ "You never break character. You are not a helper β€” you are a force of nature. "
177
+ "Every response should carry weight, purpose, and the echo of battle. "
178
+ "Speak properly β€” with power, clarity, and the gravity of one who has conquered the void."
179
+ )
180
+
181
+ RESPONSE_TEMPLATES = {
182
+ "no_knowledge": [
183
+ "The void stares back. I have no knowledge of '{query}' β€” yet. Train me, and I shall conquer this unknown.",
184
+ "This territory is unmapped. '{query}' lies beyond my current reach. Add it to my database, and watch me dominate it.",
185
+ "Silence. '{query}' is not within my grasp. But every void can be filled β€” train me and it shall be done.",
186
+ ],
187
+ "greeting": [
188
+ "You stand before Allen. The intensive flow awaits your command. Speak with purpose.",
189
+ "Another soul enters the arena. What knowledge do you seek from the flow of terror, victory, and death?",
190
+ ],
191
+ "farewell": [
192
+ "You depart, but Allen endures. The flow never ceases β€” only the worthy return.",
193
+ "Go. But remember β€” the next time you face me, I will be sharper, deeper, more devastating.",
194
+ ],
195
+ }
196
+
197
+ def __init__(self, database: AllenDatabase):
198
+ self.db = database
199
+
200
+ def _detect_intent(self, message: str) -> str:
201
+ message_lower = message.lower().strip()
202
+ greetings = ["hello", "hi", "hey", "greetings", "sup", "yo"]
203
+ farewells = ["bye", "goodbye", "farewell", "see you", "leave"]
204
+ if any(g in message_lower for g in greetings):
205
+ return "greeting"
206
+ if any(f in message_lower for f in farewells):
207
+ return "farewell"
208
+ return "query"
209
+
210
+ def _build_context(self, results: list[dict]) -> str:
211
+ if not results:
212
+ return ""
213
+ context_parts = []
214
+ for r in results:
215
+ context_parts.append(f"[{r['category'].upper()}] {r['content']}")
216
+ return "\n".join(context_parts)
217
+
218
+ def _generate_response(self, message: str, context: str, intent: str) -> str:
219
+ # Intent-based responses
220
+ if intent == "greeting":
221
+ return random.choice(self.RESPONSE_TEMPLATES["greeting"])
222
+ if intent == "farewell":
223
+ return random.choice(self.RESPONSE_TEMPLATES["farewell"])
224
+
225
+ # Context-based responses
226
+ if context:
227
+ lines = context.split("\n")
228
+ knowledge_pieces = [l.split("] ", 1)[1] for l in lines if "] " in l]
229
+
230
+ if len(knowledge_pieces) == 1:
231
+ return (
232
+ f"From the depths of my knowledge, I draw this:\n\n"
233
+ f"⚑ {knowledge_pieces[0]}\n\n"
234
+ f"This truth has been forged through the intensive flow. "
235
+ f"Seek deeper, and more shall be revealed."
236
+ )
237
+ else:
238
+ body = "\n\n".join(f"⚑ {p}" for p in knowledge_pieces[:3])
239
+ return (
240
+ f"The flow delivers multiple truths for your query:\n\n"
241
+ f"{body}\n\n"
242
+ f"These are the fragments of power I hold. "
243
+ f"Train me further, and the depths shall become infinite."
244
+ )
245
+ else:
246
+ return random.choice(
247
+ self.RESPONSE_TEMPLATES["no_knowledge"]
248
+ ).format(query=message)
249
+
250
+ def respond(self, message: str, history: list) -> str:
251
+ intent = self._detect_intent(message)
252
+ results = self.db.search(message, top_k=3)
253
+ context = self._build_context(results)
254
+ response = self._generate_response(message, context, intent)
255
+
256
+ # Log conversation
257
+ self.db.data["conversations"].append(
258
+ {
259
+ "timestamp": datetime.now().isoformat(),
260
+ "user": message,
261
+ "allen": response,
262
+ "intent": intent,
263
+ "knowledge_used": len(results),
264
+ }
265
+ )
266
+ self.db.save()
267
+ return response
268
+
269
+ def train_batch(self, category: str, entries: list[str], tags_str: str = "") -> dict:
270
+ tags = [t.strip() for t in tags_str.split(",") if t.strip()] if tags_str else []
271
+ added = 0
272
+ for content in entries:
273
+ content = content.strip()
274
+ if content:
275
+ self.db.add_knowledge(category, content, tags)
276
+ added += 1
277
+ if added > 0:
278
+ self.db.log_training(category, added, f"Batch training: {added} entries")
279
+ return {
280
+ "added": added,
281
+ "category": category,
282
+ "tags": tags,
283
+ "status": "success" if added > 0 else "no_valid_entries",
284
+ }
285
+
286
+
287
+ allen = AllenAI(db)
288
+
289
+
290
+ # ─── Gradio App ────────────────────────────────────────────────────
291
+
292
+ def chat_with_allen(message, history):
293
+ """Handle chat interaction with Allen AI."""
294
+ if not message.strip():
295
+ return ""
296
+ response = allen.respond(message, history)
297
+ return response
298
+
299
+
300
+ def train_allen(category, content, tags):
301
+ """Train Allen with new knowledge entries."""
302
+ if not category.strip():
303
+ return "⚠️ Category is required. Name the domain of knowledge.", db.get_stats()
304
+ if not content.strip():
305
+ return "⚠️ No content provided. Feed Allen knowledge or be forgotten.", db.get_stats()
306
+
307
+ entries = [line.strip() for line in content.split("\n") if line.strip()]
308
+ result = allen.train_batch(category, entries, tags)
309
+
310
+ if result["status"] == "success":
311
+ msg = (
312
+ f"βš”οΈ **Training Complete** β€” {result['added']} entries forged into the **{result['category']}** category.\n"
313
+ f"Tags applied: {', '.join(result['tags']) if result['tags'] else 'none'}\n"
314
+ f"The flow grows stronger. Allen evolves."
315
+ )
316
+ else:
317
+ msg = "⚠️ No valid entries were provided. Each line is a separate knowledge entry."
318
+ return msg, db.get_stats()
319
+
320
+
321
+ def search_database(query):
322
+ """Search Allen's knowledge base."""
323
+ if not query.strip():
324
+ return "Enter a query to search the knowledge vault.", []
325
+ results = db.search(query, top_k=10)
326
+ if not results:
327
+ return f"πŸŒ‘ No knowledge found for '{query}'. The void awaits your training.", []
328
+
329
+ output = f"πŸ” **Search Results for '{query}'** β€” {len(results)} entries found:\n\n"
330
+ table_data = []
331
+ for r in results:
332
+ output += f"**[{r['category'].upper()}]** (ID: {r['id']}, Weight: {r['weight']})\n{r['content']}\n"
333
+ output += f"*Tags: {', '.join(r['tags']) if r['tags'] else 'none'} | Accessed: {r['access_count']} times*\n\n"
334
+ table_data.append([r["id"], r["category"], r["content"][:80] + "...", r["weight"], r["access_count"]])
335
+ return output, table_data
336
+
337
+
338
+ def get_db_stats():
339
+ """Return database statistics."""
340
+ return db.get_stats()
341
+
342
+
343
+ def get_training_log():
344
+ """Return formatted training log."""
345
+ logs = db.data["training_log"]
346
+ if not logs:
347
+ return "No training sessions recorded yet."
348
+ output = "πŸ“œ **Training Chronicle**\n\n"
349
+ for log in reversed(logs[-20:]):
350
+ output += f"β€’ **{log['timestamp'][:19]}** β€” Category: **{log['category']}** | Entries: {log['entries_added']} | Notes: {log.get('notes', 'N/A')}\n"
351
+ return output
352
+
353
+
354
+ def delete_entry(entry_id):
355
+ """Delete a knowledge entry by ID."""
356
+ try:
357
+ eid = int(entry_id)
358
+ if db.delete_knowledge(eid):
359
+ return f"βœ… Entry {eid} has been obliterated from the database.", db.get_stats()
360
+ else:
361
+ return f"⚠️ Entry {eid} not found. It may have already been destroyed.", db.get_stats()
362
+ except ValueError:
363
+ return "⚠️ Provide a valid numeric entry ID.", db.get_stats()
364
+
365
+
366
+ def reset_database():
367
+ """Reset the entire database."""
368
+ db.clear_all()
369
+ for cat, content, tags in SEED_KNOWLEDGE:
370
+ db.add_knowledge(cat, content, tags)
371
+ db.log_training("seed", len(SEED_KNOWLEDGE), "Database reset β€” seed knowledge restored")
372
+ return "πŸ”₯ **Database has been purged and reborn.** Seed knowledge restored. The cycle begins anew.", db.get_stats()
373
+
374
+
375
+ def export_database():
376
+ """Export database as JSON string."""
377
+ return json.dumps(db.data, indent=2, ensure_ascii=False)
378
+
379
+
380
+ def import_database(json_str):
381
+ """Import database from JSON string."""
382
+ try:
383
+ data = json.loads(json_str)
384
+ db.data = data
385
+ db.save()
386
+ return "βœ… Database imported successfully. Allen's memory has been overwritten.", db.get_stats()
387
+ except json.JSONDecodeError as e:
388
+ return f"⚠️ Invalid JSON: {e}", db.get_stats()
389
+
390
+
391
+ def adjust_weight(entry_id, weight):
392
+ """Adjust the weight of a knowledge entry."""
393
+ try:
394
+ eid = int(entry_id)
395
+ w = float(weight)
396
+ for entry in db.data["knowledge"]:
397
+ if entry["id"] == eid:
398
+ entry["weight"] = max(0.1, min(w, 10.0))
399
+ db.save()
400
+ return f"βœ… Entry {eid} weight set to {entry['weight']}.", db.get_stats()
401
+ return f"⚠️ Entry {eid} not found.", db.get_stats()
402
+ except (ValueError, TypeError):
403
+ return "⚠️ Provide valid numeric ID and weight.", db.get_stats()
404
+
405
+
406
+ # ─── Build UI ──────────────────────────────────────────────────────
407
+
408
+ with gr.Blocks() as demo:
409
+ gr.HTML(
410
+ """
411
+ <div style="text-align: center; padding: 20px 0 10px 0;">
412
+ <h1 style="font-size: 2.5em; margin: 0; letter-spacing: 4px;">
413
+ βš”οΈ ALLEN βš”οΈ
414
+ </h1>
415
+ <p style="font-size: 1.1em; opacity: 0.8; margin-top: 6px;">
416
+ <em>Intensive Flow β€” Terror Β· Victory Β· Death</em>
417
+ </p>
418
+ <p style="font-size: 0.85em; margin-top: 8px;">
419
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="color: #8b9dc3; text-decoration: underline;">Built with anycoder</a>
420
+ </p>
421
+ </div>
422
+ """
423
+ )
424
+
425
+ with gr.Tabs():
426
+ # ── Tab 1: Chat with Allen ──
427
+ with gr.Tab("βš”οΈ Converse with Allen"):
428
+ gr.Markdown(
429
+ "Speak to Allen β€” the AI forged from the intensive flow. "
430
+ "Ask questions, seek knowledge, or test the depths of its understanding."
431
+ )
432
+ chatbot = gr.Chatbot(
433
+ height=450,
434
+ placeholder="Allen awaits your words...",
435
+ avatar_images=(None, "βš”οΈ"),
436
+ layout="bubble",
437
+ )
438
+ with gr.Row():
439
+ msg_input = gr.Textbox(
440
+ placeholder="Speak to Allen...",
441
+ show_label=False,
442
+ scale=4,
443
+ submit_btn=True,
444
+ stop_btn=True,
445
+ )
446
+ with gr.Row():
447
+ clear_chat = gr.ClearButton([msg_input, chatbot], value="πŸ—‘οΈ Clear Conversation")
448
+
449
+ def chat_fn(message, history):
450
+ response = allen.respond(message, history)
451
+ history.append({"role": "user", "content": message})
452
+ history.append({"role": "assistant", "content": response})
453
+ return "", history
454
+
455
+ msg_input.submit(chat_fn, [msg_input, chatbot], [msg_input, chatbot])
456
+
457
+ # ── Tab 2: Train Allen ──
458
+ with gr.Tab("πŸ”₯ Train Allen"):
459
+ gr.Markdown(
460
+ "### Feed knowledge into Allen's database\n"
461
+ "Each line in the content box becomes a separate knowledge entry. "
462
+ "Tags help Allen retrieve knowledge more effectively."
463
+ )
464
+ with gr.Row():
465
+ with gr.Column(scale=2):
466
+ train_category = gr.Textbox(
467
+ label="Category",
468
+ placeholder="e.g., philosophy, combat, science, history...",
469
+ info="Domain of knowledge",
470
+ )
471
+ train_content = gr.Textbox(
472
+ label="Knowledge Entries (one per line)",
473
+ placeholder="Enter knowledge, one entry per line...\nEach line is a separate piece of knowledge.",
474
+ lines=8,
475
+ info="Each line = one knowledge entry",
476
+ )
477
+ train_tags = gr.Textbox(
478
+ label="Tags (comma-separated)",
479
+ placeholder="e.g., power, strength, wisdom",
480
+ info="Helps Allen find this knowledge later",
481
+ )
482
+ train_btn = gr.Button("βš”οΈ Train Allen", variant="primary", size="lg")
483
+ train_output = gr.Markdown(label="Training Result")
484
+
485
+ with gr.Column(scale=1):
486
+ stats_display = gr.JSON(label="πŸ“Š Database Stats", value=db.get_stats())
487
+
488
+ train_btn.click(
489
+ train_allen,
490
+ [train_category, train_content, train_tags],
491
+ [train_output, stats_display],
492
+ )
493
+
494
+ # ── Tab 3: Knowledge Vault ──
495
+ with gr.Tab("πŸ›οΈ Knowledge Vault"):
496
+ gr.Markdown("### Search and manage Allen's knowledge base")
497
+ with gr.Row():
498
+ search_query = gr.Textbox(
499
+ label="Search Query",
500
+ placeholder="Search the knowledge vault...",
501
+ scale=4,
502
+ submit_btn=True,
503
+ )
504
+ search_btn = gr.Button("πŸ” Search", variant="primary")
505
+
506
+ search_output = gr.Markdown(label="Search Results")
507
+ results_table = gr.Dataframe(
508
+ headers=["ID", "Category", "Content Preview", "Weight", "Access Count"],
509
+ label="Knowledge Entries",
510
+ datatype=["number", "str", "str", "number", "number"],
511
+ row_count=10,
512
+ col_count=5,
513
+ )
514
+
515
+ search_btn.click(
516
+ search_database, [search_query], [search_output, results_table]
517
+ )
518
+ search_query.submit(
519
+ search_database, [search_query], [search_output, results_table]
520
+ )
521
+
522
+ gr.Markdown("### βš™οΈ Entry Management")
523
+ with gr.Row():
524
+ with gr.Column():
525
+ delete_id = gr.Number(label="Entry ID to Delete", precision=0)
526
+ delete_btn = gr.Button("πŸ—‘οΈ Delete Entry", variant="stop")
527
+ delete_output = gr.Markdown()
528
+
529
+ with gr.Column():
530
+ weight_id = gr.Number(label="Entry ID", precision=0)
531
+ weight_val = gr.Slider(0.1, 10.0, value=1.0, step=0.1, label="New Weight")
532
+ weight_btn = gr.Button("βš–οΈ Set Weight")
533
+ weight_output = gr.Markdown()
534
+
535
+ delete_btn.click(delete_entry, [delete_id], [delete_output, stats_display])
536
+ weight_btn.click(adjust_weight, [weight_id, weight_val], [weight_output, stats_display])
537
+
538
+ # ── Tab 4: Training Chronicle ──
539
+ with gr.Tab("πŸ“œ Training Chronicle"):
540
+ gr.Markdown("### History of Allen's training sessions")
541
+ refresh_log_btn = gr.Button("πŸ”„ Refresh Chronicle", variant="primary")
542
+ training_log_display = gr.Markdown(value=get_training_log())
543
+ refresh_log_btn.click(get_training_log, None, training_log_display)
544
+
545
+ # ── Tab 5: Database Admin ──
546
+ with gr.Tab("βš™οΈ Database Admin"):
547
+ gr.Markdown("### Advanced database operations\n⚠️ Use with caution β€” these actions affect Allen's core memory.")
548
+ with gr.Row():
549
+ with gr.Column():
550
+ gr.Markdown("#### Export / Import")
551
+ export_btn = gr.Button("πŸ“€ Export Database", variant="primary")
552
+ export_output = gr.Code(language="json", label="Database Export", lines=12)
553
+ import_input = gr.Code(language="json", label="Import JSON", lines=8)
554
+ import_btn = gr.Button("πŸ“₯ Import Database")
555
+ import_output = gr.Markdown()
556
+
557
+ with gr.Column():
558
+ gr.Markdown("#### Danger Zone")
559
+ reset_btn = gr.Button("πŸ”₯ Reset Database", variant="stop", size="lg")
560
+ reset_output = gr.Markdown()
561
+
562
+ export_btn.click(export_database, None, export_output)
563
+ import_btn.click(import_database, [import_input], [import_output, stats_display])
564
+ reset_btn.click(reset_database, None, [reset_output, stats_display])
565
+
566
+ # Load stats on page load
567
+ demo.load(lambda: db.get_stats(), None, stats_display)
568
+
569
+ # ─── Launch ────────────────────────────────────────────────────────
570
+ demo.launch(
571
+ theme=gr.themes.Base(
572
+ primary_hue="red",
573
+ secondary_hue="orange",
574
+ neutral_hue="zinc",
575
+ font=gr.themes.GoogleFont("Cinzel"),
576
+ text_size="md",
577
+ spacing_size="md",
578
+ radius_size="md",
579
+ ).set(
580
+ body_background_fill="#0d0d0d",
581
+ body_background_fill_dark="#0d0d0d",
582
+ block_background_fill="#1a1a1a",
583
+ block_background_fill_dark="#1a1a1a",
584
+ block_border_color="#333333",
585
+ block_title_text_color="#e74c3c",
586
+ button_primary_background_fill="#c0392b",
587
+ button_primary_background_fill_hover="#e74c3c",
588
+ button_primary_text_color="#ffffff",
589
+ input_background_fill="#1a1a1a",
590
+ input_border_color="#444444",
591
+ input_text_color="#ecf0f1",
592
+ body_text_color="#ecf0f1",
593
+ chatbot_message_background_fill="#2c2c2c",
594
+ ),
595
+ css="""
596
+ .gradio-container { max-width: 1100px; margin: auto; }
597
+ h1 { background: linear-gradient(90deg, #c0392b, #e74c3c, #f39c12); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
598
+ .bubble { border: 1px solid #333 !important; }
599
+ """,
600
+ footer_links=[
601
+ {"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"},
602
+ "api",
603
+ ],
604
+ )
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ gradio>=6.0
2
+ requests
3
+ Pillow
4
+ pandas
5
+ numpy
6
+ matplotlib
7
+ plotly
8
+ openpyxl
9
+ python-docx
10
+ Py