Fixing bug tool calling setelah ada perubahan

This commit is contained in:
Dita Aji Pratama 2026-06-21 11:33:17 +07:00
parent 94c364798f
commit b12bd9cf2a
2 changed files with 62 additions and 12 deletions

View File

@ -104,6 +104,7 @@ class LLMClient:
# Parse delta dari chunk # Parse delta dari chunk
delta = chunk.get('choices', [{}])[0].get('delta', {}) delta = chunk.get('choices', [{}])[0].get('delta', {})
finish_reason = chunk.get('choices', [{}])[0].get('finish_reason', None)
# Stream reasoning content jika ada # Stream reasoning content jika ada
if 'reasoning_content' in delta: if 'reasoning_content' in delta:
@ -147,7 +148,32 @@ class LLMClient:
message = {'content': full_content} message = {'content': full_content}
if full_tool_calls: if full_tool_calls:
message['tool_calls'] = full_tool_calls # Filter tool_calls yang valid (ada name dan arguments)
valid_tool_calls = []
for tc in full_tool_calls:
name = tc.get('function', {}).get('name')
args_str = tc.get('function', {}).get('arguments')
tc_id = tc.get('id')
# Pastikan name dan arguments ada
if name and args_str and args_str.strip():
# Generate ID jika kosong
if not tc_id:
tc_id = f"call_{len(valid_tool_calls)}"
tc['id'] = tc_id
try:
# Validate dan re-encode JSON untuk format yang konsisten
parsed_args = json.loads(args_str)
tc['function']['arguments'] = json.dumps(parsed_args, ensure_ascii=False)
valid_tool_calls.append(tc)
except json.JSONDecodeError:
# Invalid JSON, coba raw string tapi hanya jika tidak kosong
tc['function']['arguments'] = args_str
valid_tool_calls.append(tc)
if valid_tool_calls:
message['tool_calls'] = valid_tool_calls
response = {'choices': [{'message': message}]} response = {'choices': [{'message': message}]}
except urllib.error.HTTPError as e: except urllib.error.HTTPError as e:

View File

@ -87,17 +87,25 @@ def _agent_loop(app):
log(app, "system", f" step {step + 1} \u2014 Thinking...") log(app, "system", f" step {step + 1} \u2014 Thinking...")
app.scroll = 999999 app.scroll = 999999
# Streaming response - buat placeholder untuk AI response # Streaming response
stream_idx = len(app.log)
log(app, "ai", "...") # Placeholder sambil streaming
stream_buffer = [] stream_buffer = []
placeholder_marker = None
def on_stream_chunk(chunk): def on_stream_chunk(chunk):
nonlocal placeholder_marker
# Buat placeholder di chunk pertama saja
if placeholder_marker is None:
placeholder_marker = f"_stream_placeholder_{step}"
log(app, "ai", placeholder_marker)
stream_buffer.append(chunk) stream_buffer.append(chunk)
current_text = ''.join(stream_buffer) current_text = ''.join(stream_buffer)
# Update placeholder secara real-time # Update placeholder secara real-time
if stream_idx < len(app.log): for i in range(len(app.log) - 1, -1, -1):
app.log[stream_idx]['text'] = current_text # Cari placeholder berdasarkan content aslinya (atau apa yang sudah diupdate)
# Karena placeholder text berubah seiring streaming, kita harus teliti
if app.log[i].get('role') == 'ai' and (app.log[i].get('text') == placeholder_marker or (i > 0 and app.log[i-1].get('role') == 'system' and 'Thinking' in app.log[i-1].get('text', ''))):
app.log[i]['text'] = current_text
break
app.scroll = 999999 app.scroll = 999999
response = app.llm.chat(app.messages, tools=app.TOOLS, on_stream_chunk=on_stream_chunk) response = app.llm.chat(app.messages, tools=app.TOOLS, on_stream_chunk=on_stream_chunk)
@ -111,11 +119,23 @@ def _agent_loop(app):
if response.warning: if response.warning:
log(app, "system", f" {response.warning}") log(app, "system", f" {response.warning}")
if response.tool_calls: # Cek apakah ada tool_calls
has_tool_calls = bool(response.tool_calls)
if has_tool_calls:
# Hapus placeholder jika ada tool_calls (cari semua AI log yang mungkin placeholder)
if placeholder_marker is not None:
for i in range(len(app.log) - 1, -1, -1):
# Jika ini adalah log AI yang muncul tepat setelah "Thinking..." atau contains placeholder marker
if app.log[i].get('role') == 'ai':
text = app.log[i].get('text', '')
# Hapus jika text-nya adalah placeholder atau jika itu adalah entry AI yang baru saja kita buat untuk streaming
if placeholder_marker in text or text == "" or text == "...":
app.log.pop(i)
_add_msg(app, "assistant", response.content, tool_calls=response.tool_calls) _add_msg(app, "assistant", response.content, tool_calls=response.tool_calls)
# Placeholder sudah terupdate via streaming, jangan log lagi
if stream_idx < len(app.log) and response.content and response.content.strip(): # Log tool_calls dengan label AI
app.log[stream_idx]['text'] = response.content
for tc in response.tool_calls: for tc in response.tool_calls:
tname = tc["function"]["name"] tname = tc["function"]["name"]
targs = tc["function"]["arguments"] targs = tc["function"]["arguments"]
@ -125,6 +145,10 @@ def _agent_loop(app):
})) }))
app.scroll = 999999 app.scroll = 999999
execute_tool(app, tc) execute_tool(app, tc)
# Log content AI setelah tools (jika ada)
if response.content and response.content.strip():
log(app, "ai", response.content)
else: else:
if response.content: if response.content:
_add_msg(app, "assistant", response.content) _add_msg(app, "assistant", response.content)