Class: Ask::Conversation

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/ask/conversation.rb

Overview

Ordered collection of messages comprising a conversation with an LLM. Provides role normalization, serialization helpers, and Enumerable access.

conv = Ask::Conversation.new
conv << Ask::Message.new(role: :user, content: "Hello")
conv.system("Be helpful")
conv.to_a  # => [{ role: :user, content: "Hello" }, ...]

Instance Method Summary collapse

Constructor Details

#initialize(messages = []) ⇒ Conversation

Returns a new instance of Conversation.

Parameters:

  • messages (Array<Ask::Message>) (defaults to: [])

    initial messages



229
230
231
232
# File 'lib/ask/conversation.rb', line 229

def initialize(messages = [])
  @messages = []
  messages.each { |m| self << m }
end

Instance Method Details

#<<(message) ⇒ self Also known as: add

Add a message by object or by attributes.

Parameters:

  • message (Ask::Message, Hash, String)

    message or attributes

Returns:

  • (self)


237
238
239
240
241
# File 'lib/ask/conversation.rb', line 237

def <<(message)
  msg = message.is_a?(Message) ? message : build_message(message)
  @messages << msg
  self
end

#[](index) ⇒ Ask::Message?

Access message by index.

Parameters:

  • index (Integer)

    zero-based index

Returns:



310
311
312
# File 'lib/ask/conversation.rb', line 310

def [](index)
  @messages[index]
end

#assistant(text = nil, tool_calls: nil, **options) ⇒ self

Add an assistant message.

Parameters:

  • text (String, nil) (defaults to: nil)

    message content (nil when tool_calls are present)

  • tool_calls (Array<Hash>, nil) (defaults to: nil)

    tool call invocations

Returns:

  • (self)


270
271
272
# File 'lib/ask/conversation.rb', line 270

def assistant(text = nil, tool_calls: nil, **options)
  self << Message.new(role: :assistant, content: text, tool_calls: tool_calls, **options)
end

#assistant_messagesArray<Ask::Message>

Returns assistant messages.

Returns:



332
# File 'lib/ask/conversation.rb', line 332

def assistant_messages = by_role(:assistant)

#by_role(role) ⇒ Array<Ask::Message>

Returns messages with the given role.

Parameters:

  • role (Symbol, String)

    role to filter by

Returns:



321
322
323
# File 'lib/ask/conversation.rb', line 321

def by_role(role)
  @messages.select { |m| m.role == role.to_sym }
end

#clearself

Remove all messages.

Returns:

  • (self)


302
303
304
305
# File 'lib/ask/conversation.rb', line 302

def clear
  @messages.clear
  self
end

#dupAsk::Conversation

Deep copy of this conversation.

Returns:



348
349
350
351
352
353
354
355
356
357
358
359
# File 'lib/ask/conversation.rb', line 348

def dup
  Conversation.new(@messages.map { |m|
    opts = { role: m.role, name: m.name, tool_call_id: m.tool_call_id,
             tool_calls: m.tool_calls, metadata: m. }
    if m.content_blocks
      opts[:content] = m.content_blocks.dup
    else
      opts[:content] = m.content
    end
    Message.new(**opts)
  })
end

#each {|Message| ... } ⇒ Enumerator

Returns if no block given.

Yields:

  • (Message)

    yields each message in order

Returns:

  • (Enumerator)

    if no block given



284
285
286
# File 'lib/ask/conversation.rb', line 284

def each(&block)
  @messages.each(&block)
end

#empty?Boolean

Returns true if there are no messages.

Returns:

  • (Boolean)

    true if there are no messages



298
# File 'lib/ask/conversation.rb', line 298

def empty? = @messages.empty?

#find_matching_tool_call(tool_call_id) ⇒ Object

Walk message history to find a matching assistant tool call for a tool result. Returns the assistant message that contains the tool call, or nil.



339
340
341
342
343
344
# File 'lib/ask/conversation.rb', line 339

def find_matching_tool_call(tool_call_id)
  @messages.reverse.find do |m|
    next unless m.role == :assistant && m.tool_calls.is_a?(Hash)
    m.tool_calls.key?(tool_call_id)
  end
end

#inspectString

Returns:

  • (String)


362
363
364
# File 'lib/ask/conversation.rb', line 362

def inspect
  "#<Ask::Conversation messages=#{@messages.length}>"
end

#last(n = nil) ⇒ Ask::Message+

Returns last message or last n messages.

Returns:



289
290
291
# File 'lib/ask/conversation.rb', line 289

def last(n = nil)
  n ? @messages.last(n) : @messages.last
end

#lengthInteger Also known as: size

Returns number of messages.

Returns:

  • (Integer)

    number of messages



294
# File 'lib/ask/conversation.rb', line 294

def length = @messages.length

#system(text, **options) ⇒ self

Add a system message.

Parameters:

  • text (String, Array<Ask::Content>)

    message content or content blocks

Returns:

  • (self)


247
248
249
# File 'lib/ask/conversation.rb', line 247

def system(text, **options)
  self << Message.new(role: :system, content: text, **options)
end

#system_messagesArray<Ask::Message>

Returns system messages.

Returns:



326
# File 'lib/ask/conversation.rb', line 326

def system_messages = by_role(:system)

#to_aArray<Hash>

Returns messages as an array of hashes.

Returns:

  • (Array<Hash>)

    messages as an array of hashes



315
316
317
# File 'lib/ask/conversation.rb', line 315

def to_a
  @messages.map(&:to_h)
end

#tool_messagesArray<Ask::Message>

Returns tool messages.

Returns:



335
# File 'lib/ask/conversation.rb', line 335

def tool_messages = by_role(:tool)

#tool_result(content, tool_call_id:, **options) ⇒ self

Add a tool result message.

Parameters:

  • content (String)

    tool output

  • tool_call_id (String)

    ID of the tool call this result is for

Returns:

  • (self)


278
279
280
# File 'lib/ask/conversation.rb', line 278

def tool_result(content, tool_call_id:, **options)
  self << Message.new(role: :tool, content: content, tool_call_id: tool_call_id, **options)
end

#user(text, **options) ⇒ self

Add a user message.

Examples:

Plain text

conv.user("Hello")

Multi-modal

conv.user([
  Ask::Content::Text.new("What's in this image?"),
  Ask::Content::Image.new(url: "https://example.com/photo.jpg", mime_type: "image/jpeg")
])

Parameters:

  • text (String, Array<Ask::Content>)

    message content or content blocks. Pass an Array of Ask::Content objects for multi-modal messages.

Returns:

  • (self)


262
263
264
# File 'lib/ask/conversation.rb', line 262

def user(text, **options)
  self << Message.new(role: :user, content: text, **options)
end

#user_messagesArray<Ask::Message>

Returns user messages.

Returns:



329
# File 'lib/ask/conversation.rb', line 329

def user_messages = by_role(:user)