Class: Spacy::OpenAIHelper

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby-spacy/openai_helper.rb

Overview

A helper class for OpenAI API interactions, designed to work with spaCy's linguistic analysis via the block-based Language#with_llm / Language#with_openai API.

With a custom base_url, this helper also works with any OpenAI-compatible server such as Ollama, LM Studio, llama.cpp server, or vLLM.

Examples:

Basic usage with linguistic_summary

nlp = Spacy::Language.new("en_core_web_sm")
nlp.with_openai(model: "gpt-5-mini") do |ai|
  doc = nlp.read("Apple Inc. was founded by Steve Jobs.")
  ai.chat(system: "Analyze the linguistic data.", user: doc.linguistic_summary)
end

Local model via Ollama

nlp.with_llm(provider: :ollama, model: "llama3.2") do |ai|
  ai.chat(user: "Say hello.")
end

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(access_token: nil, model: OpenAIClient::DEFAULT_MODEL, max_completion_tokens: 1000, max_tokens: nil, temperature: nil, base_url: nil) ⇒ OpenAIHelper

Creates a new OpenAIHelper instance.

Parameters:

  • access_token (String, nil) (defaults to: nil)

    OpenAI API key (defaults to OPENAI_API_KEY env var)

  • model (String) (defaults to: OpenAIClient::DEFAULT_MODEL)

    the default model for chat requests

  • max_completion_tokens (Integer) (defaults to: 1000)

    default maximum tokens in responses

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

    alias for max_completion_tokens (takes precedence)

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

    default sampling temperature (omitted from requests when nil; models that reject it are retried without it)

  • base_url (String, nil) (defaults to: nil)

    OpenAI-compatible API endpoint (e.g., "http://localhost:11434/v1" for Ollama)



35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/ruby-spacy/openai_helper.rb', line 35

def initialize(access_token: nil, model: OpenAIClient::DEFAULT_MODEL,
               max_completion_tokens: 1000, max_tokens: nil,
               temperature: nil, base_url: nil)
  @access_token = access_token || ENV["OPENAI_API_KEY"]
  raise "Error: OPENAI_API_KEY is not set" unless @access_token

  @model = model
  @default_max_completion_tokens = max_tokens || max_completion_tokens
  @default_temperature = temperature
  @client = OpenAIClient.new(access_token: @access_token,
                             base_url: base_url || OpenAIClient::API_ENDPOINT)
end

Instance Attribute Details

#modelString (readonly)

Returns the default model for chat requests.

Returns:

  • (String)

    the default model for chat requests



24
25
26
# File 'lib/ruby-spacy/openai_helper.rb', line 24

def model
  @model
end

Instance Method Details

#chat(system: nil, user: nil, messages: nil, model: nil, max_completion_tokens: nil, max_tokens: nil, temperature: nil, response_format: nil, schema: nil, raw: false) ⇒ String, ...

Sends a chat completion request.

Provides convenient system: and user: keyword arguments as shortcuts for building simple message arrays. For more complex conversations, pass a full messages: array directly.

Parameters:

  • system (String, nil) (defaults to: nil)

    system message content (shortcut)

  • user (String, nil) (defaults to: nil)

    user message content (shortcut)

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

    full message array (overrides system:/user:)

  • model (String, nil) (defaults to: nil)

    model override (defaults to instance model)

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

    token limit override

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

    alias for max_completion_tokens (takes precedence)

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

    temperature override

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

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

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

    JSON Schema for structured outputs; when given, the model output is constrained to the schema and the parsed Hash is returned. Objects in the schema must set additionalProperties: false and list all properties in required.

  • raw (Boolean) (defaults to: false)

    if true, returns the full API response Hash instead of text

Returns:

  • (String, Hash, nil)

    the response text, parsed Hash (if schema:), full response Hash (if raw:), or nil on API error or when the schema output cannot be parsed as JSON (e.g., truncated by the token limit)



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/ruby-spacy/openai_helper.rb', line 70

def chat(system: nil, user: nil, messages: nil,
         model: nil, max_completion_tokens: nil, max_tokens: nil,
         temperature: nil, response_format: nil, schema: nil, raw: false)
  msgs = messages || build_messages(system: system, user: user)
  raise ArgumentError, "No messages provided. Use system:/user: or messages:" if msgs.empty?

  if schema
    response_format = {
      type: "json_schema",
      json_schema: { name: "response", strict: true, schema: schema }
    }
  end

  response = @client.chat(
    model: model || @model,
    messages: msgs,
    max_completion_tokens: max_tokens || max_completion_tokens || @default_max_completion_tokens,
    temperature: temperature || @default_temperature,
    response_format: response_format
  )

  return response if raw

  choice = response.dig("choices", 0)
  if choice&.dig("finish_reason") == "length"
    warn "Warning: response was truncated (finish_reason: length); consider increasing max_completion_tokens"
  end

  content = choice&.dig("message", "content")
  schema && content ? parse_json_content(content) : content
rescue OpenAIClient::APIError => e
  warn "Error: OpenAI API call failed - #{e.message}"
  nil
end

#embeddings(text, model: OpenAIClient::DEFAULT_EMBEDDINGS_MODEL, dimensions: nil) ⇒ Array<Float>?

Generates text embeddings using the embeddings API.

Parameters:

  • text (String)

    the text to embed

  • model (String) (defaults to: OpenAIClient::DEFAULT_EMBEDDINGS_MODEL)

    the embeddings model

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

    number of dimensions (nil uses model default)

Returns:

  • (Array<Float>, nil)

    the embedding vector, or nil on error



111
112
113
114
115
116
117
# File 'lib/ruby-spacy/openai_helper.rb', line 111

def embeddings(text, model: OpenAIClient::DEFAULT_EMBEDDINGS_MODEL, dimensions: nil)
  response = @client.embeddings(model: model, input: text, dimensions: dimensions)
  response.dig("data", 0, "embedding")
rescue OpenAIClient::APIError => e
  warn "Error: OpenAI API call failed - #{e.message}"
  nil
end