Simplify chat tool round flow

This commit is contained in:
2026-06-21 13:54:35 +02:00
parent d3e2397217
commit dc6fc4c631
2 changed files with 73 additions and 40 deletions

View File

@@ -29,6 +29,7 @@ after each item.
- [x] `mcp/tools.ex` - [x] `mcp/tools.ex`
- [x] `mcp/server.ex` - [x] `mcp/server.ex`
- [x] `ai/chat_tools.ex` - [x] `ai/chat_tools.ex`
- [x] `ai/chat.ex`
--- ---

View File

@@ -578,47 +578,22 @@ defmodule BDS.AI.Chat do
runtime.generate(Runtime.endpoint_with_model(endpoint, model), request, generate_opts), runtime.generate(Runtime.endpoint_with_model(endpoint, model), request, generate_opts),
{:ok, assistant_message} <- persist_assistant_response(conversation.id, response), {:ok, assistant_message} <- persist_assistant_response(conversation.id, response),
:ok <- touch_conversation(conversation.id) do :ok <- touch_conversation(conversation.id) do
if is_binary(Map.get(response, :content)) and String.trim(Map.get(response, :content)) != "" do notify_assistant_content(response, conversation.id, opts)
notify_chat_event(
opts,
{:chat_streaming_content, conversation.id, Map.get(response, :content)}
)
end
tool_calls = decode_tool_calls(Map.get(response, :tool_calls)) response
|> Map.get(:tool_calls)
Enum.each(tool_calls, fn tool_call -> |> decode_tool_calls()
notify_chat_event(opts, {:chat_tool_call, conversation.id, tool_call}) |> continue_chat_round(
end) conversation.id,
assistant_message,
cond do endpoint,
tool_calls != [] and tools != [] -> model,
with {:ok, tool_messages} <- project_id,
execute_tool_calls(conversation.id, tool_calls, project_id, opts), tools,
updated_messages <- load_chat_messages(conversation.id), runtime,
{:ok, reply} <- opts,
chat_round( rounds_left
Repo.get!(ChatConversation, conversation.id), )
updated_messages,
endpoint,
model,
project_id,
tools,
runtime,
opts,
rounds_left - 1
) do
{:ok, Map.put(reply, :tool_messages, tool_messages)}
end
true ->
{:ok,
%{
conversation: format_conversation(Repo.get!(ChatConversation, conversation.id)),
assistant_message: format_chat_message(assistant_message),
tool_messages: []
}}
end
end end
end end
@@ -673,6 +648,63 @@ defmodule BDS.AI.Chat do
{:ok, tool_messages} {:ok, tool_messages}
end end
defp continue_chat_round(
tool_calls,
conversation_id,
assistant_message,
endpoint,
model,
project_id,
tools,
runtime,
opts,
rounds_left
) do
Enum.each(tool_calls, fn tool_call ->
notify_chat_event(opts, {:chat_tool_call, conversation_id, tool_call})
end)
if tool_calls != [] and tools != [] do
with {:ok, tool_messages} <- execute_tool_calls(conversation_id, tool_calls, project_id, opts),
updated_messages <- load_chat_messages(conversation_id),
{:ok, reply} <-
chat_round(
Repo.get!(ChatConversation, conversation_id),
updated_messages,
endpoint,
model,
project_id,
tools,
runtime,
opts,
rounds_left - 1
) do
{:ok, Map.put(reply, :tool_messages, tool_messages)}
end
else
final_chat_reply(conversation_id, assistant_message)
end
end
defp final_chat_reply(conversation_id, assistant_message) do
{:ok,
%{
conversation: format_conversation(Repo.get!(ChatConversation, conversation_id)),
assistant_message: format_chat_message(assistant_message),
tool_messages: []
}}
end
defp notify_assistant_content(response, conversation_id, opts) do
content = Map.get(response, :content)
if is_binary(content) and String.trim(content) != "" do
notify_chat_event(opts, {:chat_streaming_content, conversation_id, content})
end
:ok
end
defp build_chat_request(conversation, messages, model, project_id, tools) do defp build_chat_request(conversation, messages, model, project_id, tools) do
system_message = %{"role" => "system", "content" => chat_system_prompt(project_id, tools)} system_message = %{"role" => "system", "content" => chat_system_prompt(project_id, tools)}