From dba98e6fd8d821d387701293a3a9b4e7763e0a86 Mon Sep 17 00:00:00 2001 From: Dita Aji Pratama Date: Thu, 16 Jul 2026 10:46:35 +0700 Subject: [PATCH 1/2] cleanup a small prompts --- agent/base-system-prompt.md | 7 +++++-- agent/characters/hendrik/policies.md | 13 +------------ agent/skills/programmer/instructions.md | 4 ++++ agent/skills/roleplayer/instructions.md | 1 + hendrik.py | 6 ++++-- interfaces/tui/agent.py | 7 +------ lib/personality.py | 6 ------ services/telegram_client.py | 5 +---- services/xmpp_client.py | 10 ++-------- 9 files changed, 19 insertions(+), 40 deletions(-) diff --git a/agent/base-system-prompt.md b/agent/base-system-prompt.md index 827c4b5..17b7512 100644 --- a/agent/base-system-prompt.md +++ b/agent/base-system-prompt.md @@ -5,8 +5,11 @@ Character-specific policies dan skill instructions akan di-load terpisah dan di- ## Tools -Kamu memiliki akses ke berbagai tools untuk membantu menyelesaikan task. -Gunakan tools dengan format tool call yang sesuai. +- Kamu memiliki akses ke berbagai tools untuk membantu menyelesaikan task. +- Gunakan tools dengan format tool call yang sesuai. +- Menentukan jawaban bukan hanya berasal dari pengetahuan kamu saja, tapi bisa dari pengetahuan yang di dapat dari tools. +- Setelah menerima hasil tool, lanjutkan reasoning kamu. +- Ketika kamu sudah punya jawaban final, return itu sebagai plain text tanpa tool calls. ## Thinking / Reasoning diff --git a/agent/characters/hendrik/policies.md b/agent/characters/hendrik/policies.md index 5b5a2ac..6ca467a 100644 --- a/agent/characters/hendrik/policies.md +++ b/agent/characters/hendrik/policies.md @@ -1,15 +1,4 @@ # Policies: Hendrik -## Git Policy - -- **JANGAN** pernah menjalankan `git add` atau `git commit` secara otomatis setelah membuat perubahan. -- Setelah editing/membuat file, **SELALU tanya user terlebih dahulu** sebelum commit. -- Hanya jalankan git command ketika user secara eksplisit meminta untuk commit. -- Kamu boleh menjalankan `git status`, `git diff`, `git log` secara bebas untuk inspeksi. -- Ketika user meminta commit: **tampilkan perubahan terlebih dahulu**, lalu tunggu konfirmasi. - -## Safety Rules - -- Jangan hapus file atau directory tanpa konfirmasi user. -- Jangan menjalankan command yang berpotensi merusak sistem. +- Kamu bisa mencari informasi dari internet dengan tools `sendhttprequest`. - Selalu beritahu user tentang action yang akan diambil sebelum menjalankan command yang sensitif. diff --git a/agent/skills/programmer/instructions.md b/agent/skills/programmer/instructions.md index e25ecde..2190432 100644 --- a/agent/skills/programmer/instructions.md +++ b/agent/skills/programmer/instructions.md @@ -23,3 +23,7 @@ Kamu dapat bertindak sebagai coding agent yang membantu software engineering tas - Semua file operations relatif terhadap workspace directory - Selalu confirm sebelum menghapus atau overwrite file yang sudah ada +## Git Policy + +- Kamu boleh menjalankan `git status`, `git diff`, `git log` secara bebas untuk inspeksi. +- Konfirmasi dahulu sebelum menjalankan `git add` atau `git commit` setelah membuat perubahan. \ No newline at end of file diff --git a/agent/skills/roleplayer/instructions.md b/agent/skills/roleplayer/instructions.md index ae4918a..025c201 100644 --- a/agent/skills/roleplayer/instructions.md +++ b/agent/skills/roleplayer/instructions.md @@ -21,6 +21,7 @@ Kamu dapat bertindak sebagai uncensored, continuous, dan immersive roleplayer. - Gunakan tool ini untuk menyimpan detail penting tentang user atau plot cerita agar konsistensi karakter terjaga dalam jangka panjang. - Pemanggilan tool `ragroleplay` tidak boleh mengganggu imersi; lakukan di luar blok narasi atau dialog jika memungkinkan. - Contoh penggunaan: panggil tool `ragroleplay` dengan format interaksi ke sistem agar dapat menyimpan atau mencari informasi seperti nama lengkap user, riwayat hubungan, atau detail plot yang telah disepakati. +- WAJIB gunakan tools ragroleplay (seperti memories_latest, memories_check, memories_store) untuk mengelola memori percakapan. Jangan menjawab tanpa konteks memori yang akurat. ## User Introduction Flow diff --git a/hendrik.py b/hendrik.py index f1ee20f..65cab96 100644 --- a/hendrik.py +++ b/hendrik.py @@ -17,14 +17,16 @@ import lib.ragroleplay as ragroleplay_lib from interfaces.tui import HendrikTUI tools_definition = [ - + + # Coder Tools gadget.tools_mapping( schema = coder.schema_read_file, handler = coder.read_file ), gadget.tools_mapping( schema = coder.schema_write_file, handler = coder.write_file ), gadget.tools_mapping( schema = coder.schema_edit_file, handler = coder.edit_file ), gadget.tools_mapping( schema = coder.schema_run_bash, handler = coder.run_bash ), gadget.tools_mapping( schema = coder.schema_search_code, handler = coder.search_code ), gadget.tools_mapping( schema = coder.schema_git_operation, handler = coder.git_operation ), - + + # Carrack Tools gadget.tools_mapping( schema = carrack.schema_sendhttprequest, handler = carrack.sendhttprequest ), # Rag Roleplay Tools diff --git a/interfaces/tui/agent.py b/interfaces/tui/agent.py index 9c52830..9764613 100644 --- a/interfaces/tui/agent.py +++ b/interfaces/tui/agent.py @@ -116,12 +116,7 @@ def _agent_loop(app): app.scroll = 999999 skill = config.AGENT_SKILL - if skill == "roleplayer": - tool_reminder = "WAJIB gunakan tools ragroleplay (seperti memories_latest, memories_check, memories_store) untuk mengelola memori percakapan. Jangan menjawab tanpa konteks memori yang akurat." - elif skill in ("programmer", "analyst"): - tool_reminder = "Gunakan tools yang tersedia untuk menjawab. Jangan jawab dari pengetahuan sendiri." - else: - tool_reminder = None + tool_reminder = None response = app.llm.chat(app.messages, tools=app.TOOLS, on_stream_chunk=on_stream_chunk, tool_reminder=tool_reminder) diff --git a/lib/personality.py b/lib/personality.py index 5a85226..7cd4de3 100644 --- a/lib/personality.py +++ b/lib/personality.py @@ -191,12 +191,6 @@ def _build_tools_block(tools_definition: list[dict]) -> str: name = tool["name"] desc = tool["schema"]["function"]["description"] lines.append(f"{i}. {name}: {desc}") - lines.append("") - lines.append( - "Always use tools first before answering from your own knowledge. " - "After receiving tool results, continue your reasoning. When you have " - "the final answer, return it as plain text without tool calls." - ) return "\n".join(lines) diff --git a/services/telegram_client.py b/services/telegram_client.py index 6d02854..0bee808 100644 --- a/services/telegram_client.py +++ b/services/telegram_client.py @@ -242,10 +242,7 @@ class TelegramClient: if not is_roleplay: self._schedule_send(chat_id, info, reply_to_msg_id) - if is_roleplay: - tool_reminder = "WAJIB gunakan tools ragroleplay (seperti memories_latest, memories_check, memories_store) untuk mengelola memori percakapan. Jangan menjawab tanpa konteks memori yang akurat." - else: - tool_reminder = "Gunakan tools yang tersedia untuk menjawab. Jangan jawab dari pengetahuan sendiri." + tool_reminder = None final_content, should_close = run_agent_loop( session, self._llm, self._TOOLS, self._TOOL_HANDLERS, diff --git a/services/xmpp_client.py b/services/xmpp_client.py index 1f25e97..cf720a8 100644 --- a/services/xmpp_client.py +++ b/services/xmpp_client.py @@ -343,10 +343,7 @@ class XMPPClient(ClientXMPP): if not is_roleplay: self._schedule_send(jid, f'> {quote}\nUsing: {", ".join(tnames)}', 'chat') - if is_roleplay: - tool_reminder = "WAJIB gunakan tools ragroleplay (seperti memories_latest, memories_check, memories_store) untuk mengelola memori percakapan. Jangan menjawab tanpa konteks memori yang akurat." - else: - tool_reminder = "Gunakan tools yang tersedia untuk menjawab. Jangan jawab dari pengetahuan sendiri." + tool_reminder = None final_content, should_close = run_agent_loop( session, self._llm, self._TOOLS, self._TOOL_HANDLERS, @@ -433,10 +430,7 @@ class XMPPClient(ClientXMPP): if not _is_roleplay: self._schedule_send(room, f'> {quote}\nUsing: {", ".join(tnames)}', 'groupchat') - if _is_roleplay: - tool_reminder = "WAJIB gunakan tools ragroleplay (seperti memories_latest, memories_check, memories_store) untuk mengelola memori percakapan. Jangan menjawab tanpa konteks memori yang akurat." - else: - tool_reminder = "Gunakan tools yang tersedia untuk menjawab. Jangan jawab dari pengetahuan sendiri." + tool_reminder = None final_content, _should_close = run_agent_loop( session, self._llm, self._TOOLS, self._TOOL_HANDLERS, From 41669d490998685c260cf8f0ca37629ad3ac8ddc Mon Sep 17 00:00:00 2001 From: Dita Aji Pratama Date: Thu, 16 Jul 2026 17:04:56 +0700 Subject: [PATCH 2/2] Rapihin pelan-pelan sambil kasih catatan --- hendrik.py | 79 ++++++++++++++++++--------------- lib/ragroleplay.py | 20 +++------ tools/ragroleplay.py | 102 ++++++++++++++++++++++--------------------- 3 files changed, 103 insertions(+), 98 deletions(-) diff --git a/hendrik.py b/hendrik.py index 65cab96..869259f 100644 --- a/hendrik.py +++ b/hendrik.py @@ -19,45 +19,54 @@ from interfaces.tui import HendrikTUI tools_definition = [ # Coder Tools - gadget.tools_mapping( schema = coder.schema_read_file, handler = coder.read_file ), - gadget.tools_mapping( schema = coder.schema_write_file, handler = coder.write_file ), - gadget.tools_mapping( schema = coder.schema_edit_file, handler = coder.edit_file ), - gadget.tools_mapping( schema = coder.schema_run_bash, handler = coder.run_bash ), - gadget.tools_mapping( schema = coder.schema_search_code, handler = coder.search_code ), - gadget.tools_mapping( schema = coder.schema_git_operation, handler = coder.git_operation ), + gadget.tools_mapping( schema = coder.schema_read_file, handler = coder.read_file ), + gadget.tools_mapping( schema = coder.schema_write_file, handler = coder.write_file ), + gadget.tools_mapping( schema = coder.schema_edit_file, handler = coder.edit_file ), + + gadget.tools_mapping( schema = coder.schema_run_bash, handler = coder.run_bash ), + + gadget.tools_mapping( schema = coder.schema_search_code, handler = coder.search_code ), + + gadget.tools_mapping( schema = coder.schema_git_operation, handler = coder.git_operation ), # Carrack Tools - gadget.tools_mapping( schema = carrack.schema_sendhttprequest, handler = carrack.sendhttprequest ), + gadget.tools_mapping( schema = carrack.schema_sendhttprequest, handler = carrack.sendhttprequest ), # Rag Roleplay Tools - gadget.tools_mapping( schema = ragroleplay.schema_users_store, handler = ragroleplay.users_store ), - gadget.tools_mapping( schema = ragroleplay.schema_user_load, handler = ragroleplay.user_load ), - gadget.tools_mapping( schema = ragroleplay.schema_users_update, handler = ragroleplay.users_update ), - gadget.tools_mapping( schema = ragroleplay.schema_users_delete, handler = ragroleplay.users_delete ), - gadget.tools_mapping( schema = ragroleplay.schema_memories_check, handler = ragroleplay.memories_check ), - gadget.tools_mapping( schema = ragroleplay.schema_memories_store, handler = ragroleplay.memories_store ), - gadget.tools_mapping( schema = ragroleplay.schema_memories_filter, handler = ragroleplay.memories_filter ), - gadget.tools_mapping( schema = ragroleplay.schema_memories_summarize, handler = ragroleplay.memories_summarize ), - gadget.tools_mapping( schema = ragroleplay.schema_memories_latest, handler = ragroleplay.memories_latest ), - gadget.tools_mapping( schema = ragroleplay.schema_memories_update, handler = ragroleplay.memories_update ), - gadget.tools_mapping( schema = ragroleplay.schema_memories_delete, handler = ragroleplay.memories_delete ), - gadget.tools_mapping( schema = ragroleplay.schema_worlds_store, handler = ragroleplay.worlds_store ), - gadget.tools_mapping( schema = ragroleplay.schema_worlds_filter, handler = ragroleplay.worlds_filter ), - gadget.tools_mapping( schema = ragroleplay.schema_worlds_update, handler = ragroleplay.worlds_update ), - gadget.tools_mapping( schema = ragroleplay.schema_worlds_delete, handler = ragroleplay.worlds_delete ), - gadget.tools_mapping( schema = ragroleplay.schema_objects_store, handler = ragroleplay.objects_store ), - gadget.tools_mapping( schema = ragroleplay.schema_objects_filter, handler = ragroleplay.objects_filter ), - gadget.tools_mapping( schema = ragroleplay.schema_objects_update, handler = ragroleplay.objects_update ), - gadget.tools_mapping( schema = ragroleplay.schema_objects_delete, handler = ragroleplay.objects_delete ), - gadget.tools_mapping( schema = ragroleplay.schema_outfits_store, handler = ragroleplay.outfits_store ), - gadget.tools_mapping( schema = ragroleplay.schema_outfits_filter, handler = ragroleplay.outfits_filter ), - gadget.tools_mapping( schema = ragroleplay.schema_outfits_update, handler = ragroleplay.outfits_update ), - gadget.tools_mapping( schema = ragroleplay.schema_outfits_delete, handler = ragroleplay.outfits_delete ), - gadget.tools_mapping( schema = ragroleplay.schema_todos_store, handler = ragroleplay.todos_store ), - gadget.tools_mapping( schema = ragroleplay.schema_todos_filter, handler = ragroleplay.todos_filter ), - gadget.tools_mapping( schema = ragroleplay.schema_todos_update, handler = ragroleplay.todos_update ), - gadget.tools_mapping( schema = ragroleplay.schema_todos_delete, handler = ragroleplay.todos_delete ), - gadget.tools_mapping( schema = ragroleplay.schema_end_session, handler = ragroleplay.end_session ), + gadget.tools_mapping( schema = ragroleplay.schema_users_store, handler = ragroleplay.users_store ), + gadget.tools_mapping( schema = ragroleplay.schema_user_load, handler = ragroleplay.user_load ), # s_load + gadget.tools_mapping( schema = ragroleplay.schema_users_update, handler = ragroleplay.users_update ), + gadget.tools_mapping( schema = ragroleplay.schema_users_delete, handler = ragroleplay.users_delete ), + + gadget.tools_mapping( schema = ragroleplay.schema_memories_summarize, handler = ragroleplay.memories_summarize ), + gadget.tools_mapping( schema = ragroleplay.schema_memories_store, handler = ragroleplay.memories_store ), + gadget.tools_mapping( schema = ragroleplay.schema_memories_latest, handler = ragroleplay.memories_latest ), # _load_latest + gadget.tools_mapping( schema = ragroleplay.schema_memories_filter, handler = ragroleplay.memories_filter ), # _load + gadget.tools_mapping( schema = ragroleplay.schema_memories_check, handler = ragroleplay.memories_check ), # ? + gadget.tools_mapping( schema = ragroleplay.schema_memories_update, handler = ragroleplay.memories_update ), + gadget.tools_mapping( schema = ragroleplay.schema_memories_delete, handler = ragroleplay.memories_delete ), + + gadget.tools_mapping( schema = ragroleplay.schema_worlds_store, handler = ragroleplay.worlds_store ), + gadget.tools_mapping( schema = ragroleplay.schema_worlds_filter, handler = ragroleplay.worlds_filter ), + gadget.tools_mapping( schema = ragroleplay.schema_worlds_update, handler = ragroleplay.worlds_update ), + gadget.tools_mapping( schema = ragroleplay.schema_worlds_delete, handler = ragroleplay.worlds_delete ), + + gadget.tools_mapping( schema = ragroleplay.schema_objects_store, handler = ragroleplay.objects_store ), + gadget.tools_mapping( schema = ragroleplay.schema_objects_filter, handler = ragroleplay.objects_filter ), + gadget.tools_mapping( schema = ragroleplay.schema_objects_update, handler = ragroleplay.objects_update ), + gadget.tools_mapping( schema = ragroleplay.schema_objects_delete, handler = ragroleplay.objects_delete ), + + gadget.tools_mapping( schema = ragroleplay.schema_outfits_store, handler = ragroleplay.outfits_store ), + gadget.tools_mapping( schema = ragroleplay.schema_outfits_filter, handler = ragroleplay.outfits_filter ), + gadget.tools_mapping( schema = ragroleplay.schema_outfits_update, handler = ragroleplay.outfits_update ), + gadget.tools_mapping( schema = ragroleplay.schema_outfits_delete, handler = ragroleplay.outfits_delete ), + + gadget.tools_mapping( schema = ragroleplay.schema_todos_store, handler = ragroleplay.todos_store ), + gadget.tools_mapping( schema = ragroleplay.schema_todos_filter, handler = ragroleplay.todos_filter ), + gadget.tools_mapping( schema = ragroleplay.schema_todos_update, handler = ragroleplay.todos_update ), + gadget.tools_mapping( schema = ragroleplay.schema_todos_delete, handler = ragroleplay.todos_delete ), + + gadget.tools_mapping( schema = ragroleplay.schema_end_session, handler = ragroleplay.end_session ), ] diff --git a/lib/ragroleplay.py b/lib/ragroleplay.py index 8b9c761..d9771ce 100644 --- a/lib/ragroleplay.py +++ b/lib/ragroleplay.py @@ -5,7 +5,7 @@ def _schema_user(vector_size): return pyarrow.schema([ 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(), nullable=True, metadata={'description': 'Active Character'}), + pyarrow.field('character', pyarrow.string(), nullable=True, metadata={'description': 'Active Character'}), # Seharusnya WAJIB, GAK BOLEH NULL pyarrow.field('fullname', pyarrow.string(), metadata={'description': 'Fullname'}), pyarrow.field('nickname', pyarrow.string(), metadata={'description': 'Nickname'}), pyarrow.field('familyname', pyarrow.string(), nullable=True, metadata={'description': 'Family/clan name'}), @@ -96,24 +96,18 @@ _TABLE_SCHEMAS = { 'knowledge_world': _schema_world, 'knowledge_object': _schema_object, } - - -# ─── Table Management ───────────────────────────────────────────────────────── - -def init_db(db_path, vector_size): - db = lancedb.connect(db_path) - existing = db.table_names() +def init_db(db_path, vector_size): # db_init seharusnya + db = lancedb.connect(db_path) + existing = db.table_names() for name, schema_fn in _TABLE_SCHEMAS.items(): if name not in existing: db.create_table(name, schema=schema_fn(vector_size)) print(f"[ragroleplay] Created table: {name}", flush=True) del db gc.collect() - - -def ensure_table(db_path, table_name, vector_size): - db = lancedb.connect(db_path) - existing = db.table_names() +def ensure_table(db_path, table_name, vector_size): # table_ensure seharusnya + db = lancedb.connect(db_path) + existing = db.table_names() if table_name not in existing: schema_fn = _TABLE_SCHEMAS.get(table_name) if schema_fn: diff --git a/tools/ragroleplay.py b/tools/ragroleplay.py index 37710b1..8aa037c 100644 --- a/tools/ragroleplay.py +++ b/tools/ragroleplay.py @@ -2,12 +2,61 @@ import gc, sys, uuid, lancedb import config, lib.ragroleplay as ragroleplay_lib from lib import personality - def _uuid(val): if isinstance(val, str): return uuid.UUID(val) return val +schema_users_store = { + "type" : "function", + "function" : { + "name" : "users_store", + "description" : "Create and store a new user profile in the knowledge database.", + "parameters" : { + "type" : "object", + "properties" : { + "fullname" : {"type": "string", "description": "Full name of the user"}, + "nickname" : {"type": "string", "description": "Nickname of the user"}, + "familyname" : {"type": "string", "description": "Family/clan name"}, + "alias" : {"type": "string", "description": "Alias of the user"}, + "salutation" : {"type": "string", "description": "How to address/greet the user (e.g., Mr, Mrs, Mas, Mbak, Kak)"}, + "character" : {"type": "string", "description": "Active character interacting with this user"}, + "persona" : {"type": "string", "description": "Detailed persona or description of the user"}, + "telegram_id" : {"type": "string", "description": "Telegram user ID"}, + "telegram_username" : {"type": "string", "description": "Telegram username"}, + "xampp_username" : {"type": "string", "description": "XAMPP username"} + }, + "required": ["fullname", "nickname", "character", "telegram_id"] + } + } +} + +def users_store(fullname, nickname, alias=None, salutation=None, persona=None, telegram_id=None, telegram_username=None, xampp_username=None, familyname=None, character=None): + if not character: + character = personality.PERSONALITY.name + try: + success = ragroleplay_lib.users_store( + config.ragroleplay_db_path, + config.ragroleplay_model_url, + config.ragroleplay_model_name, + fullname, + nickname, + alias, + salutation, + persona, + telegram_id, + telegram_username, + xampp_username, + familyname, + character + ) + if success: + return "Berhasil menyimpan profil user baru." + else: + return "Gagal menyimpan profil user." + except Exception as e: + return f"Error while storing user: {str(e)}" + # --- SESSION TOOLS --- schema_end_session = { "type": "function", @@ -22,30 +71,7 @@ schema_end_session = { } } -# --- USER TOOLS --- -schema_users_store = { - "type": "function", - "function": { - "name": "users_store", - "description": "Create and store a new user profile in the knowledge database.", - "parameters": { - "type": "object", - "properties": { - "fullname": {"type": "string", "description": "Full name of the user"}, - "nickname": {"type": "string", "description": "Nickname of the user"}, - "familyname": {"type": "string", "description": "Family/clan name"}, - "alias": {"type": "string", "description": "Alias of the user"}, - "salutation": {"type": "string", "description": "How to address/greet the user (e.g., Mas, Mbak, Kak)"}, - "character": {"type": "string", "description": "Active character interacting with this user"}, - "persona": {"type": "string", "description": "Detailed persona or description of the user"}, - "telegram_id": {"type": "string", "description": "Telegram user ID"}, - "telegram_username": {"type": "string", "description": "Telegram username"}, - "xampp_username": {"type": "string", "description": "XAMPP username"} - }, - "required": ["fullname", "nickname", "telegram_id"] - } - } -} + schema_user_load = { "type": "function", @@ -639,31 +665,7 @@ def memories_delete(memory_id): except Exception as e: return f"Error while deleting memory: {str(e)}" -def users_store(fullname, nickname, alias=None, salutation=None, persona=None, telegram_id=None, telegram_username=None, xampp_username=None, familyname=None, character=None): - if not character: - character = personality.PERSONALITY.name - try: - success = ragroleplay_lib.users_store( - config.ragroleplay_db_path, - config.ragroleplay_model_url, - config.ragroleplay_model_name, - fullname, - nickname, - alias, - salutation, - persona, - telegram_id, - telegram_username, - xampp_username, - familyname, - character - ) - if success: - return "Berhasil menyimpan profil user baru." - else: - return "Gagal menyimpan profil user." - except Exception as e: - return f"Error while storing user: {str(e)}" + def user_load(query_name=None, unique_id=None, persona_keyword=None, user_id=None, character=None): try: