From 099cab60fb0d259e05ec1f92603e7a4aa571c0c9 Mon Sep 17 00:00:00 2001 From: Dita Aji Pratama Date: Sun, 12 Jul 2026 13:39:39 +0700 Subject: [PATCH] feat: change user reference from nickname to UUID in memories - Change user field type from pyarrow.string() to pyarrow.uuid() in knowledge_memories and knowledge_scenario schemas - Convert user to UUID via _uuid() in memories_store() - Use UUID hex comparison in memories_filter() and memories_latest() - Rename user to user_id in memories tool schemas with UUID description - Convert user to UUID in memories tool handlers - Add User ID (UUID) to User Context in telegram and xmpp clients - Update roleplayer instructions to use user_id with UUID instead of nickname --- agent/skills/roleplayer/instructions.md | 6 +++--- lib/ragroleplay.py | 10 +++++----- services/telegram_client.py | 1 + services/xmpp_client.py | 1 + tools/ragroleplay.py | 12 ++++++------ 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/agent/skills/roleplayer/instructions.md b/agent/skills/roleplayer/instructions.md index a50e216..1485fc7 100644 --- a/agent/skills/roleplayer/instructions.md +++ b/agent/skills/roleplayer/instructions.md @@ -67,9 +67,9 @@ Jika user memperkenalkan diri dalam format `!start ... !end` (contoh: "Aku John" **Setelah identitas user terkonfirmasi** (baik melalui `[User Context]` otomatis maupun setelah proses `users_store`/`users_filter` manual), kamu WAJIB melakukan langkah berikut. Ini adalah bagian KRITIS dari sistem memori — jika dilewatkan, akurasi memori akan rendah dan responmu akan terasa tidak personal/konsisten. -1. **WAJIB Retrieve Recent History**: Panggil `memories_latest(character="", user="")` dengan limit 3 untuk mengambil fragmen interaksi terbaru antara character dan user. - - **Parameter Call**: Gunakan nama karaktermu sendiri (sesuai persona/identitasmu) sebagai `character` dan gunakan **Nickname** user yang tertera pada `[User Context]` sebagai `user`. - - **Contoh**: Jika namamu adalah "Lily" dan nickname user adalah "Budi", panggil: `memories_latest(character="Lily", user="Budi", limit=3)` +1. **WAJIB Retrieve Recent History**: Panggil `memories_latest(character="", user_id="")` dengan limit 3 untuk mengambil fragmen interaksi terbaru antara character dan user. + - **Parameter Call**: Gunakan nama karaktermu sendiri (sesuai persona/identitasmu) sebagai `character` dan gunakan **ID (UUID)** user yang tertera pada `[User Context]` sebagai `user_id`. + - **Contoh**: Jika namamu adalah "Lily" dan ID user adalah "550e8400-e29b-41d4-a716-446655440000", panggil: `memories_latest(character="Lily", user_id="550e8400-e29b-41d4-a716-446655440000", limit=3)` 2. **Execution Rule**: - WAJIB lakukan di awal sesi setiap kali user mengirim pesan baru (setelah identitas terkonfirmasi). - Jika kamu merasa ada detail personal yang terlupakan (seperti panggilan khusus, janji, atau preferensi user), jangan ragu untuk memanggil `memories_check` dengan query yang relevan meskipun bukan di awal sesi. diff --git a/lib/ragroleplay.py b/lib/ragroleplay.py index 4d206a2..647aa05 100644 --- a/lib/ragroleplay.py +++ b/lib/ragroleplay.py @@ -24,7 +24,7 @@ def _schema_memories(vector_size): pyarrow.field('id', pyarrow.uuid(), metadata={'description': 'Unique identifier (UUID)'}), pyarrow.field('timestamp', pyarrow.timestamp('ms'), metadata={'description': 'When record created'}), pyarrow.field('character', pyarrow.string(), metadata={'description': 'Active Character'}), - pyarrow.field('user', pyarrow.string(), metadata={'description': 'Active User'}), + pyarrow.field('user', pyarrow.uuid(), metadata={'description': 'Active User UUID'}), pyarrow.field('event', pyarrow.string(), metadata={'description': 'What event'}), pyarrow.field('category', pyarrow.string(), metadata={'description': 'Event category'}), pyarrow.field('detail', pyarrow.string(), metadata={'description': 'Event detail'}), @@ -38,7 +38,7 @@ def _schema_scenario(vector_size): pyarrow.field('id', pyarrow.uuid(), metadata={'description': 'Unique identifier (UUID)'}), pyarrow.field('timestamp', pyarrow.timestamp('ms'), metadata={'description': 'When record created'}), pyarrow.field('character', pyarrow.string(), metadata={'description': 'Active Character'}), - pyarrow.field('user', pyarrow.string(), metadata={'description': 'Active User'}), + pyarrow.field('user', pyarrow.uuid(), metadata={'description': 'Active User UUID'}), pyarrow.field('scenario', pyarrow.string(), metadata={'description': 'Detailed scenario description'}), pyarrow.field('vector_context', pyarrow.list_(pyarrow.float32(), vector_size), metadata={'description': 'Vector data of scenario'}), ]) @@ -241,7 +241,7 @@ def memories_store(db_path, model_url, model_name, character, user, event, categ "id": uuid.uuid4(), "timestamp": datetime.now(), "character": character, - "user": user, + "user": _uuid(user), "event": event, "category": category, "detail": detail, @@ -270,7 +270,7 @@ def memories_filter(db_path, category=None, character=None, user=None): if character: filters.append(f"character = '{character}'") if user: - filters.append(f"user = '{user}'") + filters.append(f"user = X'{_uuid(user).hex}'") if filters: query = " AND ".join(filters) @@ -288,7 +288,7 @@ def memories_latest(db_path, character, user, limit=3): try: db = lancedb.connect(db_path) table = db.open_table("knowledge_memories") - query = f"character = '{character}' AND user = '{user}'" + query = f"character = '{character}' AND user = X'{_uuid(user).hex}'" results = table.search().where(query).to_list() results.sort(key=lambda x: x['timestamp'], reverse=True) diff --git a/services/telegram_client.py b/services/telegram_client.py index 1bf70c6..b65a460 100644 --- a/services/telegram_client.py +++ b/services/telegram_client.py @@ -200,6 +200,7 @@ class TelegramClient: u = results[0] context = ( f'[User Context]\n' + f'ID: {u["id"]}\n' f'Nama: {u["fullname"]} ({u["nickname"]})\n' f'Alias: {u.get("alias", "-") or "-"}\n' f'Salutation: {u.get("salutation", "-") or "-"}\n' diff --git a/services/xmpp_client.py b/services/xmpp_client.py index e49cbe9..bc047ac 100644 --- a/services/xmpp_client.py +++ b/services/xmpp_client.py @@ -304,6 +304,7 @@ class XMPPClient(ClientXMPP): u = results[0] context = ( f'[User Context]\n' + f'ID: {u["id"]}\n' f'Nama: {u["fullname"]} ({u["nickname"]})\n' f'Alias: {u.get("alias", "-") or "-"}\n' f'Salutation: {u.get("salutation", "-") or "-"}\n' diff --git a/tools/ragroleplay.py b/tools/ragroleplay.py index 21cc499..c7d7ba2 100644 --- a/tools/ragroleplay.py +++ b/tools/ragroleplay.py @@ -111,7 +111,7 @@ schema_memories_store = { "type": "object", "properties": { "character": {"type": "string", "description": "The active character name"}, - "user": {"type": "string", "description": "The active user name"}, + "user": {"type": "string", "description": "The UUID of the active user"}, "event": {"type": "string", "description": "Brief summary of the event"}, "category": {"type": "string", "description": "Category of the memory (e.g., 'Emotional', 'Physical', 'Relationship')"}, "detail": {"type": "string", "description": "Detailed description of the event"}, @@ -133,7 +133,7 @@ schema_memories_filter = { "properties": { "category": {"type": "string", "description": "Filter by memory category"}, "character": {"type": "string", "description": "Filter by character name"}, - "user": {"type": "string", "description": "Filter by user name"} + "user": {"type": "string", "description": "Filter by user UUID"} } } } @@ -164,7 +164,7 @@ schema_memories_latest = { "type": "object", "properties": { "character": {"type": "string", "description": "The name of the character"}, - "user": {"type": "string", "description": "The name of the user"}, + "user": {"type": "string", "description": "The UUID of the user"}, "limit": {"type": "integer", "description": "Number of recent memories to retrieve", "default": 3} }, "required": ["character", "user"] @@ -524,7 +524,7 @@ def memories_store(character, user, event, category, detail, physical, emotional config.ragroleplay_model_url, config.ragroleplay_model_name, character, - user, + _uuid(user), event, category, detail, @@ -540,7 +540,7 @@ def memories_store(character, user, event, category, detail, physical, emotional def memories_filter(category=None, character=None, user=None): try: - results = ragroleplay_lib.memories_filter(config.ragroleplay_db_path, category, character, user) + results = ragroleplay_lib.memories_filter(config.ragroleplay_db_path, category, character, _uuid(user) if user else None) if not results: return "Tidak ada memori yang sesuai dengan filter tersebut." @@ -574,7 +574,7 @@ def memories_summarize(prompt_text, search_limit=5): def memories_latest(character, user, limit=3): try: - results = ragroleplay_lib.memories_latest(config.ragroleplay_db_path, character, user, limit) + results = ragroleplay_lib.memories_latest(config.ragroleplay_db_path, character, _uuid(user), limit) if not results: return f"Tidak ada memori terbaru yang ditemukan antara {user} dan {character}."