Class: OmniAI::Chat::Response

Inherits:
Object
  • Object
show all
Defined in:
lib/omniai/chat/response.rb

Overview

An ‘OmniAI::Chat::Response` encapsulates the result of generating a chat completion.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data:, choices: [], usage: nil) ⇒ Response

Returns a new instance of Response.

Parameters:

  • data (Hash)
  • choices (Array<Choice>) (defaults to: [])
  • usage (Usage, nil) (defaults to: nil)


26
27
28
29
30
# File 'lib/omniai/chat/response.rb', line 26

def initialize(data:, choices: [], usage: nil)
  @data = data
  @choices = choices
  @usage = usage
end

Instance Attribute Details

#choicesObject

Returns the value of attribute choices.



17
18
19
# File 'lib/omniai/chat/response.rb', line 17

def choices
  @choices
end

#dataObject

Returns the value of attribute data.



9
10
11
# File 'lib/omniai/chat/response.rb', line 9

def data
  @data
end

#usageObject

Returns the value of attribute usage.



13
14
15
# File 'lib/omniai/chat/response.rb', line 13

def usage
  @usage
end

Class Method Details

.deserialize(data, context: nil) ⇒ OmniAI::Chat::Response

Parameters:

Returns:



41
42
43
44
45
46
47
48
49
# File 'lib/omniai/chat/response.rb', line 41

def self.deserialize(data, context: nil)
  deserialize = context&.deserializer(:response)
  return deserialize.call(data, context:) if deserialize

  choices = data["choices"].map { |choice_data| Choice.deserialize(choice_data, context:) }
  usage = Usage.deserialize(data["usage"], context:) if data["usage"]

  new(data:, choices:, usage:)
end

Instance Method Details

#=( = (value)) ⇒ Array<Choice>

Returns:



9
# File 'lib/omniai/chat/response.rb', line 9

attr_accessor :data

#inspectString

Returns:

  • (String)


33
34
35
# File 'lib/omniai/chat/response.rb', line 33

def inspect
  "#<#{self.class.name} choices=#{@choices.inspect} usage=#{@usage.inspect}>"
end

Links this response chain to a parent response. Walks up to find the oldest response (no parent) and sets its parent.

Parameters:



115
116
117
118
119
# File 'lib/omniai/chat/response.rb', line 115

def link_to(parent)
  current = self
  current = current.parent while current.parent
  current.parent = parent
end

#messagesArray<Message>

Returns:



65
66
67
# File 'lib/omniai/chat/response.rb', line 65

def messages
  @choices.map(&:message).compact
end

#messages?Boolean

Returns:

  • (Boolean)


70
71
72
# File 'lib/omniai/chat/response.rb', line 70

def messages?
  messages.any?
end

#parentObject



21
22
23
# File 'lib/omniai/chat/response.rb', line 21

def parent
  @parent
end

#response_chainArray<Response>

Returns the chain of responses from oldest (first) to newest (self).

Returns:



124
125
126
127
128
129
130
131
132
133
134
# File 'lib/omniai/chat/response.rb', line 124

def response_chain
  chain = []
  current = self

  while current
    chain.unshift(current)
    current = current.parent
  end

  chain
end

#serialize(context:) ⇒ Hash

Parameters:

Returns:

  • (Hash)


54
55
56
57
58
59
60
61
62
# File 'lib/omniai/chat/response.rb', line 54

def serialize(context:)
  serialize = context&.serializer(:response)
  return serialize.call(self, context:) if serialize

  {
    choices: @choices.map { |choice| choice.serialize(context:) },
    usage: @usage&.serialize(context:),
  }
end

#textString?

Returns:

  • (String, nil)


75
76
77
78
79
# File 'lib/omniai/chat/response.rb', line 75

def text
  return unless text?

  messages.filter(&:text?).map(&:text).join("\n\n")
end

#text?Boolean

Returns:

  • (Boolean)


82
83
84
# File 'lib/omniai/chat/response.rb', line 82

def text?
  messages.any?(&:text?)
end

#thinkingString?

Returns:

  • (String, nil)


87
88
89
90
91
# File 'lib/omniai/chat/response.rb', line 87

def thinking
  return unless thinking?

  messages.filter(&:thinking?).map(&:thinking).join("\n\n")
end

#thinking?Boolean

Returns:

  • (Boolean)


94
95
96
# File 'lib/omniai/chat/response.rb', line 94

def thinking?
  messages.any?(&:thinking?)
end

#tool_call_listToolCallList?

Returns:



99
100
101
102
103
104
# File 'lib/omniai/chat/response.rb', line 99

def tool_call_list
  tool_call_lists = messages.filter(&:tool_call_list?).map(&:tool_call_list)
  return if tool_call_lists.empty?

  tool_call_lists.reduce(&:+)
end

#tool_call_list?Boolean

Returns:

  • (Boolean)


107
108
109
# File 'lib/omniai/chat/response.rb', line 107

def tool_call_list?
  !tool_call_list.nil?
end

#total_usageUsage?

Returns aggregated usage across all responses in the chain. Walks the parent chain and sums all token counts.

Returns:



140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/omniai/chat/response.rb', line 140

def total_usage
  chain = response_chain
  usages = chain.map(&:usage).compact
  return nil if usages.empty?

  input_tokens = usages.sum { |u| u.input_tokens || 0 }
  output_tokens = usages.sum { |u| u.output_tokens || 0 }

  Usage.new(
    input_tokens:,
    output_tokens:,
    total_tokens: input_tokens + output_tokens
  )
end