ruby_llm 1.5.1 → 1.6.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/README.md +1 -1
- data/lib/ruby_llm/active_record/acts_as.rb +46 -6
- data/lib/ruby_llm/aliases.json +27 -3
- data/lib/ruby_llm/chat.rb +27 -6
- data/lib/ruby_llm/configuration.rb +7 -18
- data/lib/ruby_llm/connection.rb +11 -6
- data/lib/ruby_llm/context.rb +2 -3
- data/lib/ruby_llm/embedding.rb +3 -4
- data/lib/ruby_llm/error.rb +2 -2
- data/lib/ruby_llm/image.rb +3 -4
- data/lib/ruby_llm/message.rb +4 -0
- data/lib/ruby_llm/models.json +7306 -6676
- data/lib/ruby_llm/models.rb +22 -31
- data/lib/ruby_llm/provider.rb +150 -89
- data/lib/ruby_llm/providers/anthropic/capabilities.rb +1 -2
- data/lib/ruby_llm/providers/anthropic/chat.rb +1 -1
- data/lib/ruby_llm/providers/anthropic/embeddings.rb +1 -1
- data/lib/ruby_llm/providers/anthropic/media.rb +1 -1
- data/lib/ruby_llm/providers/anthropic/models.rb +1 -1
- data/lib/ruby_llm/providers/anthropic/streaming.rb +1 -1
- data/lib/ruby_llm/providers/anthropic/tools.rb +1 -1
- data/lib/ruby_llm/providers/anthropic.rb +17 -22
- data/lib/ruby_llm/providers/bedrock/capabilities.rb +3 -63
- data/lib/ruby_llm/providers/bedrock/chat.rb +5 -4
- data/lib/ruby_llm/providers/bedrock/media.rb +1 -1
- data/lib/ruby_llm/providers/bedrock/models.rb +5 -6
- data/lib/ruby_llm/providers/bedrock/signing.rb +1 -1
- data/lib/ruby_llm/providers/bedrock/streaming/base.rb +5 -4
- data/lib/ruby_llm/providers/bedrock/streaming/content_extraction.rb +1 -1
- data/lib/ruby_llm/providers/bedrock/streaming/message_processing.rb +1 -1
- data/lib/ruby_llm/providers/bedrock/streaming/payload_processing.rb +1 -1
- data/lib/ruby_llm/providers/bedrock/streaming/prelude_handling.rb +1 -1
- data/lib/ruby_llm/providers/bedrock/streaming.rb +1 -1
- data/lib/ruby_llm/providers/bedrock.rb +26 -31
- data/lib/ruby_llm/providers/deepseek/capabilities.rb +16 -57
- data/lib/ruby_llm/providers/deepseek/chat.rb +1 -1
- data/lib/ruby_llm/providers/deepseek.rb +12 -17
- data/lib/ruby_llm/providers/gemini/capabilities.rb +1 -1
- data/lib/ruby_llm/providers/gemini/chat.rb +1 -1
- data/lib/ruby_llm/providers/gemini/embeddings.rb +1 -1
- data/lib/ruby_llm/providers/gemini/images.rb +1 -1
- data/lib/ruby_llm/providers/gemini/media.rb +1 -1
- data/lib/ruby_llm/providers/gemini/models.rb +1 -1
- data/lib/ruby_llm/providers/gemini/streaming.rb +1 -1
- data/lib/ruby_llm/providers/gemini/tools.rb +1 -7
- data/lib/ruby_llm/providers/gemini.rb +18 -23
- data/lib/ruby_llm/providers/gpustack/chat.rb +1 -1
- data/lib/ruby_llm/providers/gpustack/models.rb +1 -1
- data/lib/ruby_llm/providers/gpustack.rb +16 -19
- data/lib/ruby_llm/providers/mistral/capabilities.rb +1 -1
- data/lib/ruby_llm/providers/mistral/chat.rb +1 -1
- data/lib/ruby_llm/providers/mistral/embeddings.rb +1 -1
- data/lib/ruby_llm/providers/mistral/models.rb +1 -1
- data/lib/ruby_llm/providers/mistral.rb +14 -19
- data/lib/ruby_llm/providers/ollama/chat.rb +1 -1
- data/lib/ruby_llm/providers/ollama/media.rb +1 -1
- data/lib/ruby_llm/providers/ollama.rb +13 -18
- data/lib/ruby_llm/providers/openai/capabilities.rb +2 -2
- data/lib/ruby_llm/providers/openai/chat.rb +2 -2
- data/lib/ruby_llm/providers/openai/embeddings.rb +1 -1
- data/lib/ruby_llm/providers/openai/images.rb +1 -1
- data/lib/ruby_llm/providers/openai/media.rb +1 -1
- data/lib/ruby_llm/providers/openai/models.rb +1 -1
- data/lib/ruby_llm/providers/openai/streaming.rb +1 -1
- data/lib/ruby_llm/providers/openai/tools.rb +1 -1
- data/lib/ruby_llm/providers/openai.rb +24 -36
- data/lib/ruby_llm/providers/openrouter/models.rb +1 -1
- data/lib/ruby_llm/providers/openrouter.rb +9 -14
- data/lib/ruby_llm/providers/perplexity/capabilities.rb +1 -30
- data/lib/ruby_llm/providers/perplexity/chat.rb +1 -1
- data/lib/ruby_llm/providers/perplexity/models.rb +1 -1
- data/lib/ruby_llm/providers/perplexity.rb +13 -18
- data/lib/ruby_llm/stream_accumulator.rb +3 -3
- data/lib/ruby_llm/streaming.rb +16 -3
- data/lib/ruby_llm/tool.rb +19 -0
- data/lib/ruby_llm/version.rb +1 -1
- data/lib/tasks/models_docs.rake +18 -11
- data/lib/tasks/models_update.rake +5 -4
- metadata +1 -1
@@ -2,14 +2,11 @@
|
|
2
2
|
|
3
3
|
module RubyLLM
|
4
4
|
module Providers
|
5
|
-
|
5
|
+
class Bedrock
|
6
6
|
# Determines capabilities and pricing for AWS Bedrock models
|
7
7
|
module Capabilities
|
8
8
|
module_function
|
9
9
|
|
10
|
-
# Returns the context window size for the given model ID
|
11
|
-
# @param model_id [String] the model identifier
|
12
|
-
# @return [Integer] the context window size in tokens
|
13
10
|
def context_window_for(model_id)
|
14
11
|
case model_id
|
15
12
|
when /anthropic\.claude-2/ then 100_000
|
@@ -17,95 +14,56 @@ module RubyLLM
|
|
17
14
|
end
|
18
15
|
end
|
19
16
|
|
20
|
-
# Returns the maximum output tokens for the given model ID
|
21
|
-
# @param model_id [String] the model identifier
|
22
|
-
# @return [Integer] the maximum output tokens
|
23
17
|
def max_tokens_for(_model_id)
|
24
18
|
4_096
|
25
19
|
end
|
26
20
|
|
27
|
-
# Returns the input price per million tokens for the given model ID
|
28
|
-
# @param model_id [String] the model identifier
|
29
|
-
# @return [Float] the price per million tokens for input
|
30
21
|
def input_price_for(model_id)
|
31
22
|
PRICES.dig(model_family(model_id), :input) || default_input_price
|
32
23
|
end
|
33
24
|
|
34
|
-
# Returns the output price per million tokens for the given model ID
|
35
|
-
# @param model_id [String] the model identifier
|
36
|
-
# @return [Float] the price per million tokens for output
|
37
25
|
def output_price_for(model_id)
|
38
26
|
PRICES.dig(model_family(model_id), :output) || default_output_price
|
39
27
|
end
|
40
28
|
|
41
|
-
# Determines if the model supports chat capabilities
|
42
|
-
# @param model_id [String] the model identifier
|
43
|
-
# @return [Boolean] true if the model supports chat
|
44
29
|
def supports_chat?(model_id)
|
45
30
|
model_id.match?(/anthropic\.claude/)
|
46
31
|
end
|
47
32
|
|
48
|
-
# Determines if the model supports streaming capabilities
|
49
|
-
# @param model_id [String] the model identifier
|
50
|
-
# @return [Boolean] true if the model supports streaming
|
51
33
|
def supports_streaming?(model_id)
|
52
34
|
model_id.match?(/anthropic\.claude/)
|
53
35
|
end
|
54
36
|
|
55
|
-
# Determines if the model supports image input/output
|
56
|
-
# @param model_id [String] the model identifier
|
57
|
-
# @return [Boolean] true if the model supports images
|
58
37
|
def supports_images?(model_id)
|
59
38
|
model_id.match?(/anthropic\.claude/)
|
60
39
|
end
|
61
40
|
|
62
|
-
# Determines if the model supports vision capabilities
|
63
|
-
# @param model_id [String] the model identifier
|
64
|
-
# @return [Boolean] true if the model supports vision
|
65
41
|
def supports_vision?(model_id)
|
66
42
|
model_id.match?(/anthropic\.claude/)
|
67
43
|
end
|
68
44
|
|
69
|
-
# Determines if the model supports function calling
|
70
|
-
# @param model_id [String] the model identifier
|
71
|
-
# @return [Boolean] true if the model supports functions
|
72
45
|
def supports_functions?(model_id)
|
73
46
|
model_id.match?(/anthropic\.claude/)
|
74
47
|
end
|
75
48
|
|
76
|
-
# Determines if the model supports audio input/output
|
77
|
-
# @param model_id [String] the model identifier
|
78
|
-
# @return [Boolean] true if the model supports audio
|
79
49
|
def supports_audio?(_model_id)
|
80
50
|
false
|
81
51
|
end
|
82
52
|
|
83
|
-
# Determines if the model supports JSON mode
|
84
|
-
# @param model_id [String] the model identifier
|
85
|
-
# @return [Boolean] true if the model supports JSON mode
|
86
53
|
def supports_json_mode?(model_id)
|
87
54
|
model_id.match?(/anthropic\.claude/)
|
88
55
|
end
|
89
56
|
|
90
|
-
# Formats the model ID into a human-readable display name
|
91
|
-
# @param model_id [String] the model identifier
|
92
|
-
# @return [String] the formatted display name
|
93
57
|
def format_display_name(model_id)
|
94
58
|
model_id.then { |id| humanize(id) }
|
95
59
|
end
|
96
60
|
|
97
|
-
# Determines the type of model
|
98
|
-
# @param model_id [String] the model identifier
|
99
|
-
# @return [String] the model type (chat, embedding, image, audio)
|
100
61
|
def model_type(_model_id)
|
101
62
|
'chat'
|
102
63
|
end
|
103
64
|
|
104
|
-
|
105
|
-
|
106
|
-
# @return [Boolean] true if the model supports structured output
|
107
|
-
def supports_structured_output?(model_id)
|
108
|
-
model_id.match?(/anthropic\.claude/)
|
65
|
+
def supports_structured_output?(_model_id)
|
66
|
+
false
|
109
67
|
end
|
110
68
|
|
111
69
|
# Model family patterns for capability lookup
|
@@ -120,9 +78,6 @@ module RubyLLM
|
|
120
78
|
/anthropic\.claude-instant/ => :claude_instant
|
121
79
|
}.freeze
|
122
80
|
|
123
|
-
# Determines the model family for pricing and capability lookup
|
124
|
-
# @param model_id [String] the model identifier
|
125
|
-
# @return [Symbol] the model family identifier
|
126
81
|
def model_family(model_id)
|
127
82
|
MODEL_FAMILIES.find { |pattern, _family| model_id.match?(pattern) }&.last || :other
|
128
83
|
end
|
@@ -137,21 +92,14 @@ module RubyLLM
|
|
137
92
|
claude_instant: { input: 0.8, output: 2.4 }
|
138
93
|
}.freeze
|
139
94
|
|
140
|
-
# Default input price when model-specific pricing is not available
|
141
|
-
# @return [Float] the default price per million tokens
|
142
95
|
def default_input_price
|
143
96
|
0.1
|
144
97
|
end
|
145
98
|
|
146
|
-
# Default output price when model-specific pricing is not available
|
147
|
-
# @return [Float] the default price per million tokens
|
148
99
|
def default_output_price
|
149
100
|
0.2
|
150
101
|
end
|
151
102
|
|
152
|
-
# Converts a model ID to a human-readable format
|
153
|
-
# @param id [String] the model identifier
|
154
|
-
# @return [String] the humanized model name
|
155
103
|
def humanize(id)
|
156
104
|
id.tr('-', ' ')
|
157
105
|
.split('.')
|
@@ -167,7 +115,6 @@ module RubyLLM
|
|
167
115
|
output: ['text']
|
168
116
|
}
|
169
117
|
|
170
|
-
# Vision support for Claude models
|
171
118
|
if model_id.match?(/anthropic\.claude/) && supports_vision?(model_id)
|
172
119
|
modalities[:input] << 'image'
|
173
120
|
modalities[:input] << 'pdf'
|
@@ -179,18 +126,12 @@ module RubyLLM
|
|
179
126
|
def capabilities_for(model_id)
|
180
127
|
capabilities = []
|
181
128
|
|
182
|
-
# Streaming
|
183
129
|
capabilities << 'streaming' if model_id.match?(/anthropic\.claude/)
|
184
130
|
|
185
|
-
# Function calling & structured output
|
186
131
|
capabilities << 'function_calling' if supports_functions?(model_id)
|
187
132
|
|
188
|
-
capabilities << 'structured_output' if supports_json_mode?(model_id)
|
189
|
-
|
190
|
-
# Extended thinking for 3.7 models
|
191
133
|
capabilities << 'reasoning' if model_id.match?(/claude-3-7/)
|
192
134
|
|
193
|
-
# Batch capabilities for newer Claude models
|
194
135
|
if model_id.match?(/claude-3\.5|claude-3-7/)
|
195
136
|
capabilities << 'batch'
|
196
137
|
capabilities << 'citations'
|
@@ -208,7 +149,6 @@ module RubyLLM
|
|
208
149
|
output_per_million: prices[:output]
|
209
150
|
}
|
210
151
|
|
211
|
-
# Batch pricing - typically 50% of standard
|
212
152
|
batch_pricing = {
|
213
153
|
input_per_million: prices[:input] * 0.5,
|
214
154
|
output_per_million: prices[:output] * 0.5
|
@@ -2,16 +2,17 @@
|
|
2
2
|
|
3
3
|
module RubyLLM
|
4
4
|
module Providers
|
5
|
-
|
5
|
+
class Bedrock
|
6
6
|
# Chat methods for the AWS Bedrock API implementation
|
7
7
|
module Chat
|
8
8
|
module_function
|
9
9
|
|
10
|
-
def sync_response(connection, payload)
|
11
|
-
signature = sign_request("#{connection.connection.url_prefix}#{completion_url}",
|
12
|
-
payload:)
|
10
|
+
def sync_response(connection, payload, additional_headers = {})
|
11
|
+
signature = sign_request("#{connection.connection.url_prefix}#{completion_url}", payload:)
|
13
12
|
response = connection.post completion_url, payload do |req|
|
14
13
|
req.headers.merge! build_headers(signature.headers, streaming: block_given?)
|
14
|
+
# Merge additional headers, with existing headers taking precedence
|
15
|
+
req.headers = additional_headers.merge(req.headers) unless additional_headers.empty?
|
15
16
|
end
|
16
17
|
Anthropic::Chat.parse_completion_response response
|
17
18
|
end
|
@@ -2,15 +2,14 @@
|
|
2
2
|
|
3
3
|
module RubyLLM
|
4
4
|
module Providers
|
5
|
-
|
5
|
+
class Bedrock
|
6
6
|
# Models methods for the AWS Bedrock API implementation
|
7
7
|
module Models
|
8
|
-
def list_models
|
9
|
-
|
10
|
-
mgmt_api_base = "https://bedrock.#{config.bedrock_region}.amazonaws.com"
|
8
|
+
def list_models
|
9
|
+
mgmt_api_base = "https://bedrock.#{@config.bedrock_region}.amazonaws.com"
|
11
10
|
full_models_url = "#{mgmt_api_base}/#{models_url}"
|
12
|
-
signature = sign_request(full_models_url,
|
13
|
-
response = connection.get(full_models_url) do |req|
|
11
|
+
signature = sign_request(full_models_url, method: :get)
|
12
|
+
response = @connection.get(full_models_url) do |req|
|
14
13
|
req.headers.merge! signature.headers
|
15
14
|
end
|
16
15
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module RubyLLM
|
4
4
|
module Providers
|
5
|
-
|
5
|
+
class Bedrock
|
6
6
|
module Streaming
|
7
7
|
# Base module for AWS Bedrock streaming functionality.
|
8
8
|
# Serves as the core module that includes all other streaming-related modules
|
@@ -29,13 +29,14 @@ module RubyLLM
|
|
29
29
|
"model/#{@model_id}/invoke-with-response-stream"
|
30
30
|
end
|
31
31
|
|
32
|
-
def stream_response(connection, payload, &block)
|
33
|
-
signature = sign_request("#{connection.connection.url_prefix}#{stream_url}",
|
34
|
-
payload:)
|
32
|
+
def stream_response(connection, payload, additional_headers = {}, &block)
|
33
|
+
signature = sign_request("#{connection.connection.url_prefix}#{stream_url}", payload:)
|
35
34
|
accumulator = StreamAccumulator.new
|
36
35
|
|
37
36
|
response = connection.post stream_url, payload do |req|
|
38
37
|
req.headers.merge! build_headers(signature.headers, streaming: block_given?)
|
38
|
+
# Merge additional headers, with existing headers taking precedence
|
39
|
+
req.headers = additional_headers.merge(req.headers) unless additional_headers.empty?
|
39
40
|
req.options.on_data = handle_stream do |chunk|
|
40
41
|
accumulator.add chunk
|
41
42
|
block.call chunk
|
@@ -8,7 +8,7 @@ require_relative 'streaming/prelude_handling'
|
|
8
8
|
|
9
9
|
module RubyLLM
|
10
10
|
module Providers
|
11
|
-
|
11
|
+
class Bedrock
|
12
12
|
# Streaming implementation for the AWS Bedrock API.
|
13
13
|
# This module provides functionality for handling streaming responses from AWS Bedrock,
|
14
14
|
# including message processing, content extraction, and error handling.
|
@@ -7,19 +7,16 @@ module RubyLLM
|
|
7
7
|
module Providers
|
8
8
|
# AWS Bedrock API integration. Handles chat completion and streaming
|
9
9
|
# for Claude models.
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
extend Anthropic::Tools
|
10
|
+
class Bedrock < Provider
|
11
|
+
include Bedrock::Chat
|
12
|
+
include Bedrock::Streaming
|
13
|
+
include Bedrock::Models
|
14
|
+
include Bedrock::Signing
|
15
|
+
include Bedrock::Media
|
16
|
+
include Anthropic::Tools
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
def api_base(config)
|
22
|
-
"https://bedrock-runtime.#{config.bedrock_region}.amazonaws.com"
|
18
|
+
def api_base
|
19
|
+
"https://bedrock-runtime.#{@config.bedrock_region}.amazonaws.com"
|
23
20
|
end
|
24
21
|
|
25
22
|
def parse_error(response)
|
@@ -38,25 +35,25 @@ module RubyLLM
|
|
38
35
|
end
|
39
36
|
end
|
40
37
|
|
41
|
-
def sign_request(url,
|
42
|
-
signer = create_signer
|
43
|
-
request = build_request(url,
|
38
|
+
def sign_request(url, method: :post, payload: nil)
|
39
|
+
signer = create_signer
|
40
|
+
request = build_request(url, method:, payload:)
|
44
41
|
signer.sign_request(request)
|
45
42
|
end
|
46
43
|
|
47
|
-
def create_signer
|
44
|
+
def create_signer
|
48
45
|
Signing::Signer.new({
|
49
|
-
access_key_id: config.bedrock_api_key,
|
50
|
-
secret_access_key: config.bedrock_secret_key,
|
51
|
-
session_token: config.bedrock_session_token,
|
52
|
-
region: config.bedrock_region,
|
46
|
+
access_key_id: @config.bedrock_api_key,
|
47
|
+
secret_access_key: @config.bedrock_secret_key,
|
48
|
+
session_token: @config.bedrock_session_token,
|
49
|
+
region: @config.bedrock_region,
|
53
50
|
service: 'bedrock'
|
54
51
|
})
|
55
52
|
end
|
56
53
|
|
57
|
-
def build_request(url,
|
54
|
+
def build_request(url, method: :post, payload: nil)
|
58
55
|
{
|
59
|
-
connection: connection
|
56
|
+
connection: @connection,
|
60
57
|
http_method: method,
|
61
58
|
url: url || completion_url,
|
62
59
|
body: payload ? JSON.generate(payload, ascii_only: false) : nil
|
@@ -72,16 +69,14 @@ module RubyLLM
|
|
72
69
|
)
|
73
70
|
end
|
74
71
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
def slug
|
80
|
-
'bedrock'
|
81
|
-
end
|
72
|
+
class << self
|
73
|
+
def capabilities
|
74
|
+
Bedrock::Capabilities
|
75
|
+
end
|
82
76
|
|
83
|
-
|
84
|
-
|
77
|
+
def configuration_requirements
|
78
|
+
%i[bedrock_api_key bedrock_secret_key bedrock_region]
|
79
|
+
end
|
85
80
|
end
|
86
81
|
end
|
87
82
|
end
|
@@ -2,14 +2,11 @@
|
|
2
2
|
|
3
3
|
module RubyLLM
|
4
4
|
module Providers
|
5
|
-
|
5
|
+
class DeepSeek
|
6
6
|
# Determines capabilities and pricing for DeepSeek models
|
7
7
|
module Capabilities
|
8
8
|
module_function
|
9
9
|
|
10
|
-
# Returns the context window size for the given model
|
11
|
-
# @param model_id [String] the model identifier
|
12
|
-
# @return [Integer] the context window size in tokens
|
13
10
|
def context_window_for(model_id)
|
14
11
|
case model_id
|
15
12
|
when /deepseek-(?:chat|reasoner)/ then 64_000
|
@@ -17,61 +14,37 @@ module RubyLLM
|
|
17
14
|
end
|
18
15
|
end
|
19
16
|
|
20
|
-
# Returns the maximum number of tokens that can be generated
|
21
|
-
# @param model_id [String] the model identifier
|
22
|
-
# @return [Integer] the maximum number of tokens
|
23
17
|
def max_tokens_for(model_id)
|
24
18
|
case model_id
|
25
19
|
when /deepseek-(?:chat|reasoner)/ then 8_192
|
26
|
-
else 4_096
|
20
|
+
else 4_096
|
27
21
|
end
|
28
22
|
end
|
29
23
|
|
30
|
-
# Returns the price per million tokens for input (cache miss)
|
31
|
-
# @param model_id [String] the model identifier
|
32
|
-
# @return [Float] the price per million tokens in USD
|
33
24
|
def input_price_for(model_id)
|
34
25
|
PRICES.dig(model_family(model_id), :input_miss) || default_input_price
|
35
26
|
end
|
36
27
|
|
37
|
-
# Returns the price per million tokens for output
|
38
|
-
# @param model_id [String] the model identifier
|
39
|
-
# @return [Float] the price per million tokens in USD
|
40
28
|
def output_price_for(model_id)
|
41
29
|
PRICES.dig(model_family(model_id), :output) || default_output_price
|
42
30
|
end
|
43
31
|
|
44
|
-
# Returns the price per million tokens for input with cache hit
|
45
|
-
# @param model_id [String] the model identifier
|
46
|
-
# @return [Float] the price per million tokens in USD
|
47
32
|
def cache_hit_price_for(model_id)
|
48
33
|
PRICES.dig(model_family(model_id), :input_hit) || default_cache_hit_price
|
49
34
|
end
|
50
35
|
|
51
|
-
# Determines if the model supports vision capabilities
|
52
|
-
# @param model_id [String] the model identifier
|
53
|
-
# @return [Boolean] true if the model supports vision
|
54
36
|
def supports_vision?(_model_id)
|
55
|
-
false
|
37
|
+
false
|
56
38
|
end
|
57
39
|
|
58
|
-
# Determines if the model supports function calling
|
59
|
-
# @param model_id [String] the model identifier
|
60
|
-
# @return [Boolean] true if the model supports function calling
|
61
40
|
def supports_functions?(model_id)
|
62
|
-
model_id.match?(/deepseek-chat/)
|
41
|
+
model_id.match?(/deepseek-chat/)
|
63
42
|
end
|
64
43
|
|
65
|
-
# Determines if the model supports JSON mode
|
66
|
-
# @param model_id [String] the model identifier
|
67
|
-
# @return [Boolean] true if the model supports JSON mode
|
68
44
|
def supports_json_mode?(_model_id)
|
69
|
-
false
|
45
|
+
false
|
70
46
|
end
|
71
47
|
|
72
|
-
# Returns a formatted display name for the model
|
73
|
-
# @param model_id [String] the model identifier
|
74
|
-
# @return [String] the formatted display name
|
75
48
|
def format_display_name(model_id)
|
76
49
|
case model_id
|
77
50
|
when 'deepseek-chat' then 'DeepSeek V3'
|
@@ -83,53 +56,41 @@ module RubyLLM
|
|
83
56
|
end
|
84
57
|
end
|
85
58
|
|
86
|
-
# Returns the model type
|
87
|
-
# @param model_id [String] the model identifier
|
88
|
-
# @return [String] the model type (e.g., 'chat')
|
89
59
|
def model_type(_model_id)
|
90
|
-
'chat'
|
60
|
+
'chat'
|
91
61
|
end
|
92
62
|
|
93
|
-
# Returns the model family
|
94
|
-
# @param model_id [String] the model identifier
|
95
|
-
# @return [Symbol] the model family
|
96
63
|
def model_family(model_id)
|
97
64
|
case model_id
|
98
65
|
when /deepseek-reasoner/ then :reasoner
|
99
|
-
else :chat
|
66
|
+
else :chat
|
100
67
|
end
|
101
68
|
end
|
102
69
|
|
103
70
|
# Pricing information for DeepSeek models (USD per 1M tokens)
|
104
71
|
PRICES = {
|
105
72
|
chat: {
|
106
|
-
input_hit: 0.07,
|
107
|
-
input_miss: 0.27,
|
108
|
-
output: 1.10
|
73
|
+
input_hit: 0.07,
|
74
|
+
input_miss: 0.27,
|
75
|
+
output: 1.10
|
109
76
|
},
|
110
77
|
reasoner: {
|
111
|
-
input_hit: 0.14,
|
112
|
-
input_miss: 0.55,
|
113
|
-
output: 2.19
|
78
|
+
input_hit: 0.14,
|
79
|
+
input_miss: 0.55,
|
80
|
+
output: 2.19
|
114
81
|
}
|
115
82
|
}.freeze
|
116
83
|
|
117
|
-
# Default input price when model family can't be determined
|
118
|
-
# @return [Float] the default input price
|
119
84
|
def default_input_price
|
120
|
-
0.27
|
85
|
+
0.27
|
121
86
|
end
|
122
87
|
|
123
|
-
# Default output price when model family can't be determined
|
124
|
-
# @return [Float] the default output price
|
125
88
|
def default_output_price
|
126
|
-
1.10
|
89
|
+
1.10
|
127
90
|
end
|
128
91
|
|
129
|
-
# Default cache hit price when model family can't be determined
|
130
|
-
# @return [Float] the default cache hit price
|
131
92
|
def default_cache_hit_price
|
132
|
-
0.07
|
93
|
+
0.07
|
133
94
|
end
|
134
95
|
|
135
96
|
def modalities_for(_model_id)
|
@@ -142,7 +103,6 @@ module RubyLLM
|
|
142
103
|
def capabilities_for(model_id)
|
143
104
|
capabilities = ['streaming']
|
144
105
|
|
145
|
-
# Function calling for chat models
|
146
106
|
capabilities << 'function_calling' if model_id.match?(/deepseek-chat/)
|
147
107
|
|
148
108
|
capabilities
|
@@ -157,7 +117,6 @@ module RubyLLM
|
|
157
117
|
output_per_million: prices[:output]
|
158
118
|
}
|
159
119
|
|
160
|
-
# Add cached pricing if available
|
161
120
|
standard_pricing[:cached_input_per_million] = prices[:input_hit] if prices[:input_hit]
|
162
121
|
|
163
122
|
{
|
@@ -3,32 +3,27 @@
|
|
3
3
|
module RubyLLM
|
4
4
|
module Providers
|
5
5
|
# DeepSeek API integration.
|
6
|
-
|
7
|
-
|
8
|
-
extend DeepSeek::Chat
|
6
|
+
class DeepSeek < OpenAI
|
7
|
+
include DeepSeek::Chat
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
def api_base(_config)
|
9
|
+
def api_base
|
13
10
|
'https://api.deepseek.com'
|
14
11
|
end
|
15
12
|
|
16
|
-
def headers
|
13
|
+
def headers
|
17
14
|
{
|
18
|
-
'Authorization' => "Bearer #{config.deepseek_api_key}"
|
15
|
+
'Authorization' => "Bearer #{@config.deepseek_api_key}"
|
19
16
|
}
|
20
17
|
end
|
21
18
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
def slug
|
27
|
-
'deepseek'
|
28
|
-
end
|
19
|
+
class << self
|
20
|
+
def capabilities
|
21
|
+
DeepSeek::Capabilities
|
22
|
+
end
|
29
23
|
|
30
|
-
|
31
|
-
|
24
|
+
def configuration_requirements
|
25
|
+
%i[deepseek_api_key]
|
26
|
+
end
|
32
27
|
end
|
33
28
|
end
|
34
29
|
end
|