fix(captain): força provider :openai quando há config dedicada de embedding

RubyLLM auto-detecta provider pelo prefixo do nome do modelo (ex:
`gemini-*` → provider Gemini → exige `gemini_api_key`). Quando temos
config dedicada de embedding (CAPTAIN_EMBEDDING_API_KEY) apontando pra
endpoint OpenAI-compatible (ex: Gemini OpenAI-compat em
generativelanguage.googleapis.com/v1beta/openai), queremos que o RubyLLM
mande a request via OpenAI client mesmo que o nome do modelo bata com
outro provider.

Solução: passar provider: :openai e assume_model_exists: true ao chamar
embed quando dedicated_embedding_config? retornar true. Sem isso, o
RubyLLM falha com `Missing configuration for Gemini: gemini_api_key`
mesmo com a key correta setada.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Rodribm10 2026-05-01 16:18:50 -03:00
parent 2ade066468
commit 60759b955c

View File

@ -40,11 +40,22 @@ class Captain::Llm::EmbeddingService
api_base = settings[:api_base].present? ? "#{settings[:api_base]}/v1" : nil
embed_options = embed_extra_options
# Quando há config dedicada de embedding (CAPTAIN_EMBEDDING_API_KEY etc),
# forçamos provider :openai pra que o RubyLLM trate como OpenAI-compatible
# mesmo com modelos cujo nome auto-detectaria outro provider (ex:
# `gemini-embedding-001` apontado pro endpoint Gemini OpenAI-compat).
embed_options[:provider] = :openai if dedicated_embedding_config?
embed_options[:assume_model_exists] = true if dedicated_embedding_config?
Llm::Config.with_api_key(settings[:api_key], api_base: api_base) do |ctx|
ctx.embed(content, model: model, **embed_options).vectors
end
end
def dedicated_embedding_config?
installation_config_value('CAPTAIN_EMBEDDING_API_KEY').present?
end
def embedding_settings
custom_key = installation_config_value('CAPTAIN_EMBEDDING_API_KEY')
return Captain::Llm::ProviderConfig.legacy_openai_settings if custom_key.blank?