Fixing tools calling failure

This commit is contained in:
Dita Aji Pratama 2026-07-03 10:45:00 +07:00
parent f32e2330a7
commit 9993f1f0e7
6 changed files with 39 additions and 13 deletions

View File

@ -115,7 +115,11 @@ def _agent_loop(app):
break break
app.scroll = 999999 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 # Hapus "Thinking..." log
for i in range(len(app.log) - 1, -1, -1): for i in range(len(app.log) - 1, -1, -1):

View File

@ -24,7 +24,7 @@ def execute_tool(tool_call, TOOL_HANDLERS):
except Exception as e: except Exception as e:
return f'Error executing tool: {str(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): for step in range(max_iterations):
print(f'[{_ts()}] Step {step + 1} — calling LLM...', flush=True) 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', {}) personality = getattr(session, 'personality', {})
disable_reasoning = personality.get('disable_reasoning', False) 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: if response.tool_calls:
amsg = { amsg = {

View File

@ -181,9 +181,9 @@ def _build_tools_block(tools_definition: list[dict]) -> str:
lines.append(f"{i}. {name}: {desc}") lines.append(f"{i}. {name}: {desc}")
lines.append("") lines.append("")
lines.append( lines.append(
"Use tools by returning tool calls when needed. After receiving tool " "Always use tools first before answering from your own knowledge. "
"results, continue your reasoning. When you have the final answer, " "After receiving tool results, continue your reasoning. When you have "
"return it as plain text without tool calls." "the final answer, return it as plain text without tool calls."
) )
return "\n".join(lines) return "\n".join(lines)

View File

@ -19,7 +19,7 @@ class LLMClient:
self.timeout = timeout self.timeout = timeout
self.cancel_requested = False 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" url = f"{self.base_url}/chat/completions"
payload = { payload = {
"model": self.model, "model": self.model,
@ -29,6 +29,14 @@ class LLMClient:
if tools: if tools:
payload["tools"] = tools payload["tools"] = tools
payload["tool_choice"] = "auto" 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 # Hanya kirim parameter reasoning jika diminta eksplisit
# Beberapa model/provider justru error jika parameter ini ada tapi tidak didukung # Beberapa model/provider justru error jika parameter ini ada tapi tidak didukung

View File

@ -207,9 +207,13 @@ class TelegramClient:
if not is_roleplay: if not is_roleplay:
self._schedule_send(chat_id, info, reply_to_msg_id) 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( final_content = run_agent_loop(
session, self._llm, self._TOOLS, self._TOOL_HANDLERS, 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 final_content is not None:

View File

@ -313,9 +313,13 @@ class XMPPClient(ClientXMPP):
if not is_roleplay: if not is_roleplay:
self._schedule_send(jid, f'> {quote}\nUsing: {", ".join(tnames)}', 'chat') 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( final_content = run_agent_loop(
session, self._llm, self._TOOLS, self._TOOL_HANDLERS, 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 final_content is not None:
@ -387,17 +391,23 @@ class XMPPClient(ClientXMPP):
my_name = personality.PERSONALITY.name my_name = personality.PERSONALITY.name
quote = f'[{nick}] {body}' quote = f'[{nick}] {body}'
_is_roleplay = self._skill == 'roleplayer'
def on_tool_calls(tnames): def on_tool_calls(tnames):
if not is_roleplay: if not _is_roleplay:
self._schedule_send(room, f'> {quote}\nUsing: {", ".join(tnames)}', 'groupchat') 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( final_content = run_agent_loop(
session, self._llm, self._TOOLS, self._TOOL_HANDLERS, 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 final_content is not None:
if is_roleplay: if _is_roleplay:
if config.XMPP_SELECTIVE_RESPONSE: if config.XMPP_SELECTIVE_RESPONSE:
recent_msgs = [] recent_msgs = []
for msg in session.messages[-6:]: for msg in session.messages[-6:]:
@ -428,7 +438,7 @@ class XMPPClient(ClientXMPP):
self._schedule_send(room, f'> {quote}\n{final_content}', 'groupchat') self._schedule_send(room, f'> {quote}\n{final_content}', 'groupchat')
else: else:
msg = 'Max iterations reached without final answer.' msg = 'Max iterations reached without final answer.'
if is_roleplay: if _is_roleplay:
self._schedule_send(room, msg, 'groupchat') self._schedule_send(room, msg, 'groupchat')
else: else:
self._schedule_send(room, f'> {quote}\n{msg}', 'groupchat') self._schedule_send(room, f'> {quote}\n{msg}', 'groupchat')