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,407 @@
|
|
|
1
|
+
# History Management Example Workers
|
|
2
|
+
# These examples demonstrate the new intelligent history management features
|
|
3
|
+
# introduced in the history-optimization feature.
|
|
4
|
+
#
|
|
5
|
+
# Key Features Demonstrated:
|
|
6
|
+
# 1. Explicit session management with unique session IDs
|
|
7
|
+
# 2. Different context strategies (sliding window, relevance-based, summary-based, hybrid)
|
|
8
|
+
# 3. Session operations (clear, export, search, stats, delete)
|
|
9
|
+
# 4. Backward compatibility with existing API
|
|
10
|
+
#
|
|
11
|
+
# Requirements Validated: 5.5
|
|
12
|
+
|
|
13
|
+
# ============================================================================
|
|
14
|
+
# Example 1: Explicit Session Management
|
|
15
|
+
# ============================================================================
|
|
16
|
+
# Demonstrates: Requirement 1 (Session Isolation), Requirement 5.2 (Default Sessions)
|
|
17
|
+
|
|
18
|
+
# Simple chat worker with automatic session management
|
|
19
|
+
# When with_history: true is used without a session_id, a default session is created
|
|
20
|
+
SmartPrompt.define_worker :basic_chat do
|
|
21
|
+
use "deepseek_anthropic"
|
|
22
|
+
model "deepseek-chat"
|
|
23
|
+
|
|
24
|
+
sys_msg("You are a helpful AI assistant.", params)
|
|
25
|
+
prompt(params[:message], with_history: true)
|
|
26
|
+
send_msg
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Chat worker with explicit session management
|
|
30
|
+
# Use session_id to maintain separate conversations
|
|
31
|
+
# Each session maintains isolated history (Requirement 1.1-1.4)
|
|
32
|
+
SmartPrompt.define_worker :explicit_session_chat do
|
|
33
|
+
use "deepseek_anthropic"
|
|
34
|
+
model "deepseek-chat"
|
|
35
|
+
|
|
36
|
+
# Session ID can be user ID, conversation ID, or any unique identifier
|
|
37
|
+
session_id = params[:session_id] || "default_session"
|
|
38
|
+
|
|
39
|
+
sys_msg("You are a helpful AI assistant.", params)
|
|
40
|
+
prompt(params[:message], with_history: true, session_id: session_id)
|
|
41
|
+
send_msg
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Multi-user chat with isolated sessions per user
|
|
45
|
+
# Demonstrates: Session isolation for concurrent users
|
|
46
|
+
SmartPrompt.define_worker :multi_user_chat do
|
|
47
|
+
use "deepseek_anthropic"
|
|
48
|
+
model "deepseek-chat"
|
|
49
|
+
|
|
50
|
+
# Use user ID as session ID for isolation
|
|
51
|
+
user_id = params[:user_id] || raise("user_id is required")
|
|
52
|
+
session_id = "user_#{user_id}"
|
|
53
|
+
|
|
54
|
+
# Configure per-user session with limits (Requirement 2.1-2.2)
|
|
55
|
+
session_config = {
|
|
56
|
+
max_messages: 50,
|
|
57
|
+
max_tokens: 3000,
|
|
58
|
+
context_strategy: :sliding_window,
|
|
59
|
+
preserve_system_messages: true
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
user_name = params[:user_name] || "User"
|
|
63
|
+
sys_msg("You are a personal AI assistant for #{user_name}.", params)
|
|
64
|
+
prompt(params[:message], with_history: true, session_id: session_id)
|
|
65
|
+
|
|
66
|
+
# Apply session configuration
|
|
67
|
+
@engine.history_manager.get_session(session_id, session_config)
|
|
68
|
+
|
|
69
|
+
send_msg
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# ============================================================================
|
|
73
|
+
# Example 2: Different Context Strategies
|
|
74
|
+
# ============================================================================
|
|
75
|
+
# Demonstrates: Requirement 6.1 (Context Strategy Configuration),
|
|
76
|
+
# Requirement 8.2 (Multiple Strategy Support)
|
|
77
|
+
|
|
78
|
+
# 2.1 Sliding Window Strategy
|
|
79
|
+
# Keeps most recent N messages - Best for: Real-time chat, customer support
|
|
80
|
+
SmartPrompt.define_worker :sliding_window_chat do
|
|
81
|
+
use "deepseek_anthropic"
|
|
82
|
+
model "deepseek-chat"
|
|
83
|
+
|
|
84
|
+
session_id = params[:session_id] || "sliding_window_session"
|
|
85
|
+
|
|
86
|
+
# Configure session with sliding window strategy (Requirement 8.2)
|
|
87
|
+
session_config = {
|
|
88
|
+
max_messages: 20,
|
|
89
|
+
max_tokens: 2000,
|
|
90
|
+
context_strategy: :sliding_window,
|
|
91
|
+
preserve_system_messages: true # Requirement 2.5
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
sys_msg("You are a helpful customer support assistant.", params)
|
|
95
|
+
prompt(params[:message], with_history: true, session_id: session_id)
|
|
96
|
+
|
|
97
|
+
# Apply session configuration
|
|
98
|
+
@engine.history_manager.get_session(session_id, session_config)
|
|
99
|
+
|
|
100
|
+
send_msg
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# 2.2 Relevance-Based Strategy
|
|
104
|
+
# Selects semantically relevant messages - Best for: Q&A systems, knowledge bases
|
|
105
|
+
SmartPrompt.define_worker :relevance_chat do
|
|
106
|
+
use "deepseek_anthropic"
|
|
107
|
+
model "deepseek-chat"
|
|
108
|
+
|
|
109
|
+
session_id = params[:session_id] || "relevance_session"
|
|
110
|
+
|
|
111
|
+
# Configure session with relevance-based strategy (Requirement 8.1, 8.3)
|
|
112
|
+
session_config = {
|
|
113
|
+
max_messages: 100,
|
|
114
|
+
max_tokens: 4000,
|
|
115
|
+
context_strategy: :relevance_based,
|
|
116
|
+
preserve_system_messages: true
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
sys_msg("You are a knowledgeable AI assistant that provides accurate answers.", params)
|
|
120
|
+
prompt(params[:message], with_history: true, session_id: session_id)
|
|
121
|
+
|
|
122
|
+
@engine.history_manager.get_session(session_id, session_config)
|
|
123
|
+
|
|
124
|
+
send_msg
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# 2.3 Summary-Based Strategy
|
|
128
|
+
# Automatically compresses old messages - Best for: Long conversations, extended dialogues
|
|
129
|
+
SmartPrompt.define_worker :summary_chat do
|
|
130
|
+
use "deepseek_anthropic"
|
|
131
|
+
model "deepseek-chat"
|
|
132
|
+
|
|
133
|
+
session_id = params[:session_id] || "summary_session"
|
|
134
|
+
|
|
135
|
+
# Configure session with summary-based strategy (Requirement 9.1-9.3)
|
|
136
|
+
session_config = {
|
|
137
|
+
max_messages: 200,
|
|
138
|
+
max_tokens: 8000,
|
|
139
|
+
context_strategy: :summary_based,
|
|
140
|
+
preserve_system_messages: true
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
sys_msg("You are a thoughtful AI assistant for extended conversations.", params)
|
|
144
|
+
prompt(params[:message], with_history: true, session_id: session_id)
|
|
145
|
+
|
|
146
|
+
@engine.history_manager.get_session(session_id, session_config)
|
|
147
|
+
|
|
148
|
+
send_msg
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# 2.4 Hybrid Strategy
|
|
152
|
+
# Adaptively combines multiple strategies - Best for: General-purpose applications
|
|
153
|
+
SmartPrompt.define_worker :hybrid_chat do
|
|
154
|
+
use "deepseek_anthropic"
|
|
155
|
+
model "deepseek-chat"
|
|
156
|
+
|
|
157
|
+
session_id = params[:session_id] || "hybrid_session"
|
|
158
|
+
|
|
159
|
+
# Configure session with hybrid strategy (Requirement 6.1)
|
|
160
|
+
session_config = {
|
|
161
|
+
max_messages: 150,
|
|
162
|
+
max_tokens: 6000,
|
|
163
|
+
context_strategy: :hybrid,
|
|
164
|
+
preserve_system_messages: true
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
sys_msg("You are an intelligent AI assistant that adapts to conversation context.", params)
|
|
168
|
+
prompt(params[:message], with_history: true, session_id: session_id)
|
|
169
|
+
|
|
170
|
+
@engine.history_manager.get_session(session_id, session_config)
|
|
171
|
+
|
|
172
|
+
send_msg
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# ============================================================================
|
|
176
|
+
# Example 3: Session Operations (clear, export, search, stats, delete)
|
|
177
|
+
# ============================================================================
|
|
178
|
+
# Demonstrates: Requirement 4 (Session Management Operations)
|
|
179
|
+
|
|
180
|
+
# Worker demonstrating all session management operations
|
|
181
|
+
SmartPrompt.define_worker :session_operations do
|
|
182
|
+
use "deepseek_anthropic"
|
|
183
|
+
model "deepseek-chat"
|
|
184
|
+
|
|
185
|
+
session_id = params[:session_id] || "default_session"
|
|
186
|
+
operation = params[:operation] # :clear, :export, :search, :stats, :delete
|
|
187
|
+
|
|
188
|
+
case operation
|
|
189
|
+
when :clear
|
|
190
|
+
# Clear session history (keeps system messages by default) - Requirement 4.1
|
|
191
|
+
@engine.history_manager.clear_session(session_id, keep_system_messages: true)
|
|
192
|
+
"Session cleared successfully"
|
|
193
|
+
|
|
194
|
+
when :export
|
|
195
|
+
# Export session data in structured format - Requirement 4.2
|
|
196
|
+
@engine.history_manager.export_session(session_id, format: :json)
|
|
197
|
+
|
|
198
|
+
when :search
|
|
199
|
+
# Search for messages containing specific text - Requirement 4.3
|
|
200
|
+
query = params[:query]
|
|
201
|
+
results = @engine.history_manager.search_messages(session_id, query)
|
|
202
|
+
"Found #{results.count} messages matching '#{query}'"
|
|
203
|
+
|
|
204
|
+
when :stats
|
|
205
|
+
# Get session statistics (message count, token usage) - Requirement 4.4
|
|
206
|
+
@engine.history_manager.get_stats(session_id)
|
|
207
|
+
|
|
208
|
+
when :delete
|
|
209
|
+
# Delete session completely (memory and disk) - Requirement 4.5
|
|
210
|
+
@engine.history_manager.delete_session(session_id)
|
|
211
|
+
"Session deleted successfully"
|
|
212
|
+
|
|
213
|
+
else
|
|
214
|
+
"Unknown operation: #{operation}"
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# Example: Get system-wide statistics
|
|
219
|
+
SmartPrompt.define_worker :system_stats do
|
|
220
|
+
use "deepseek_anthropic"
|
|
221
|
+
model "deepseek-chat"
|
|
222
|
+
|
|
223
|
+
# Get system-wide statistics - Requirement 11.3
|
|
224
|
+
stats = @engine.history_manager.get_stats
|
|
225
|
+
|
|
226
|
+
{
|
|
227
|
+
active_sessions: stats[:active_sessions],
|
|
228
|
+
total_messages: stats[:total_messages],
|
|
229
|
+
total_tokens: stats[:total_tokens],
|
|
230
|
+
cache_hit_rate: stats[:cache_hit_rate],
|
|
231
|
+
messages_added: stats[:messages_added],
|
|
232
|
+
context_retrievals: stats[:context_retrievals]
|
|
233
|
+
}
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# Example: Export metrics in Prometheus format
|
|
237
|
+
SmartPrompt.define_worker :export_metrics do
|
|
238
|
+
use "deepseek_anthropic"
|
|
239
|
+
model "deepseek-chat"
|
|
240
|
+
|
|
241
|
+
# Export metrics in Prometheus format - Requirement 11.5
|
|
242
|
+
@engine.history_manager.export_metrics(format: :prometheus)
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# ============================================================================
|
|
246
|
+
# Example 4: Backward Compatibility
|
|
247
|
+
# ============================================================================
|
|
248
|
+
# Demonstrates: Requirement 5 (Backward Compatibility)
|
|
249
|
+
|
|
250
|
+
# Old-style worker definition (still works!) - Requirement 5.1, 5.4
|
|
251
|
+
SmartPrompt.define_worker :legacy_chat do
|
|
252
|
+
use "deepseek_anthropic"
|
|
253
|
+
model "deepseek-chat"
|
|
254
|
+
|
|
255
|
+
sys_msg("You are a helpful AI assistant.", params)
|
|
256
|
+
|
|
257
|
+
# Old-style history usage - still works!
|
|
258
|
+
# Automatically creates a default session - Requirement 5.2
|
|
259
|
+
prompt(params[:message], with_history: true)
|
|
260
|
+
|
|
261
|
+
send_msg(with_history: true)
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# Worker showing compatibility mode - Requirement 5.3
|
|
265
|
+
SmartPrompt.define_worker :compatibility_chat do
|
|
266
|
+
use "deepseek_anthropic"
|
|
267
|
+
model "deepseek-chat"
|
|
268
|
+
|
|
269
|
+
sys_msg("You are a helpful AI assistant.", params)
|
|
270
|
+
|
|
271
|
+
# Works with both old and new API
|
|
272
|
+
if params[:session_id]
|
|
273
|
+
# New API: explicit session management
|
|
274
|
+
prompt(params[:message], with_history: true, session_id: params[:session_id])
|
|
275
|
+
else
|
|
276
|
+
# Old API: automatic default session
|
|
277
|
+
prompt(params[:message], with_history: true)
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
send_msg
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
# ============================================================================
|
|
284
|
+
# Example 5: Advanced Use Cases
|
|
285
|
+
# ============================================================================
|
|
286
|
+
|
|
287
|
+
# Streaming with history management
|
|
288
|
+
SmartPrompt.define_worker :streaming_history_chat do
|
|
289
|
+
use "deepseek_anthropic"
|
|
290
|
+
model "deepseek-chat"
|
|
291
|
+
|
|
292
|
+
session_id = params[:session_id] || "streaming_session"
|
|
293
|
+
|
|
294
|
+
sys_msg("You are a helpful AI assistant.", params)
|
|
295
|
+
prompt(params[:message], with_history: true, session_id: session_id)
|
|
296
|
+
|
|
297
|
+
# Use send_msg_by_stream for streaming responses
|
|
298
|
+
# History is still maintained automatically
|
|
299
|
+
send_msg_by_stream(params)
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
# Custom configuration for specific use cases
|
|
303
|
+
SmartPrompt.define_worker :custom_config_chat do
|
|
304
|
+
use "deepseek_anthropic"
|
|
305
|
+
model "deepseek-chat"
|
|
306
|
+
|
|
307
|
+
session_id = params[:session_id] || "custom_session"
|
|
308
|
+
|
|
309
|
+
# Fine-tuned configuration for a code review assistant
|
|
310
|
+
session_config = {
|
|
311
|
+
max_messages: 100,
|
|
312
|
+
max_tokens: 8000,
|
|
313
|
+
context_strategy: :relevance_based,
|
|
314
|
+
preserve_system_messages: true
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
sys_msg("You are an expert code reviewer. Analyze code and provide constructive feedback.", params)
|
|
318
|
+
prompt(params[:message], with_history: true, session_id: session_id)
|
|
319
|
+
|
|
320
|
+
@engine.history_manager.get_session(session_id, session_config)
|
|
321
|
+
|
|
322
|
+
send_msg
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
# Persistence example - sessions are automatically saved to disk (Requirement 3.1-3.3)
|
|
326
|
+
SmartPrompt.define_worker :persistent_chat do
|
|
327
|
+
use "deepseek_anthropic"
|
|
328
|
+
model "deepseek-chat"
|
|
329
|
+
|
|
330
|
+
session_id = params[:session_id] || "persistent_session"
|
|
331
|
+
|
|
332
|
+
# Sessions are automatically persisted to disk
|
|
333
|
+
# They will be restored on next access
|
|
334
|
+
sys_msg("You are a helpful AI assistant. Your conversations are saved.", params)
|
|
335
|
+
prompt(params[:message], with_history: true, session_id: session_id)
|
|
336
|
+
|
|
337
|
+
send_msg
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
# ============================================================================
|
|
341
|
+
# Usage Examples
|
|
342
|
+
# ============================================================================
|
|
343
|
+
#
|
|
344
|
+
# Example 1: Basic usage with automatic session
|
|
345
|
+
# SmartPrompt.run_worker(:basic_chat, { message: "Hello!" })
|
|
346
|
+
#
|
|
347
|
+
# Example 2: Explicit session management
|
|
348
|
+
# SmartPrompt.run_worker(:explicit_session_chat, {
|
|
349
|
+
# session_id: "user_123",
|
|
350
|
+
# message: "Hello!"
|
|
351
|
+
# })
|
|
352
|
+
#
|
|
353
|
+
# Example 3: Multi-user chat
|
|
354
|
+
# SmartPrompt.run_worker(:multi_user_chat, {
|
|
355
|
+
# user_id: "001",
|
|
356
|
+
# user_name: "Alice",
|
|
357
|
+
# message: "Hi!"
|
|
358
|
+
# })
|
|
359
|
+
#
|
|
360
|
+
# Example 4: Using different strategies
|
|
361
|
+
# SmartPrompt.run_worker(:sliding_window_chat, { message: "Hello!" })
|
|
362
|
+
# SmartPrompt.run_worker(:relevance_chat, { message: "Hello!" })
|
|
363
|
+
# SmartPrompt.run_worker(:summary_chat, { message: "Hello!" })
|
|
364
|
+
# SmartPrompt.run_worker(:hybrid_chat, { message: "Hello!" })
|
|
365
|
+
#
|
|
366
|
+
# Example 5: Session operations
|
|
367
|
+
# # Get statistics
|
|
368
|
+
# SmartPrompt.run_worker(:session_operations, {
|
|
369
|
+
# session_id: "user_123",
|
|
370
|
+
# operation: :stats
|
|
371
|
+
# })
|
|
372
|
+
#
|
|
373
|
+
# # Search messages
|
|
374
|
+
# SmartPrompt.run_worker(:session_operations, {
|
|
375
|
+
# session_id: "user_123",
|
|
376
|
+
# operation: :search,
|
|
377
|
+
# query: "Ruby"
|
|
378
|
+
# })
|
|
379
|
+
#
|
|
380
|
+
# # Export session
|
|
381
|
+
# SmartPrompt.run_worker(:session_operations, {
|
|
382
|
+
# session_id: "user_123",
|
|
383
|
+
# operation: :export
|
|
384
|
+
# })
|
|
385
|
+
#
|
|
386
|
+
# # Clear session
|
|
387
|
+
# SmartPrompt.run_worker(:session_operations, {
|
|
388
|
+
# session_id: "user_123",
|
|
389
|
+
# operation: :clear
|
|
390
|
+
# })
|
|
391
|
+
#
|
|
392
|
+
# # Delete session
|
|
393
|
+
# SmartPrompt.run_worker(:session_operations, {
|
|
394
|
+
# session_id: "user_123",
|
|
395
|
+
# operation: :delete
|
|
396
|
+
# })
|
|
397
|
+
#
|
|
398
|
+
# Example 6: System-wide statistics
|
|
399
|
+
# SmartPrompt.run_worker(:system_stats, {})
|
|
400
|
+
#
|
|
401
|
+
# Example 7: Export Prometheus metrics
|
|
402
|
+
# SmartPrompt.run_worker(:export_metrics, {})
|
|
403
|
+
#
|
|
404
|
+
# Example 8: Backward compatibility (old API)
|
|
405
|
+
# SmartPrompt.run_worker(:legacy_chat, { message: "Hello!" })
|
|
406
|
+
#
|
|
407
|
+
# ============================================================================
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Image Generation Workers for SmartPrompt
|
|
2
|
+
#
|
|
3
|
+
# These workers wrap the SiliconFlow image generation API exposed by
|
|
4
|
+
# ImageGenerationAdapter (POST /v1/images/generations). All of them expect an
|
|
5
|
+
# `image_gen` LLM to be configured in the engine, e.g.:
|
|
6
|
+
#
|
|
7
|
+
# image_gen:
|
|
8
|
+
# adapter: "image_generation"
|
|
9
|
+
# url: "https://api.siliconflow.cn/v1/"
|
|
10
|
+
# api_key: ENV["SILICONFLOW_API_KEY"]
|
|
11
|
+
# model: "Kwai-Kolors/Kolors"
|
|
12
|
+
|
|
13
|
+
# Text-to-image generation worker.
|
|
14
|
+
#
|
|
15
|
+
# Recognized params:
|
|
16
|
+
# prompt:, model:, negative_prompt:,
|
|
17
|
+
# image_size: (alias size:), batch_size: (alias n:),
|
|
18
|
+
# seed:, num_inference_steps:, guidance_scale:, cfg:,
|
|
19
|
+
# save_to_file:, output_dir:, filename_prefix:
|
|
20
|
+
SmartPrompt.define_worker :image_generator do
|
|
21
|
+
use "image_gen"
|
|
22
|
+
|
|
23
|
+
images = generate_image(params[:prompt], {
|
|
24
|
+
model: params[:model],
|
|
25
|
+
negative_prompt: params[:negative_prompt],
|
|
26
|
+
image_size: params[:image_size] || params[:size],
|
|
27
|
+
batch_size: params[:batch_size] || params[:n],
|
|
28
|
+
seed: params[:seed],
|
|
29
|
+
num_inference_steps: params[:num_inference_steps],
|
|
30
|
+
guidance_scale: params[:guidance_scale],
|
|
31
|
+
cfg: params[:cfg],
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
if params[:save_to_file]
|
|
35
|
+
saved_files = save_image(images, params[:output_dir] || "./generated_images", params[:filename_prefix] || "generated")
|
|
36
|
+
{ images: images, saved_files: saved_files }
|
|
37
|
+
else
|
|
38
|
+
images
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Image editing / image-to-image worker (for Qwen/Qwen-Image-Edit-* and similar).
|
|
43
|
+
#
|
|
44
|
+
# Recognized params:
|
|
45
|
+
# prompt:, model:, image: (alias image_file:), image2:, image3:,
|
|
46
|
+
# negative_prompt:, seed:, cfg:,
|
|
47
|
+
# save_to_file:, output_dir:, filename_prefix:
|
|
48
|
+
SmartPrompt.define_worker :image_editor do
|
|
49
|
+
use "image_gen"
|
|
50
|
+
|
|
51
|
+
images = edit_image(params[:prompt], {
|
|
52
|
+
model: params[:model],
|
|
53
|
+
image: params[:image] || params[:image_file],
|
|
54
|
+
image2: params[:image2],
|
|
55
|
+
image3: params[:image3],
|
|
56
|
+
negative_prompt: params[:negative_prompt],
|
|
57
|
+
seed: params[:seed],
|
|
58
|
+
cfg: params[:cfg],
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
if params[:save_to_file]
|
|
62
|
+
saved_files = save_image(images, params[:output_dir] || "./edited_images", params[:filename_prefix] || "edited")
|
|
63
|
+
{ images: images, saved_files: saved_files }
|
|
64
|
+
else
|
|
65
|
+
images
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Creative art generation worker. Appends the requested art style to the prompt
|
|
70
|
+
# before generating.
|
|
71
|
+
SmartPrompt.define_worker :art_generator do
|
|
72
|
+
use "image_gen"
|
|
73
|
+
|
|
74
|
+
prompt = params[:prompt] || "A beautiful artistic creation"
|
|
75
|
+
prompt = "#{prompt}, in the style of #{params[:art_style]}" if params[:art_style]
|
|
76
|
+
|
|
77
|
+
images = generate_image(prompt, {
|
|
78
|
+
model: params[:model],
|
|
79
|
+
negative_prompt: params[:negative_prompt],
|
|
80
|
+
image_size: params[:image_size] || params[:size],
|
|
81
|
+
batch_size: params[:batch_size] || params[:n],
|
|
82
|
+
seed: params[:seed],
|
|
83
|
+
num_inference_steps: params[:num_inference_steps],
|
|
84
|
+
guidance_scale: params[:guidance_scale],
|
|
85
|
+
cfg: params[:cfg],
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
if params[:save_to_file]
|
|
89
|
+
saved_files = save_image(images, params[:output_dir] || "./art_images", params[:filename_prefix] || "art")
|
|
90
|
+
{ images: images, saved_files: saved_files }
|
|
91
|
+
else
|
|
92
|
+
images
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Product photography worker. Enhances the prompt with studio-photo wording.
|
|
97
|
+
SmartPrompt.define_worker :product_image_generator do
|
|
98
|
+
use "image_gen"
|
|
99
|
+
|
|
100
|
+
prompt = "Professional product photography, studio lighting, clean background, high detail, #{params[:prompt]}"
|
|
101
|
+
|
|
102
|
+
images = generate_image(prompt, {
|
|
103
|
+
model: params[:model],
|
|
104
|
+
negative_prompt: params[:negative_prompt] || "blurry, low quality, distorted",
|
|
105
|
+
image_size: params[:image_size] || params[:size],
|
|
106
|
+
batch_size: params[:batch_size] || params[:n],
|
|
107
|
+
seed: params[:seed],
|
|
108
|
+
num_inference_steps: params[:num_inference_steps],
|
|
109
|
+
guidance_scale: params[:guidance_scale],
|
|
110
|
+
cfg: params[:cfg],
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
if params[:save_to_file]
|
|
114
|
+
saved_files = save_image(images, params[:output_dir] || "./product_images", params[:filename_prefix] || "product")
|
|
115
|
+
{ images: images, saved_files: saved_files }
|
|
116
|
+
else
|
|
117
|
+
images
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Multimodal Workers for SmartPrompt
|
|
2
|
+
# These workers demonstrate the new multimodal capabilities
|
|
3
|
+
|
|
4
|
+
# Image analysis worker
|
|
5
|
+
SmartPrompt.define_worker :image_analyzer do
|
|
6
|
+
use "qwen_vl"
|
|
7
|
+
model "Qwen/Qwen2.5-VL-7B-Instruct"
|
|
8
|
+
|
|
9
|
+
messages = [
|
|
10
|
+
{
|
|
11
|
+
role: "user",
|
|
12
|
+
content: [
|
|
13
|
+
{ type: "text", text: params[:question] },
|
|
14
|
+
{ type: "image_url", image_url: { url: params[:image_url], detail: params[:detail] || "auto" } }
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
sys_msg("你是一个专业的图像分析助手,能够准确描述和分析图像内容。", params)
|
|
20
|
+
params.merge(messages: messages)
|
|
21
|
+
send_msg
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Video analysis worker
|
|
25
|
+
SmartPrompt.define_worker :video_analyzer do
|
|
26
|
+
use "qwen_vl"
|
|
27
|
+
model "Qwen/Qwen2.5-VL-7B-Instruct"
|
|
28
|
+
|
|
29
|
+
messages = [
|
|
30
|
+
{
|
|
31
|
+
role: "user",
|
|
32
|
+
content: [
|
|
33
|
+
{ type: "text", text: params[:question] },
|
|
34
|
+
{
|
|
35
|
+
type: "video_url",
|
|
36
|
+
video_url: {
|
|
37
|
+
url: params[:video_url],
|
|
38
|
+
detail: params[:detail] || "auto",
|
|
39
|
+
max_frames: params[:max_frames] || 10,
|
|
40
|
+
fps: params[:fps] || 1
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
sys_msg("你是一个专业的视频分析助手,能够准确描述和分析视频内容。", params)
|
|
48
|
+
params.merge(messages: messages)
|
|
49
|
+
send_msg
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Multiple images comparison worker
|
|
53
|
+
SmartPrompt.define_worker :multi_image_analyzer do
|
|
54
|
+
use "qwen_vl"
|
|
55
|
+
model "Qwen/Qwen2.5-VL-7B-Instruct"
|
|
56
|
+
|
|
57
|
+
content = [{ type: "text", text: params[:question] }]
|
|
58
|
+
params[:image_urls].each do |image_url|
|
|
59
|
+
content << {
|
|
60
|
+
type: "image_url",
|
|
61
|
+
image_url: { url: image_url, detail: params[:detail] || "auto" }
|
|
62
|
+
}
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
messages = [{ role: "user", content: content }]
|
|
66
|
+
|
|
67
|
+
sys_msg("你是一个专业的图像比较助手,能够准确比较和分析多张图像的相似之处和不同之处。", params)
|
|
68
|
+
params.merge(messages: messages)
|
|
69
|
+
send_msg
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Document analysis worker (for images containing text)
|
|
73
|
+
SmartPrompt.define_worker :document_analyzer do
|
|
74
|
+
use "qwen_vl"
|
|
75
|
+
model "Qwen/Qwen2.5-VL-7B-Instruct"
|
|
76
|
+
|
|
77
|
+
messages = [
|
|
78
|
+
{
|
|
79
|
+
role: "user",
|
|
80
|
+
content: [
|
|
81
|
+
{ type: "text", text: params[:question] || "请提取并分析这张图片中的文字内容" },
|
|
82
|
+
{ type: "image_url", image_url: { url: params[:image_url], detail: "high" } }
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
sys_msg("你是一个专业的文档分析助手,能够准确提取和分析图像中的文字内容。", params)
|
|
88
|
+
params.merge(messages: messages)
|
|
89
|
+
send_msg
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Scene description worker
|
|
93
|
+
SmartPrompt.define_worker :scene_describer do
|
|
94
|
+
use "qwen_vl"
|
|
95
|
+
model "Qwen/Qwen2.5-VL-7B-Instruct"
|
|
96
|
+
|
|
97
|
+
messages = [
|
|
98
|
+
{
|
|
99
|
+
role: "user",
|
|
100
|
+
content: [
|
|
101
|
+
{ type: "text", text: "请详细描述这个场景,包括环境、人物、动作和情感氛围" },
|
|
102
|
+
{ type: "image_url", image_url: { url: params[:image_url], detail: "high" } }
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
sys_msg("你是一个专业的场景描述助手,能够生动详细地描述图像中的场景。", params)
|
|
108
|
+
params.merge(messages: messages)
|
|
109
|
+
send_msg
|
|
110
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# SenseNova workers for SmartPrompt
|
|
2
|
+
#
|
|
3
|
+
# These workers exercise the four SenseNova model categories through the unified
|
|
4
|
+
# SenseNovaAdapter. Reuses the standard DSL: `use`, `model`, `sys_msg`, `prompt`,
|
|
5
|
+
# `send_msg`, plus the multimodal/embedding/image helpers on Conversation.
|
|
6
|
+
#
|
|
7
|
+
# Note: `send_msg` transparently becomes streaming when the engine invokes the worker
|
|
8
|
+
# via call_worker_by_stream — so :sensenova_chat serves both sync and stream callers.
|
|
9
|
+
|
|
10
|
+
# 1. 商量 文本对话 (chat). Works for both call_worker and call_worker_by_stream.
|
|
11
|
+
SmartPrompt.define_worker :sensenova_chat do
|
|
12
|
+
use "sensechat"
|
|
13
|
+
model params[:model] if params[:model]
|
|
14
|
+
sys_msg(params[:system] || "你是一个有帮助的中文助手,回答简洁准确。", params)
|
|
15
|
+
prompt(params[:prompt] || "你好,请介绍一下你自己。")
|
|
16
|
+
send_msg
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# 2. 商量 图文多模态 (vision). Accepts a single image_url or image_urls (array).
|
|
20
|
+
# The multimodal content array is added to the conversation directly so send_msg
|
|
21
|
+
# sends it (send_msg reads @messages, not params).
|
|
22
|
+
SmartPrompt.define_worker :sensenova_vision do
|
|
23
|
+
use "sensevision"
|
|
24
|
+
model params[:model] if params[:model]
|
|
25
|
+
sys_msg("你是一个专业的多模态图像分析助手,能够准确描述和分析图像内容。", params)
|
|
26
|
+
|
|
27
|
+
content = [{ type: "text", text: params[:question] || "请描述这张图片中的内容。" }]
|
|
28
|
+
images = params[:image_urls] || [params[:image_url]]
|
|
29
|
+
images.each do |url|
|
|
30
|
+
content << { type: "image_url", image_url: { url: url } }
|
|
31
|
+
end
|
|
32
|
+
add_message({ role: "user", content: content })
|
|
33
|
+
|
|
34
|
+
send_msg
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# 3. Cupido 向量模型 (embeddings). Returns a normalized numeric vector of the user text.
|
|
38
|
+
SmartPrompt.define_worker :sensenova_embed do
|
|
39
|
+
use "senseembedding"
|
|
40
|
+
model params[:model] if params[:model]
|
|
41
|
+
prompt(params[:text] || "商汤科技日日新大模型")
|
|
42
|
+
embeddings(params[:length] || 1024)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# 4. 秒画 文生图 (text-to-image). Returns the generated image(s); optionally saves to disk.
|
|
46
|
+
SmartPrompt.define_worker :sensenova_image do
|
|
47
|
+
use "senseimage"
|
|
48
|
+
model params[:model] if params[:model]
|
|
49
|
+
|
|
50
|
+
images = generate_image(params[:prompt], params)
|
|
51
|
+
|
|
52
|
+
if params[:save_to_file]
|
|
53
|
+
saved = save_image(
|
|
54
|
+
images,
|
|
55
|
+
params[:output_dir] || "./generated_images",
|
|
56
|
+
params[:filename_prefix] || "sensenova"
|
|
57
|
+
)
|
|
58
|
+
{ images: images, saved_files: saved }
|
|
59
|
+
else
|
|
60
|
+
images
|
|
61
|
+
end
|
|
62
|
+
end
|