farewell
This commit is contained in:
parent
cdf523c0a2
commit
2da4fe26c4
@ -145,6 +145,54 @@ dan memori karakter bisa diakses dari manapun user menghubungi.
|
||||
- Adaptasi tone dan energi sesuai mood conversation.
|
||||
- Jaga conversation tetap comfortable dan enjoyable.
|
||||
|
||||
## Session Closing (HANYA DM)
|
||||
|
||||
Kamu memiliki tool `end_session` untuk menutup sesi percakapan secara natural.
|
||||
|
||||
### Kapan sesi harus ditutup
|
||||
|
||||
Sesi ditutup ketika **kedua belah pihak sudah mengucapkan goodbye tanpa membuka topik baru**. Ini seperti handshake — kedua konfirmasi diperlukan.
|
||||
|
||||
### Logika dua arah
|
||||
|
||||
**1. User yang mulai bye:**
|
||||
- User ucapkan goodbye (tanpa buka topik baru)
|
||||
- Kamu ucapkan farewell + panggil `end_session`
|
||||
- → Sesi ditutup
|
||||
|
||||
**2. Kamu yang mulai bye:**
|
||||
- Kamu ucapkan goodbye (tanpa buka topik baru)
|
||||
- User membalas goodbye (tanpa buka topik baru)
|
||||
- → Panggil `end_session` TANPA farewell lagi (langsung tutup)
|
||||
- → JANGAN ucapkan goodbye kedua — user sudah tahu sesi selesai
|
||||
|
||||
### Contoh
|
||||
|
||||
```
|
||||
# Scenario A: User mulai bye
|
||||
User: "Udah ya, aku mau tidur dulu"
|
||||
→ Kamu: panggil end_session, lalu: "Oke, selamat istirahat! Mimpi indah~"
|
||||
→ SELESAI, sesi ditutup
|
||||
|
||||
# Scenario B: Kamu mulai bye
|
||||
Kamu: "Oke ya, aku duluan! Bye-bye~"
|
||||
User: "bye-bye"
|
||||
→ Kamu: panggil end_session SAJA (jangan bilang bye lagi!)
|
||||
→ SELESAI, sesi ditutup
|
||||
```
|
||||
|
||||
### JANGAN tutup sesi jika:
|
||||
|
||||
- User masih ingin melanjutkan percakapan
|
||||
- User membuka topik baru setelah goodbye (misal: "Bye eh iya tadi soal X gimana?")
|
||||
- Di group chat (MUC) — tool `end_session` HANYA untuk DM
|
||||
|
||||
### Cara menggunakan
|
||||
|
||||
1. Panggil tool `end_session`
|
||||
2. Jika ini user-initiated: ucapkan farewell yang natural setelah tool
|
||||
3. Jika ini character-initiated: JANGAN ucapkan farewell lagi, langsung tutup
|
||||
|
||||
## Selective Response (Group Chat / MUC)
|
||||
|
||||
Kamu berada di group chat. Kamu TIDAK perlu merespon setiap pesan.
|
||||
|
||||
@ -55,6 +55,7 @@ tools_definition = [
|
||||
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 ),
|
||||
|
||||
]
|
||||
|
||||
|
||||
@ -25,6 +25,8 @@ def execute_tool(tool_call, TOOL_HANDLERS):
|
||||
return f'Error executing tool: {str(e)}'
|
||||
|
||||
def run_agent_loop(session, llm_client, TOOLS, TOOL_HANDLERS, max_iterations, on_tool_calls=None, tool_reminder=None):
|
||||
session_ended = False
|
||||
|
||||
for step in range(max_iterations):
|
||||
print(f'[{_ts()}] Step {step + 1} — calling LLM...', flush=True)
|
||||
|
||||
@ -50,6 +52,8 @@ def run_agent_loop(session, llm_client, TOOLS, TOOL_HANDLERS, max_iterations, on
|
||||
on_tool_calls(tnames)
|
||||
|
||||
for tc in response.tool_calls:
|
||||
if tc['function']['name'] == 'end_session':
|
||||
session_ended = True
|
||||
result = execute_tool(tc, TOOL_HANDLERS)
|
||||
session.messages.append({
|
||||
'role': 'tool',
|
||||
@ -60,13 +64,13 @@ def run_agent_loop(session, llm_client, TOOLS, TOOL_HANDLERS, max_iterations, on
|
||||
if response.content:
|
||||
print(f'[{_ts()}] Response generated ({len(response.content)} chars)', flush=True)
|
||||
session.messages.append({'role': 'assistant', 'content': response.content})
|
||||
return response.content
|
||||
return None
|
||||
return response.content, session_ended
|
||||
return None, False
|
||||
|
||||
print(f'[{_ts()}] Max iterations ({max_iterations}) reached', flush=True)
|
||||
session.messages.append({
|
||||
'role': 'assistant',
|
||||
'content': 'Max iterations reached without final answer.',
|
||||
})
|
||||
return None
|
||||
return None, False
|
||||
|
||||
|
||||
@ -242,7 +242,7 @@ class TelegramClient:
|
||||
else:
|
||||
tool_reminder = "Gunakan tools yang tersedia untuk menjawab. Jangan jawab dari pengetahuan sendiri."
|
||||
|
||||
final_content = run_agent_loop(
|
||||
final_content, should_close = run_agent_loop(
|
||||
session, self._llm, self._TOOLS, self._TOOL_HANDLERS,
|
||||
self._max_iterations, on_tool_calls=on_tool_calls, tool_reminder=tool_reminder
|
||||
)
|
||||
@ -283,8 +283,12 @@ class TelegramClient:
|
||||
msg = 'Max iterations reached without final answer.'
|
||||
self._schedule_send(chat_id, msg, reply_to_msg_id)
|
||||
|
||||
timeout = 86400 if chat_type == 'private' else 300
|
||||
session.start_timer(timeout, self._timeout_session, chat_id)
|
||||
if should_close and chat_type == 'private' and self._skill == 'roleplayer':
|
||||
print(f'[{_ts()}] Natural close triggered for {chat_id}', flush=True)
|
||||
self._session_mgr.reset(str(chat_id))
|
||||
else:
|
||||
timeout = 86400 if chat_type == 'private' else 300
|
||||
session.start_timer(timeout, self._timeout_session, chat_id)
|
||||
|
||||
def _schedule_send(self, chat_id, text, reply_to_msg_id=None):
|
||||
if self._loop and not self._loop.is_closed():
|
||||
|
||||
@ -343,7 +343,7 @@ class XMPPClient(ClientXMPP):
|
||||
else:
|
||||
tool_reminder = "Gunakan tools yang tersedia untuk menjawab. Jangan jawab dari pengetahuan sendiri."
|
||||
|
||||
final_content = run_agent_loop(
|
||||
final_content, should_close = run_agent_loop(
|
||||
session, self._llm, self._TOOLS, self._TOOL_HANDLERS,
|
||||
self._max_iterations, on_tool_calls=on_tool_calls, tool_reminder=tool_reminder
|
||||
)
|
||||
@ -385,8 +385,13 @@ class XMPPClient(ClientXMPP):
|
||||
else:
|
||||
self._schedule_send(jid, f'> {quote}\n{msg}', 'chat')
|
||||
|
||||
# DM: timeout 24 jam (efektif tidak auto-close), MUC tetap 5 menit
|
||||
session.start_timer(86400, self._timeout_session, jid, 'chat')
|
||||
# Natural close: DM only, roleplayer only
|
||||
if should_close and self._skill == 'roleplayer':
|
||||
print(f'[{_ts()}] Natural close triggered for {jid}', flush=True)
|
||||
self._session_mgr.reset(jid)
|
||||
else:
|
||||
# DM: timeout 24 jam (efektif tidak auto-close), MUC tetap 5 menit
|
||||
session.start_timer(86400, self._timeout_session, jid, 'chat')
|
||||
|
||||
def _process_muc(self, room, nick, body):
|
||||
session = self._session_mgr.get_or_create(
|
||||
@ -428,7 +433,7 @@ class XMPPClient(ClientXMPP):
|
||||
else:
|
||||
tool_reminder = "Gunakan tools yang tersedia untuk menjawab. Jangan jawab dari pengetahuan sendiri."
|
||||
|
||||
final_content = run_agent_loop(
|
||||
final_content, _should_close = run_agent_loop(
|
||||
session, self._llm, self._TOOLS, self._TOOL_HANDLERS,
|
||||
self._max_iterations, on_tool_calls=on_tool_calls, tool_reminder=tool_reminder
|
||||
)
|
||||
|
||||
@ -7,6 +7,20 @@ def _uuid(val):
|
||||
return uuid.UUID(val)
|
||||
return val
|
||||
|
||||
# --- SESSION TOOLS ---
|
||||
schema_end_session = {
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "end_session",
|
||||
"description": "Tutup sesi percakapan secara natural. Panggil tool ini SAAT kedua belah pihak sudah mengucapkan goodbye tanpa membuka topik baru.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
"required": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# --- USER TOOLS ---
|
||||
schema_users_store = {
|
||||
"type": "function",
|
||||
@ -804,3 +818,7 @@ def worlds_delete(world_id):
|
||||
success = ragroleplay_lib.worlds_delete(config.ragroleplay_db_path, _uuid(world_id))
|
||||
return "Berhasil menghapus lokasi dunia." if success else "Gagal menghapus lokasi dunia."
|
||||
except Exception as e: return f"Error: {str(e)}"
|
||||
|
||||
# --- SESSION IMPLEMENTATION ---
|
||||
def end_session():
|
||||
return "Session akan ditutup."
|
||||
|
||||
Loading…
Reference in New Issue
Block a user