diff --git a/interfaces/tui/agent.py b/interfaces/tui/agent.py index 2dc00ab..ce6db7e 100644 --- a/interfaces/tui/agent.py +++ b/interfaces/tui/agent.py @@ -115,7 +115,11 @@ def _agent_loop(app): break app.scroll = 999999 - response = app.llm.chat(app.messages, tools=app.TOOLS, on_stream_chunk=on_stream_chunk) + tool_reminder = None + if config.AGENT_SKILL in ("programmer", "analyst"): + tool_reminder = "Gunakan tools yang tersedia untuk menjawab. Jangan jawab dari pengetahuan sendiri." + + response = app.llm.chat(app.messages, tools=app.TOOLS, on_stream_chunk=on_stream_chunk, tool_reminder=tool_reminder) # Hapus "Thinking..." log for i in range(len(app.log) - 1, -1, -1): diff --git a/lib/agent_loop.py b/lib/agent_loop.py index c924fae..bed35c0 100644 --- a/lib/agent_loop.py +++ b/lib/agent_loop.py @@ -24,7 +24,7 @@ def execute_tool(tool_call, TOOL_HANDLERS): except Exception as e: return f'Error executing tool: {str(e)}' -def run_agent_loop(session, llm_client, TOOLS, TOOL_HANDLERS, max_iterations, on_tool_calls=None): +def run_agent_loop(session, llm_client, TOOLS, TOOL_HANDLERS, max_iterations, on_tool_calls=None, tool_reminder=None): for step in range(max_iterations): print(f'[{_ts()}] Step {step + 1} — calling LLM...', flush=True) @@ -33,7 +33,7 @@ def run_agent_loop(session, llm_client, TOOLS, TOOL_HANDLERS, max_iterations, on personality = getattr(session, 'personality', {}) disable_reasoning = personality.get('disable_reasoning', False) - response = llm_client.chat(session.messages, tools=TOOLS, disable_reasoning=disable_reasoning) + response = llm_client.chat(session.messages, tools=TOOLS, disable_reasoning=disable_reasoning, tool_reminder=tool_reminder) if response.tool_calls: amsg = { diff --git a/lib/personality.py b/lib/personality.py index aa7b57e..1c961c9 100644 --- a/lib/personality.py +++ b/lib/personality.py @@ -181,9 +181,9 @@ def _build_tools_block(tools_definition: list[dict]) -> str: lines.append(f"{i}. {name}: {desc}") lines.append("") lines.append( - "Use tools by returning tool calls when needed. After receiving tool " - "results, continue your reasoning. When you have the final answer, " - "return it as plain text without tool calls." + "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/llm_client.py b/services/llm_client.py index c19046c..a2d0a36 100644 --- a/services/llm_client.py +++ b/services/llm_client.py @@ -19,7 +19,7 @@ class LLMClient: self.timeout = timeout self.cancel_requested = False - def chat(self, messages, tools=None, on_stream_chunk=None, disable_reasoning=False): + def chat(self, messages, tools=None, on_stream_chunk=None, disable_reasoning=False, tool_reminder=None): url = f"{self.base_url}/chat/completions" payload = { "model": self.model, @@ -29,6 +29,14 @@ class LLMClient: if tools: payload["tools"] = tools payload["tool_choice"] = "auto" + if tool_reminder: + # Inject tool reminder sebagai system message sebelum user message terakhir + for i in range(len(messages) - 1, -1, -1): + if messages[i].get("role") == "user": + payload["messages"] = messages[:i] + [ + {"role": "system", "content": tool_reminder} + ] + messages[i:] + break # Hanya kirim parameter reasoning jika diminta eksplisit # Beberapa model/provider justru error jika parameter ini ada tapi tidak didukung diff --git a/services/telegram_client.py b/services/telegram_client.py index ec611fc..18b1556 100644 --- a/services/telegram_client.py +++ b/services/telegram_client.py @@ -207,9 +207,13 @@ class TelegramClient: if not is_roleplay: self._schedule_send(chat_id, info, reply_to_msg_id) + tool_reminder = None + if not is_roleplay: + tool_reminder = "Gunakan tools yang tersedia untuk menjawab. Jangan jawab dari pengetahuan sendiri." + final_content = run_agent_loop( session, self._llm, self._TOOLS, self._TOOL_HANDLERS, - self._max_iterations, on_tool_calls=on_tool_calls + self._max_iterations, on_tool_calls=on_tool_calls, tool_reminder=tool_reminder ) if final_content is not None: diff --git a/services/xmpp_client.py b/services/xmpp_client.py index 50b9c0d..18523dc 100644 --- a/services/xmpp_client.py +++ b/services/xmpp_client.py @@ -313,9 +313,13 @@ class XMPPClient(ClientXMPP): if not is_roleplay: self._schedule_send(jid, f'> {quote}\nUsing: {", ".join(tnames)}', 'chat') + tool_reminder = None + if not is_roleplay: + tool_reminder = "Gunakan tools yang tersedia untuk menjawab. Jangan jawab dari pengetahuan sendiri." + final_content = run_agent_loop( session, self._llm, self._TOOLS, self._TOOL_HANDLERS, - self._max_iterations, on_tool_calls=on_tool_calls + self._max_iterations, on_tool_calls=on_tool_calls, tool_reminder=tool_reminder ) if final_content is not None: @@ -387,17 +391,23 @@ class XMPPClient(ClientXMPP): my_name = personality.PERSONALITY.name quote = f'[{nick}] {body}' + _is_roleplay = self._skill == 'roleplayer' + def on_tool_calls(tnames): - if not is_roleplay: + if not _is_roleplay: self._schedule_send(room, f'> {quote}\nUsing: {", ".join(tnames)}', 'groupchat') + tool_reminder = None + if not _is_roleplay: + tool_reminder = "Gunakan tools yang tersedia untuk menjawab. Jangan jawab dari pengetahuan sendiri." + final_content = run_agent_loop( session, self._llm, self._TOOLS, self._TOOL_HANDLERS, - self._max_iterations, on_tool_calls=on_tool_calls + self._max_iterations, on_tool_calls=on_tool_calls, tool_reminder=tool_reminder ) if final_content is not None: - if is_roleplay: + if _is_roleplay: if config.XMPP_SELECTIVE_RESPONSE: recent_msgs = [] for msg in session.messages[-6:]: @@ -428,7 +438,7 @@ class XMPPClient(ClientXMPP): self._schedule_send(room, f'> {quote}\n{final_content}', 'groupchat') else: msg = 'Max iterations reached without final answer.' - if is_roleplay: + if _is_roleplay: self._schedule_send(room, msg, 'groupchat') else: self._schedule_send(room, f'> {quote}\n{msg}', 'groupchat')