Class: Spacy::OpenAIClient

Inherits:
LLMClientBase show all
Defined in:
lib/ruby-spacy/openai_client.rb

Overview

A lightweight OpenAI API client with tools support. This client implements the chat completions and embeddings endpoints without external dependencies.

A custom base_url makes it work with any OpenAI-compatible server (Ollama, LM Studio, llama.cpp server, vLLM, OpenRouter, etc.).

Constant Summary collapse

API_ENDPOINT =

Default OpenAI API endpoint

"https://api.openai.com/v1"
DEFAULT_MODEL =

Default model for chat requests

"gpt-5-mini"
DEFAULT_EMBEDDINGS_MODEL =

Default model for embeddings requests

"text-embedding-3-small"
APIError =

Raised when an LLM API request fails after retries; carries the HTTP status code and the parsed response body when available.

LLMClientBase::APIError

Constants inherited from LLMClientBase

LLMClientBase::BASE_RETRY_DELAY, LLMClientBase::DEFAULT_TIMEOUT, LLMClientBase::MAX_RETRIES

Instance Method Summary collapse

Constructor Details

#initialize(access_token:, timeout: DEFAULT_TIMEOUT, base_url: API_ENDPOINT) ⇒ OpenAIClient

Returns a new instance of OpenAIClient.

Parameters:

  • access_token (String)

    API key ("ollama" or any placeholder for local servers)

  • timeout (Integer) (defaults to: DEFAULT_TIMEOUT)

    request timeout in seconds

  • base_url (String) (defaults to: API_ENDPOINT)

    API endpoint; include the version path (e.g., "http://localhost:11434/v1" for Ollama)



26
27
28
29
# File 'lib/ruby-spacy/openai_client.rb', line 26

def initialize(access_token:, timeout: DEFAULT_TIMEOUT, base_url: API_ENDPOINT)
  super(base_url: base_url, timeout: timeout)
  @access_token = access_token
end

Instance Method Details

#chat(model:, messages:, max_completion_tokens: 1000, temperature: nil, tools: nil, tool_choice: nil, response_format: nil) ⇒ Hash

Sends a chat completion request with optional tools support.

The temperature parameter is sent only when explicitly given. If the model rejects it (e.g., GPT-5 series and o-series models), the request is retried once without it.

Parameters:

  • model (String)

    The model to use (e.g., "gpt-5-mini")

  • messages (Array<Hash>)

    The conversation messages

  • max_completion_tokens (Integer) (defaults to: 1000)

    Maximum tokens in the response

  • temperature (Float, nil) (defaults to: nil)

    Sampling temperature (omitted when nil)

  • tools (Array<Hash>, nil) (defaults to: nil)

    Tool definitions for function calling

  • tool_choice (String, Hash, nil) (defaults to: nil)

    Tool selection strategy

  • response_format (Hash, nil) (defaults to: nil)

    Response format specification (e.g., { type: "json_object" })

Returns:

  • (Hash)

    The API response



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/ruby-spacy/openai_client.rb', line 45

def chat(model:, messages:, max_completion_tokens: 1000, temperature: nil, tools: nil, tool_choice: nil, response_format: nil)
  body = {
    model: model,
    messages: messages,
    max_completion_tokens: max_completion_tokens
  }
  body[:temperature] = temperature unless temperature.nil?

  if tools && !tools.empty?
    body[:tools] = tools
    body[:tool_choice] = tool_choice || "auto"
  end

  body[:response_format] = response_format if response_format

  post_with_temperature_fallback("/chat/completions", body)
end

#embeddings(model:, input:, dimensions: nil) ⇒ Hash

Sends an embeddings request.

Parameters:

  • model (String)

    The embeddings model (e.g., "text-embedding-3-small")

  • input (String)

    The text to embed

  • dimensions (Integer, nil) (defaults to: nil)

    The number of dimensions for the output embeddings

Returns:

  • (Hash)

    The API response



69
70
71
72
73
74
75
76
77
# File 'lib/ruby-spacy/openai_client.rb', line 69

def embeddings(model:, input:, dimensions: nil)
  body = {
    model: model,
    input: input
  }
  body[:dimensions] = dimensions if dimensions

  post("/embeddings", body)
end