Class: Locallingo::Providers::RubyLLM

Inherits:
Object
  • Object
show all
Defined in:
lib/locallingo/providers/ruby_llm.rb

Overview

Thin wrapper over the ruby_llm gem. Every translation and quality-review call goes through here so the rest of the gem never touches a provider SDK directly and stays provider-agnostic.

A fresh chat is created per call (assume_model_exists: true skips RubyLLM's registry lookup — the configured model id is the source of truth) so independent batches don't share conversation history. The response is parsed with the robust JsonExtraction extractor because not every provider guarantees fenceless JSON.

Constant Summary collapse

CREDENTIAL_ENV =

Maps a RubyLLM provider symbol to the ENV var whose presence indicates credentials are available, so we can fail fast with a clear message before making a network call.

{
  openai: "OPENAI_API_KEY",
  anthropic: "ANTHROPIC_API_KEY",
  gemini: "GEMINI_API_KEY",
  deepseek: "DEEPSEEK_API_KEY",
  openrouter: "OPENROUTER_API_KEY"
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(provider:) ⇒ RubyLLM

Returns a new instance of RubyLLM.



30
31
32
# File 'lib/locallingo/providers/ruby_llm.rb', line 30

def initialize(provider:)
  @provider = provider.to_sym
end

Instance Attribute Details

#providerObject (readonly)

Returns the value of attribute provider.



28
29
30
# File 'lib/locallingo/providers/ruby_llm.rb', line 28

def provider
  @provider
end

Instance Method Details

#chat(model:, instructions:, payload:) ⇒ Object

Send instructions (system prompt) + payload (user message, JSON) to the model and return the parsed JSON object as a Hash.



55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/locallingo/providers/ruby_llm.rb', line 55

def chat(model:, instructions:, payload:)
  require "ruby_llm"

  conversation = ::RubyLLM.chat(
    model:,
    provider:,
    assume_model_exists: true
  ).with_instructions(instructions)

  response = conversation.ask(JSON.pretty_generate(payload))
  JsonExtraction.extract_object(response.content)
end

#credentials?Boolean

True when credentials for the configured provider are present in ENV. Unknown providers are assumed configured (RubyLLM may source the key elsewhere) rather than blocking.

Returns:

  • (Boolean)


37
38
39
40
41
42
# File 'lib/locallingo/providers/ruby_llm.rb', line 37

def credentials?
  env = CREDENTIAL_ENV[provider]
  return true unless env

  !ENV.fetch(env, "").to_s.strip.empty?
end

#ensure_credentials!Object

Raise a precise error when the provider has no credentials.



45
46
47
48
49
50
51
# File 'lib/locallingo/providers/ruby_llm.rb', line 45

def ensure_credentials!
  return if credentials?

  raise MissingCredentialsError,
        "No credentials for provider #{provider.inspect} " \
        "(expected #{CREDENTIAL_ENV[provider]} in ENV)"
end