Class: Truffle::Providers::OpenAI

Inherits:
Base
  • Object
show all
Defined in:
lib/truffle/providers/openai.rb

Overview

OpenAI Chat Completions provider with tool calling.

Deliberately dependency-free: it speaks the HTTP API directly with Net::HTTP and the stdlib JSON, so a fresh Ruby can run Truffle with nothing but gem install truffle. It also works against any OpenAI-compatible endpoint (Ollama, vLLM, Together, OpenRouter, ...) by passing :base_url.

Constant Summary collapse

DEFAULT_MODEL =
"gpt-4o-mini"
DEFAULT_BASE_URL =
"https://api.openai.com/v1"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(api_key: ENV["OPENAI_API_KEY"], model: DEFAULT_MODEL, base_url: DEFAULT_BASE_URL, open_timeout: 15, read_timeout: 120) ⇒ OpenAI

Returns a new instance of OpenAI.

Raises:

  • (ArgumentError)


21
22
23
24
25
26
27
28
29
30
31
# File 'lib/truffle/providers/openai.rb', line 21

def initialize(api_key: ENV["OPENAI_API_KEY"], model: DEFAULT_MODEL,
               base_url: DEFAULT_BASE_URL, open_timeout: 15, read_timeout: 120)
  super()
  raise ArgumentError, "missing OpenAI API key (set OPENAI_API_KEY or pass :api_key)" if api_key.nil? || api_key.empty?

  @api_key = api_key
  @model = model
  @base_url = base_url.chomp("/")
  @open_timeout = open_timeout
  @read_timeout = read_timeout
end

Instance Attribute Details

#modelObject (readonly)

Returns the value of attribute model.



19
20
21
# File 'lib/truffle/providers/openai.rb', line 19

def model
  @model
end

Instance Method Details

#chat(messages:, tools: [], model: nil, **options) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/truffle/providers/openai.rb', line 37

def chat(messages:, tools: [], model: nil, **options)
  body = {
    model: model || @model,
    messages: serialize_messages(messages)
  }
  unless tools.empty?
    body[:tools] = tools.map { |t| { type: "function", function: t } }
    body[:tool_choice] = options.fetch(:tool_choice, "auto")
  end
  body[:temperature] = options[:temperature] if options.key?(:temperature)
  body[:max_tokens] = options[:max_tokens] if options.key?(:max_tokens)

  payload = post("/chat/completions", body)
  choice = payload.fetch("choices").first
  Response.new(
    message: deserialize_message(choice.fetch("message")),
    usage: payload["usage"] || {},
    raw: payload,
    model: payload["model"],
    finish_reason: choice["finish_reason"]
  )
end

#nameObject



33
34
35
# File 'lib/truffle/providers/openai.rb', line 33

def name
  "openai"
end