Skip to content

Implement message() and messages() #12

@raghubetina

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions