Module: LLM
- Extended by:
- LLM
- Included in:
- LLM
- Defined in:
- lib/llm.rb,
lib/llm/eval.rb,
lib/llm/lock.rb,
lib/llm/pipe.rb,
lib/llm/step.rb,
lib/llm/agent.rb,
lib/llm/error.rb,
lib/llm/utils.rb,
lib/llm/buffer.rb,
lib/llm/rescue.rb,
lib/llm/stream.rb,
lib/llm/tracer.rb,
lib/llm/console.rb,
lib/llm/context.rb,
lib/llm/message.rb,
lib/llm/session.rb,
lib/llm/uridata.rb,
lib/llm/version.rb,
lib/llm/contract.rb,
lib/llm/response.rb,
lib/llm/compactor.rb,
lib/llm/intercept.rb,
lib/llm/transport.rb,
lib/llm/tracer/null.rb,
lib/llm/eventhandler.rb,
lib/llm/json_adapter.rb,
lib/llm/providers/xai.rb,
lib/llm/providers/zai.rb,
lib/llm/tracer/logger.rb,
lib/llm/message_filter.rb,
lib/llm/providers/hanzo.rb,
lib/llm/request_adapter.rb,
lib/llm/providers/google.rb,
lib/llm/providers/ollama.rb,
lib/llm/providers/openai.rb,
lib/llm/tracer/telemetry.rb,
lib/llm/providers/alibaba.rb,
lib/llm/providers/bedrock.rb,
lib/llm/providers/mistral.rb,
lib/llm/providers/deepseek.rb,
lib/llm/providers/llamacpp.rb,
lib/llm/providers/moonshot.rb,
lib/llm/providers/anthropic.rb,
lib/llm/providers/deepinfra.rb,
lib/llm/providers/openrouter.rb,
lib/llm/tracer/enhanced_logger.rb
Overview
An agentic runtime.
Defined Under Namespace
Modules: ActiveRecord, Contract, Gem, Lock, RbConfig, RequestAdapter, Rescue, Sequel, Step, Utils Classes: A2A, Agent, Alibaba, Anthropic, Bedrock, Buffer, Command, Compactor, Console, Context, Cost, DeepInfra, DeepSeek, Error, Eval, File, Function, Google, Hanzo, Intercept, JSONAdapter, LlamaCpp, MCP, Message, MessageFilter, Mistral, Model, Moonshot, Object, Ollama, OpenAI, OpenRouter, Paint, Pipe, Prompt, Provider, Registry, Response, Schema, ServerTool, Stream, Tool, Tracer, Transport, URIData, Usage, XAI, ZAI
Constant Summary collapse
- UNDEFINED =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
::Object.new.freeze
Class.new(Error)
- RateLimitError =
HTTPTooManyRequests
Class.new(Error)
- InsufficientQuotaError =
A tokens-per-minute (TPM) rate limit. Alibaba reports this as
Throttling.AllocationQuota/insufficient_quota. It is a rate limit (retriable), distinct from a request-rate limit only for classification. Class.new(RateLimitError)
- ServerError =
HTTPServerError
Class.new(Error)
- NotFoundError =
HTTPNotFound
Class.new(Error)
- FormatError =
When an given an input object that is not understood
Class.new(Error)
- PromptError =
When given a prompt object that is not understood
Class.new(FormatError)
- InvalidRequestError =
When given an invalid request
Class.new(Error)
- ContextWindowError =
When the context window is exceeded
Class.new(InvalidRequestError)
- Interrupt =
When a request is interrupted.
It sits outside
StandardError, so that neither a barerescuenor arescue => ecan swallow it by mistake: an interrupt is a request to stop, and a turn whose cancel was eaten looks like a turn that ignored one.It is not a
SignalExceptioneither. A signal is a framework's own condition rather than a task's - RSpec re-raises one that escapes an example, and an async reactor ends its own thread rather than failing the task that raised it - and an interrupt has to be something a caller can catch. Class.new(Exception)
- RactorError =
When a concurrency strategy cannot execute a given tool
Class.new(Error)
- FiberError =
When a fiber tool's scheduler cannot hold a cancel until the tool starts.
A cancel that arrives before a call opens is issued at the call's first instruction, and only a scheduler that implements
fiber_interruptcan be asked for a raise from there - it schedules the raise rather than issuing it. A scheduler that cannot is told so, rather than delivering the cancel before the call and never running the tool.Name it in full. Ruby has a
FiberErrorof its own, so a bareFiberErrorin a rescue written outside this namespace is core's rather than this one. Class.new(Error)
- NoSuchToolError =
When a tool call cannot be mapped to a local tool
Class.new(Error)
- NoSuchModelError =
When Registry can't map a model
Class.new(Error)
- NoSuchRegistryError =
When Registry can't map a registry
Class.new(Error)
- LoadError =
When an optional runtime dependency cannot be required
Class.new(Error)
- Repl =
Alias: LLM::Repl
Console- Session =
Deprecated.
Use Context instead. Scheduled for removal in v6.0.
Backward-compatible alias for LLM::Context
Context- VERSION =
"19.0.1"
Class Method Summary collapse
- .File(obj) ⇒ LLM::File
-
.debug(msg, io = debug_io)
Logs a debug message to
$stderr. - .debug_io=(io)
-
.debug_io ⇒ IO
The IO used by the LLM.debug method.
-
.debug_mode!
Toggles debug mode.
-
.debug_mode? ⇒ Boolean
Are we in debug mode?.
-
.require(name, version = nil) ⇒ Object
Requires an optional runtime dependency.
- .registry_for(llm) ⇒ LLM::Object
- .lock(name, &b) ⇒ Object private
-
.share!(obj) ⇒ Object
private
Tries to deep-freeze an object so it can be shared across ractors.
Instance Method Summary collapse
- #mcp(**opts) ⇒ LLM::MCP
-
#a2a(http:, binding: :rest) ⇒ LLM::A2A
Creates a new A2A client connected to a remote agent.
-
#function(key, &b) ⇒ LLM::Function
Define a function.
-
#interrupt(agent: nil, id: nil, attempts: 1, interval: 0.1) ⇒ LLM::Agent, false
Interrupt an agent.
-
#json ⇒ Class
Returns the JSON adapter used by the library.
-
#json=(adapter)
Sets the JSON adapter used by the library.
- #anthropic(key: UNDEFINED) ⇒ Object
- #google(key: UNDEFINED) ⇒ Object
- #ollama(key: nil) ⇒ Object
- #llamacpp(key: nil) ⇒ Object
- #deepseek(key: UNDEFINED) ⇒ Object
- #hanzo(key: UNDEFINED) ⇒ Object
- #openai(key: UNDEFINED) ⇒ Object
- #deepinfra(key: UNDEFINED) ⇒ Object
- #xai(key: UNDEFINED) ⇒ Object
- #mistral(key: UNDEFINED) ⇒ Object
- #zai(key: UNDEFINED) ⇒ Object
- #moonshot(key: UNDEFINED) ⇒ Object
- #openrouter(key: UNDEFINED) ⇒ Object
- #alibaba(key: UNDEFINED) ⇒ Object (also: #aliyun)
- #bedrock(access_key_id: UNDEFINED, secret_access_key: UNDEFINED, region: UNDEFINED) ⇒ Object
Class Method Details
.File(obj) ⇒ LLM::File
89 90 91 92 93 94 95 96 97 98 |
# File 'lib/llm/file.rb', line 89 def LLM.File(obj) case obj when File obj.close unless obj.closed? LLM.File(obj.path) when LLM::File, LLM::Response then obj when String then LLM::File.new(obj) else raise TypeError, "don't know how to handle #{obj.class} objects" end end |
.debug(msg, io = debug_io)
This method is a noop when the debug_mode: method returns false and when the $LLMRB_DEBUG variable is not set.
This method returns an undefined value.
Logs a debug message to $stderr
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
# File 'lib/llm.rb', line 192 def self.debug(msg, io = debug_io) return unless @debug_mode || ENV["LLMRB_DEBUG_MODE"] == "1" log = -> do io.puts sprintf("runtime llm.rb " \ "\n" \ "runtime.version %s" \ "\n" \ "runtime.message #{msg}" \ "\n" \ "runtime.info" \ "\n" \ " time.now %s" \ "\n" \ " ractor.main %s" \ "\n" \ " ractor.count %s" \ "\n" \ "\n", LLM::VERSION.to_s, Time.now.utc.to_s, Ractor.main? ? "yes" : "no", Ractor.count.to_s) end lock(:debug, &log) end |
.debug_io=(io)
Defaults to $stderr.
This method returns an undefined value.
224 225 226 |
# File 'lib/llm.rb', line 224 def self.debug_io=(io) @io = io end |
.debug_io ⇒ IO
The IO used by the debug method. Defaults to $stderr.
232 233 234 |
# File 'lib/llm.rb', line 232 def self.debug_io @io || $stderr end |
.debug_mode!
This method returns an undefined value.
Toggles debug mode
239 240 241 |
# File 'lib/llm.rb', line 239 def self.debug_mode! @debug_mode = !@debug_mode end |
.debug_mode? ⇒ Boolean
Are we in debug mode?
246 247 248 |
# File 'lib/llm.rb', line 246 def self.debug_mode? !!@debug_mode end |
.require(name, version = nil) ⇒ Object
Requires an optional runtime dependency
258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
# File 'lib/llm.rb', line 258 def self.require(name, version = nil) names = {"xchan" => "xchan.rb", "net/http/persistent" => "net-http-persistent", "unicode/display_width" => "unicode-display_width"} gem(names[name] || name, version) if version super(name) rescue ::LoadError name = names[name] || name raise LLM::LoadError, "#{name}#{version ? " #{version}" : ""} is an optional " \ "runtime dependency but it does not appear to be installed. " \ "Consider 'gem install #{name}', adding '#{name}' to your Gemfile or " \ "opting out of the functionality provided by '#{name}'" end |
.registry_for(llm) ⇒ LLM::Object
277 278 279 280 281 282 |
# File 'lib/llm.rb', line 277 def self.registry_for(llm) lock(:registry) do name = Symbol === llm ? llm : llm.name @registry[name] ||= Registry.for(name) end end |
.lock(name, &b) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
503 504 505 |
# File 'lib/llm.rb', line 503 def self.lock(name, &b) LLM::Lock.synchronize(name, &b) end |
.share!(obj) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method is used on class-level agent attributes that can be accessed across a Ractor boundary via a global reference (eg Agent.name).
Tries to deep-freeze an object so it can be shared across ractors. Might fail when the object cannot be deeply frozen. Failure is a noop that returns the parameter it is given.
41 42 43 44 45 46 |
# File 'lib/llm.rb', line 41 def self.share!(obj) ::Ractor.make_shareable(obj) rescue ::Ractor::Error debug "'#{obj.inspect}' cannot be made Ractor-shareable" obj end |
Instance Method Details
#mcp(**opts) ⇒ LLM::MCP
116 117 118 |
# File 'lib/llm.rb', line 116 def mcp(**opts) LLM::MCP.new(**opts) end |
#a2a(http:, binding: :rest) ⇒ LLM::A2A
Creates a new A2A client connected to a remote agent.
135 136 137 |
# File 'lib/llm.rb', line 135 def a2a(http:, binding: :rest) LLM::A2A.http(**http, binding:) end |
#function(key, &b) ⇒ LLM::Function
Define a function
154 155 156 |
# File 'lib/llm.rb', line 154 def function(key, &b) LLM::Function.new(key, &b) end |
#interrupt(agent: nil, id: nil, attempts: 1, interval: 0.1) ⇒ LLM::Agent, false
Interrupt an agent.
167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/llm.rb', line 167 def interrupt(agent: nil, id: nil, attempts: 1, interval: 0.1) attempts.times do |count| record = LLM::Agent.registry.find(agent:, id:) if record record.interrupt! return record else break if (count+1) == attempts sleep(interval) end end false end |
#json ⇒ Class
Returns the JSON adapter used by the library
288 289 290 |
# File 'lib/llm.rb', line 288 def json @json end |
#json=(adapter)
This should be set once from the main thread when your program starts. Defaults to LLM::JSONAdapter::JSON.
This method returns an undefined value.
Sets the JSON adapter used by the library
300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
# File 'lib/llm.rb', line 300 def json=(adapter) @json = case adapter.to_s when "JSON", "json" then JSONAdapter::JSON when "Oj", "oj" then JSONAdapter::Oj else is_class = Class === adapter is_subclass = is_class && adapter.ancestors.include?(LLM::JSONAdapter) if is_subclass adapter else raise TypeError, "Adapter must be a subclass of LLM::JSONAdapter" end end end |
#anthropic(key: UNDEFINED) ⇒ Object
319 320 321 322 323 324 325 326 |
# File 'lib/llm.rb', line 319 def anthropic(key: UNDEFINED, **) lock(:require) { require_relative "llm/providers/anthropic" unless defined?(LLM::Anthropic) } if key == UNDEFINED LLM::Anthropic.new(key: key(name: __method__), **) else LLM::Anthropic.new(key:, **) end end |
#google(key: UNDEFINED) ⇒ Object
331 332 333 334 335 336 337 338 |
# File 'lib/llm.rb', line 331 def google(key: UNDEFINED, **) lock(:require) { require_relative "llm/providers/google" unless defined?(LLM::Google) } if key == UNDEFINED LLM::Google.new(key: key(name: __method__), **) else LLM::Google.new(key:, **) end end |
#ollama(key: nil) ⇒ Object
343 344 345 346 |
# File 'lib/llm.rb', line 343 def ollama(key: nil, **) lock(:require) { require_relative "llm/providers/ollama" unless defined?(LLM::Ollama) } LLM::Ollama.new(key:, **) end |
#llamacpp(key: nil) ⇒ Object
351 352 353 354 |
# File 'lib/llm.rb', line 351 def llamacpp(key: nil, **) lock(:require) { require_relative "llm/providers/llamacpp" unless defined?(LLM::LlamaCpp) } LLM::LlamaCpp.new(key:, **) end |
#deepseek(key: UNDEFINED) ⇒ Object
359 360 361 362 363 364 365 366 |
# File 'lib/llm.rb', line 359 def deepseek(key: UNDEFINED, **) lock(:require) { require_relative "llm/providers/deepseek" unless defined?(LLM::DeepSeek) } if key == UNDEFINED LLM::DeepSeek.new(key: key(name: __method__), **) else LLM::DeepSeek.new(key:, **) end end |
#hanzo(key: UNDEFINED) ⇒ Object
371 372 373 374 375 376 377 378 |
# File 'lib/llm.rb', line 371 def hanzo(key: UNDEFINED, **) lock(:require) { require_relative "llm/providers/hanzo" unless defined?(LLM::Hanzo) } if key == UNDEFINED LLM::Hanzo.new(key: key(name: __method__), **) else LLM::Hanzo.new(key:, **) end end |
#openai(key: UNDEFINED) ⇒ Object
383 384 385 386 387 388 389 390 |
# File 'lib/llm.rb', line 383 def openai(key: UNDEFINED, **) lock(:require) { require_relative "llm/providers/openai" unless defined?(LLM::OpenAI) } if key == UNDEFINED LLM::OpenAI.new(key: key(name: __method__), **) else LLM::OpenAI.new(key:, **) end end |
#deepinfra(key: UNDEFINED) ⇒ Object
395 396 397 398 399 400 401 402 |
# File 'lib/llm.rb', line 395 def deepinfra(key: UNDEFINED, **) lock(:require) { require_relative "llm/providers/deepinfra" unless defined?(LLM::DeepInfra) } if key == UNDEFINED LLM::DeepInfra.new(key: key(name: __method__), **) else LLM::DeepInfra.new(key:, **) end end |
#xai(key: UNDEFINED) ⇒ Object
408 409 410 411 412 413 414 415 |
# File 'lib/llm.rb', line 408 def xai(key: UNDEFINED, **) lock(:require) { require_relative "llm/providers/xai" unless defined?(LLM::XAI) } if key == UNDEFINED LLM::XAI.new(key: key(name: __method__), **) else LLM::XAI.new(key:, **) end end |
#mistral(key: UNDEFINED) ⇒ Object
421 422 423 424 425 426 427 428 |
# File 'lib/llm.rb', line 421 def mistral(key: UNDEFINED, **) lock(:require) { require_relative "llm/providers/mistral" unless defined?(LLM::Mistral) } if key == UNDEFINED LLM::Mistral.new(key: key(name: __method__), **) else LLM::Mistral.new(key:, **) end end |
#zai(key: UNDEFINED) ⇒ Object
434 435 436 437 438 439 440 441 |
# File 'lib/llm.rb', line 434 def zai(key: UNDEFINED, **) lock(:require) { require_relative "llm/providers/zai" unless defined?(LLM::ZAI) } if key == UNDEFINED LLM::ZAI.new(key: key(name: __method__), **) else LLM::ZAI.new(key:, **) end end |
#moonshot(key: UNDEFINED) ⇒ Object
447 448 449 450 451 452 453 454 |
# File 'lib/llm.rb', line 447 def moonshot(key: UNDEFINED, **) lock(:require) { require_relative "llm/providers/moonshot" unless defined?(LLM::Moonshot) } if key == UNDEFINED LLM::Moonshot.new(key: key(name: __method__), **) else LLM::Moonshot.new(key:, **) end end |
#openrouter(key: UNDEFINED) ⇒ Object
460 461 462 463 464 465 466 467 |
# File 'lib/llm.rb', line 460 def openrouter(key: UNDEFINED, **) lock(:require) { require_relative "llm/providers/openrouter" unless defined?(LLM::OpenRouter) } if key == UNDEFINED LLM::OpenRouter.new(key: key(name: __method__), **) else LLM::OpenRouter.new(key:, **) end end |
#alibaba(key: UNDEFINED) ⇒ Object Also known as: aliyun
473 474 475 476 477 478 479 480 |
# File 'lib/llm.rb', line 473 def alibaba(key: UNDEFINED, **) lock(:require) { require_relative "llm/providers/alibaba" unless defined?(LLM::Alibaba) } if key == UNDEFINED LLM::Alibaba.new(key: key(name: :alibaba), **) else LLM::Alibaba.new(key:, **) end end |
#bedrock(access_key_id: UNDEFINED, secret_access_key: UNDEFINED, region: UNDEFINED) ⇒ Object
486 487 488 489 490 491 492 493 494 495 496 497 498 499 |
# File 'lib/llm.rb', line 486 def bedrock(access_key_id: UNDEFINED, secret_access_key: UNDEFINED, region: UNDEFINED, **) lock(:require) { require_relative "llm/providers/bedrock" unless defined?(LLM::Bedrock) } if [access_key_id, secret_access_key, region].any? { _1 == UNDEFINED } access_key_id = ENV["AWS_ACCESS_KEY_ID"] if access_key_id == UNDEFINED secret_access_key = ENV["AWS_SECRET_ACCESS_KEY"] if secret_access_key == UNDEFINED region = ENV["AWS_REGION"] if region == UNDEFINED if access_key_id.to_s.strip.empty? || secret_access_key.to_s.strip.empty? raise ArgumentError, "you must provide an API key" end LLM::Bedrock.new(access_key_id:, secret_access_key:, region:, **) else LLM::Bedrock.new(access_key_id:, secret_access_key:, region:, **) end end |