From abf32bb480f5f097fcf2e0e0f2427efec9497185 Mon Sep 17 00:00:00 2001 From: Sebskyo Date: Sun, 2 Mar 2025 08:17:31 +0100 Subject: [PATCH] allow conversations to use different agents called agents instead of models to avoid confusion with rails models --- app/agents/application_agent.rb | 7 +++++++ app/agents/dummy_agent.rb | 9 +++++++++ app/controllers/conversations_controller.rb | 3 ++- app/jobs/generate_reply_job.rb | 4 +++- app/models/conversation.rb | 9 +++++++++ .../20250302065926_add_agent_to_conversation.rb | 11 +++++++++++ db/schema.rb | 3 ++- 7 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 app/agents/application_agent.rb create mode 100644 app/agents/dummy_agent.rb create mode 100644 db/migrate/20250302065926_add_agent_to_conversation.rb diff --git a/app/agents/application_agent.rb b/app/agents/application_agent.rb new file mode 100644 index 0000000..18603ce --- /dev/null +++ b/app/agents/application_agent.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class ApplicationAgent + def prompt(_conversation) + raise NotImplementedError + end +end diff --git a/app/agents/dummy_agent.rb b/app/agents/dummy_agent.rb new file mode 100644 index 0000000..079a6bb --- /dev/null +++ b/app/agents/dummy_agent.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class DummyAgent + def prompt(_conversation) + # NOTE: Put logic for however we get a reply in this method (HTTP/RPC/IPC/etc) + # NOTE: Use the conversation record to supply necessary context for the agent. + 'AI Reply' + end +end diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index 1de96d3..e9740d6 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -12,7 +12,8 @@ class ConversationsController < ApplicationController end def create - @conversation = @current_user.conversations.new + # NOTE: Real application would have agent be given from params + @conversation = @current_user.conversations.new(agent: 'DummyAgent') if @conversation.save redirect_to @conversation else diff --git a/app/jobs/generate_reply_job.rb b/app/jobs/generate_reply_job.rb index 6596840..de98eed 100644 --- a/app/jobs/generate_reply_job.rb +++ b/app/jobs/generate_reply_job.rb @@ -4,6 +4,8 @@ class GenerateReplyJob < ApplicationJob queue_as :default def perform(conversation) - conversation.messages.create(body: 'AI Reply', reply: true) + agent = conversation.agent_klass.new + reply = agent.prompt(conversation) + conversation.messages.create!(body: reply, reply: true) end end diff --git a/app/models/conversation.rb b/app/models/conversation.rb index 645f0dc..2fb45bc 100644 --- a/app/models/conversation.rb +++ b/app/models/conversation.rb @@ -5,7 +5,16 @@ class Conversation < ApplicationRecord has_many :messages, dependent: :destroy + AGENTS = { + 'DummyAgent' => DummyAgent, + }.freeze + validates :agent, presence: true, inclusion: { in: AGENTS.keys } + def pending_reply? messages.last.promt? end + + def agent_klass + AGENTS[agent] + end end diff --git a/db/migrate/20250302065926_add_agent_to_conversation.rb b/db/migrate/20250302065926_add_agent_to_conversation.rb new file mode 100644 index 0000000..625b1df --- /dev/null +++ b/db/migrate/20250302065926_add_agent_to_conversation.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class AddAgentToConversation < ActiveRecord::Migration[8.0] + def change + # NOTE: Violating Rails/NotNullColumn is fine if there's no production environment yet. + # Otherwise I usually make a migration that uses null: true, + # then backfills something reasonable, then sets null: false. + # Of course only in the case if I don't want the column to just have a default. + add_column :conversations, :agent, :string, null: false # rubocop:disable Rails/NotNullColumn + end +end diff --git a/db/schema.rb b/db/schema.rb index 8162576..60d7a1d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,11 +10,12 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.0].define(version: 2025_03_01_202033) do +ActiveRecord::Schema[8.0].define(version: 2025_03_02_065926) do create_table "conversations", force: :cascade do |t| t.integer "user_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "agent", null: false t.index ["user_id"], name: "index_conversations_on_user_id" end