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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/README.cn.md +305 -11
- data/README.md +309 -11
- 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/docs/ANTHROPIC_EXAMPLES.md +559 -0
- data/docs/CONVERSATION_INTEGRATION_SUMMARY.md +155 -0
- data/docs/HISTORY_EXAMPLES_README.md +533 -0
- data/docs/HISTORY_MANAGEMENT_GUIDE.md +797 -0
- data/docs/MONITORING_GUIDE.md +278 -0
- data/docs/MULTIMODAL_README.md +265 -0
- data/docs/RELEVANCE_BASED_STRATEGY_IMPLEMENTATION.md +124 -0
- data/docs/STT_README.md +302 -0
- data/docs/TTS_README.md +303 -0
- data/docs/VIDEO_GENERATION_README.md +246 -0
- data/docs/delete_files_list.md +124 -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 +407 -298
- data/lib/smart_prompt/compression_engine.rb +201 -0
- data/lib/smart_prompt/context_strategy.rb +22 -0
- data/lib/smart_prompt/conversation.rb +47 -4
- data/lib/smart_prompt/engine.rb +29 -2
- 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/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 +28 -3
- data/lib/smart_prompt/zhipu_adapter.rb +616 -0
- data/lib/smart_prompt.rb +21 -0
- 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 +88 -1
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# SenseNova (商汤 日日新) Configuration for SmartPrompt
|
|
2
|
+
#
|
|
3
|
+
# Get an API key from https://platform.sensenova.cn/console and export it as
|
|
4
|
+
# SENSENOVA_API_KEY. A single SenseNovaAdapter covers all four model categories —
|
|
5
|
+
# just point a different llm entry at each model.
|
|
6
|
+
#
|
|
7
|
+
# Two base hosts are in play (verified 2026-06-19):
|
|
8
|
+
# * token.sensenova.cn/v1 — the free-tier models (sensenova-6.7-flash-lite
|
|
9
|
+
# chat/vision, sensenova-u1-fast image). Works
|
|
10
|
+
# out-of-the-box with a free key.
|
|
11
|
+
# * api.sensenova.cn/compatible-mode/v2 — paid models (SenseChat-5, SenseNova-V6-Pro).
|
|
12
|
+
# Returns 403 if your key lacks that model.
|
|
13
|
+
# * api.sensenova.cn/v1/llm/embeddings — Cupido embeddings (native; paid).
|
|
14
|
+
#
|
|
15
|
+
# The image endpoint is NOT under compatible-mode (it 404s there) — it lives on
|
|
16
|
+
# token.sensenova.cn/v1/images/generations and only accepts specific sizes
|
|
17
|
+
# (see VALID_IMAGE_SIZES in sensenova_adapter.rb; default 2048x2048).
|
|
18
|
+
|
|
19
|
+
adapters:
|
|
20
|
+
sensenova: "SenseNovaAdapter"
|
|
21
|
+
|
|
22
|
+
llms:
|
|
23
|
+
# 1. 商量 文本对话 (free-tier; works with a free key)
|
|
24
|
+
sensechat:
|
|
25
|
+
adapter: "sensenova"
|
|
26
|
+
url: "https://token.sensenova.cn/v1"
|
|
27
|
+
api_key: ENV["SENSENOVA_API_KEY"]
|
|
28
|
+
model: "sensenova-6.7-flash-lite"
|
|
29
|
+
temperature: 0.7
|
|
30
|
+
# Optional SenseNova sampling extras (forwarded to /chat/completions):
|
|
31
|
+
# reasoning_effort: "medium"
|
|
32
|
+
# max_completion_tokens: 4096
|
|
33
|
+
# Paid alternative: url https://api.sensenova.cn/compatible-mode/v2, model SenseChat-5
|
|
34
|
+
|
|
35
|
+
# 2. 商量 图文多模态 (sensenova-6.7-flash-lite is natively multimodal)
|
|
36
|
+
sensevision:
|
|
37
|
+
adapter: "sensenova"
|
|
38
|
+
url: "https://token.sensenova.cn/v1"
|
|
39
|
+
api_key: ENV["SENSENOVA_API_KEY"]
|
|
40
|
+
model: "sensenova-6.7-flash-lite"
|
|
41
|
+
# Paid alternative: url https://api.sensenova.cn/compatible-mode/v2, model SenseNova-V6-Pro
|
|
42
|
+
|
|
43
|
+
# 3. Cupido 向量模型 (paid; native endpoint, non-OpenAI response shape)
|
|
44
|
+
senseembedding:
|
|
45
|
+
adapter: "sensenova"
|
|
46
|
+
url: "https://api.sensenova.cn/compatible-mode/v2"
|
|
47
|
+
embeddings_url: "https://api.sensenova.cn/v1/llm/embeddings"
|
|
48
|
+
api_key: ENV["SENSENOVA_API_KEY"]
|
|
49
|
+
model: "Cupido"
|
|
50
|
+
|
|
51
|
+
# 4. 秒画 文生图 (free-tier sensenova-u1-fast; native token.sensenova.cn base)
|
|
52
|
+
senseimage:
|
|
53
|
+
adapter: "sensenova"
|
|
54
|
+
url: "https://token.sensenova.cn/v1"
|
|
55
|
+
image_url: "https://token.sensenova.cn/v1/images/generations"
|
|
56
|
+
api_key: ENV["SENSENOVA_API_KEY"]
|
|
57
|
+
model: "sensenova-u1-fast"
|
|
58
|
+
|
|
59
|
+
default_llm: "sensechat"
|
|
60
|
+
|
|
61
|
+
template_path: "./templates"
|
|
62
|
+
worker_path: "./workers"
|
|
63
|
+
logger_file: "./logs/smart_prompt.log"
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# 智谱 AI (BigModel / GLM) Configuration for SmartPrompt
|
|
2
|
+
#
|
|
3
|
+
# Get an API key from https://open.bigmodel.cn/ and export it as ZHIPUAI_API_KEY.
|
|
4
|
+
# A single ZhipuAIAdapter covers all REST model categories — just point a different
|
|
5
|
+
# llm entry at each model. Defaults use the free-tier models so it runs out-of-box.
|
|
6
|
+
#
|
|
7
|
+
# Base URL: https://open.bigmodel.cn/api/paas/v4 (coding models: .../api/coding/paas/v4)
|
|
8
|
+
# Auth: Authorization: Bearer <API_KEY>
|
|
9
|
+
|
|
10
|
+
adapters:
|
|
11
|
+
zhipu: "ZhipuAIAdapter"
|
|
12
|
+
|
|
13
|
+
llms:
|
|
14
|
+
# 1. 文本对话 (free-tier glm-4-flash; paid: glm-4-plus / glm-4-long / glm-5.2)
|
|
15
|
+
glm:
|
|
16
|
+
adapter: "zhipu"
|
|
17
|
+
url: "https://open.bigmodel.cn/api/paas/v4"
|
|
18
|
+
api_key: ENV["ZHIPUAI_API_KEY"]
|
|
19
|
+
model: "glm-4-flash"
|
|
20
|
+
temperature: 0.7
|
|
21
|
+
# Optional sampling extras (forwarded to /chat/completions):
|
|
22
|
+
# top_p: 0.7
|
|
23
|
+
# max_tokens: 2048
|
|
24
|
+
# CodeGeeX-4: set `coding: true` (uses the coding base) and model: codegeex-4
|
|
25
|
+
|
|
26
|
+
# 2. 图文多模态 (free-tier glm-4v-flash; paid: glm-4v-plus)
|
|
27
|
+
glm_vision:
|
|
28
|
+
adapter: "zhipu"
|
|
29
|
+
url: "https://open.bigmodel.cn/api/paas/v4"
|
|
30
|
+
api_key: ENV["ZHIPUAI_API_KEY"]
|
|
31
|
+
model: "glm-4v-flash"
|
|
32
|
+
|
|
33
|
+
# 3. 向量模型 (embedding-3 supports custom dimensions: 256/512/1024/2048)
|
|
34
|
+
embedding:
|
|
35
|
+
adapter: "zhipu"
|
|
36
|
+
url: "https://open.bigmodel.cn/api/paas/v4"
|
|
37
|
+
api_key: ENV["ZHIPUAI_API_KEY"]
|
|
38
|
+
model: "embedding-3"
|
|
39
|
+
dimensions: 1024
|
|
40
|
+
|
|
41
|
+
# 4. 文生图 (free-tier cogview-3-flash; paid: cogview-4 / glm-image)
|
|
42
|
+
cogview:
|
|
43
|
+
adapter: "zhipu"
|
|
44
|
+
url: "https://open.bigmodel.cn/api/paas/v4"
|
|
45
|
+
api_key: ENV["ZHIPUAI_API_KEY"]
|
|
46
|
+
model: "cogview-3-flash"
|
|
47
|
+
|
|
48
|
+
# 5. 文生视频 (async: submit -> poll -> download; free-tier cogvideox-flash)
|
|
49
|
+
cogvideo:
|
|
50
|
+
adapter: "zhipu"
|
|
51
|
+
url: "https://open.bigmodel.cn/api/paas/v4"
|
|
52
|
+
api_key: ENV["ZHIPUAI_API_KEY"]
|
|
53
|
+
model: "cogvideox-flash"
|
|
54
|
+
|
|
55
|
+
# 6. 语音合成 (GLM-TTS)
|
|
56
|
+
glm_tts:
|
|
57
|
+
adapter: "zhipu"
|
|
58
|
+
url: "https://open.bigmodel.cn/api/paas/v4"
|
|
59
|
+
api_key: ENV["ZHIPUAI_API_KEY"]
|
|
60
|
+
model: "glm-tts"
|
|
61
|
+
|
|
62
|
+
# 7. 语音识别 (GLM-ASR-2512)
|
|
63
|
+
glm_asr:
|
|
64
|
+
adapter: "zhipu"
|
|
65
|
+
url: "https://open.bigmodel.cn/api/paas/v4"
|
|
66
|
+
api_key: ENV["ZHIPUAI_API_KEY"]
|
|
67
|
+
model: "glm-asr-2512"
|
|
68
|
+
|
|
69
|
+
default_llm: "glm"
|
|
70
|
+
|
|
71
|
+
template_path: "./templates"
|
|
72
|
+
worker_path: "./workers"
|
|
73
|
+
logger_file: "./logs/smart_prompt.log"
|
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
# Anthropic Claude Examples for SmartPrompt
|
|
2
|
+
|
|
3
|
+
This document provides comprehensive examples for using Anthropic's Claude models with SmartPrompt. Claude offers powerful capabilities including advanced reasoning, multimodal understanding (text + images), tool calling, and streaming responses.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
1. [Setup and Configuration](#setup-and-configuration)
|
|
8
|
+
2. [Basic Chat Examples](#basic-chat-examples)
|
|
9
|
+
3. [Multimodal Examples (Vision)](#multimodal-examples-vision)
|
|
10
|
+
4. [Tool Calling Examples](#tool-calling-examples)
|
|
11
|
+
5. [Streaming Response Examples](#streaming-response-examples)
|
|
12
|
+
6. [Advanced Usage](#advanced-usage)
|
|
13
|
+
7. [Best Practices](#best-practices)
|
|
14
|
+
|
|
15
|
+
## Setup and Configuration
|
|
16
|
+
|
|
17
|
+
### 1. Install Dependencies
|
|
18
|
+
|
|
19
|
+
Ensure you have the `anthropic` gem installed:
|
|
20
|
+
|
|
21
|
+
```ruby
|
|
22
|
+
gem 'anthropic', '~> 1.14'
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### 2. Set API Key
|
|
26
|
+
|
|
27
|
+
Set your Anthropic API key as an environment variable:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
export ANTHROPIC_API_KEY='your-api-key-here'
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 3. Configure SmartPrompt
|
|
34
|
+
|
|
35
|
+
Create or update `config/anthropic_config.yml`:
|
|
36
|
+
|
|
37
|
+
```yaml
|
|
38
|
+
adapters:
|
|
39
|
+
anthropic: "AnthropicAdapter"
|
|
40
|
+
|
|
41
|
+
llms:
|
|
42
|
+
claude:
|
|
43
|
+
adapter: "anthropic"
|
|
44
|
+
api_key: ENV["ANTHROPIC_API_KEY"]
|
|
45
|
+
model: "claude-3-5-sonnet-20241022"
|
|
46
|
+
temperature: 0.7
|
|
47
|
+
max_tokens: 4096
|
|
48
|
+
|
|
49
|
+
claude_haiku:
|
|
50
|
+
adapter: "anthropic"
|
|
51
|
+
api_key: ENV["ANTHROPIC_API_KEY"]
|
|
52
|
+
model: "claude-3-5-haiku-20241022"
|
|
53
|
+
temperature: 0.7
|
|
54
|
+
max_tokens: 4096
|
|
55
|
+
|
|
56
|
+
claude_opus:
|
|
57
|
+
adapter: "anthropic"
|
|
58
|
+
api_key: ENV["ANTHROPIC_API_KEY"]
|
|
59
|
+
model: "claude-3-opus-20240229"
|
|
60
|
+
temperature: 0.7
|
|
61
|
+
max_tokens: 4096
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Basic Chat Examples
|
|
65
|
+
|
|
66
|
+
### Simple Question-Answer
|
|
67
|
+
|
|
68
|
+
```ruby
|
|
69
|
+
require 'smart_prompt'
|
|
70
|
+
|
|
71
|
+
engine = SmartPrompt::Engine.new('config/anthropic_config.yml')
|
|
72
|
+
|
|
73
|
+
SmartPrompt.define_worker :simple_chat do
|
|
74
|
+
use "claude"
|
|
75
|
+
sys_msg("You are a helpful AI assistant.")
|
|
76
|
+
prompt(params[:message])
|
|
77
|
+
send_msg
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
response = engine.call_worker(:simple_chat, {
|
|
81
|
+
message: "What is the capital of France?"
|
|
82
|
+
})
|
|
83
|
+
puts response
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Run the example:**
|
|
87
|
+
```bash
|
|
88
|
+
ruby examples/anthropic_basic_chat.rb
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Multi-turn Conversation
|
|
92
|
+
|
|
93
|
+
```ruby
|
|
94
|
+
SmartPrompt.define_worker :conversation do
|
|
95
|
+
use "claude"
|
|
96
|
+
sys_msg("You are a knowledgeable history teacher.")
|
|
97
|
+
prompt(params[:message], with_history: true)
|
|
98
|
+
send_msg
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# First message
|
|
102
|
+
response1 = engine.call_worker(:conversation, {
|
|
103
|
+
message: "Who was the first president of the United States?"
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
# Follow-up message (maintains context)
|
|
107
|
+
response2 = engine.call_worker(:conversation, {
|
|
108
|
+
message: "What were his major accomplishments?"
|
|
109
|
+
})
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Using Different Models
|
|
113
|
+
|
|
114
|
+
```ruby
|
|
115
|
+
# Claude 3.5 Sonnet - Best balance of intelligence and speed
|
|
116
|
+
SmartPrompt.define_worker :sonnet_chat do
|
|
117
|
+
use "claude"
|
|
118
|
+
model "claude-3-5-sonnet-20241022"
|
|
119
|
+
prompt(params[:message])
|
|
120
|
+
send_msg
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Claude 3.5 Haiku - Fastest, most cost-effective
|
|
124
|
+
SmartPrompt.define_worker :haiku_chat do
|
|
125
|
+
use "claude_haiku"
|
|
126
|
+
model "claude-3-5-haiku-20241022"
|
|
127
|
+
prompt(params[:message])
|
|
128
|
+
send_msg
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Claude 3 Opus - Highest quality for complex tasks
|
|
132
|
+
SmartPrompt.define_worker :opus_chat do
|
|
133
|
+
use "claude_opus"
|
|
134
|
+
model "claude-3-opus-20240229"
|
|
135
|
+
prompt(params[:message])
|
|
136
|
+
send_msg
|
|
137
|
+
end
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Temperature Control
|
|
141
|
+
|
|
142
|
+
```ruby
|
|
143
|
+
# Creative writing (high temperature)
|
|
144
|
+
SmartPrompt.define_worker :creative_chat do
|
|
145
|
+
use "claude_creative" # temperature: 0.9
|
|
146
|
+
sys_msg("You are a creative writer.")
|
|
147
|
+
prompt("Write a creative tagline for a coffee shop.")
|
|
148
|
+
send_msg
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Precise analysis (low temperature)
|
|
152
|
+
SmartPrompt.define_worker :precise_chat do
|
|
153
|
+
use "claude_precise" # temperature: 0.3
|
|
154
|
+
sys_msg("You are a precise analyst.")
|
|
155
|
+
prompt("Analyze this data and provide key insights.")
|
|
156
|
+
send_msg
|
|
157
|
+
end
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Multimodal Examples (Vision)
|
|
161
|
+
|
|
162
|
+
Claude can analyze images alongside text. Supported formats: JPEG, PNG, GIF, WebP (up to 5MB).
|
|
163
|
+
|
|
164
|
+
### Analyze Image from URL
|
|
165
|
+
|
|
166
|
+
```ruby
|
|
167
|
+
SmartPrompt.define_worker :image_analyzer do
|
|
168
|
+
use "claude"
|
|
169
|
+
sys_msg("You are an expert at analyzing images.")
|
|
170
|
+
prompt(params[:message])
|
|
171
|
+
send_msg
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
response = engine.call_worker(:image_analyzer, {
|
|
175
|
+
message: [
|
|
176
|
+
{ type: "text", text: "What do you see in this image?" },
|
|
177
|
+
{ type: "image_url", image_url: "https://example.com/image.jpg" }
|
|
178
|
+
]
|
|
179
|
+
})
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Run the example:**
|
|
183
|
+
```bash
|
|
184
|
+
ruby examples/anthropic_multimodal.rb
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Analyze Local Image (Base64)
|
|
188
|
+
|
|
189
|
+
```ruby
|
|
190
|
+
require 'base64'
|
|
191
|
+
|
|
192
|
+
# Read and encode image
|
|
193
|
+
image_data = File.binread("./path/to/image.jpg")
|
|
194
|
+
base64_image = Base64.strict_encode64(image_data)
|
|
195
|
+
data_url = "data:image/jpeg;base64,#{base64_image}"
|
|
196
|
+
|
|
197
|
+
response = engine.call_worker(:image_analyzer, {
|
|
198
|
+
message: [
|
|
199
|
+
{ type: "text", text: "Describe this image in detail." },
|
|
200
|
+
{ type: "image_url", image_url: data_url }
|
|
201
|
+
]
|
|
202
|
+
})
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Compare Multiple Images
|
|
206
|
+
|
|
207
|
+
```ruby
|
|
208
|
+
response = engine.call_worker(:image_analyzer, {
|
|
209
|
+
message: [
|
|
210
|
+
{ type: "text", text: "Compare these two images." },
|
|
211
|
+
{ type: "image_url", image_url: "https://example.com/image1.jpg" },
|
|
212
|
+
{ type: "image_url", image_url: "https://example.com/image2.jpg" }
|
|
213
|
+
]
|
|
214
|
+
})
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### OCR and Text Extraction
|
|
218
|
+
|
|
219
|
+
```ruby
|
|
220
|
+
SmartPrompt.define_worker :ocr_extractor do
|
|
221
|
+
use "claude"
|
|
222
|
+
sys_msg("You are an expert at reading text from images.")
|
|
223
|
+
prompt(params[:message])
|
|
224
|
+
send_msg
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
response = engine.call_worker(:ocr_extractor, {
|
|
228
|
+
message: [
|
|
229
|
+
{ type: "text", text: "Extract all text from this image." },
|
|
230
|
+
{ type: "image_url", image_url: "https://example.com/document.jpg" }
|
|
231
|
+
]
|
|
232
|
+
})
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Product Image Analysis
|
|
236
|
+
|
|
237
|
+
```ruby
|
|
238
|
+
SmartPrompt.define_worker :product_analyzer do
|
|
239
|
+
use "claude"
|
|
240
|
+
sys_msg("You are a product analyst for e-commerce.")
|
|
241
|
+
prompt(params[:message])
|
|
242
|
+
send_msg
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
response = engine.call_worker(:product_analyzer, {
|
|
246
|
+
message: [
|
|
247
|
+
{ type: "text", text: "Analyze this product image and provide:\n1. Product description\n2. Key features\n3. Suggested title" },
|
|
248
|
+
{ type: "image_url", image_url: "https://example.com/product.jpg" }
|
|
249
|
+
]
|
|
250
|
+
})
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Tool Calling Examples
|
|
254
|
+
|
|
255
|
+
Claude can use external tools/functions to perform actions or retrieve information.
|
|
256
|
+
|
|
257
|
+
### Simple Weather Tool
|
|
258
|
+
|
|
259
|
+
```ruby
|
|
260
|
+
weather_tool = [
|
|
261
|
+
{
|
|
262
|
+
type: "function",
|
|
263
|
+
function: {
|
|
264
|
+
name: "get_weather",
|
|
265
|
+
description: "Get the current weather for a location",
|
|
266
|
+
parameters: {
|
|
267
|
+
type: "object",
|
|
268
|
+
properties: {
|
|
269
|
+
location: {
|
|
270
|
+
type: "string",
|
|
271
|
+
description: "The city and state, e.g. San Francisco, CA"
|
|
272
|
+
},
|
|
273
|
+
unit: {
|
|
274
|
+
type: "string",
|
|
275
|
+
enum: ["celsius", "fahrenheit"],
|
|
276
|
+
description: "Temperature unit"
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
required: ["location"]
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
]
|
|
284
|
+
|
|
285
|
+
SmartPrompt.define_worker :weather_assistant do
|
|
286
|
+
use "claude"
|
|
287
|
+
sys_msg("You are a weather assistant. Use the get_weather tool.")
|
|
288
|
+
prompt(params[:message])
|
|
289
|
+
params.merge(tools: weather_tool)
|
|
290
|
+
send_msg
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
response = engine.call_worker(:weather_assistant, {
|
|
294
|
+
message: "What's the weather in Tokyo?"
|
|
295
|
+
})
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
**Run the example:**
|
|
299
|
+
```bash
|
|
300
|
+
ruby examples/anthropic_tool_calling.rb
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Multiple Calculator Tools
|
|
304
|
+
|
|
305
|
+
```ruby
|
|
306
|
+
calculator_tools = [
|
|
307
|
+
{
|
|
308
|
+
type: "function",
|
|
309
|
+
function: {
|
|
310
|
+
name: "add",
|
|
311
|
+
description: "Add two numbers",
|
|
312
|
+
parameters: {
|
|
313
|
+
type: "object",
|
|
314
|
+
properties: {
|
|
315
|
+
a: { type: "number" },
|
|
316
|
+
b: { type: "number" }
|
|
317
|
+
},
|
|
318
|
+
required: ["a", "b"]
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
type: "function",
|
|
324
|
+
function: {
|
|
325
|
+
name: "multiply",
|
|
326
|
+
description: "Multiply two numbers",
|
|
327
|
+
parameters: {
|
|
328
|
+
type: "object",
|
|
329
|
+
properties: {
|
|
330
|
+
a: { type: "number" },
|
|
331
|
+
b: { type: "number" }
|
|
332
|
+
},
|
|
333
|
+
required: ["a", "b"]
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
]
|
|
338
|
+
|
|
339
|
+
SmartPrompt.define_worker :calculator do
|
|
340
|
+
use "claude"
|
|
341
|
+
sys_msg("You are a calculator assistant.")
|
|
342
|
+
prompt(params[:message])
|
|
343
|
+
params.merge(tools: calculator_tools)
|
|
344
|
+
send_msg
|
|
345
|
+
end
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Database Query Tool
|
|
349
|
+
|
|
350
|
+
```ruby
|
|
351
|
+
database_tool = [
|
|
352
|
+
{
|
|
353
|
+
type: "function",
|
|
354
|
+
function: {
|
|
355
|
+
name: "query_database",
|
|
356
|
+
description: "Query the customer database",
|
|
357
|
+
parameters: {
|
|
358
|
+
type: "object",
|
|
359
|
+
properties: {
|
|
360
|
+
query_type: {
|
|
361
|
+
type: "string",
|
|
362
|
+
enum: ["customer_info", "order_history", "product_details"]
|
|
363
|
+
},
|
|
364
|
+
customer_id: { type: "string" }
|
|
365
|
+
},
|
|
366
|
+
required: ["query_type"]
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
]
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### Complex Tool with Nested Parameters
|
|
374
|
+
|
|
375
|
+
```ruby
|
|
376
|
+
search_tool = [
|
|
377
|
+
{
|
|
378
|
+
type: "function",
|
|
379
|
+
function: {
|
|
380
|
+
name: "search_products",
|
|
381
|
+
description: "Search products with filters",
|
|
382
|
+
parameters: {
|
|
383
|
+
type: "object",
|
|
384
|
+
properties: {
|
|
385
|
+
query: { type: "string" },
|
|
386
|
+
filters: {
|
|
387
|
+
type: "object",
|
|
388
|
+
properties: {
|
|
389
|
+
category: { type: "string" },
|
|
390
|
+
price_range: {
|
|
391
|
+
type: "object",
|
|
392
|
+
properties: {
|
|
393
|
+
min: { type: "number" },
|
|
394
|
+
max: { type: "number" }
|
|
395
|
+
}
|
|
396
|
+
},
|
|
397
|
+
in_stock: { type: "boolean" }
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
sort_by: {
|
|
401
|
+
type: "string",
|
|
402
|
+
enum: ["price_asc", "price_desc", "popularity"]
|
|
403
|
+
}
|
|
404
|
+
},
|
|
405
|
+
required: ["query"]
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
]
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
## Streaming Response Examples
|
|
413
|
+
|
|
414
|
+
Streaming provides better user experience by showing responses as they're generated.
|
|
415
|
+
|
|
416
|
+
### Basic Streaming
|
|
417
|
+
|
|
418
|
+
```ruby
|
|
419
|
+
SmartPrompt.define_worker :streaming_chat do
|
|
420
|
+
use "claude"
|
|
421
|
+
sys_msg("You are a helpful assistant.")
|
|
422
|
+
prompt(params[:message])
|
|
423
|
+
send_msg
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
engine.call_worker_by_stream(:streaming_chat, {
|
|
427
|
+
message: "Tell me a story about a brave knight."
|
|
428
|
+
}) do |chunk, bytesize|
|
|
429
|
+
if chunk.is_a?(Hash) && chunk["type"] == "content_block_delta"
|
|
430
|
+
text = chunk.dig("delta", "text")
|
|
431
|
+
print text if text
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
**Run the example:**
|
|
437
|
+
```bash
|
|
438
|
+
ruby examples/anthropic_streaming.rb
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### Handling Different Event Types
|
|
442
|
+
|
|
443
|
+
```ruby
|
|
444
|
+
engine.call_worker_by_stream(:streaming_chat, {
|
|
445
|
+
message: "Explain photosynthesis."
|
|
446
|
+
}) do |chunk, bytesize|
|
|
447
|
+
if chunk.is_a?(Hash)
|
|
448
|
+
case chunk["type"]
|
|
449
|
+
when "message_start"
|
|
450
|
+
# Message started
|
|
451
|
+
puts "[Starting response...]"
|
|
452
|
+
when "content_block_start"
|
|
453
|
+
# Content block started
|
|
454
|
+
when "content_block_delta"
|
|
455
|
+
# Incremental text
|
|
456
|
+
text = chunk.dig("delta", "text")
|
|
457
|
+
print text if text
|
|
458
|
+
when "content_block_stop"
|
|
459
|
+
# Content block finished
|
|
460
|
+
when "message_stop"
|
|
461
|
+
# Message complete
|
|
462
|
+
puts "\n[Response complete]"
|
|
463
|
+
end
|
|
464
|
+
end
|
|
465
|
+
end
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### Streaming with Progress Tracking
|
|
469
|
+
|
|
470
|
+
```ruby
|
|
471
|
+
char_count = 0
|
|
472
|
+
|
|
473
|
+
engine.call_worker_by_stream(:streaming_chat, {
|
|
474
|
+
message: "Write a Python function for Fibonacci."
|
|
475
|
+
}) do |chunk, bytesize|
|
|
476
|
+
if chunk.is_a?(Hash) && chunk["type"] == "content_block_delta"
|
|
477
|
+
text = chunk.dig("delta", "text")
|
|
478
|
+
if text
|
|
479
|
+
print text
|
|
480
|
+
char_count += text.length
|
|
481
|
+
end
|
|
482
|
+
end
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
puts "\n[Total characters: #{char_count}]"
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
### Streaming with Error Handling
|
|
489
|
+
|
|
490
|
+
```ruby
|
|
491
|
+
begin
|
|
492
|
+
engine.call_worker_by_stream(:streaming_chat, {
|
|
493
|
+
message: "What are the benefits of exercise?"
|
|
494
|
+
}) do |chunk, bytesize|
|
|
495
|
+
if chunk.is_a?(Hash) && chunk["type"] == "content_block_delta"
|
|
496
|
+
text = chunk.dig("delta", "text")
|
|
497
|
+
print text if text
|
|
498
|
+
end
|
|
499
|
+
end
|
|
500
|
+
puts "\n[Stream completed successfully]"
|
|
501
|
+
rescue SmartPrompt::LLMAPIError => e
|
|
502
|
+
puts "\n[Error: #{e.message}]"
|
|
503
|
+
end
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
## Advanced Usage
|
|
507
|
+
|
|
508
|
+
### Custom Endpoint (Proxy or Private Deployment)
|
|
509
|
+
|
|
510
|
+
```yaml
|
|
511
|
+
llms:
|
|
512
|
+
claude_custom:
|
|
513
|
+
adapter: "anthropic"
|
|
514
|
+
api_key: ENV["ANTHROPIC_API_KEY"]
|
|
515
|
+
url: "https://your-custom-endpoint.com"
|
|
516
|
+
model: "claude-3-5-sonnet-20241022"
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
### Combining Multimodal and Tool Calling
|
|
520
|
+
|
|
521
|
+
```ruby
|
|
522
|
+
tools = [
|
|
523
|
+
{
|
|
524
|
+
type: "function",
|
|
525
|
+
function: {
|
|
526
|
+
name: "identify_object",
|
|
527
|
+
description: "Identify objects in the image",
|
|
528
|
+
parameters: {
|
|
529
|
+
type: "object",
|
|
530
|
+
properties: {
|
|
531
|
+
object_name: { type: "string" }
|
|
532
|
+
},
|
|
533
|
+
required: ["object_name"]
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
]
|
|
538
|
+
|
|
539
|
+
SmartPrompt.define_worker :multimodal_tools do
|
|
540
|
+
use "claude"
|
|
541
|
+
sys_msg("You can analyze images and use tools.")
|
|
542
|
+
prompt(params[:message])
|
|
543
|
+
params.merge(tools: tools)
|
|
544
|
+
send_msg
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
response = engine.call_worker(:multimodal_tools, {
|
|
548
|
+
message: [
|
|
549
|
+
{ type: "text", text: "What objects do you see? Use the identify_object tool." },
|
|
550
|
+
{ type: "image_url", image_url: "https://example.com/scene.jpg" }
|
|
551
|
+
]
|
|
552
|
+
})
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
### Conversation with Mixed Content
|
|
556
|
+
|
|
557
|
+
```ruby
|
|
558
|
+
SmartPrompt.define_worker :mixed_conversation do
|
|
559
|
+
use "cla
|