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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -10
  3. data/README.cn.md +307 -64
  4. data/README.md +311 -64
  5. data/Rakefile +10 -1
  6. data/config/anthropic_config.yml +151 -0
  7. data/config/image_generation_config.yml +22 -0
  8. data/config/multimodal_config.yml +85 -0
  9. data/config/sensenova_config.yml +63 -0
  10. data/config/zhipu_config.yml +73 -0
  11. data/examples/anthropic_basic_chat.rb +143 -0
  12. data/examples/anthropic_example.rb +232 -0
  13. data/examples/anthropic_multimodal.rb +212 -0
  14. data/examples/anthropic_streaming.rb +312 -0
  15. data/examples/anthropic_tool_calling.rb +393 -0
  16. data/examples/automatic_cleanup_example.rb +109 -0
  17. data/examples/history_management_examples.rb +522 -0
  18. data/examples/image_generation_example.rb +130 -0
  19. data/examples/monitoring_example.rb +121 -0
  20. data/examples/multimodal_example.rb +63 -0
  21. data/examples/relevance_based_strategy_example.rb +87 -0
  22. data/examples/sensenova_example.rb +129 -0
  23. data/examples/stt_example.rb +287 -0
  24. data/examples/tts_example.rb +244 -0
  25. data/examples/video_generation_example.rb +189 -0
  26. data/examples/zhipu_example.rb +151 -0
  27. data/lib/smart_prompt/anthropic_adapter.rb +363 -281
  28. data/lib/smart_prompt/compression_engine.rb +201 -0
  29. data/lib/smart_prompt/context_strategy.rb +22 -0
  30. data/lib/smart_prompt/conversation.rb +81 -191
  31. data/lib/smart_prompt/engine.rb +36 -19
  32. data/lib/smart_prompt/history_manager.rb +596 -0
  33. data/lib/smart_prompt/hybrid_strategy.rb +222 -0
  34. data/lib/smart_prompt/image_generation_adapter.rb +297 -0
  35. data/lib/smart_prompt/lru_cache.rb +133 -0
  36. data/lib/smart_prompt/message.rb +57 -0
  37. data/lib/smart_prompt/multimodal_adapter.rb +277 -0
  38. data/lib/smart_prompt/openai_adapter.rb +1 -25
  39. data/lib/smart_prompt/persistence_layer.rb +197 -0
  40. data/lib/smart_prompt/relevance_based_strategy.rb +221 -0
  41. data/lib/smart_prompt/sensenova_adapter.rb +410 -0
  42. data/lib/smart_prompt/session.rb +140 -0
  43. data/lib/smart_prompt/sliding_window_strategy.rb +100 -0
  44. data/lib/smart_prompt/stt_adapter.rb +381 -0
  45. data/lib/smart_prompt/summary_based_strategy.rb +152 -0
  46. data/lib/smart_prompt/token_counter.rb +74 -0
  47. data/lib/smart_prompt/tts_adapter.rb +403 -0
  48. data/lib/smart_prompt/version.rb +1 -1
  49. data/lib/smart_prompt/video_generation_adapter.rb +330 -0
  50. data/lib/smart_prompt/worker.rb +25 -3
  51. data/lib/smart_prompt/zhipu_adapter.rb +616 -0
  52. data/lib/smart_prompt.rb +22 -2
  53. data/workers/history_management_examples.rb +407 -0
  54. data/workers/image_generation_workers.rb +119 -0
  55. data/workers/multimodal_workers.rb +110 -0
  56. data/workers/sensenova_workers.rb +62 -0
  57. data/workers/stt_workers.rb +195 -0
  58. data/workers/tts_workers.rb +388 -0
  59. data/workers/video_generation_workers.rb +264 -0
  60. data/workers/zhipu_workers.rb +113 -0
  61. 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