This commit is contained in:
@@ -40,11 +40,11 @@ defmodule ElixirAi.ChatUtils do
|
||||
}
|
||||
end
|
||||
|
||||
def request_ai_response(server, messages, tools) do
|
||||
def request_ai_response(server, messages, tools, provider) do
|
||||
Task.start(fn ->
|
||||
api_url = Application.fetch_env!(:elixir_ai, :ai_endpoint)
|
||||
api_key = Application.fetch_env!(:elixir_ai, :ai_token)
|
||||
model = Application.fetch_env!(:elixir_ai, :ai_model)
|
||||
api_url = provider.completions_url
|
||||
api_key = provider.api_token
|
||||
model = provider.model_name
|
||||
|
||||
if is_nil(api_url) or api_url == "" do
|
||||
Logger.warning("AI endpoint is empty or nil")
|
||||
|
||||
@@ -38,12 +38,18 @@ defmodule ElixirAi.ChatRunner do
|
||||
|
||||
last_message = List.last(messages)
|
||||
|
||||
provider =
|
||||
case Conversation.find_provider(name) do
|
||||
{:ok, p} -> p
|
||||
_ -> nil
|
||||
end
|
||||
|
||||
if last_message && last_message.role == :user do
|
||||
Logger.info(
|
||||
"Last message role was #{last_message.role}, requesting AI response for conversation #{name}"
|
||||
)
|
||||
|
||||
ElixirAi.ChatUtils.request_ai_response(self(), messages, tools(self(), name))
|
||||
ElixirAi.ChatUtils.request_ai_response(self(), messages, tools(self(), name), provider)
|
||||
end
|
||||
|
||||
{:ok,
|
||||
@@ -53,9 +59,7 @@ defmodule ElixirAi.ChatRunner do
|
||||
streaming_response: nil,
|
||||
pending_tool_calls: [],
|
||||
tools: tools(self(), name),
|
||||
ai_provider_url: Application.get_env(:elixir_ai, :ai_provider_url),
|
||||
ai_model: Application.get_env(:elixir_ai, :ai_model),
|
||||
ai_token: Application.get_env(:elixir_ai, :ai_token)
|
||||
provider: provider
|
||||
}}
|
||||
end
|
||||
|
||||
@@ -107,7 +111,13 @@ defmodule ElixirAi.ChatRunner do
|
||||
store_message(state.name, new_message)
|
||||
new_state = %{state | messages: state.messages ++ [new_message]}
|
||||
|
||||
ElixirAi.ChatUtils.request_ai_response(self(), new_state.messages, state.tools)
|
||||
ElixirAi.ChatUtils.request_ai_response(
|
||||
self(),
|
||||
new_state.messages,
|
||||
state.tools,
|
||||
state.provider
|
||||
)
|
||||
|
||||
{:noreply, new_state}
|
||||
end
|
||||
|
||||
@@ -296,7 +306,13 @@ defmodule ElixirAi.ChatRunner do
|
||||
|
||||
if new_pending_tool_calls == [] do
|
||||
broadcast_ui(state.name, :tool_calls_finished)
|
||||
ElixirAi.ChatUtils.request_ai_response(self(), state.messages ++ [new_message], state.tools)
|
||||
|
||||
ElixirAi.ChatUtils.request_ai_response(
|
||||
self(),
|
||||
state.messages ++ [new_message],
|
||||
state.tools,
|
||||
state.provider
|
||||
)
|
||||
end
|
||||
|
||||
{:noreply,
|
||||
|
||||
@@ -52,25 +52,16 @@ defmodule ElixirAi.ConversationManager do
|
||||
def handle_call(
|
||||
{:create, name, ai_provider_id},
|
||||
_from,
|
||||
%{conversations: conversations, subscriptions: subscriptions} = state
|
||||
%{conversations: conversations} = state
|
||||
) do
|
||||
if Map.has_key?(conversations, name) do
|
||||
{:reply, {:error, :already_exists}, state}
|
||||
else
|
||||
case Conversation.create(name, ai_provider_id) do
|
||||
:ok ->
|
||||
case start_and_subscribe(name, subscriptions) do
|
||||
{:ok, pid, new_subscriptions} ->
|
||||
{:reply, {:ok, pid},
|
||||
%{
|
||||
state
|
||||
| conversations: Map.put(conversations, name, []),
|
||||
subscriptions: new_subscriptions
|
||||
}}
|
||||
|
||||
{:error, _reason} = error ->
|
||||
{:reply, error, state}
|
||||
end
|
||||
reply_with_started(name, state, fn new_state ->
|
||||
%{new_state | conversations: Map.put(new_state.conversations, name, [])}
|
||||
end)
|
||||
|
||||
{:error, _} = error ->
|
||||
{:reply, error, state}
|
||||
@@ -81,16 +72,10 @@ defmodule ElixirAi.ConversationManager do
|
||||
def handle_call(
|
||||
{:open, name},
|
||||
_from,
|
||||
%{conversations: conversations, subscriptions: subscriptions} = state
|
||||
%{conversations: conversations} = state
|
||||
) do
|
||||
if Map.has_key?(conversations, name) do
|
||||
case start_and_subscribe(name, subscriptions) do
|
||||
{:ok, pid, new_subscriptions} ->
|
||||
{:reply, {:ok, pid}, %{state | subscriptions: new_subscriptions}}
|
||||
|
||||
{:error, _reason} = error ->
|
||||
{:reply, error, state}
|
||||
end
|
||||
reply_with_started(name, state)
|
||||
else
|
||||
{:reply, {:error, :not_found}, state}
|
||||
end
|
||||
@@ -148,6 +133,17 @@ defmodule ElixirAi.ConversationManager do
|
||||
end
|
||||
end
|
||||
|
||||
defp reply_with_started(name, state, update_state \\ fn s -> s end) do
|
||||
case start_and_subscribe(name, state.subscriptions) do
|
||||
{:ok, pid, new_subscriptions} ->
|
||||
new_state = update_state.(%{state | subscriptions: new_subscriptions})
|
||||
{:reply, {:ok, pid}, new_state}
|
||||
|
||||
{:error, _reason} = error ->
|
||||
{:reply, error, state}
|
||||
end
|
||||
end
|
||||
|
||||
defp start_and_subscribe(name, subscriptions) do
|
||||
result =
|
||||
case Horde.DynamicSupervisor.start_child(
|
||||
|
||||
@@ -113,5 +113,23 @@ defmodule ElixirAi.Conversation do
|
||||
end
|
||||
end
|
||||
|
||||
def find_provider(name) do
|
||||
sql = """
|
||||
SELECT p.name, p.model_name, p.api_token, p.completions_url
|
||||
FROM conversations c
|
||||
JOIN ai_providers p ON c.ai_provider_id = p.id
|
||||
WHERE c.name = $(name)
|
||||
LIMIT 1
|
||||
"""
|
||||
|
||||
params = %{"name" => name}
|
||||
|
||||
case DbHelpers.run_sql(sql, params, "conversations", Provider.schema()) do
|
||||
{:error, _} -> {:error, :db_error}
|
||||
[] -> {:error, :not_found}
|
||||
[row | _] -> {:ok, struct(Provider, row)}
|
||||
end
|
||||
end
|
||||
|
||||
defp now, do: DateTime.truncate(DateTime.utc_now(), :second)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user