Class: Ragents::Context
- Inherits:
-
Object
- Object
- Ragents::Context
- Includes:
- Enumerable
- Defined in:
- lib/ragents/context.rb
Overview
Immutable conversation context. Context is Ractor-shareable when frozen, enabling safe passage between Ractors.
Instance Attribute Summary collapse
-
#messages ⇒ Object
readonly
Returns the value of attribute messages.
-
#metadata ⇒ Object
readonly
Returns the value of attribute metadata.
Class Method Summary collapse
-
.from_h(hash) ⇒ Object
Create from hash.
-
.make_shareable(context) ⇒ Object
Make Ractor-shareable.
- .symbolize_keys(hash) ⇒ Object
Instance Method Summary collapse
-
#add_message(message) ⇒ Object
(also: #<<)
Add a message and return a new Context.
-
#add_messages(*new_messages) ⇒ Object
Add multiple messages and return a new Context.
-
#conversation_messages ⇒ Object
Get all non-system messages.
-
#each(&block) ⇒ Object
Iterate over messages.
- #empty? ⇒ Boolean
-
#fork(**new_metadata) ⇒ Object
Create a fork of this context (for branching conversations).
-
#initialize(messages: [], metadata: {}) ⇒ Context
constructor
A new instance of Context.
-
#last_assistant_message ⇒ Object
Get the last assistant message.
-
#last_message ⇒ Object
Get the last message.
-
#pending_tool_calls ⇒ Object
Get pending tool calls from the last assistant message.
-
#pending_tool_calls? ⇒ Boolean
Check if the last message has tool calls.
-
#size ⇒ Object
(also: #length)
Count total messages.
-
#system_message ⇒ Object
Get the system message if present.
-
#to_a ⇒ Object
Convert to array of message hashes.
-
#to_h ⇒ Object
Serialize to hash.
-
#truncate(max_messages:, keep_system: true) ⇒ Object
Truncate context to last N messages (keeping system message).
-
#with_metadata(**new_metadata) ⇒ Object
Return a new Context with updated metadata.
Constructor Details
#initialize(messages: [], metadata: {}) ⇒ Context
Returns a new instance of Context.
18 19 20 21 22 |
# File 'lib/ragents/context.rb', line 18 def initialize(messages: [], metadata: {}) @messages = .map { |m| (m) }.freeze @metadata = .freeze freeze end |
Instance Attribute Details
#messages ⇒ Object (readonly)
Returns the value of attribute messages.
16 17 18 |
# File 'lib/ragents/context.rb', line 16 def @messages end |
#metadata ⇒ Object (readonly)
Returns the value of attribute metadata.
16 17 18 |
# File 'lib/ragents/context.rb', line 16 def @metadata end |
Class Method Details
.from_h(hash) ⇒ Object
Create from hash
116 117 118 119 120 121 122 123 124 |
# File 'lib/ragents/context.rb', line 116 def self.from_h(hash) = (hash[:messages] || hash["messages"] || []).map do |msg| Message.new(**symbolize_keys(msg)) end = hash[:metadata] || hash["metadata"] || {} new(messages: , metadata: symbolize_keys()) end |
.make_shareable(context) ⇒ Object
Make Ractor-shareable
150 151 152 |
# File 'lib/ragents/context.rb', line 150 def self.make_shareable(context) Ractor.make_shareable(context) end |
.symbolize_keys(hash) ⇒ Object
167 168 169 |
# File 'lib/ragents/context.rb', line 167 def self.symbolize_keys(hash) hash.transform_keys(&:to_sym) end |
Instance Method Details
#add_message(message) ⇒ Object Also known as: <<
Add a message and return a new Context
25 26 27 28 29 30 31 |
# File 'lib/ragents/context.rb', line 25 def () = () self.class.new( messages: @messages + [], metadata: @metadata ) end |
#add_messages(*new_messages) ⇒ Object
Add multiple messages and return a new Context
36 37 38 39 40 41 42 |
# File 'lib/ragents/context.rb', line 36 def (*) = .flatten.map { |m| (m) } self.class.new( messages: @messages + , metadata: @metadata ) end |
#conversation_messages ⇒ Object
Get all non-system messages
58 59 60 |
# File 'lib/ragents/context.rb', line 58 def @messages.reject(&:system?) end |
#each(&block) ⇒ Object
Iterate over messages
96 97 98 |
# File 'lib/ragents/context.rb', line 96 def each(&block) @messages.each(&block) end |
#empty? ⇒ Boolean
91 92 93 |
# File 'lib/ragents/context.rb', line 91 def empty? @messages.empty? end |
#fork(**new_metadata) ⇒ Object
Create a fork of this context (for branching conversations)
142 143 144 145 146 147 |
# File 'lib/ragents/context.rb', line 142 def fork(**) self.class.new( messages: @messages.dup, metadata: @metadata.merge().merge(forked_at: Time.now.iso8601) ) end |
#last_assistant_message ⇒ Object
Get the last assistant message
68 69 70 |
# File 'lib/ragents/context.rb', line 68 def @messages.reverse.find(&:assistant?) end |
#last_message ⇒ Object
Get the last message
63 64 65 |
# File 'lib/ragents/context.rb', line 63 def @messages.last end |
#pending_tool_calls ⇒ Object
Get pending tool calls from the last assistant message
78 79 80 81 82 |
# File 'lib/ragents/context.rb', line 78 def pending_tool_calls return [] unless pending_tool_calls? .tool_calls end |
#pending_tool_calls? ⇒ Boolean
Check if the last message has tool calls
73 74 75 |
# File 'lib/ragents/context.rb', line 73 def pending_tool_calls? &.has_tool_calls? || false end |
#size ⇒ Object Also known as: length
Count total messages
85 86 87 |
# File 'lib/ragents/context.rb', line 85 def size @messages.size end |
#system_message ⇒ Object
Get the system message if present
53 54 55 |
# File 'lib/ragents/context.rb', line 53 def @messages.find(&:system?) end |
#to_a ⇒ Object
Convert to array of message hashes
103 104 105 |
# File 'lib/ragents/context.rb', line 103 def to_a @messages.map(&:to_h) end |
#to_h ⇒ Object
Serialize to hash
108 109 110 111 112 113 |
# File 'lib/ragents/context.rb', line 108 def to_h { messages: to_a, metadata: @metadata } end |
#truncate(max_messages:, keep_system: true) ⇒ Object
Truncate context to last N messages (keeping system message)
127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/ragents/context.rb', line 127 def truncate(max_messages:, keep_system: true) return self if @messages.size <= system_msg = if keep_system = kept = .last(keep_system && system_msg ? - 1 : ) self.class.new( messages: system_msg ? [system_msg] + kept : kept, metadata: @metadata ) end |
#with_metadata(**new_metadata) ⇒ Object
Return a new Context with updated metadata
45 46 47 48 49 50 |
# File 'lib/ragents/context.rb', line 45 def (**) self.class.new( messages: @messages, metadata: @metadata.merge() ) end |