ruby_llm_swarm 1.9.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +175 -0
- data/lib/generators/ruby_llm/chat_ui/chat_ui_generator.rb +187 -0
- data/lib/generators/ruby_llm/chat_ui/templates/controllers/chats_controller.rb.tt +39 -0
- data/lib/generators/ruby_llm/chat_ui/templates/controllers/messages_controller.rb.tt +24 -0
- data/lib/generators/ruby_llm/chat_ui/templates/controllers/models_controller.rb.tt +14 -0
- data/lib/generators/ruby_llm/chat_ui/templates/jobs/chat_response_job.rb.tt +12 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/chats/_chat.html.erb.tt +16 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/chats/_form.html.erb.tt +29 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/chats/index.html.erb.tt +16 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/chats/new.html.erb.tt +11 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/chats/show.html.erb.tt +23 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_content.html.erb.tt +1 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_form.html.erb.tt +21 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_message.html.erb.tt +13 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_tool_calls.html.erb.tt +7 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/messages/create.turbo_stream.erb.tt +9 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/models/_model.html.erb.tt +16 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/models/index.html.erb.tt +28 -0
- data/lib/generators/ruby_llm/chat_ui/templates/views/models/show.html.erb.tt +18 -0
- data/lib/generators/ruby_llm/generator_helpers.rb +194 -0
- data/lib/generators/ruby_llm/install/install_generator.rb +106 -0
- data/lib/generators/ruby_llm/install/templates/add_references_to_chats_tool_calls_and_messages_migration.rb.tt +9 -0
- data/lib/generators/ruby_llm/install/templates/chat_model.rb.tt +3 -0
- data/lib/generators/ruby_llm/install/templates/create_chats_migration.rb.tt +7 -0
- data/lib/generators/ruby_llm/install/templates/create_messages_migration.rb.tt +16 -0
- data/lib/generators/ruby_llm/install/templates/create_models_migration.rb.tt +45 -0
- data/lib/generators/ruby_llm/install/templates/create_tool_calls_migration.rb.tt +20 -0
- data/lib/generators/ruby_llm/install/templates/initializer.rb.tt +12 -0
- data/lib/generators/ruby_llm/install/templates/message_model.rb.tt +4 -0
- data/lib/generators/ruby_llm/install/templates/model_model.rb.tt +3 -0
- data/lib/generators/ruby_llm/install/templates/tool_call_model.rb.tt +3 -0
- data/lib/generators/ruby_llm/upgrade_to_v1_7/templates/migration.rb.tt +145 -0
- data/lib/generators/ruby_llm/upgrade_to_v1_7/upgrade_to_v1_7_generator.rb +124 -0
- data/lib/generators/ruby_llm/upgrade_to_v1_9/templates/add_v1_9_message_columns.rb.tt +15 -0
- data/lib/generators/ruby_llm/upgrade_to_v1_9/upgrade_to_v1_9_generator.rb +49 -0
- data/lib/ruby_llm/active_record/acts_as.rb +174 -0
- data/lib/ruby_llm/active_record/acts_as_legacy.rb +384 -0
- data/lib/ruby_llm/active_record/chat_methods.rb +350 -0
- data/lib/ruby_llm/active_record/message_methods.rb +81 -0
- data/lib/ruby_llm/active_record/model_methods.rb +84 -0
- data/lib/ruby_llm/aliases.json +295 -0
- data/lib/ruby_llm/aliases.rb +38 -0
- data/lib/ruby_llm/attachment.rb +220 -0
- data/lib/ruby_llm/chat.rb +816 -0
- data/lib/ruby_llm/chunk.rb +6 -0
- data/lib/ruby_llm/configuration.rb +78 -0
- data/lib/ruby_llm/connection.rb +126 -0
- data/lib/ruby_llm/content.rb +73 -0
- data/lib/ruby_llm/context.rb +29 -0
- data/lib/ruby_llm/embedding.rb +29 -0
- data/lib/ruby_llm/error.rb +84 -0
- data/lib/ruby_llm/image.rb +49 -0
- data/lib/ruby_llm/message.rb +86 -0
- data/lib/ruby_llm/mime_type.rb +71 -0
- data/lib/ruby_llm/model/info.rb +111 -0
- data/lib/ruby_llm/model/modalities.rb +22 -0
- data/lib/ruby_llm/model/pricing.rb +48 -0
- data/lib/ruby_llm/model/pricing_category.rb +46 -0
- data/lib/ruby_llm/model/pricing_tier.rb +33 -0
- data/lib/ruby_llm/model.rb +7 -0
- data/lib/ruby_llm/models.json +33198 -0
- data/lib/ruby_llm/models.rb +231 -0
- data/lib/ruby_llm/models_schema.json +168 -0
- data/lib/ruby_llm/moderation.rb +56 -0
- data/lib/ruby_llm/provider.rb +243 -0
- data/lib/ruby_llm/providers/anthropic/capabilities.rb +134 -0
- data/lib/ruby_llm/providers/anthropic/chat.rb +125 -0
- data/lib/ruby_llm/providers/anthropic/content.rb +44 -0
- data/lib/ruby_llm/providers/anthropic/embeddings.rb +20 -0
- data/lib/ruby_llm/providers/anthropic/media.rb +92 -0
- data/lib/ruby_llm/providers/anthropic/models.rb +63 -0
- data/lib/ruby_llm/providers/anthropic/streaming.rb +45 -0
- data/lib/ruby_llm/providers/anthropic/tools.rb +109 -0
- data/lib/ruby_llm/providers/anthropic.rb +36 -0
- data/lib/ruby_llm/providers/bedrock/capabilities.rb +167 -0
- data/lib/ruby_llm/providers/bedrock/chat.rb +63 -0
- data/lib/ruby_llm/providers/bedrock/media.rb +61 -0
- data/lib/ruby_llm/providers/bedrock/models.rb +98 -0
- data/lib/ruby_llm/providers/bedrock/signing.rb +831 -0
- data/lib/ruby_llm/providers/bedrock/streaming/base.rb +51 -0
- data/lib/ruby_llm/providers/bedrock/streaming/content_extraction.rb +71 -0
- data/lib/ruby_llm/providers/bedrock/streaming/message_processing.rb +67 -0
- data/lib/ruby_llm/providers/bedrock/streaming/payload_processing.rb +80 -0
- data/lib/ruby_llm/providers/bedrock/streaming/prelude_handling.rb +78 -0
- data/lib/ruby_llm/providers/bedrock/streaming.rb +18 -0
- data/lib/ruby_llm/providers/bedrock.rb +82 -0
- data/lib/ruby_llm/providers/deepseek/capabilities.rb +130 -0
- data/lib/ruby_llm/providers/deepseek/chat.rb +16 -0
- data/lib/ruby_llm/providers/deepseek.rb +30 -0
- data/lib/ruby_llm/providers/gemini/capabilities.rb +281 -0
- data/lib/ruby_llm/providers/gemini/chat.rb +454 -0
- data/lib/ruby_llm/providers/gemini/embeddings.rb +37 -0
- data/lib/ruby_llm/providers/gemini/images.rb +47 -0
- data/lib/ruby_llm/providers/gemini/media.rb +112 -0
- data/lib/ruby_llm/providers/gemini/models.rb +40 -0
- data/lib/ruby_llm/providers/gemini/streaming.rb +61 -0
- data/lib/ruby_llm/providers/gemini/tools.rb +198 -0
- data/lib/ruby_llm/providers/gemini/transcription.rb +116 -0
- data/lib/ruby_llm/providers/gemini.rb +37 -0
- data/lib/ruby_llm/providers/gpustack/chat.rb +27 -0
- data/lib/ruby_llm/providers/gpustack/media.rb +46 -0
- data/lib/ruby_llm/providers/gpustack/models.rb +90 -0
- data/lib/ruby_llm/providers/gpustack.rb +34 -0
- data/lib/ruby_llm/providers/mistral/capabilities.rb +155 -0
- data/lib/ruby_llm/providers/mistral/chat.rb +24 -0
- data/lib/ruby_llm/providers/mistral/embeddings.rb +33 -0
- data/lib/ruby_llm/providers/mistral/models.rb +48 -0
- data/lib/ruby_llm/providers/mistral.rb +32 -0
- data/lib/ruby_llm/providers/ollama/chat.rb +27 -0
- data/lib/ruby_llm/providers/ollama/media.rb +46 -0
- data/lib/ruby_llm/providers/ollama/models.rb +36 -0
- data/lib/ruby_llm/providers/ollama.rb +30 -0
- data/lib/ruby_llm/providers/openai/capabilities.rb +299 -0
- data/lib/ruby_llm/providers/openai/chat.rb +88 -0
- data/lib/ruby_llm/providers/openai/embeddings.rb +33 -0
- data/lib/ruby_llm/providers/openai/images.rb +38 -0
- data/lib/ruby_llm/providers/openai/media.rb +81 -0
- data/lib/ruby_llm/providers/openai/models.rb +39 -0
- data/lib/ruby_llm/providers/openai/moderation.rb +34 -0
- data/lib/ruby_llm/providers/openai/streaming.rb +46 -0
- data/lib/ruby_llm/providers/openai/tools.rb +98 -0
- data/lib/ruby_llm/providers/openai/transcription.rb +70 -0
- data/lib/ruby_llm/providers/openai.rb +44 -0
- data/lib/ruby_llm/providers/openai_responses.rb +395 -0
- data/lib/ruby_llm/providers/openrouter/models.rb +73 -0
- data/lib/ruby_llm/providers/openrouter.rb +26 -0
- data/lib/ruby_llm/providers/perplexity/capabilities.rb +137 -0
- data/lib/ruby_llm/providers/perplexity/chat.rb +16 -0
- data/lib/ruby_llm/providers/perplexity/models.rb +42 -0
- data/lib/ruby_llm/providers/perplexity.rb +48 -0
- data/lib/ruby_llm/providers/vertexai/chat.rb +14 -0
- data/lib/ruby_llm/providers/vertexai/embeddings.rb +32 -0
- data/lib/ruby_llm/providers/vertexai/models.rb +130 -0
- data/lib/ruby_llm/providers/vertexai/streaming.rb +14 -0
- data/lib/ruby_llm/providers/vertexai/transcription.rb +16 -0
- data/lib/ruby_llm/providers/vertexai.rb +55 -0
- data/lib/ruby_llm/railtie.rb +35 -0
- data/lib/ruby_llm/responses_session.rb +77 -0
- data/lib/ruby_llm/stream_accumulator.rb +101 -0
- data/lib/ruby_llm/streaming.rb +153 -0
- data/lib/ruby_llm/tool.rb +209 -0
- data/lib/ruby_llm/tool_call.rb +22 -0
- data/lib/ruby_llm/tool_executors.rb +125 -0
- data/lib/ruby_llm/transcription.rb +35 -0
- data/lib/ruby_llm/utils.rb +91 -0
- data/lib/ruby_llm/version.rb +5 -0
- data/lib/ruby_llm.rb +140 -0
- data/lib/tasks/models.rake +525 -0
- data/lib/tasks/release.rake +67 -0
- data/lib/tasks/ruby_llm.rake +15 -0
- data/lib/tasks/vcr.rake +92 -0
- metadata +346 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RubyLLM
|
|
4
|
+
# Provides utility functions for data manipulation within the RubyLLM library
|
|
5
|
+
module Utils
|
|
6
|
+
module_function
|
|
7
|
+
|
|
8
|
+
def hash_get(hash, key)
|
|
9
|
+
hash[key.to_sym] || hash[key.to_s]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def to_safe_array(item)
|
|
13
|
+
case item
|
|
14
|
+
when Array
|
|
15
|
+
item
|
|
16
|
+
when Hash
|
|
17
|
+
[item]
|
|
18
|
+
else
|
|
19
|
+
Array(item)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def to_time(value)
|
|
24
|
+
return unless value
|
|
25
|
+
|
|
26
|
+
value.is_a?(Time) ? value : Time.parse(value.to_s)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def to_date(value)
|
|
30
|
+
return unless value
|
|
31
|
+
|
|
32
|
+
value.is_a?(Date) ? value : Date.parse(value.to_s)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def deep_merge(original, overrides)
|
|
36
|
+
original.merge(overrides) do |_key, original_value, overrides_value|
|
|
37
|
+
if original_value.is_a?(Hash) && overrides_value.is_a?(Hash)
|
|
38
|
+
deep_merge(original_value, overrides_value)
|
|
39
|
+
else
|
|
40
|
+
overrides_value
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def deep_dup(value)
|
|
46
|
+
case value
|
|
47
|
+
when Hash
|
|
48
|
+
value.each_with_object({}) do |(key, val), duped|
|
|
49
|
+
duped[deep_dup(key)] = deep_dup(val)
|
|
50
|
+
end
|
|
51
|
+
when Array
|
|
52
|
+
value.map { |item| deep_dup(item) }
|
|
53
|
+
else
|
|
54
|
+
begin
|
|
55
|
+
value.dup
|
|
56
|
+
rescue TypeError
|
|
57
|
+
value
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def deep_stringify_keys(value)
|
|
63
|
+
case value
|
|
64
|
+
when Hash
|
|
65
|
+
value.each_with_object({}) do |(key, val), result|
|
|
66
|
+
result[key.to_s] = deep_stringify_keys(val)
|
|
67
|
+
end
|
|
68
|
+
when Array
|
|
69
|
+
value.map { |item| deep_stringify_keys(item) }
|
|
70
|
+
when Symbol
|
|
71
|
+
value.to_s
|
|
72
|
+
else
|
|
73
|
+
value
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def deep_symbolize_keys(value)
|
|
78
|
+
case value
|
|
79
|
+
when Hash
|
|
80
|
+
value.each_with_object({}) do |(key, val), result|
|
|
81
|
+
symbolized_key = key.respond_to?(:to_sym) ? key.to_sym : key
|
|
82
|
+
result[symbolized_key] = deep_symbolize_keys(val)
|
|
83
|
+
end
|
|
84
|
+
when Array
|
|
85
|
+
value.map { |item| deep_symbolize_keys(item) }
|
|
86
|
+
else
|
|
87
|
+
value
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
data/lib/ruby_llm.rb
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'base64'
|
|
4
|
+
require 'event_stream_parser'
|
|
5
|
+
require 'faraday'
|
|
6
|
+
require 'faraday/multipart'
|
|
7
|
+
require 'faraday/retry'
|
|
8
|
+
require 'json'
|
|
9
|
+
require 'logger'
|
|
10
|
+
require 'marcel'
|
|
11
|
+
require 'securerandom'
|
|
12
|
+
require 'zeitwerk'
|
|
13
|
+
require 'async/http/faraday/default'
|
|
14
|
+
|
|
15
|
+
loader = Zeitwerk::Loader.for_gem
|
|
16
|
+
loader.inflector.inflect(
|
|
17
|
+
'ruby_llm' => 'RubyLLM',
|
|
18
|
+
'llm' => 'LLM',
|
|
19
|
+
'openai' => 'OpenAI',
|
|
20
|
+
'openai_responses' => 'OpenAIResponses',
|
|
21
|
+
'api' => 'API',
|
|
22
|
+
'deepseek' => 'DeepSeek',
|
|
23
|
+
'perplexity' => 'Perplexity',
|
|
24
|
+
'bedrock' => 'Bedrock',
|
|
25
|
+
'openrouter' => 'OpenRouter',
|
|
26
|
+
'gpustack' => 'GPUStack',
|
|
27
|
+
'mistral' => 'Mistral',
|
|
28
|
+
'vertexai' => 'VertexAI',
|
|
29
|
+
'pdf' => 'PDF',
|
|
30
|
+
'UI' => 'UI'
|
|
31
|
+
)
|
|
32
|
+
loader.ignore("#{__dir__}/tasks")
|
|
33
|
+
loader.ignore("#{__dir__}/generators")
|
|
34
|
+
loader.ignore("#{__dir__}/ruby_llm/railtie.rb")
|
|
35
|
+
loader.setup
|
|
36
|
+
|
|
37
|
+
# A delightful Ruby interface to modern AI language models.
|
|
38
|
+
module RubyLLM
|
|
39
|
+
class Error < StandardError; end
|
|
40
|
+
|
|
41
|
+
class << self
|
|
42
|
+
def context
|
|
43
|
+
context_config = config.dup
|
|
44
|
+
yield context_config if block_given?
|
|
45
|
+
Context.new(context_config)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def chat(...)
|
|
49
|
+
Chat.new(...)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def embed(...)
|
|
53
|
+
Embedding.embed(...)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def moderate(...)
|
|
57
|
+
Moderation.moderate(...)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def paint(...)
|
|
61
|
+
Image.paint(...)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def transcribe(...)
|
|
65
|
+
Transcription.transcribe(...)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def models
|
|
69
|
+
Models.instance
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def providers
|
|
73
|
+
Provider.providers.values
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def configure
|
|
77
|
+
yield config
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def config
|
|
81
|
+
@config ||= Configuration.new
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def logger
|
|
85
|
+
@logger ||= config.logger || Logger.new(
|
|
86
|
+
config.log_file,
|
|
87
|
+
progname: 'RubyLLM',
|
|
88
|
+
level: config.log_level
|
|
89
|
+
)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Registry for tool execution strategies.
|
|
93
|
+
# Executors receive an array of tool_calls and a block to execute each one.
|
|
94
|
+
# They must return a hash mapping tool_call.id to result.
|
|
95
|
+
#
|
|
96
|
+
# @return [Hash{Symbol => Proc}] Map of executor names to implementations
|
|
97
|
+
def tool_executors
|
|
98
|
+
@tool_executors ||= {}
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Registers a new tool executor for concurrent execution.
|
|
102
|
+
#
|
|
103
|
+
# @param name [Symbol] Executor name (e.g., :async, :threads)
|
|
104
|
+
# @yield [tool_calls, max_concurrency:, &execute] Block that executes tools concurrently
|
|
105
|
+
# @yieldparam tool_calls [Array<ToolCall>] Tools to execute
|
|
106
|
+
# @yieldparam max_concurrency [Integer, nil] Maximum concurrent executions
|
|
107
|
+
# @yieldparam execute [Proc] Block to call for each tool
|
|
108
|
+
# @yieldreturn [Hash{String => Object}] Map of tool_call.id to result
|
|
109
|
+
#
|
|
110
|
+
# @example
|
|
111
|
+
# RubyLLM.register_tool_executor(:custom) do |tool_calls, max_concurrency:, &execute|
|
|
112
|
+
# results = {}
|
|
113
|
+
# tool_calls.each { |tc| results[tc.id] = execute.call(tc) }
|
|
114
|
+
# results
|
|
115
|
+
# end
|
|
116
|
+
def register_tool_executor(name, &block)
|
|
117
|
+
tool_executors[name] = block
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
RubyLLM::Provider.register :anthropic, RubyLLM::Providers::Anthropic
|
|
123
|
+
RubyLLM::Provider.register :bedrock, RubyLLM::Providers::Bedrock
|
|
124
|
+
RubyLLM::Provider.register :deepseek, RubyLLM::Providers::DeepSeek
|
|
125
|
+
RubyLLM::Provider.register :gemini, RubyLLM::Providers::Gemini
|
|
126
|
+
RubyLLM::Provider.register :gpustack, RubyLLM::Providers::GPUStack
|
|
127
|
+
RubyLLM::Provider.register :mistral, RubyLLM::Providers::Mistral
|
|
128
|
+
RubyLLM::Provider.register :ollama, RubyLLM::Providers::Ollama
|
|
129
|
+
RubyLLM::Provider.register :openai, RubyLLM::Providers::OpenAI
|
|
130
|
+
RubyLLM::Provider.register :openrouter, RubyLLM::Providers::OpenRouter
|
|
131
|
+
RubyLLM::Provider.register :perplexity, RubyLLM::Providers::Perplexity
|
|
132
|
+
RubyLLM::Provider.register :vertexai, RubyLLM::Providers::VertexAI
|
|
133
|
+
|
|
134
|
+
# Load built-in tool executors for concurrent execution
|
|
135
|
+
require_relative 'ruby_llm/tool_executors'
|
|
136
|
+
|
|
137
|
+
if defined?(Rails::Railtie)
|
|
138
|
+
require 'ruby_llm/railtie'
|
|
139
|
+
require 'ruby_llm/active_record/acts_as'
|
|
140
|
+
end
|