Class: Ask::Providers::Mistral

Inherits:
Ask::Provider
  • Object
show all
Defined in:
lib/ask/provider/mistral.rb

Overview

Mistral AI provider. Uses OpenAI-compatible wire format.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config = {}) ⇒ Mistral

Returns a new instance of Mistral.



7
8
9
10
11
# File 'lib/ask/provider/mistral.rb', line 7

def initialize(config = {})
  config = normalize_config(config)
  super(config)
  @http = build_http
end

Class Method Details

.capabilitiesObject



47
48
49
# File 'lib/ask/provider/mistral.rb', line 47

def capabilities
  { chat: true, streaming: true, tool_calls: true, structured_output: true, embed: true }
end

.configuration_optionsObject



50
# File 'lib/ask/provider/mistral.rb', line 50

def configuration_options; %i[api_key api_base]; end

.configuration_requirementsObject



51
# File 'lib/ask/provider/mistral.rb', line 51

def configuration_requirements; %i[api_key]; end

.slugObject



52
# File 'lib/ask/provider/mistral.rb', line 52

def slug; "mistral"; end

Instance Method Details

#api_baseObject



13
14
15
# File 'lib/ask/provider/mistral.rb', line 13

def api_base
  @config.api_base || "https://api.mistral.ai/v1"
end

#chat(messages, model:, tools: nil, temperature: nil, stream: nil, schema: nil, **params, &block) ⇒ Object



21
22
23
24
25
# File 'lib/ask/provider/mistral.rb', line 21

def chat(messages, model:, tools: nil, temperature: nil, stream: nil, schema: nil, **params, &block)
  # Reuse OpenAI provider's logic since Mistral is OpenAI-compatible
  openai = Providers::OpenAI.new(api_key: @config.api_key, base_url: api_base)
  openai.chat(messages, model: model, tools: tools, temperature: temperature, stream: stream, schema: schema, **params, &block)
end

#embed(texts, model:) ⇒ Object



27
28
29
30
31
32
33
# File 'lib/ask/provider/mistral.rb', line 27

def embed(texts, model:)
  texts = Array(texts)
  response = @http.post("embeddings") { |r| r.body = { model: model, input: texts } }
  raise LLM::HTTP.map_error(response.status, response.body, provider: "Mistral") unless response.success?
  embeddings = response.body["data"].map { |d| d["embedding"] }
  Ask::Result.success(embeddings.one? ? embeddings.first : embeddings)
end

#headersObject



17
18
19
# File 'lib/ask/provider/mistral.rb', line 17

def headers
  { "Content-Type" => "application/json", "Authorization" => "Bearer #{@config.api_key}" }.compact
end

#list_modelsObject



35
36
37
38
39
# File 'lib/ask/provider/mistral.rb', line 35

def list_models
  response = @http.get("models")
  return [] unless response.success?
  response.body["data"].map { |m| Ask::ModelInfo.new(id: m["id"], provider: slug) }
end

#parse_error(response) ⇒ Object



41
42
43
44
# File 'lib/ask/provider/mistral.rb', line 41

def parse_error(response)
  body = response.body rescue nil
  body&.dig("error", "message") || body&.dig("error", "type")
end