Module: RubyLLM::Mongoid::ChatMethods

Extended by:
ActiveSupport::Concern
Includes:
Transaction
Defined in:
lib/ruby_llm/mongoid/chat_methods.rb

Overview

Mixes into a Mongoid document that represents a persisted chat session. Mirrors RubyLLM::ActiveRecord::ChatMethods, replacing AR-specific persistence and query calls with Mongoid equivalents.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Transaction

#with_transaction

Instance Attribute Details

#assume_model_existsObject

Returns the value of attribute assume_model_exists.



19
20
21
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 19

def assume_model_exists
  @assume_model_exists
end

#contextObject

Returns the value of attribute context.



19
20
21
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 19

def context
  @context
end

Instance Method Details

#add_message(message_or_attributes) ⇒ Object



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 176

def add_message(message_or_attributes)
  llm_message = message_or_attributes.is_a?(RubyLLM::Message) ? message_or_attributes : RubyLLM::Message.new(message_or_attributes)
  content_text, attachments, content_raw = prepare_content_for_storage(llm_message.content)

  attrs = { role: llm_message.role, content: content_text }

  if llm_message.tool_call_id
    tc_db_id = find_tool_call_db_id(llm_message.tool_call_id)
    attrs[:parent_tool_call_id] = tc_db_id if tc_db_id
  end

  message_record = messages_association.create!(attrs)
  message_record.update!(content_raw: content_raw) if content_raw_field?(message_record)

  persist_content(message_record, attachments) if attachments.present?
  persist_tool_calls(llm_message.tool_calls, message_record: message_record) if llm_message.tool_calls.present?

  message_record
end

#after_messageObject



151
152
153
154
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 151

def after_message(...)
  to_llm.after_message(...)
  self
end

#after_tool_resultObject



161
162
163
164
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 161

def after_tool_result(...)
  to_llm.after_tool_result(...)
  self
end

#ask(message = nil, with: nil) ⇒ Object Also known as: say



204
205
206
207
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 204

def ask(message = nil, with: nil, &)
  add_message(role: :user, content: build_content(message, with))
  complete(&)
end

#before_messageObject



146
147
148
149
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 146

def before_message(...)
  to_llm.before_message(...)
  self
end

#before_tool_callObject



156
157
158
159
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 156

def before_tool_call(...)
  to_llm.before_tool_call(...)
  self
end

#completeObject



211
212
213
214
215
216
217
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 211

def complete(...)
  to_llm.complete(...)
rescue RubyLLM::Error => e
  cleanup_failed_messages if @message&.persisted? && @message.content.blank?
  cleanup_orphaned_tool_results
  raise e
end

#costObject



196
197
198
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 196

def cost
  RubyLLM::Cost.aggregate(messages_association.map(&:cost))
end

#create_user_message(content, with: nil) ⇒ Object



200
201
202
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 200

def create_user_message(content, with: nil)
  add_message(role: :user, content: build_content(content, with))
end

#model=(value) ⇒ Object


Model / provider assignment




25
26
27
28
29
30
31
32
33
34
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 25

def model=(value)
  @model_string = value if value.is_a?(String)
  return if value.is_a?(String)

  if self.class.model_association_name == :model
    super
  else
    self.model_association = value
  end
end

#model_idObject



44
45
46
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 44

def model_id
  model_association&.model_id
end

#model_id=(value) ⇒ Object



36
37
38
39
40
41
42
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 36

def model_id=(value)
  if value.is_a?(String)
    @model_string = value
  else
    super
  end
end

#on_end_messageObject



141
142
143
144
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 141

def on_end_message(&)
  to_llm.on_end_message(&)
  self
end

#on_new_messageObject



136
137
138
139
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 136

def on_new_message(&)
  to_llm.on_new_message(&)
  self
end

#on_tool_callObject



166
167
168
169
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 166

def on_tool_call(...)
  to_llm.on_tool_call(...)
  self
end

#on_tool_resultObject



171
172
173
174
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 171

def on_tool_result(...)
  to_llm.on_tool_result(...)
  self
end

#providerObject



52
53
54
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 52

def provider
  model_association&.provider
end

#provider=(value) ⇒ Object



48
49
50
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 48

def provider=(value)
  @provider_string = value
end

#to_llmObject


Chat interface — mirrors the AR version




60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 60

def to_llm
  model_record = model_association
  @chat ||= (context || RubyLLM).chat(
    model: model_record.model_id,
    provider: model_record.provider.to_sym,
    assume_model_exists: assume_model_exists || false
  )
  @chat.reset_messages!

  ordered_messages = order_messages_for_llm(messages_association.to_a)
  ordered_messages.each { |msg| @chat.add_message(msg.to_llm) }
  reapply_runtime_instructions(@chat)

  setup_persistence_callbacks
end

#with_headersObject



126
127
128
129
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 126

def with_headers(...)
  to_llm.with_headers(...)
  self
end

#with_instructions(instructions, append: false, replace: nil) ⇒ Object



76
77
78
79
80
81
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 76

def with_instructions(instructions, append: false, replace: nil)
  append = append_instructions?(append: append, replace: replace)
  persist_system_instruction(instructions, append: append)
  to_llm.with_instructions(instructions, append: append, replace: replace)
  self
end

#with_model(model_name, provider: nil, assume_exists: false) ⇒ Object



100
101
102
103
104
105
106
107
108
109
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 100

def with_model(model_name, provider: nil, assume_exists: false)
  self.model = model_name
  self.provider = provider if provider
  self.assume_model_exists = assume_exists
  resolve_model_from_strings
  save!
  to_llm.with_model(model_association.model_id, provider: model_association.provider.to_sym,
                                                assume_exists: assume_exists)
  self
end

#with_paramsObject



121
122
123
124
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 121

def with_params(...)
  to_llm.with_params(...)
  self
end

#with_runtime_instructions(instructions, append: false, replace: nil) ⇒ Object



83
84
85
86
87
88
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 83

def with_runtime_instructions(instructions, append: false, replace: nil)
  append = append_instructions?(append: append, replace: replace)
  store_runtime_instruction(instructions, append: append)
  to_llm.with_instructions(instructions, append: append, replace: replace)
  self
end

#with_schemaObject



131
132
133
134
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 131

def with_schema(...)
  to_llm.with_schema(...)
  self
end

#with_temperatureObject



111
112
113
114
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 111

def with_temperature(...)
  to_llm.with_temperature(...)
  self
end

#with_thinkingObject



116
117
118
119
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 116

def with_thinking(...)
  to_llm.with_thinking(...)
  self
end

#with_toolObject



90
91
92
93
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 90

def with_tool(...)
  to_llm.with_tool(...)
  self
end

#with_toolsObject



95
96
97
98
# File 'lib/ruby_llm/mongoid/chat_methods.rb', line 95

def with_tools(...)
  to_llm.with_tools(...)
  self
end