smart_prompt 0.4.4 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -10
- data/README.cn.md +307 -64
- data/README.md +311 -64
- data/Rakefile +10 -1
- data/config/anthropic_config.yml +151 -0
- data/config/image_generation_config.yml +22 -0
- data/config/multimodal_config.yml +85 -0
- data/config/sensenova_config.yml +63 -0
- data/config/zhipu_config.yml +73 -0
- data/examples/anthropic_basic_chat.rb +143 -0
- data/examples/anthropic_example.rb +232 -0
- data/examples/anthropic_multimodal.rb +212 -0
- data/examples/anthropic_streaming.rb +312 -0
- data/examples/anthropic_tool_calling.rb +393 -0
- data/examples/automatic_cleanup_example.rb +109 -0
- data/examples/history_management_examples.rb +522 -0
- data/examples/image_generation_example.rb +130 -0
- data/examples/monitoring_example.rb +121 -0
- data/examples/multimodal_example.rb +63 -0
- data/examples/relevance_based_strategy_example.rb +87 -0
- data/examples/sensenova_example.rb +129 -0
- data/examples/stt_example.rb +287 -0
- data/examples/tts_example.rb +244 -0
- data/examples/video_generation_example.rb +189 -0
- data/examples/zhipu_example.rb +151 -0
- data/lib/smart_prompt/anthropic_adapter.rb +363 -281
- data/lib/smart_prompt/compression_engine.rb +201 -0
- data/lib/smart_prompt/context_strategy.rb +22 -0
- data/lib/smart_prompt/conversation.rb +81 -191
- data/lib/smart_prompt/engine.rb +36 -19
- data/lib/smart_prompt/history_manager.rb +596 -0
- data/lib/smart_prompt/hybrid_strategy.rb +222 -0
- data/lib/smart_prompt/image_generation_adapter.rb +297 -0
- data/lib/smart_prompt/lru_cache.rb +133 -0
- data/lib/smart_prompt/message.rb +57 -0
- data/lib/smart_prompt/multimodal_adapter.rb +277 -0
- data/lib/smart_prompt/openai_adapter.rb +1 -25
- data/lib/smart_prompt/persistence_layer.rb +197 -0
- data/lib/smart_prompt/relevance_based_strategy.rb +221 -0
- data/lib/smart_prompt/sensenova_adapter.rb +410 -0
- data/lib/smart_prompt/session.rb +140 -0
- data/lib/smart_prompt/sliding_window_strategy.rb +100 -0
- data/lib/smart_prompt/stt_adapter.rb +381 -0
- data/lib/smart_prompt/summary_based_strategy.rb +152 -0
- data/lib/smart_prompt/token_counter.rb +74 -0
- data/lib/smart_prompt/tts_adapter.rb +403 -0
- data/lib/smart_prompt/version.rb +1 -1
- data/lib/smart_prompt/video_generation_adapter.rb +330 -0
- data/lib/smart_prompt/worker.rb +25 -3
- data/lib/smart_prompt/zhipu_adapter.rb +616 -0
- data/lib/smart_prompt.rb +22 -2
- data/workers/history_management_examples.rb +407 -0
- data/workers/image_generation_workers.rb +119 -0
- data/workers/multimodal_workers.rb +110 -0
- data/workers/sensenova_workers.rb +62 -0
- data/workers/stt_workers.rb +195 -0
- data/workers/tts_workers.rb +388 -0
- data/workers/video_generation_workers.rb +264 -0
- data/workers/zhipu_workers.rb +113 -0
- metadata +84 -8
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# History Management Example Workers
|
|
5
|
+
# These examples demonstrate the new intelligent history management features
|
|
6
|
+
# introduced in the history-optimization feature.
|
|
7
|
+
|
|
8
|
+
require_relative "../lib/smart_prompt"
|
|
9
|
+
|
|
10
|
+
=begin
|
|
11
|
+
# ============================================================================
|
|
12
|
+
# Example 1: Explicit Session Management
|
|
13
|
+
# ============================================================================
|
|
14
|
+
# This example demonstrates how to explicitly manage sessions with unique IDs.
|
|
15
|
+
# Each session maintains its own isolated conversation history.
|
|
16
|
+
|
|
17
|
+
puts "\n=== Example 1: Explicit Session Management ==="
|
|
18
|
+
|
|
19
|
+
# Initialize engine
|
|
20
|
+
engine = SmartPrompt::Engine.new("config/anthropic_config.yml")
|
|
21
|
+
|
|
22
|
+
# Define a worker with explicit session management
|
|
23
|
+
SmartPrompt.define_worker :explicit_session_chat do
|
|
24
|
+
use "deepseek_anthropic"
|
|
25
|
+
model "deepseek-chat"
|
|
26
|
+
|
|
27
|
+
# Use a unique session ID for each conversation
|
|
28
|
+
# This could be a user ID, conversation ID, or any unique identifier
|
|
29
|
+
# session_id is passed via params and automatically used by the conversation
|
|
30
|
+
|
|
31
|
+
sys_msg("You are a helpful AI assistant.")
|
|
32
|
+
prompt(params[:message])
|
|
33
|
+
send_msg
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Example usage: Multiple isolated conversations
|
|
37
|
+
puts "\nCreating two separate conversations..."
|
|
38
|
+
|
|
39
|
+
# Conversation 1 with Alice
|
|
40
|
+
response1 = engine.call_worker(:explicit_session_chat, {
|
|
41
|
+
session_id: "user_alice",
|
|
42
|
+
message: "My name is Alice and I love programming.",
|
|
43
|
+
with_history: true,
|
|
44
|
+
})
|
|
45
|
+
puts "Alice: #{response1}"
|
|
46
|
+
|
|
47
|
+
# Conversation 2 with Bob
|
|
48
|
+
response2 = engine.call_worker(:explicit_session_chat, {
|
|
49
|
+
session_id: "user_bob",
|
|
50
|
+
message: "My name is Bob and I enjoy cooking.",
|
|
51
|
+
with_history: true,
|
|
52
|
+
})
|
|
53
|
+
puts "Bob: #{response2}"
|
|
54
|
+
|
|
55
|
+
# Continue Alice's conversation - should remember her name
|
|
56
|
+
response3 = engine.call_worker(:explicit_session_chat, {
|
|
57
|
+
session_id: "user_alice",
|
|
58
|
+
message: "What did I say I love?",
|
|
59
|
+
with_history: true,
|
|
60
|
+
})
|
|
61
|
+
puts "Alice (follow-up): #{response3}"
|
|
62
|
+
|
|
63
|
+
# Continue Bob's conversation - should remember his name
|
|
64
|
+
response4 = engine.call_worker(:explicit_session_chat, {
|
|
65
|
+
session_id: "user_bob",
|
|
66
|
+
message: "What did I say I enjoy?",
|
|
67
|
+
with_history: true,
|
|
68
|
+
})
|
|
69
|
+
puts "Bob (follow-up): #{response4}"
|
|
70
|
+
=end
|
|
71
|
+
|
|
72
|
+
# ============================================================================
|
|
73
|
+
# Example 2: Different Context Strategies
|
|
74
|
+
# ============================================================================
|
|
75
|
+
# This example demonstrates the different context strategies available:
|
|
76
|
+
# - Sliding Window: Keeps most recent N messages
|
|
77
|
+
# - Relevance-Based: Selects semantically relevant messages
|
|
78
|
+
# - Summary-Based: Automatically compresses old messages
|
|
79
|
+
# - Hybrid: Adaptively combines strategies
|
|
80
|
+
|
|
81
|
+
puts "\n\n=== Example 2: Different Context Strategies ==="
|
|
82
|
+
engine = SmartPrompt::Engine.new("config/anthropic_config.yml")
|
|
83
|
+
# 2.1 Sliding Window Strategy
|
|
84
|
+
# Best for: Real-time chat, customer support, short conversations
|
|
85
|
+
SmartPrompt.define_worker :sliding_window_chat do
|
|
86
|
+
use "deepseek_anthropic"
|
|
87
|
+
model "deepseek-chat"
|
|
88
|
+
|
|
89
|
+
session_id = params[:session_id] || "sliding_window_session"
|
|
90
|
+
|
|
91
|
+
# Configure session with sliding window strategy
|
|
92
|
+
session_config = {
|
|
93
|
+
max_messages: 3, # Keep only last 10 messages
|
|
94
|
+
max_tokens: 2000, # Maximum 2000 tokens
|
|
95
|
+
context_strategy: :sliding_window,
|
|
96
|
+
preserve_system_messages: true,
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
sys_msg("You are a customer support assistant.", params)
|
|
100
|
+
prompt(params[:message], with_history: true, session_id: session_id)
|
|
101
|
+
|
|
102
|
+
# Apply session configuration
|
|
103
|
+
@engine.history_manager.get_session(session_id, session_config)
|
|
104
|
+
|
|
105
|
+
send_msg
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
puts "\nSliding Window Strategy Example:"
|
|
109
|
+
puts "This strategy keeps only the most recent messages."
|
|
110
|
+
|
|
111
|
+
# Simulate a conversation with many messages
|
|
112
|
+
5.times do |i|
|
|
113
|
+
response = engine.call_worker(:sliding_window_chat, {
|
|
114
|
+
session_id: "sliding_demo",
|
|
115
|
+
message: "This is message number #{i + 1}. Can you count?",
|
|
116
|
+
})
|
|
117
|
+
puts "Message #{i + 1} response: #{response[0..50]}..."
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
=begin
|
|
121
|
+
# 2.2 Relevance-Based Strategy
|
|
122
|
+
# Best for: Q&A systems, knowledge bases, context-aware assistants
|
|
123
|
+
SmartPrompt.define_worker :relevance_chat do
|
|
124
|
+
use "deepseek_anthropic"
|
|
125
|
+
model "deepseek-chat"
|
|
126
|
+
|
|
127
|
+
session_id = params[:session_id] || "relevance_session"
|
|
128
|
+
|
|
129
|
+
# Configure session with relevance-based strategy
|
|
130
|
+
session_config = {
|
|
131
|
+
max_messages: 50,
|
|
132
|
+
max_tokens: 4000,
|
|
133
|
+
context_strategy: :relevance_based,
|
|
134
|
+
preserve_system_messages: true,
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
sys_msg("You are a knowledgeable AI assistant.", params)
|
|
138
|
+
prompt(params[:message], with_history: true, session_id: session_id)
|
|
139
|
+
|
|
140
|
+
@engine.history_manager.get_session(session_id, session_config)
|
|
141
|
+
|
|
142
|
+
send_msg
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
puts "\nRelevance-Based Strategy Example:"
|
|
146
|
+
puts "This strategy selects semantically relevant messages."
|
|
147
|
+
|
|
148
|
+
# Example conversation with topic changes
|
|
149
|
+
topics = [
|
|
150
|
+
"Tell me about Ruby programming.",
|
|
151
|
+
"What about Python?",
|
|
152
|
+
"Now explain JavaScript.",
|
|
153
|
+
"Going back to Ruby, what are its best features?",
|
|
154
|
+
]
|
|
155
|
+
|
|
156
|
+
topics.each_with_index do |message, i|
|
|
157
|
+
response = engine.call_worker(:relevance_chat, {
|
|
158
|
+
session_id: "relevance_demo",
|
|
159
|
+
message: message,
|
|
160
|
+
})
|
|
161
|
+
puts "Topic #{i + 1}: #{message}"
|
|
162
|
+
puts "Response: #{response[0..80]}...\n"
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# 2.3 Summary-Based Strategy
|
|
166
|
+
# Best for: Long conversations, documentation, extended dialogues
|
|
167
|
+
SmartPrompt.define_worker :summary_chat do
|
|
168
|
+
use "deepseek_anthropic"
|
|
169
|
+
model "deepseek-chat"
|
|
170
|
+
|
|
171
|
+
session_id = params[:session_id] || "summary_session"
|
|
172
|
+
|
|
173
|
+
# Configure session with summary-based strategy
|
|
174
|
+
session_config = {
|
|
175
|
+
max_messages: 100,
|
|
176
|
+
max_tokens: 8000,
|
|
177
|
+
context_strategy: :summary_based,
|
|
178
|
+
preserve_system_messages: true,
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
sys_msg("You are a thoughtful AI assistant for extended conversations.", params)
|
|
182
|
+
prompt(params[:message], with_history: true, session_id: session_id)
|
|
183
|
+
|
|
184
|
+
@engine.history_manager.get_session(session_id, session_config)
|
|
185
|
+
|
|
186
|
+
send_msg
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
puts "\nSummary-Based Strategy Example:"
|
|
190
|
+
puts "This strategy automatically compresses old messages into summaries."
|
|
191
|
+
|
|
192
|
+
# Simulate a long conversation
|
|
193
|
+
10.times do |i|
|
|
194
|
+
response = engine.call_worker(:summary_chat, {
|
|
195
|
+
session_id: "summary_demo",
|
|
196
|
+
message: "Tell me fact number #{i + 1} about space exploration.",
|
|
197
|
+
})
|
|
198
|
+
puts "Fact #{i + 1} received (#{response.length} chars)"
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# 2.4 Hybrid Strategy
|
|
202
|
+
# Best for: General-purpose applications, varied conversation types
|
|
203
|
+
SmartPrompt.define_worker :hybrid_chat do
|
|
204
|
+
use "deepseek_anthropic"
|
|
205
|
+
model "deepseek-chat"
|
|
206
|
+
|
|
207
|
+
session_id = params[:session_id] || "hybrid_session"
|
|
208
|
+
|
|
209
|
+
# Configure session with hybrid strategy
|
|
210
|
+
session_config = {
|
|
211
|
+
max_messages: 75,
|
|
212
|
+
max_tokens: 6000,
|
|
213
|
+
context_strategy: :hybrid,
|
|
214
|
+
preserve_system_messages: true,
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
sys_msg("You are an intelligent AI assistant that adapts to conversation context.", params)
|
|
218
|
+
prompt(params[:message], with_history: true, session_id: session_id)
|
|
219
|
+
|
|
220
|
+
@engine.history_manager.get_session(session_id, session_config)
|
|
221
|
+
|
|
222
|
+
send_msg
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
puts "\nHybrid Strategy Example:"
|
|
226
|
+
puts "This strategy adaptively combines multiple strategies."
|
|
227
|
+
|
|
228
|
+
response = engine.call_worker(:hybrid_chat, {
|
|
229
|
+
session_id: "hybrid_demo",
|
|
230
|
+
message: "Let's have a conversation that covers many topics.",
|
|
231
|
+
})
|
|
232
|
+
puts "Response: #{response[0..80]}..."
|
|
233
|
+
|
|
234
|
+
# ============================================================================
|
|
235
|
+
# Example 3: Session Operations (clear, export, search, stats, delete)
|
|
236
|
+
# ============================================================================
|
|
237
|
+
# This example demonstrates various session management operations.
|
|
238
|
+
|
|
239
|
+
puts "\n\n=== Example 3: Session Operations ==="
|
|
240
|
+
|
|
241
|
+
# Create a session with some messages
|
|
242
|
+
session_id = "operations_demo"
|
|
243
|
+
engine = SmartPrompt::Engine.new
|
|
244
|
+
|
|
245
|
+
# Add some messages
|
|
246
|
+
puts "\nAdding messages to session..."
|
|
247
|
+
engine.history_manager.add_message(session_id, {
|
|
248
|
+
role: "system",
|
|
249
|
+
content: "You are a helpful assistant.",
|
|
250
|
+
})
|
|
251
|
+
engine.history_manager.add_message(session_id, {
|
|
252
|
+
role: "user",
|
|
253
|
+
content: "Hello! My name is Alice.",
|
|
254
|
+
})
|
|
255
|
+
engine.history_manager.add_message(session_id, {
|
|
256
|
+
role: "assistant",
|
|
257
|
+
content: "Hello Alice! Nice to meet you.",
|
|
258
|
+
})
|
|
259
|
+
engine.history_manager.add_message(session_id, {
|
|
260
|
+
role: "user",
|
|
261
|
+
content: "Can you help me with Ruby programming?",
|
|
262
|
+
})
|
|
263
|
+
engine.history_manager.add_message(session_id, {
|
|
264
|
+
role: "assistant",
|
|
265
|
+
content: "Of course! I'd be happy to help with Ruby programming.",
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
# 3.1 Get Statistics
|
|
269
|
+
puts "\n--- Get Statistics ---"
|
|
270
|
+
stats = engine.history_manager.get_stats(session_id)
|
|
271
|
+
puts "Session Statistics:"
|
|
272
|
+
puts " Message Count: #{stats[:message_count]}"
|
|
273
|
+
puts " Total Tokens: #{stats[:total_tokens]}"
|
|
274
|
+
puts " Created At: #{stats[:created_at]}"
|
|
275
|
+
puts " Updated At: #{stats[:updated_at]}"
|
|
276
|
+
|
|
277
|
+
# 3.2 Search Messages
|
|
278
|
+
puts "\n--- Search Messages ---"
|
|
279
|
+
search_results = engine.history_manager.search_messages(session_id, "Ruby")
|
|
280
|
+
puts "Search results for 'Ruby': #{search_results.count} messages found"
|
|
281
|
+
search_results.each do |msg|
|
|
282
|
+
puts " [#{msg.role}]: #{msg.content[0..50]}..."
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
# 3.3 Export Session
|
|
286
|
+
puts "\n--- Export Session ---"
|
|
287
|
+
exported_data = engine.history_manager.export_session(session_id, format: :hash)
|
|
288
|
+
puts "Exported session data:"
|
|
289
|
+
puts " ID: #{exported_data[:id]}"
|
|
290
|
+
puts " Messages: #{exported_data[:messages].count}"
|
|
291
|
+
puts " First message: #{exported_data[:messages].first[:content][0..50]}..."
|
|
292
|
+
|
|
293
|
+
# 3.4 Clear Session (keeping system messages)
|
|
294
|
+
puts "\n--- Clear Session ---"
|
|
295
|
+
puts "Messages before clear: #{engine.history_manager.get_stats(session_id)[:message_count]}"
|
|
296
|
+
engine.history_manager.clear_session(session_id, keep_system_messages: true)
|
|
297
|
+
puts "Messages after clear: #{engine.history_manager.get_stats(session_id)[:message_count]}"
|
|
298
|
+
|
|
299
|
+
# 3.5 Delete Session
|
|
300
|
+
puts "\n--- Delete Session ---"
|
|
301
|
+
puts "Session exists before delete: #{engine.history_manager.session_exists?(session_id)}"
|
|
302
|
+
engine.history_manager.delete_session(session_id)
|
|
303
|
+
puts "Session exists after delete: #{engine.history_manager.session_exists?(session_id)}"
|
|
304
|
+
|
|
305
|
+
# ============================================================================
|
|
306
|
+
# Example 4: Backward Compatibility
|
|
307
|
+
# ============================================================================
|
|
308
|
+
# This example demonstrates backward compatibility with the old API.
|
|
309
|
+
|
|
310
|
+
puts "\n\n=== Example 4: Backward Compatibility ==="
|
|
311
|
+
|
|
312
|
+
# Old-style worker definition (still works!)
|
|
313
|
+
SmartPrompt.define_worker :legacy_chat do
|
|
314
|
+
use "deepseek_anthropic"
|
|
315
|
+
model "deepseek-chat"
|
|
316
|
+
|
|
317
|
+
sys_msg("You are a helpful AI assistant.")
|
|
318
|
+
|
|
319
|
+
# Old-style history usage - still works!
|
|
320
|
+
prompt(params[:message], with_history: true)
|
|
321
|
+
|
|
322
|
+
send_msg
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
puts "\nUsing legacy API (with_history: true)..."
|
|
326
|
+
response = engine.call_worker(:legacy_chat, {
|
|
327
|
+
message: "Hello! This is using the old API.",
|
|
328
|
+
})
|
|
329
|
+
puts "Response: #{response[0..80]}..."
|
|
330
|
+
|
|
331
|
+
# The new system automatically creates a default session
|
|
332
|
+
# and maintains backward compatibility
|
|
333
|
+
|
|
334
|
+
# ============================================================================
|
|
335
|
+
# Example 5: Advanced - Multi-User Chat Application
|
|
336
|
+
# ============================================================================
|
|
337
|
+
# This example shows how to build a multi-user chat application
|
|
338
|
+
# with isolated sessions per user.
|
|
339
|
+
|
|
340
|
+
puts "\n\n=== Example 5: Multi-User Chat Application ==="
|
|
341
|
+
|
|
342
|
+
SmartPrompt.define_worker :multi_user_chat do
|
|
343
|
+
use "deepseek_anthropic"
|
|
344
|
+
model "deepseek-chat"
|
|
345
|
+
|
|
346
|
+
# Use user ID as session ID for isolation
|
|
347
|
+
user_id = params[:user_id] || raise("user_id is required")
|
|
348
|
+
session_id = "user_#{user_id}"
|
|
349
|
+
|
|
350
|
+
# Configure per-user session
|
|
351
|
+
session_config = {
|
|
352
|
+
max_messages: 50,
|
|
353
|
+
max_tokens: 3000,
|
|
354
|
+
context_strategy: :sliding_window,
|
|
355
|
+
preserve_system_messages: true,
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
user_name = params[:user_name] || "User"
|
|
359
|
+
sys_msg("You are a personal AI assistant for #{user_name}.")
|
|
360
|
+
prompt(params[:message], with_history: true, session_id: session_id)
|
|
361
|
+
|
|
362
|
+
@engine.history_manager.get_session(session_id, session_config)
|
|
363
|
+
|
|
364
|
+
send_msg
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
puts "\nSimulating multi-user chat..."
|
|
368
|
+
|
|
369
|
+
# User 1
|
|
370
|
+
response1 = engine.call_worker(:multi_user_chat, {
|
|
371
|
+
user_id: "001",
|
|
372
|
+
user_name: "Alice",
|
|
373
|
+
message: "Hi! I'm working on a Ruby project.",
|
|
374
|
+
})
|
|
375
|
+
puts "Alice: #{response1[0..60]}..."
|
|
376
|
+
|
|
377
|
+
# User 2
|
|
378
|
+
response2 = engine.call_worker(:multi_user_chat, {
|
|
379
|
+
user_id: "002",
|
|
380
|
+
user_name: "Bob",
|
|
381
|
+
message: "Hello! I need help with Python.",
|
|
382
|
+
})
|
|
383
|
+
puts "Bob: #{response2[0..60]}..."
|
|
384
|
+
|
|
385
|
+
# User 1 continues (should remember Ruby context)
|
|
386
|
+
response3 = engine.call_worker(:multi_user_chat, {
|
|
387
|
+
user_id: "001",
|
|
388
|
+
user_name: "Alice",
|
|
389
|
+
message: "What language was I asking about?",
|
|
390
|
+
})
|
|
391
|
+
puts "Alice (follow-up): #{response3[0..60]}..."
|
|
392
|
+
|
|
393
|
+
# ============================================================================
|
|
394
|
+
# Example 6: Monitoring and Debugging
|
|
395
|
+
# ============================================================================
|
|
396
|
+
# This example demonstrates how to monitor and debug the history system.
|
|
397
|
+
|
|
398
|
+
puts "\n\n=== Example 6: Monitoring and Debugging ==="
|
|
399
|
+
|
|
400
|
+
engine = SmartPrompt::Engine.new
|
|
401
|
+
|
|
402
|
+
# Get system-wide statistics
|
|
403
|
+
puts "\n--- System-Wide Statistics ---"
|
|
404
|
+
system_stats = engine.history_manager.get_stats
|
|
405
|
+
puts "Active Sessions: #{system_stats[:active_sessions]}"
|
|
406
|
+
puts "Total Messages: #{system_stats[:total_messages]}"
|
|
407
|
+
puts "Total Tokens: #{system_stats[:total_tokens]}"
|
|
408
|
+
puts "Cache Hit Rate: #{(system_stats[:cache_hit_rate] * 100).round(2)}%"
|
|
409
|
+
puts "Messages Added: #{system_stats[:messages_added]}"
|
|
410
|
+
puts "Context Retrievals: #{system_stats[:context_retrievals]}"
|
|
411
|
+
|
|
412
|
+
# Export metrics in Prometheus format
|
|
413
|
+
puts "\n--- Prometheus Metrics ---"
|
|
414
|
+
prometheus_metrics = engine.history_manager.export_metrics(format: :prometheus)
|
|
415
|
+
puts prometheus_metrics.lines.first(10).join
|
|
416
|
+
|
|
417
|
+
# List all active sessions
|
|
418
|
+
puts "\n--- Active Sessions ---"
|
|
419
|
+
session_ids = engine.history_manager.session_ids
|
|
420
|
+
puts "Total active sessions: #{session_ids.count}"
|
|
421
|
+
session_ids.first(5).each do |sid|
|
|
422
|
+
puts " - #{sid}"
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
# ============================================================================
|
|
426
|
+
# Example 7: Custom Configuration
|
|
427
|
+
# ============================================================================
|
|
428
|
+
# This example shows how to fine-tune session configuration for specific use cases.
|
|
429
|
+
|
|
430
|
+
puts "\n\n=== Example 7: Custom Configuration ==="
|
|
431
|
+
|
|
432
|
+
SmartPrompt.define_worker :custom_config_chat do
|
|
433
|
+
use "deepseek_anthropic"
|
|
434
|
+
model "deepseek-chat"
|
|
435
|
+
|
|
436
|
+
session_id = params[:session_id] || "custom_session"
|
|
437
|
+
|
|
438
|
+
# Fine-tuned configuration for a code review assistant
|
|
439
|
+
session_config = {
|
|
440
|
+
max_messages: 100,
|
|
441
|
+
max_tokens: 8000,
|
|
442
|
+
context_strategy: :relevance_based,
|
|
443
|
+
preserve_system_messages: true,
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
sys_msg("You are an expert code reviewer. Analyze code and provide constructive feedback.")
|
|
447
|
+
prompt(params[:message], with_history: true, session_id: session_id)
|
|
448
|
+
|
|
449
|
+
@engine.history_manager.get_session(session_id, session_config)
|
|
450
|
+
|
|
451
|
+
send_msg
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
puts "\nCode review assistant with custom configuration..."
|
|
455
|
+
response = SmartPrompt.run_worker(:custom_config_chat, {
|
|
456
|
+
session_id: "code_review_001",
|
|
457
|
+
message: "Please review this Ruby code: def hello; puts 'world'; end",
|
|
458
|
+
})
|
|
459
|
+
puts "Review: #{response[0..100]}..."
|
|
460
|
+
|
|
461
|
+
# ============================================================================
|
|
462
|
+
# Example 8: Session Lifecycle Management
|
|
463
|
+
# ============================================================================
|
|
464
|
+
# This example demonstrates the complete lifecycle of a session.
|
|
465
|
+
|
|
466
|
+
puts "\n\n=== Example 8: Session Lifecycle Management ==="
|
|
467
|
+
|
|
468
|
+
engine = SmartPrompt::Engine.new
|
|
469
|
+
lifecycle_session_id = "lifecycle_demo"
|
|
470
|
+
|
|
471
|
+
# 1. Create session (implicitly through add_message)
|
|
472
|
+
puts "\n1. Creating session..."
|
|
473
|
+
engine.history_manager.add_message(lifecycle_session_id, {
|
|
474
|
+
role: "system",
|
|
475
|
+
content: "You are a helpful assistant.",
|
|
476
|
+
})
|
|
477
|
+
puts " Session created: #{engine.history_manager.session_exists?(lifecycle_session_id)}"
|
|
478
|
+
|
|
479
|
+
# 2. Add messages
|
|
480
|
+
puts "\n2. Adding messages..."
|
|
481
|
+
3.times do |i|
|
|
482
|
+
engine.history_manager.add_message(lifecycle_session_id, {
|
|
483
|
+
role: "user",
|
|
484
|
+
content: "Message #{i + 1}",
|
|
485
|
+
})
|
|
486
|
+
end
|
|
487
|
+
stats = engine.history_manager.get_stats(lifecycle_session_id)
|
|
488
|
+
puts " Messages in session: #{stats[:message_count]}"
|
|
489
|
+
|
|
490
|
+
# 3. Retrieve context
|
|
491
|
+
puts "\n3. Retrieving context..."
|
|
492
|
+
context = engine.history_manager.get_context(lifecycle_session_id)
|
|
493
|
+
puts " Retrieved #{context.count} messages"
|
|
494
|
+
|
|
495
|
+
# 4. Export for backup
|
|
496
|
+
puts "\n4. Exporting session..."
|
|
497
|
+
backup = engine.history_manager.export_session(lifecycle_session_id, format: :json)
|
|
498
|
+
puts " Exported #{backup.length} bytes"
|
|
499
|
+
|
|
500
|
+
# 5. Clear session
|
|
501
|
+
puts "\n5. Clearing session..."
|
|
502
|
+
engine.history_manager.clear_session(lifecycle_session_id)
|
|
503
|
+
stats = engine.history_manager.get_stats(lifecycle_session_id)
|
|
504
|
+
puts " Messages after clear: #{stats[:message_count]}"
|
|
505
|
+
|
|
506
|
+
# 6. Delete session
|
|
507
|
+
puts "\n6. Deleting session..."
|
|
508
|
+
engine.history_manager.delete_session(lifecycle_session_id)
|
|
509
|
+
puts " Session exists: #{engine.history_manager.session_exists?(lifecycle_session_id)}"
|
|
510
|
+
|
|
511
|
+
puts "\n\n=== All Examples Completed ==="
|
|
512
|
+
puts "These examples demonstrate the key features of the new history management system:"
|
|
513
|
+
puts " ✓ Explicit session management with unique IDs"
|
|
514
|
+
puts " ✓ Multiple context strategies (sliding window, relevance, summary, hybrid)"
|
|
515
|
+
puts " ✓ Session operations (clear, export, search, stats, delete)"
|
|
516
|
+
puts " ✓ Backward compatibility with existing API"
|
|
517
|
+
puts " ✓ Multi-user applications with session isolation"
|
|
518
|
+
puts " ✓ Monitoring and debugging capabilities"
|
|
519
|
+
puts " ✓ Custom configuration for specific use cases"
|
|
520
|
+
puts " ✓ Complete session lifecycle management"
|
|
521
|
+
|
|
522
|
+
=end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Image Generation Example for SmartPrompt
|
|
2
|
+
#
|
|
3
|
+
# Demonstrates calling SiliconFlow's image generation API
|
|
4
|
+
# (POST /v1/images/generations) through the ImageGenerationAdapter.
|
|
5
|
+
#
|
|
6
|
+
# Requires a valid SiliconFlow API key in the SILICONFLOW_API_KEY (or APIKey)
|
|
7
|
+
# environment variable.
|
|
8
|
+
|
|
9
|
+
require_relative "../lib/smart_prompt"
|
|
10
|
+
|
|
11
|
+
api_key = ENV["SILICONFLOW_API_KEY"] || ENV["APIKey"]
|
|
12
|
+
|
|
13
|
+
# Configuration for image generation capabilities.
|
|
14
|
+
config = {
|
|
15
|
+
"adapters" => {
|
|
16
|
+
"image_generation" => "ImageGenerationAdapter",
|
|
17
|
+
},
|
|
18
|
+
"llms" => {
|
|
19
|
+
"image_gen" => {
|
|
20
|
+
"adapter" => "image_generation",
|
|
21
|
+
"url" => "https://api.siliconflow.cn/v1/",
|
|
22
|
+
"api_key" => api_key,
|
|
23
|
+
# Kolors supports batch_size, guidance_scale and a range of image_size values.
|
|
24
|
+
"model" => "Kwai-Kolors/Kolors",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
"default_llm" => "image_gen",
|
|
28
|
+
"template_path" => "./templates",
|
|
29
|
+
"worker_path" => "./workers",
|
|
30
|
+
"logger_file" => "./logs/smart_prompt.log",
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
# Write config to file
|
|
34
|
+
File.write("image_generation_config.yml", config.to_yaml)
|
|
35
|
+
|
|
36
|
+
# Initialize engine
|
|
37
|
+
engine = SmartPrompt::Engine.new("image_generation_config.yml")
|
|
38
|
+
|
|
39
|
+
puts "=== SmartPrompt Image Generation Demo ==="
|
|
40
|
+
|
|
41
|
+
unless api_key
|
|
42
|
+
puts "Note: SILICONFLOW_API_KEY is not set — the API calls below will fail at the network layer."
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Example 1: Simple text-to-image generation (Kolors)
|
|
46
|
+
puts "\n=== Example 1: Text-to-Image Generation ==="
|
|
47
|
+
begin
|
|
48
|
+
result = engine.call_worker(:image_generator, {
|
|
49
|
+
prompt: "A beautiful sunset over a mountain lake with pine trees, digital art style",
|
|
50
|
+
image_size: "1024x1024",
|
|
51
|
+
batch_size: 1,
|
|
52
|
+
save_to_file: true,
|
|
53
|
+
output_dir: "./generated_images",
|
|
54
|
+
filename_prefix: "sunset",
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
puts "Image generation successful!"
|
|
58
|
+
puts "Generated images: #{result[:images].size}"
|
|
59
|
+
puts "First image URL: #{result[:images].first[:url]}"
|
|
60
|
+
puts "Saved files: #{result[:saved_files]}"
|
|
61
|
+
rescue => e
|
|
62
|
+
puts "Error in image generation: #{e.message}"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Example 2: Art generation with a specific style (more inference steps)
|
|
66
|
+
puts "\n=== Example 2: Artistic Image Generation ==="
|
|
67
|
+
begin
|
|
68
|
+
result = engine.call_worker(:art_generator, {
|
|
69
|
+
prompt: "A mystical forest with glowing mushrooms and fairies",
|
|
70
|
+
art_style: "fantasy art, detailed painting",
|
|
71
|
+
image_size: "960x1280",
|
|
72
|
+
num_inference_steps: 30,
|
|
73
|
+
guidance_scale: 7.5,
|
|
74
|
+
save_to_file: true,
|
|
75
|
+
output_dir: "./generated_images",
|
|
76
|
+
filename_prefix: "fantasy_forest",
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
puts "Art generation successful!"
|
|
80
|
+
puts "Generated art images: #{result[:images].size}"
|
|
81
|
+
puts "Saved files: #{result[:saved_files]}"
|
|
82
|
+
rescue => e
|
|
83
|
+
puts "Error in art generation: #{e.message}"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Example 3: Product image generation (with a negative prompt)
|
|
87
|
+
puts "\n=== Example 3: Product Image Generation ==="
|
|
88
|
+
begin
|
|
89
|
+
result = engine.call_worker(:product_image_generator, {
|
|
90
|
+
prompt: "A modern smartphone on a marble surface",
|
|
91
|
+
image_size: "1024x1024",
|
|
92
|
+
negative_prompt: "text, watermark, logo",
|
|
93
|
+
save_to_file: true,
|
|
94
|
+
output_dir: "./generated_images",
|
|
95
|
+
filename_prefix: "smartphone",
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
puts "Product image generation successful!"
|
|
99
|
+
puts "Generated product images: #{result[:images].size}"
|
|
100
|
+
puts "Saved files: #{result[:saved_files]}"
|
|
101
|
+
rescue => e
|
|
102
|
+
puts "Error in product image generation: #{e.message}"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Example 4: Direct adapter usage (without a worker)
|
|
106
|
+
puts "\n=== Example 4: Direct Adapter Usage ==="
|
|
107
|
+
begin
|
|
108
|
+
adapter = engine.llms["image_gen"]
|
|
109
|
+
|
|
110
|
+
images = adapter.generate_image(
|
|
111
|
+
"A cute robot reading a book in a cozy library",
|
|
112
|
+
image_size: "1024x1024",
|
|
113
|
+
seed: 42,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
puts "Direct adapter usage successful!"
|
|
117
|
+
puts "Generated #{images.size} image(s)"
|
|
118
|
+
puts "First image URL: #{images.first[:url]}"
|
|
119
|
+
|
|
120
|
+
# Optionally save to disk
|
|
121
|
+
saved = adapter.save_image(images, "./generated_images", "robot")
|
|
122
|
+
puts "Saved files: #{saved}"
|
|
123
|
+
rescue => e
|
|
124
|
+
puts "Error in direct adapter usage: #{e.message}"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
puts "\n=== All examples completed ==="
|
|
128
|
+
|
|
129
|
+
# Clean up
|
|
130
|
+
File.delete("image_generation_config.yml") if File.exist?("image_generation_config.yml")
|