smart_prompt 0.4.4 → 0.5.1

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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/README.cn.md +305 -11
  4. data/README.md +309 -11
  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/docs/ANTHROPIC_EXAMPLES.md +559 -0
  12. data/docs/CONVERSATION_INTEGRATION_SUMMARY.md +155 -0
  13. data/docs/HISTORY_EXAMPLES_README.md +533 -0
  14. data/docs/HISTORY_MANAGEMENT_GUIDE.md +797 -0
  15. data/docs/MONITORING_GUIDE.md +278 -0
  16. data/docs/MULTIMODAL_README.md +265 -0
  17. data/docs/RELEVANCE_BASED_STRATEGY_IMPLEMENTATION.md +124 -0
  18. data/docs/STT_README.md +302 -0
  19. data/docs/TTS_README.md +303 -0
  20. data/docs/VIDEO_GENERATION_README.md +246 -0
  21. data/docs/delete_files_list.md +124 -0
  22. data/examples/anthropic_basic_chat.rb +143 -0
  23. data/examples/anthropic_example.rb +232 -0
  24. data/examples/anthropic_multimodal.rb +212 -0
  25. data/examples/anthropic_streaming.rb +312 -0
  26. data/examples/anthropic_tool_calling.rb +393 -0
  27. data/examples/automatic_cleanup_example.rb +109 -0
  28. data/examples/history_management_examples.rb +522 -0
  29. data/examples/image_generation_example.rb +130 -0
  30. data/examples/monitoring_example.rb +121 -0
  31. data/examples/multimodal_example.rb +63 -0
  32. data/examples/relevance_based_strategy_example.rb +87 -0
  33. data/examples/sensenova_example.rb +129 -0
  34. data/examples/stt_example.rb +287 -0
  35. data/examples/tts_example.rb +244 -0
  36. data/examples/video_generation_example.rb +189 -0
  37. data/examples/zhipu_example.rb +151 -0
  38. data/lib/smart_prompt/anthropic_adapter.rb +407 -298
  39. data/lib/smart_prompt/compression_engine.rb +201 -0
  40. data/lib/smart_prompt/context_strategy.rb +22 -0
  41. data/lib/smart_prompt/conversation.rb +47 -4
  42. data/lib/smart_prompt/engine.rb +29 -2
  43. data/lib/smart_prompt/history_manager.rb +596 -0
  44. data/lib/smart_prompt/hybrid_strategy.rb +222 -0
  45. data/lib/smart_prompt/image_generation_adapter.rb +297 -0
  46. data/lib/smart_prompt/lru_cache.rb +133 -0
  47. data/lib/smart_prompt/message.rb +57 -0
  48. data/lib/smart_prompt/multimodal_adapter.rb +277 -0
  49. data/lib/smart_prompt/persistence_layer.rb +197 -0
  50. data/lib/smart_prompt/relevance_based_strategy.rb +221 -0
  51. data/lib/smart_prompt/sensenova_adapter.rb +410 -0
  52. data/lib/smart_prompt/session.rb +140 -0
  53. data/lib/smart_prompt/sliding_window_strategy.rb +100 -0
  54. data/lib/smart_prompt/stt_adapter.rb +381 -0
  55. data/lib/smart_prompt/summary_based_strategy.rb +152 -0
  56. data/lib/smart_prompt/token_counter.rb +74 -0
  57. data/lib/smart_prompt/tts_adapter.rb +403 -0
  58. data/lib/smart_prompt/version.rb +1 -1
  59. data/lib/smart_prompt/video_generation_adapter.rb +330 -0
  60. data/lib/smart_prompt/worker.rb +28 -3
  61. data/lib/smart_prompt/zhipu_adapter.rb +616 -0
  62. data/lib/smart_prompt.rb +21 -0
  63. data/workers/history_management_examples.rb +407 -0
  64. data/workers/image_generation_workers.rb +119 -0
  65. data/workers/multimodal_workers.rb +110 -0
  66. data/workers/sensenova_workers.rb +62 -0
  67. data/workers/stt_workers.rb +195 -0
  68. data/workers/tts_workers.rb +388 -0
  69. data/workers/video_generation_workers.rb +264 -0
  70. data/workers/zhipu_workers.rb +113 -0
  71. metadata +88 -1
@@ -0,0 +1,232 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "./lib/smart_prompt"
5
+
6
+ # Example: Using Anthropic Claude with SmartPrompt
7
+ # This example demonstrates various features of the AnthropicAdapter
8
+
9
+ # Initialize the engine with Anthropic configuration
10
+ engine = SmartPrompt::Engine.new("config/anthropic_config.yml")
11
+
12
+ puts "=" * 60
13
+ puts "Anthropic Claude Examples with SmartPrompt"
14
+ puts "=" * 60
15
+
16
+ =begin
17
+ # Example 1: Basic Chat
18
+ puts "\n1. Basic Chat Example"
19
+ puts "-" * 60
20
+
21
+ SmartPrompt.define_worker :basic_chat do
22
+ use "deepseek_anthropic"
23
+ model "deepseek-chat"
24
+ sys_msg("You are a helpful AI assistant.")
25
+ prompt(params[:message])
26
+ send_msg
27
+ end
28
+
29
+ response = engine.call_worker(:basic_chat, {
30
+ message: "What is the capital of France?",
31
+ })
32
+ puts "User: What is the capital of France?"
33
+ puts "DeepSeek: #{response}"
34
+
35
+ # Example 2: Multi-turn Conversation
36
+ puts "\n2. Multi-turn Conversation Example"
37
+ puts "-" * 60
38
+
39
+ SmartPrompt.define_worker :conversation do
40
+ use "deepseek_anthropic"
41
+ model "deepseek-chat"
42
+ sys_msg("You are a knowledgeable history teacher.")
43
+ prompt(params[:message], with_history: true)
44
+ send_msg
45
+ end
46
+
47
+ response1 = engine.call_worker(:conversation, {
48
+ message: "Who was the first president of the United States?",
49
+ with_history: true,
50
+ })
51
+ puts "User: Who was the first president of the United States?"
52
+ puts "Claude: #{response1}"
53
+
54
+ response2 = engine.call_worker(:conversation, {
55
+ message: "What were his major accomplishments?",
56
+ with_history: true,
57
+ })
58
+ puts "\nUser: What were his major accomplishments?"
59
+ puts "Claude: #{response2}"
60
+
61
+ # Example 3: Code Generation
62
+ puts "\n3. Code Generation Example"
63
+ puts "-" * 60
64
+
65
+ SmartPrompt.define_worker :code_generator do
66
+ use "deepseek_anthropic"
67
+ model "deepseek-chat"
68
+ sys_msg("You are an expert programmer. Generate clean, well-documented code.")
69
+ prompt("Write a Ruby function that #{params[:task]}")
70
+ send_msg
71
+ end
72
+
73
+ code = engine.call_worker(:code_generator, {
74
+ task: "calculates the factorial of a number using recursion",
75
+ })
76
+ puts "Task: Write a Ruby function that calculates the factorial of a number using recursion"
77
+ puts "Generated Code:\n#{code}"
78
+
79
+ # Example 4: Streaming Response
80
+ puts "\n4. Streaming Response Example"
81
+ puts "-" * 60
82
+
83
+ SmartPrompt.define_worker :streaming_chat do
84
+ use "deepseek_anthropic"
85
+ model "deepseek-chat"
86
+ sys_msg("You are a storyteller.")
87
+ prompt(params[:message])
88
+ send_msg
89
+ end
90
+
91
+ print "User: Tell me a short story about a brave knight.\n"
92
+ print "Claude (streaming): "
93
+
94
+ engine.call_worker_by_stream(:streaming_chat, {
95
+ message: "Tell me a short story about a brave knight.",
96
+ }) do |chunk, bytesize|
97
+ # Handle Anthropic streaming format
98
+ if chunk.is_a?(Hash)
99
+ if chunk["type"] == "content_block_delta"
100
+ text = chunk.dig("delta", "text")
101
+ print text if text
102
+ end
103
+ end
104
+ end
105
+
106
+ puts "\n"
107
+ =end
108
+
109
+ # Example 7: Tool Calling (Function Calling)
110
+ puts "\n7. Tool Calling Example"
111
+ puts "-" * 60
112
+
113
+ # Define tools
114
+ weather_tools = [
115
+ {
116
+ type: "function",
117
+ function: {
118
+ name: "get_weather",
119
+ description: "Get the current weather for a location",
120
+ parameters: {
121
+ type: "object",
122
+ properties: {
123
+ location: {
124
+ type: "string",
125
+ description: "The city and state, e.g. San Francisco, CA",
126
+ },
127
+ unit: {
128
+ type: "string",
129
+ enum: ["celsius", "fahrenheit"],
130
+ description: "The temperature unit",
131
+ },
132
+ },
133
+ required: ["location"],
134
+ },
135
+ },
136
+ },
137
+ ]
138
+
139
+ SmartPrompt.define_worker :weather_assistant do
140
+ use "deepseek_anthropic"
141
+ model "deepseek-chat"
142
+ sys_msg("You are a helpful weather assistant. Use the get_weather tool when users ask about weather.")
143
+ prompt(params[:message])
144
+ send_msg
145
+ end
146
+
147
+ response = engine.call_worker(:weather_assistant, {
148
+ message: "What's the weather like in Tokyo?",
149
+ tools: weather_tools,
150
+ })
151
+ puts "User: What's the weather like in Tokyo?"
152
+ puts "Claude: #{response}"
153
+
154
+ =begin
155
+
156
+ # Example 8: Image Analysis (Multimodal)
157
+ puts "\n8. Image Analysis Example (Multimodal)"
158
+ puts "-" * 60
159
+
160
+ SmartPrompt.define_worker :image_analyzer do
161
+ use "claude"
162
+ sys_msg("You are an expert at analyzing images and describing what you see.")
163
+ prompt(params[:message])
164
+ send_msg
165
+ end
166
+
167
+ # Using a public image URL
168
+ image_url = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg"
169
+
170
+ response = engine.call_worker(:image_analyzer, {
171
+ message: [
172
+ { type: "text", text: "What do you see in this image? Describe it in detail." },
173
+ { type: "image_url", image_url: image_url }
174
+ ]
175
+ })
176
+ puts "User: [Sends image of a cat]"
177
+ puts "Claude: #{response}"
178
+
179
+ # Example 9: Different Models Comparison
180
+ puts "\n9. Different Models Comparison"
181
+ puts "-" * 60
182
+
183
+ question = "Explain quantum entanglement in simple terms."
184
+
185
+ # Using Claude 3.5 Sonnet
186
+ SmartPrompt.define_worker :sonnet_chat do
187
+ use "claude"
188
+ model "claude-3-5-sonnet-20241022"
189
+ prompt(params[:message])
190
+ send_msg
191
+ end
192
+
193
+ sonnet_response = engine.call_worker(:sonnet_chat, { message: question })
194
+ puts "Question: #{question}"
195
+ puts "\nClaude 3.5 Sonnet Response:"
196
+ puts sonnet_response[0..200] + "..."
197
+
198
+ # Using Claude 3.5 Haiku (faster)
199
+ SmartPrompt.define_worker :haiku_chat do
200
+ use "claude_haiku"
201
+ model "claude-3-5-haiku-20241022"
202
+ prompt(params[:message])
203
+ send_msg
204
+ end
205
+
206
+ haiku_response = engine.call_worker(:haiku_chat, { message: question })
207
+ puts "\nClaude 3.5 Haiku Response:"
208
+ puts haiku_response[0..200] + "..."
209
+
210
+ # Example 10: Error Handling
211
+ puts "\n10. Error Handling Example"
212
+ puts "-" * 60
213
+
214
+ begin
215
+ # Try to use a non-existent model
216
+ SmartPrompt.define_worker :error_test do
217
+ use "claude"
218
+ model "non-existent-model"
219
+ prompt(params[:message])
220
+ send_msg
221
+ end
222
+
223
+ engine.call_worker(:error_test, { message: "Hello" })
224
+ rescue SmartPrompt::LLMAPIError => e
225
+ puts "Caught API Error: #{e.message}"
226
+ puts "Error handling works correctly!"
227
+ end
228
+
229
+ puts "\n" + "=" * 60
230
+ puts "All examples completed!"
231
+ puts "=" * 60
232
+ =end
@@ -0,0 +1,212 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require './lib/smart_prompt'
5
+ require 'base64'
6
+
7
+ # Example: Multimodal (Text + Image) with Anthropic Claude
8
+ # This example demonstrates how to use Claude's vision capabilities
9
+
10
+ puts "=" * 60
11
+ puts "Anthropic Claude - Multimodal (Vision) Example"
12
+ puts "=" * 60
13
+
14
+ # Initialize the engine with Anthropic configuration
15
+ engine = SmartPrompt::Engine.new('config/anthropic_config.yml')
16
+
17
+ # Example 1: Analyze Image from URL
18
+ puts "\n1. Analyze Image from URL"
19
+ puts "-" * 60
20
+
21
+ SmartPrompt.define_worker :image_analyzer do
22
+ use "claude"
23
+ sys_msg("You are an expert at analyzing images and describing what you see in detail.")
24
+ prompt(params[:message])
25
+ send_msg
26
+ end
27
+
28
+ # Using a public image URL
29
+ image_url = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/400px-Cat03.jpg"
30
+
31
+ response = engine.call_worker(:image_analyzer, {
32
+ message: [
33
+ { type: "text", text: "What do you see in this image? Describe it in detail." },
34
+ { type: "image_url", image_url: image_url }
35
+ ]
36
+ })
37
+ puts "User: [Sends image URL: #{image_url}]"
38
+ puts "User: What do you see in this image? Describe it in detail."
39
+ puts "\nClaude: #{response}\n"
40
+
41
+ # Example 2: Analyze Local Image using Base64
42
+ puts "\n2. Analyze Local Image (Base64 Encoding)"
43
+ puts "-" * 60
44
+
45
+ # Check if local image exists
46
+ local_image_path = "./product_images/smartphone_1.png"
47
+
48
+ if File.exist?(local_image_path)
49
+ # Read and encode image to base64
50
+ image_data = File.binread(local_image_path)
51
+ base64_image = Base64.strict_encode64(image_data)
52
+
53
+ # Determine media type
54
+ media_type = case File.extname(local_image_path).downcase
55
+ when '.jpg', '.jpeg' then 'image/jpeg'
56
+ when '.png' then 'image/png'
57
+ when '.gif' then 'image/gif'
58
+ when '.webp' then 'image/webp'
59
+ else 'image/jpeg'
60
+ end
61
+
62
+ data_url = "data:#{media_type};base64,#{base64_image}"
63
+
64
+ response = engine.call_worker(:image_analyzer, {
65
+ message: [
66
+ { type: "text", text: "Describe this product image. What features can you identify?" },
67
+ { type: "image_url", image_url: data_url }
68
+ ]
69
+ })
70
+ puts "User: [Sends local image: #{local_image_path}]"
71
+ puts "User: Describe this product image. What features can you identify?"
72
+ puts "\nClaude: #{response}\n"
73
+ else
74
+ puts "Local image not found at #{local_image_path}"
75
+ puts "Skipping base64 example.\n"
76
+ end
77
+
78
+ # Example 3: Multiple Images Analysis
79
+ puts "\n3. Compare Multiple Images"
80
+ puts "-" * 60
81
+
82
+ SmartPrompt.define_worker :image_comparator do
83
+ use "claude"
84
+ sys_msg("You are an expert at comparing and contrasting images.")
85
+ prompt(params[:message])
86
+ send_msg
87
+ end
88
+
89
+ image1_url = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/400px-Cat03.jpg"
90
+ image2_url = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4d/Cat_November_2010-1a.jpg/400px-Cat_November_2010-1a.jpg"
91
+
92
+ response = engine.call_worker(:image_comparator, {
93
+ message: [
94
+ { type: "text", text: "Compare these two images. What are the similarities and differences?" },
95
+ { type: "image_url", image_url: image1_url },
96
+ { type: "image_url", image_url: image2_url }
97
+ ]
98
+ })
99
+ puts "User: [Sends two cat images]"
100
+ puts "User: Compare these two images. What are the similarities and differences?"
101
+ puts "\nClaude: #{response}\n"
102
+
103
+ # Example 4: Image + Text Context
104
+ puts "\n4. Image Analysis with Additional Context"
105
+ puts "-" * 60
106
+
107
+ SmartPrompt.define_worker :contextual_analyzer do
108
+ use "claude"
109
+ sys_msg("You are a product analyst helping with e-commerce listings.")
110
+ prompt(params[:message])
111
+ send_msg
112
+ end
113
+
114
+ product_image = "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c4/Smartphone.jpg/400px-Smartphone.jpg"
115
+
116
+ response = engine.call_worker(:contextual_analyzer, {
117
+ message: [
118
+ { type: "text", text: "This is a product image for our online store. Please:" },
119
+ { type: "text", text: "1. Describe the product" },
120
+ { type: "text", text: "2. Suggest a catchy product title" },
121
+ { type: "text", text: "3. Write a brief product description (2-3 sentences)" },
122
+ { type: "text", text: "4. List 3-5 key features" },
123
+ { type: "image_url", image_url: product_image }
124
+ ]
125
+ })
126
+ puts "User: [Sends product image with detailed instructions]"
127
+ puts "\nClaude: #{response}\n"
128
+
129
+ # Example 5: OCR and Text Extraction
130
+ puts "\n5. Text Extraction from Image (OCR)"
131
+ puts "-" * 60
132
+
133
+ SmartPrompt.define_worker :ocr_extractor do
134
+ use "claude"
135
+ sys_msg("You are an expert at reading and extracting text from images.")
136
+ prompt(params[:message])
137
+ send_msg
138
+ end
139
+
140
+ # Using an image with text (e.g., a sign or document)
141
+ text_image_url = "https://upload.wikimedia.org/wikipedia/commons/thumb/8/87/PDF_file_icon.svg/400px-PDF_file_icon.svg.png"
142
+
143
+ response = engine.call_worker(:ocr_extractor, {
144
+ message: [
145
+ { type: "text", text: "Extract and transcribe any text you see in this image." },
146
+ { type: "image_url", image_url: text_image_url }
147
+ ]
148
+ })
149
+ puts "User: [Sends image with text]"
150
+ puts "User: Extract and transcribe any text you see in this image."
151
+ puts "\nClaude: #{response}\n"
152
+
153
+ # Example 6: Image Classification
154
+ puts "\n6. Image Classification and Categorization"
155
+ puts "-" * 60
156
+
157
+ SmartPrompt.define_worker :image_classifier do
158
+ use "claude"
159
+ sys_msg("You are an expert at categorizing and classifying images.")
160
+ prompt(params[:message])
161
+ send_msg
162
+ end
163
+
164
+ classify_image = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/400px-Cat03.jpg"
165
+
166
+ response = engine.call_worker(:image_classifier, {
167
+ message: [
168
+ { type: "text", text: "Classify this image into categories. Provide:\n1. Main category\n2. Sub-categories\n3. Tags/keywords\n4. Suitable use cases" },
169
+ { type: "image_url", image_url: classify_image }
170
+ ]
171
+ })
172
+ puts "User: [Sends image for classification]"
173
+ puts "\nClaude: #{response}\n"
174
+
175
+ # Example 7: Image-based Question Answering
176
+ puts "\n7. Question Answering about Image Content"
177
+ puts "-" * 60
178
+
179
+ SmartPrompt.define_worker :image_qa do
180
+ use "claude"
181
+ sys_msg("You are helpful at answering questions about images.")
182
+ prompt(params[:message])
183
+ send_msg
184
+ end
185
+
186
+ qa_image = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/400px-Cat03.jpg"
187
+
188
+ questions = [
189
+ "What color is the animal?",
190
+ "What is the animal doing?",
191
+ "What is the setting or environment?"
192
+ ]
193
+
194
+ questions.each_with_index do |question, index|
195
+ response = engine.call_worker(:image_qa, {
196
+ message: [
197
+ { type: "image_url", image_url: qa_image },
198
+ { type: "text", text: question }
199
+ ]
200
+ })
201
+ puts "Q#{index + 1}: #{question}"
202
+ puts "A#{index + 1}: #{response}\n"
203
+ end
204
+
205
+ puts "\n" + "=" * 60
206
+ puts "Multimodal examples completed!"
207
+ puts "=" * 60
208
+ puts "\nNote: Claude's vision capabilities work best with:"
209
+ puts "- Clear, well-lit images"
210
+ puts "- Images in JPEG, PNG, GIF, or WebP format"
211
+ puts "- Images up to 5MB in size"
212
+ puts "- Both URLs and base64-encoded images"