Skip to content

Commit 9d8522d

Browse files
committed
Introducing chat.with_instructions("instructions", replace: true)
1 parent 92b2672 commit 9d8522d

File tree

4 files changed

+63
-5
lines changed

4 files changed

+63
-5
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ chat.ask "Tell me a story about a Ruby programmer" do |chunk|
136136
end
137137

138138
# Set personality or behavior with instructions (aka system prompts)
139-
chat.with_instructions("You are a friendly Ruby expert who loves to help beginners")
139+
chat.with_instructions "You are a friendly Ruby expert who loves to help beginners"
140140

141141
# Understand content in multiple forms
142142
chat.ask "Compare these diagrams", with: { image: ["diagram1.png", "diagram2.png"] }
@@ -169,10 +169,10 @@ class ToolCall < ApplicationRecord
169169
end
170170

171171
# In a background job
172-
chat = Chat.create!(model_id: "gpt-4o-mini")
172+
chat = Chat.create! model_id: "gpt-4o-mini"
173173

174174
# Set personality or behavior with instructions (aka system prompts) - they're persisted too!
175-
chat.with_instructions("You are a friendly Ruby expert who loves to help beginners")
175+
chat.with_instructions "You are a friendly Ruby expert who loves to help beginners"
176176

177177
chat.ask("What's your favorite Ruby gem?") do |chunk|
178178
Turbo::StreamsChannel.broadcast_append_to(

docs/guides/rails.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,37 @@ Instructions are great for:
162162
3. Enforcing specific response formats
163163
4. Creating specialized assistants
164164

165+
### Managing Instructions
166+
167+
You can add multiple instructions or replace existing ones:
168+
169+
```ruby
170+
# Add initial instructions
171+
chat.with_instructions("Be a helpful Ruby expert")
172+
173+
# Add another instruction (keeps the first one)
174+
chat.with_instructions("Always include code examples")
175+
176+
# Replace all previous instructions
177+
chat.with_instructions("Be a concise Ruby expert who always shows examples", replace: true)
178+
```
179+
180+
This is particularly useful in controllers:
181+
182+
```ruby
183+
def update_instructions
184+
@chat = Chat.find(params[:id])
185+
186+
# Replace existing instructions with new ones
187+
@chat.with_instructions(params[:instructions], replace: true)
188+
189+
respond_to do |format|
190+
format.html { redirect_to @chat }
191+
format.turbo_stream
192+
end
193+
end
194+
```
195+
165196
## Streaming Responses
166197

167198
You can stream responses while still persisting the final result:

lib/ruby_llm/active_record/acts_as.rb

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,18 @@ def to_llm
7979
.on_end_message { |msg| persist_message_completion(msg) }
8080
end
8181

82-
def with_instructions(instructions)
83-
messages.create!(role: :system, content: instructions)
82+
def with_instructions(instructions, replace: false)
83+
transaction do
84+
# If replace is true, remove existing system messages
85+
messages.where(role: :system).destroy_all if replace
86+
87+
# Create the new system message
88+
messages.create!(
89+
role: :system,
90+
content: instructions
91+
)
92+
end
93+
to_llm.with_instructions(instructions)
8494
self
8595
end
8696

spec/ruby_llm/active_record/acts_as_spec.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,5 +152,22 @@ def execute(expression:)
152152
expect(chat.messages.first.role).to eq('system')
153153
expect(chat.messages.first.content).to eq('You are a Ruby expert')
154154
end
155+
156+
it 'optionally replaces existing system messages' do # rubocop:disable RSpec/ExampleLength,RSpec/MultipleExpectations
157+
chat = Chat.create!(model_id: 'gpt-4o-mini')
158+
159+
# Add first instruction
160+
chat.with_instructions('Be helpful')
161+
expect(chat.messages.where(role: 'system').count).to eq(1)
162+
163+
# Add second instruction without replace
164+
chat.with_instructions('Be concise')
165+
expect(chat.messages.where(role: 'system').count).to eq(2)
166+
167+
# Replace all instructions
168+
chat.with_instructions('Be awesome', replace: true)
169+
expect(chat.messages.where(role: 'system').count).to eq(1)
170+
expect(chat.messages.find_by(role: 'system').content).to eq('Be awesome')
171+
end
155172
end
156173
end

0 commit comments

Comments
 (0)