Unofficial community-maintained Elixr wrapper for Mistral's platform REST APIs
See https://docs.mistral.ai/ for further info on REST endpoints
Add :mistral_client as a dependency in your mix.exs file.
def deps do
[
{:mistral_client, "~> 0.1.0"}
]
end
You can configure mistral_client in your mix config.exs (default $project_root/config/config.exs). If you're using Phoenix add the configuration in your config/dev.exs|test.exs|prod.exs files. An example config is:
import Config
config :mistral_client,
# find it at https://console.mistral.ai/users/api-keys/
api_key: "your-api-key",
# optional, passed to [HTTPoison.Request](https://hexdocs.pm/httpoison/HTTPoison.Request.html) options
http_options: [recv_timeout: 30_000],
api_url: "https://api.mistral.ai/"
Client library configuration can be overwritten in runtime by passing MistralClient.config(api_key: "KEY", http_options: [recv_timeout: 15_000]) as last argument of the function you need to use. For instance if you need to use a different api_key
, or http_options
you can simply do:
config_override = MistralClient.config( api_key: "test-api-key" ) # this will return a config struct with "test-api-key" as api_key, all the other config are defaulted by the client by using values taken from config.exs, so you don't need to set the defaults manually
# chat with overriden config
MistralClient.chat(
[
"model": "open-mistral-7b",
"messages": [
%{
"role": "user",
"content": "What is the best French cheese?"
}
]
],
config_override # <--- pass the overriden configuration as last argument of the function
)
# chat with standard config
MistralClient.chat(
"model": "open-mistral-7b",
"messages": [
%{
"role": "user",
"content": "What is the best French cheese?"
}
]
)
you can perform a config override in all the functions, note that params
argument must be passed explicitly as a list in square brackets if the configuration is to be overwritten, as in the example above.
Get your API key from https://console.mistral.ai/users/api-keys/
Retrieve the list of available models
MistralClient.models()
{:ok,
%{
data: [
%{
"created" => 1702997889,
"id" => "mistral-medium-latest",
"object" => "model",
"owned_by" => "mistralai",
"parent" => nil,
"permission" => [
%{
"allow_create_engine" => false,
"allow_fine_tuning" => false,
"allow_logprobs" => false,
....
}
],
"root" => nil
}
....],
object: "list"
}
}
See: https://docs.mistral.ai/api#operation/listModels
Creates a completion for the chat message
MistralClient.chat(
"model": "open-mistral-7b",
"messages": [
%{
"role": "user",
"content": "What is the best French cheese?"
}
]
)
{:ok,
%{
choices: [
%{
"finish_reason" => "stop",
"index" => 0,
"message" => %{
"content" => "It's subjective to determine the 'best' French cheese as it depends on personal preferences. Here are some popular and highly regarded French cheeses in various categories:\n\n1. Soft and Bloomy Rind: Brie de Meaux or Brie de Melun, Camembert de Normandie\n2. Hard and Cooked: Comté, Gruyère\n3. Hard and Uncooked: Cheddar-like: Comté, Beaufort, Appenzeller-style: Vacherin Fribourgeois, Alpine-style: Reblochon\n4. Blue Cheese: Roquefort, Fourme d'Ambert\n5. Goat Cheese: Chavignol, Crottin de Chavignol, Sainte-Maure de Touraine\n\nHowever, I would recommend trying a variety of French cheeses to discover your favorite. It's an enjoyable and delicious experience!",
"role" => "assistant"
}
}
],
created: 1702997889,
id: "cmpl-83f575cf654b4a83b99d342f644db292",
model: "open-mistral-7b",
object: "chat.completion",
usage: %{
"completion_tokens" => 204,
"prompt_tokens" => 15,
"total_tokens" => 219
}
}
}
See: https://docs.mistral.ai/api#operation/createChatCompletion for the complete list of parameters you can pass to the chat function
Creates a completion for the chat message, by default it streams to self()
, but you can override the configuration by passing a config override to the function with a different stream_to
http_options parameter.
MistralClient.chat(
[
model: "open-mistral-7b",
messages: [
%{role: "user", content: "What is the best French cheese?"}
],
stream: true
],
MistralClient.config(http_options: %{stream_to: self(), async: :once})
)
|> Stream.each(fn res ->
IO.inspect(res)
end)
|> Stream.run()
%{
"choices" => [
%{"delta" => %{"role" => "assistant"}, "finish_reason" => nil, "index" => 0}
],
"id" => "cmpl-9d2c56da16394e009cafbbde9cb5d725",
"model" => "open-mistral-7b"
}
%{
"choices" => [
%{
"delta" => %{
"content" => "It's subjective to determine the 'best'",
"role" => nil
},
"finish_reason" => nil,
"index" => 0
}
],
"created" => 1702999980,
"id" => "cmpl-9d2c56da16394e009cafbbde9cb5d725",
"model" => "open-mistral-7b",
"object" => "chat.completion.chunk"
}
%{
"choices" => [
%{
"delta" => %{
"content" => " French cheese as it largely depends on personal preferences. Here are a",
"role" => nil
},
"finish_reason" => nil,
"index" => 0
}
],
"created" => 1702999980,
"id" => "cmpl-9d2c56da16394e009cafbbde9cb5d725",
"model" => "open-mistral-7b",
"object" => "chat.completion.chunk"
}
...
MistralClient.embeddings(
model: "mistral-embed",
input: [
"Embed this sentence.",
"As well as this one."
]
)
{:ok,
%{
data: [
%{
"embedding" => [-0.0165863037109375, 0.07012939453125, 0.031494140625,
0.013092041015625, 0.020416259765625, 0.00977325439453125,
0.0256195068359375, 0.0021114349365234375, -0.00867462158203125,
-0.00876617431640625, -0.039520263671875, 0.058441162109375,
-0.025390625, 0.00748443603515625, -0.0290679931640625,
0.040557861328125, 0.05474853515625, 0.0258636474609375,
0.031890869140625, 0.0230255126953125, -0.056427001953125,
-0.01617431640625, -0.061248779296875, 0.012115478515625,
-0.045745849609375, -0.0269622802734375, -0.0079498291015625,
-0.03778076171875, -0.040008544921875, 8.23974609375e-4,
0.0242767333984375, -0.02996826171875, 0.0305023193359375,
-0.0022830963134765625, -0.012237548828125, -0.036163330078125,
-0.033172607421875, -0.044891357421875, 0.01326751708984375,
0.0021228790283203125, 0.00978851318359375, -2.1147727966308594e-4,
-0.0305633544921875, -0.0230865478515625, -0.024932861328125, ...],
"index" => 0,
"object" => "embedding"
},
%{
"embedding" => [-0.0234222412109375, 0.039337158203125,
0.052398681640625, -0.0183868408203125, 0.03399658203125,
0.003879547119140625, 0.024688720703125, -5.402565002441406e-4,
-0.0119171142578125, -0.006988525390625, -0.0136260986328125,
0.041839599609375, -0.0274810791015625, -0.015411376953125,
-0.041412353515625, 0.0305328369140625, 0.006023406982421875,
0.001140594482421875, -0.007167816162109375, 0.01085662841796875,
-0.03668212890625, -0.033111572265625, -0.044586181640625,
0.020538330078125, -0.0423583984375, -0.03131103515625,
-0.0119781494140625, -0.048736572265625, -0.0850830078125,
0.0203857421875, -0.0023899078369140625, -0.0249176025390625,
0.019500732421875, 0.007068634033203125, 0.0301055908203125,
-0.041534423828125, -0.0255584716796875, -0.0246429443359375,
0.022674560546875, -2.760887145996094e-4, -0.015045166015625,
-0.01788330078125, 0.0146484375, -0.005573272705078125, ...],
"index" => 1,
"object" => "embedding"
}
],
id: "embd-7d921a4410e249b9960195ab6705b255",
model: "mistral-embed",
object: "list",
usage: %{
"completion_tokens" => 0,
"prompt_tokens" => 15,
"total_tokens" => 15
}
}}
See: https://docs.mistral.ai/api#operation/createEmbedding
This client library was inspired and contains snippets from https://github.com/mgallo/openai.ex
The package is available as open source under the terms of the MIT License.