1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-07-19 05:09:38 +02:00
Maybe/app/models/assistant.rb
Zach Gollwitzer 5cf758bd03
improvements(ai): Improve AI streaming UI/UX interactions + better separation of AI provider responsibilities (#2039)
* Start refactor

* Interface updates

* Rework Assistant, Provider, and tests for better domain boundaries

* Consolidate and simplify OpenAI provider and provider concepts

* Clean up assistant streaming

* Improve assistant message orchestration logic

* Clean up "thinking" UI interactions

* Remove stale class

* Regenerate VCR test responses
2025-04-01 07:21:54 -04:00

75 lines
1.8 KiB
Ruby

class Assistant
include Provided, Configurable, Broadcastable
attr_reader :chat, :instructions
class << self
def for_chat(chat)
config = config_for(chat)
new(chat, instructions: config[:instructions], functions: config[:functions])
end
end
def initialize(chat, instructions: nil, functions: [])
@chat = chat
@instructions = instructions
@functions = functions
end
def respond_to(message)
assistant_message = AssistantMessage.new(
chat: chat,
content: "",
ai_model: message.ai_model
)
responder = Assistant::Responder.new(
message: message,
instructions: instructions,
function_tool_caller: function_tool_caller,
llm: get_model_provider(message.ai_model)
)
latest_response_id = chat.latest_assistant_response_id
responder.on(:output_text) do |text|
if assistant_message.content.blank?
stop_thinking
Chat.transaction do
assistant_message.append_text!(text)
chat.update_latest_response!(latest_response_id)
end
else
assistant_message.append_text!(text)
end
end
responder.on(:response) do |data|
update_thinking("Analyzing your data...")
if data[:function_tool_calls].present?
assistant_message.tool_calls = data[:function_tool_calls]
latest_response_id = data[:id]
else
chat.update_latest_response!(data[:id])
end
end
responder.respond(previous_response_id: latest_response_id)
rescue => e
stop_thinking
chat.add_error(e)
end
private
attr_reader :functions
def function_tool_caller
function_instances = functions.map do |fn|
fn.new(chat.user)
end
@function_tool_caller ||= FunctionToolCaller.new(function_instances)
end
end