Skip to content

Commit 883ecfc

Browse files
committed
feat(mistral): Enhance Mistral provider with new models and API integration
- Updated model aliases in aliases.json to include specific paths for Mistral models. - Added `mistral_api_base` configuration option in configuration.rb. - Introduced new models in models.json, including Mistral Tiny, Pixtral Large, and others. - Refactored Mistral provider methods to support new API structure and error handling. - Removed deprecated image generation methods from the Mistral provider. - Updated tests to reflect changes in model handling and API responses.
1 parent 0df2751 commit 883ecfc

File tree

55 files changed

+6682
-203
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+6682
-203
lines changed

lib/ruby_llm/aliases.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,12 @@
7878
"openrouter": "openai/o3-mini"
7979
},
8080
"mistral-medium": {
81-
"mistral": "mistral-medium-latest"
81+
"mistral": "mistral/mistral-medium-latest"
8282
},
8383
"mistral-large": {
84-
"mistral": "mistral-large-latest"
84+
"mistral": "mistral/mistral-large"
8585
},
8686
"mistral-small": {
87-
"mistral": "mistral-small-latest"
87+
"mistral": "mistral/mistral-small"
8888
}
8989
}

lib/ruby_llm/configuration.rb

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class Configuration
2222
:bedrock_session_token,
2323
:openrouter_api_key,
2424
:ollama_api_base,
25+
:mistral_api_base,
2526
:mistral_api_key,
2627
# Default models
2728
:default_model,

lib/ruby_llm/models.json

+164-2
Original file line numberDiff line numberDiff line change
@@ -11410,8 +11410,62 @@
1141011410
}
1141111411
},
1141211412
{
11413-
"id": "mistralai/mistral-embed",
11414-
"created_at": "2024-03-15T00:00:00Z",
11413+
"id": "mistral-tiny",
11414+
"created_at": "2024-12-23T00:00:00Z",
11415+
"display_name": "Mistral Tiny",
11416+
"provider": "mistral",
11417+
"context_window": 32768,
11418+
"max_tokens": 32768,
11419+
"type": "chat",
11420+
"family": "mistral_tiny",
11421+
"supports_vision": false,
11422+
"supports_functions": true,
11423+
"supports_json_mode": true,
11424+
"input_price_per_million": 0.14,
11425+
"output_price_per_million": 0.42,
11426+
"metadata": {
11427+
"description": "Most affordable model in the Mistral lineup"
11428+
}
11429+
},
11430+
{
11431+
"id": "pixtral-large",
11432+
"created_at": "2024-11-24T00:00:00Z",
11433+
"display_name": "Pixtral Large",
11434+
"provider": "mistral",
11435+
"context_window": 131072,
11436+
"max_tokens": 131072,
11437+
"type": "chat",
11438+
"family": "pixtral_large",
11439+
"supports_vision": true,
11440+
"supports_functions": true,
11441+
"supports_json_mode": true,
11442+
"input_price_per_million": 3,
11443+
"output_price_per_million": 9,
11444+
"metadata": {
11445+
"description": "Pixtral Large - frontier-class multimodal model"
11446+
}
11447+
},
11448+
{
11449+
"id": "codestral",
11450+
"created_at": "2025-01-25T00:00:00Z",
11451+
"display_name": "Codestral",
11452+
"provider": "mistral",
11453+
"context_window": 262144,
11454+
"max_tokens": 262144,
11455+
"type": "chat",
11456+
"family": "codestral",
11457+
"supports_vision": false,
11458+
"supports_functions": true,
11459+
"supports_json_mode": true,
11460+
"input_price_per_million": 1,
11461+
"output_price_per_million": 3,
11462+
"metadata": {
11463+
"description": "Codestral - specialized model for code generation"
11464+
}
11465+
},
11466+
{
11467+
"id": "mistral-embed",
11468+
"created_at": "2023-12-23T00:00:00Z",
1141511469
"display_name": "Mistral Embed",
1141611470
"provider": "mistral",
1141711471
"context_window": 32768,
@@ -11427,6 +11481,114 @@
1142711481
"description": "Mistral Embed - specialized model for generating text embeddings"
1142811482
}
1142911483
},
11484+
{
11485+
"id": "mistral-large-latest",
11486+
"created_at": "2024-11-24T00:00:00Z",
11487+
"display_name": "Mistral Large (Latest)",
11488+
"provider": "mistral",
11489+
"context_window": 131072,
11490+
"max_tokens": 131072,
11491+
"type": "chat",
11492+
"family": "mistral_large",
11493+
"supports_vision": false,
11494+
"supports_functions": true,
11495+
"supports_json_mode": true,
11496+
"input_price_per_million": 3,
11497+
"output_price_per_million": 9,
11498+
"metadata": {
11499+
"description": "Mistral Large 2 - top-tier reasoning model for high-complexity tasks"
11500+
}
11501+
},
11502+
{
11503+
"id": "mistral-small-latest",
11504+
"created_at": "2025-03-25T00:00:00Z",
11505+
"display_name": "Mistral Small (Latest)",
11506+
"provider": "mistral",
11507+
"context_window": 131072,
11508+
"max_tokens": 131072,
11509+
"type": "chat",
11510+
"family": "mistral_small",
11511+
"supports_vision": true,
11512+
"supports_functions": true,
11513+
"supports_json_mode": true,
11514+
"input_price_per_million": 0.2,
11515+
"output_price_per_million": 0.6,
11516+
"metadata": {
11517+
"description": "Mistral Small (Latest) - balanced model with good performance/cost ratio"
11518+
}
11519+
},
11520+
{
11521+
"id": "pixtral-12b-latest",
11522+
"created_at": "2024-09-25T00:00:00Z",
11523+
"display_name": "Pixtral 12B (Latest)",
11524+
"provider": "mistral",
11525+
"context_window": 131072,
11526+
"max_tokens": 131072,
11527+
"type": "chat",
11528+
"family": "pixtral",
11529+
"supports_vision": true,
11530+
"supports_functions": true,
11531+
"supports_json_mode": true,
11532+
"input_price_per_million": 0.15,
11533+
"output_price_per_million": 0.15,
11534+
"metadata": {
11535+
"description": "Pixtral 12B - Mistral's first multimodal model with vision capabilities"
11536+
}
11537+
},
11538+
{
11539+
"id": "mistral-saba",
11540+
"created_at": "2025-02-25T00:00:00Z",
11541+
"display_name": "Mistral Saba",
11542+
"provider": "mistral",
11543+
"context_window": 32768,
11544+
"max_tokens": 32768,
11545+
"type": "chat",
11546+
"family": "mistral_saba",
11547+
"supports_vision": false,
11548+
"supports_functions": true,
11549+
"supports_json_mode": true,
11550+
"input_price_per_million": 0.3,
11551+
"output_price_per_million": 0.3,
11552+
"metadata": {
11553+
"description": "Mistral Saba - powerful and efficient model for languages from the Middle East and South Asia"
11554+
}
11555+
},
11556+
{
11557+
"id": "mistral-moderation",
11558+
"created_at": "2024-11-24T00:00:00Z",
11559+
"display_name": "Mistral Moderation",
11560+
"provider": "mistral",
11561+
"context_window": 32768,
11562+
"max_tokens": 32768,
11563+
"type": "moderation",
11564+
"family": "mistral_moderation",
11565+
"supports_vision": false,
11566+
"supports_functions": false,
11567+
"supports_json_mode": false,
11568+
"input_price_per_million": 0.0,
11569+
"output_price_per_million": 0.0,
11570+
"metadata": {
11571+
"description": "Mistral Moderation - service that enables users to detect harmful text content"
11572+
}
11573+
},
11574+
{
11575+
"id": "mistral-ocr",
11576+
"created_at": "2025-03-25T00:00:00Z",
11577+
"display_name": "Mistral OCR",
11578+
"provider": "mistral",
11579+
"context_window": 32768,
11580+
"max_tokens": 32768,
11581+
"type": "ocr",
11582+
"family": "mistral_ocr",
11583+
"supports_vision": true,
11584+
"supports_functions": false,
11585+
"supports_json_mode": false,
11586+
"input_price_per_million": 0.0,
11587+
"output_price_per_million": 0.0,
11588+
"metadata": {
11589+
"description": "Mistral OCR - service that enables users to extract interleaved text and images"
11590+
}
11591+
},
1143011592
{
1143111593
"id": "moonshotai/kimi-vl-a3b-thinking:free",
1143211594
"created_at": "2025-04-10T19:07:21+02:00",

lib/ruby_llm/providers/mistral.rb

+34-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ module Mistral
1111
extend Mistral::Tools
1212
extend Mistral::Capabilities
1313
extend Mistral::Media
14+
# Mistral::Images removed as API doesn't support image generation
1415

1516
def self.extended(base)
1617
base.extend(Provider)
@@ -25,13 +26,42 @@ def self.extended(base)
2526

2627
module_function
2728

28-
def api_base
29-
'https://api.mistral.ai/v1'
29+
def api_base(config)
30+
config.mistral_api_base || 'https://api.mistral.ai/v1'
3031
end
3132

32-
def headers
33+
# Add provider-specific error parsing
34+
def parse_error(response)
35+
return if response.body.empty?
36+
37+
body = try_parse_json(response.body)
38+
error_message = case body
39+
when Hash
40+
# Check for standard { detail: [{ msg: ... }] } structure
41+
if body['detail'].is_a?(Array)
42+
body['detail'].map { |err| err['msg'] }.join("; ")
43+
# Check for simple { message: ... } structure (some Mistral errors use this)
44+
elsif body['message']
45+
body['message']
46+
# Fallback for other hash structures
47+
else
48+
body.to_s
49+
end
50+
else
51+
body.to_s # Return raw body if not a hash
52+
end
53+
54+
# Format the error message
55+
if error_message.include?('Input should be a valid')
56+
"Invalid message format: The message content is not properly formatted"
57+
else
58+
error_message
59+
end
60+
end
61+
62+
def headers(config)
3363
{
34-
'Authorization' => "Bearer #{RubyLLM.config.mistral_api_key}"
64+
'Authorization' => "Bearer #{config.mistral_api_key}"
3565
}
3666
end
3767

lib/ruby_llm/providers/mistral/capabilities.rb

+2-11
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,8 @@ def output_price_for(model_id)
5151
# @param model_id [String] the model identifier
5252
# @return [Boolean] true if the model supports vision
5353
def supports_vision?(model_id)
54-
# Check for all vision-capable models in Mistral's lineup
55-
#
56-
# NOTE: While this correctly identifies models that support vision capabilities,
57-
# there are currently issues with the image handling in the test suite.
58-
# The 'pixtral-12b-latest can understand images' test fails because image data
59-
# isn't properly passed to the API. This requires fixes in the core Content handling code.
60-
#
61-
# Known vision-capable models in Mistral's lineup:
62-
# - pixtral-12b-latest
63-
# - pixtral-large-latest
64-
model_id.match?(/pixtral|mistral-large-vision|other-vision-models/)
54+
# Determine vision support based on model ID pattern
55+
model_id.match?(/pixtral/)
6556
end
6657

6758
# Determines if the model supports function calling

0 commit comments

Comments
 (0)