Skip to content

Implement message() and messages() #12

Description

@raghubetina

When I demo'd the gem in class today, I ended up with something like this:

      # Get all the older messages for this topic from the db      

      the_topic = the_message.topic
      the_history = the_topic.messages.order(:created_at)

      # Reconstruct an AI::Chat from scratch

      chat = OpenAI::Chat.new

      the_history.each do |a_message|
        if a_message.role == "system"
          chat.system(a_message.content)
        elsif a_message.role == "user"
          chat.user(a_message.content)
        else
          chat.assistant(a_message.content)
        end
      end

      # Get the next assistant message

      next_message = Message.new
      next_message.topic_id = the_topic.id
      next_message.role = "assistant"
      next_message.content = chat.assistant!
      next_message.save

I think it would be nice if:

We could directly assign a hash as a message:

chat.message({ :role => "user", :content => "stuff" })
chat.message({ :role => "user", :content => "stuff", :image => an_imagelike })
chat.message({ :role => "user", :content => "stuff", :images => array_of_imagelikes })

Interwoven text and images:

chat.message({
  :role => :user,
  :content =>  [
    {"image" => "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/Eubalaena_glacialis_with_calf.jpg/215px-Eubalaena_glacialis_with_calf.jpg"},
    {"text" => "What is in the above image? What is in the below image?"},
    {"image" => "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1a/Elephant_Diversity.jpg/305px-Elephant_Diversity.jpg"},
    {"text" => "What are the differences between the images?"}
  ]
})

We can directly assign any object:

chat.message(thing)

... assuming that thing responds to thing.role/thing[:role] and thing.content/thing[:content]. It will also check thing.image/thing.images, unless prevented with the image: false option: chat.message(thing, image: false).

And, we could allow for custom mappings:

chat.message(thing, :role => "kind", :content => :body)
chat.message(thing, :image => "pic" )
chat.message(thing, :images => "photos") # assumes that each object returned by `send("photos") responds to `:image`
chat.message(thing, :images => "photos", :source => "pic_url" )

Once we have such a method message() implemented, system(), user(), and assistant() could delegate to it. And it should be straightforward to add messages():

def messages(collection, options = nil)
  collection.each { message(_1, options) }
end

Hopefully this would allow for passing an ActiveRecord::Relation:

chat.messages(topic.messages.order(:created_at)
chat.assistant!

I started working on this here, but I think the above implementation would be better than what I started there.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions