Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.

Commit 755b63f

Browse files
authored
FEATURE: Add support for Mistral models (#919)
Adds support for mistral models (pixtral and mistral large now have presets) Also corrects token accounting in AWS bedrock models
1 parent 0d7f353 commit 755b63f

File tree

12 files changed

+224
-22
lines changed

12 files changed

+224
-22
lines changed

app/models/ai_api_audit_log.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ module Provider
1313
Cohere = 6
1414
Ollama = 7
1515
SambaNova = 8
16+
Mistral = 9
1617
end
1718

1819
def next_log_id

app/models/llm_model.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ def self.provider_params
2828
organization: :text,
2929
disable_native_tools: :checkbox,
3030
},
31+
mistral: {
32+
disable_native_tools: :checkbox,
33+
},
3134
google: {
3235
disable_native_tools: :checkbox,
3336
},

config/locales/client.en.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,8 @@ en:
290290
open_ai-o1-preview: "Open AI's most capabale reasoning model"
291291
samba_nova-Meta-Llama-3-1-8B-Instruct: "Efficient lightweight multilingual model"
292292
samba_nova-Meta-Llama-3-1-70B-Instruct": "Powerful multipurpose model"
293+
mistral-mistral-large-latest: "Mistral's most powerful model"
294+
mistral-pixtral-large-latest: "Mistral's most powerful vision capable model"
293295

294296
configured:
295297
title: "Configured LLMs"
@@ -325,6 +327,7 @@ en:
325327
ollama: "Ollama"
326328
CDCK: "CDCK"
327329
samba_nova: "SambaNova"
330+
mistral: "Mistral"
328331
fake: "Custom"
329332

330333
provider_fields:

lib/completions/dialects/dialect.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ def all_dialects
1616
DiscourseAi::Completions::Dialects::Claude,
1717
DiscourseAi::Completions::Dialects::Command,
1818
DiscourseAi::Completions::Dialects::Ollama,
19+
DiscourseAi::Completions::Dialects::Mistral,
1920
DiscourseAi::Completions::Dialects::OpenAiCompatible,
2021
]
2122
end
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# frozen_string_literal: true
2+
3+
# basically the same as Open AI, except for no support for user names
4+
5+
module DiscourseAi
6+
module Completions
7+
module Dialects
8+
class Mistral < ChatGpt
9+
class << self
10+
def can_translate?(model_provider)
11+
model_provider == "mistral"
12+
end
13+
end
14+
15+
def translate
16+
corrected = super
17+
corrected.each do |msg|
18+
msg[:content] = "" if msg[:tool_calls] && msg[:role] == "assistant"
19+
end
20+
corrected
21+
end
22+
23+
private
24+
25+
def user_msg(msg)
26+
mapped = super
27+
if name = mapped.delete(:name)
28+
if mapped[:content].is_a?(String)
29+
mapped[:content] = "#{name}: #{mapped[:content]}"
30+
else
31+
mapped[:content].each do |inner|
32+
if inner[:text]
33+
inner[:text] = "#{name}: #{inner[:text]}"
34+
break
35+
end
36+
end
37+
end
38+
end
39+
mapped
40+
end
41+
end
42+
end
43+
end
44+
end

lib/completions/endpoints/aws_bedrock.rb

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ def normalize_model_params(model_params)
1919
end
2020

2121
def default_options(dialect)
22-
options = { max_tokens: 3_000, anthropic_version: "bedrock-2023-05-31" }
22+
max_tokens = 4096
23+
max_tokens = 8192 if bedrock_model_id.match?(/3.5/)
24+
25+
options = { max_tokens: max_tokens, anthropic_version: "bedrock-2023-05-31" }
2326

2427
options[:stop_sequences] = ["</function_calls>"] if !dialect.native_tool_support? &&
2528
dialect.prompt.has_tools?
@@ -40,6 +43,27 @@ def xml_tags_to_strip(dialect)
4043

4144
private
4245

46+
def bedrock_model_id
47+
case llm_model.name
48+
when "claude-2"
49+
"anthropic.claude-v2:1"
50+
when "claude-3-haiku"
51+
"anthropic.claude-3-haiku-20240307-v1:0"
52+
when "claude-3-sonnet"
53+
"anthropic.claude-3-sonnet-20240229-v1:0"
54+
when "claude-instant-1"
55+
"anthropic.claude-instant-v1"
56+
when "claude-3-opus"
57+
"anthropic.claude-3-opus-20240229-v1:0"
58+
when "claude-3-5-sonnet"
59+
"anthropic.claude-3-5-sonnet-20241022-v2:0"
60+
when "claude-3-5-haiku"
61+
"anthropic.claude-3-5-haiku-20241022-v1:0"
62+
else
63+
llm_model.name
64+
end
65+
end
66+
4367
def prompt_size(prompt)
4468
# approximation
4569
tokenizer.size(prompt.system_prompt.to_s + " " + prompt.messages.to_s)
@@ -48,24 +72,6 @@ def prompt_size(prompt)
4872
def model_uri
4973
region = llm_model.lookup_custom_param("region")
5074

51-
bedrock_model_id =
52-
case llm_model.name
53-
when "claude-2"
54-
"anthropic.claude-v2:1"
55-
when "claude-3-haiku"
56-
"anthropic.claude-3-haiku-20240307-v1:0"
57-
when "claude-3-sonnet"
58-
"anthropic.claude-3-sonnet-20240229-v1:0"
59-
when "claude-instant-1"
60-
"anthropic.claude-instant-v1"
61-
when "claude-3-opus"
62-
"anthropic.claude-3-opus-20240229-v1:0"
63-
when "claude-3-5-sonnet"
64-
"anthropic.claude-3-5-sonnet-20241022-v2:0"
65-
else
66-
llm_model.name
67-
end
68-
6975
if region.blank? || bedrock_model_id.blank?
7076
raise CompletionFailed.new(I18n.t("discourse_ai.llm_models.bedrock_invalid_url"))
7177
end

lib/completions/endpoints/base.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def endpoint_for(provider_name)
2020
DiscourseAi::Completions::Endpoints::Anthropic,
2121
DiscourseAi::Completions::Endpoints::Cohere,
2222
DiscourseAi::Completions::Endpoints::SambaNova,
23+
DiscourseAi::Completions::Endpoints::Mistral,
2324
]
2425

2526
endpoints << DiscourseAi::Completions::Endpoints::Ollama if Rails.env.development?
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# frozen_string_literal: true
2+
3+
module DiscourseAi
4+
module Completions
5+
module Endpoints
6+
class Mistral < OpenAi
7+
def self.can_contact?(model_provider)
8+
model_provider == "mistral"
9+
end
10+
11+
def provider_id
12+
AiApiAuditLog::Provider::Mistral
13+
end
14+
end
15+
end
16+
end
17+
end

lib/completions/llm.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,24 @@ def presets
9090
endpoint: "https://api.sambanova.ai/v1/chat/completions",
9191
provider: "samba_nova",
9292
},
93+
{
94+
id: "mistral",
95+
models: [
96+
{
97+
name: "mistral-large-latest",
98+
tokens: 128_000,
99+
display_name: "Mistral Large",
100+
},
101+
{
102+
name: "pixtral-large-latest",
103+
tokens: 128_000,
104+
display_name: "Pixtral Large",
105+
},
106+
],
107+
tokenizer: DiscourseAi::Tokenizer::MixtralTokenizer,
108+
endpoint: "https://api.mistral.ai/v1/chat/completions",
109+
provider: "mistral",
110+
},
93111
]
94112
end
95113
end
@@ -105,6 +123,7 @@ def provider_names
105123
google
106124
azure
107125
samba_nova
126+
mistral
108127
]
109128
if !Rails.env.production?
110129
providers << "fake"

spec/fabricators/llm_model_fabricator.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,16 @@
9090
provider_params { { enable_native_tool: true } }
9191
end
9292

93+
Fabricator(:mistral_model, from: :llm_model) do
94+
display_name "Mistral Large"
95+
name "mistral-large-latest"
96+
provider "mistral"
97+
api_key "ABC"
98+
tokenizer "DiscourseAi::Tokenizer::MixtralTokenizer"
99+
url "https://api.mistral.ai/v1/chat/completions"
100+
provider_params { { disable_native_tools: false } }
101+
end
102+
93103
Fabricator(:seeded_model, from: :llm_model) do
94104
id "-2"
95105
display_name "CDCK Hosted Model"

0 commit comments

Comments
 (0)