mistral-ai 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/template.md ADDED
@@ -0,0 +1,497 @@
1
+ # Mistral AI
2
+
3
+ A Ruby gem for interacting with [Mistral AI](https://mistral.ai)'s large language models.
4
+
5
+ ![The image features a graphic that merges a red ruby gem with a robotic face to symbolize the integration of a Ruby software library with Mistral AI's technology. The ruby has a reflective white top facet and the robot face includes two orange eyes, reflecting the Mistral AI logo's color. The design is modern and set against a dark background to emphasize the gem and robotic features.](https://raw.githubusercontent.com/gbaptista/assets/main/mistral-ai/ruby-mistral-ai.png)
6
+
7
+ > _This Gem is designed to provide low-level access to Mistral, enabling people to build abstractions on top of it. If you are interested in more high-level abstractions or more user-friendly tools, you may want to consider [Nano Bots](https://github.com/icebaker/ruby-nano-bots) 💎 🤖._
8
+
9
+ ## TL;DR and Quick Start
10
+
11
+ ```ruby
12
+ gem 'mistral-ai', '~> 1.0.0'
13
+ ```
14
+
15
+ ```ruby
16
+ require 'mistral-ai'
17
+
18
+ client = Mistral.new(
19
+ credentials: { api_key: ENV['MISTRAL_API_KEY'] },
20
+ options: { server_sent_events: true }
21
+ )
22
+
23
+ result = client.chat_completions(
24
+ { model: 'mistral-medium',
25
+ messages: [{ role: 'user', content: 'hi!' }] }
26
+ )
27
+ ```
28
+
29
+ Result:
30
+ ```ruby
31
+ { 'id' => 'cmpl-74fb544d49d04195a4182342936af43b',
32
+ 'object' => 'chat.completion',
33
+ 'created' => 1_703_792_737,
34
+ 'model' => 'mistral-medium',
35
+ 'choices' =>
36
+ [{ 'index' => 0,
37
+ 'message' =>
38
+ { 'role' => 'assistant',
39
+ 'content' =>
40
+ "Hello! How can I assist you today? If you have any questions or need help with something, feel free to ask. I'm here to help.\n" \
41
+ "\n" \
42
+ "If you're not sure where to start, you can ask me about a specific topic, such as a programming language, a scientific concept, or a current event. You can also ask me to tell you a joke, generate a random number, or provide a fun fact.\n" \
43
+ "\n" \
44
+ "I'm a large language model trained by Mistral AI, so I can understand and generate human-like text on a wide range of topics. I can also perform tasks such as summarizing text, translating between languages, and answering questions about a given text. I look forward to helping you!" },
45
+ 'finish_reason' => 'stop' }],
46
+ 'usage' => { 'prompt_tokens' => 10, 'total_tokens' => 166, 'completion_tokens' => 156 } }
47
+ ```
48
+
49
+ ## Index
50
+
51
+ {index}
52
+
53
+ ## Setup
54
+
55
+ ### Installing
56
+
57
+ ```sh
58
+ gem install mistral-ai -v 1.0.0
59
+ ```
60
+
61
+ ```sh
62
+ gem 'mistral-ai', '~> 1.0.0'
63
+ ```
64
+
65
+ ### Credentials
66
+
67
+ You can obtain your API key from the [Mistral AI Platform](https://console.mistral.ai).
68
+
69
+ ## Usage
70
+
71
+ ### Client
72
+
73
+ Ensure that you have an [API Key](#credentials) for authentication.
74
+
75
+ Create a new client:
76
+ ```ruby
77
+ require 'mistral-ai'
78
+
79
+ client = Mistral.new(
80
+ credentials: { api_key: ENV['MISTRAL_API_KEY'] },
81
+ options: { server_sent_events: true }
82
+ )
83
+ ```
84
+
85
+ #### Custom Address
86
+
87
+ You can use a custom address:
88
+
89
+ ```ruby
90
+ require 'mistral-ai'
91
+
92
+ client = Mistral.new(
93
+ credentials: {
94
+ address: 'https://api.mistral.ai',
95
+ api_key: ENV['MISTRAL_API_KEY']
96
+ },
97
+ options: { server_sent_events: true }
98
+ )
99
+ ```
100
+
101
+ ### Methods
102
+
103
+ #### chat_completions
104
+
105
+ ##### Without Streaming Events
106
+
107
+ ```ruby
108
+ result = client.chat_completions(
109
+ { model: 'mistral-medium',
110
+ messages: [{ role: 'user', content: 'hi!' }] }
111
+ )
112
+ ```
113
+
114
+ Result:
115
+ ```ruby
116
+ { 'id' => 'cmpl-74fb544d49d04195a4182342936af43b',
117
+ 'object' => 'chat.completion',
118
+ 'created' => 1_703_792_737,
119
+ 'model' => 'mistral-medium',
120
+ 'choices' =>
121
+ [{ 'index' => 0,
122
+ 'message' =>
123
+ { 'role' => 'assistant',
124
+ 'content' =>
125
+ "Hello! How can I assist you today? If you have any questions or need help with something, feel free to ask. I'm here to help.\n" \
126
+ "\n" \
127
+ "If you're not sure where to start, you can ask me about a specific topic, such as a programming language, a scientific concept, or a current event. You can also ask me to tell you a joke, generate a random number, or provide a fun fact.\n" \
128
+ "\n" \
129
+ "I'm a large language model trained by Mistral AI, so I can understand and generate human-like text on a wide range of topics. I can also perform tasks such as summarizing text, translating between languages, and answering questions about a given text. I look forward to helping you!" },
130
+ 'finish_reason' => 'stop' }],
131
+ 'usage' => { 'prompt_tokens' => 10, 'total_tokens' => 166, 'completion_tokens' => 156 } }
132
+ ```
133
+
134
+ ##### Receiving Stream Events
135
+
136
+ Ensure that you have enabled [Server-Sent Events](#streaming-and-server-sent-events-sse) before using blocks for streaming. You also need to add `stream: true` in your payload:
137
+
138
+ ```ruby
139
+ client.chat_completions(
140
+ { model: 'mistral-medium',
141
+ stream: true,
142
+ messages: [{ role: 'user', content: 'hi!' }] }
143
+ ) do |event, parsed, raw|
144
+ puts event
145
+ end
146
+ ```
147
+
148
+ Event:
149
+ ```ruby
150
+ { 'id' => 'cmpl-011e6223d8414df4840293b98e0b18ca',
151
+ 'object' => 'chat.completion.chunk',
152
+ 'created' => 1_703_796_464,
153
+ 'model' => 'mistral-medium',
154
+ 'choices' => [
155
+ { 'index' => 0, 'delta' => { 'role' => nil, 'content' => 'Hello' },
156
+ 'finish_reason' => nil }
157
+ ] }
158
+ ```
159
+
160
+ You can get all the receive events at once as an array:
161
+ ```ruby
162
+ result = client.chat_completions(
163
+ { model: 'mistral-medium',
164
+ stream: true,
165
+ messages: [{ role: 'user', content: 'hi!' }] }
166
+ )
167
+ ```
168
+
169
+ Result:
170
+ ```ruby
171
+ [{ 'id' => 'cmpl-20bc384332d749958251e11427aeeb42',
172
+ 'model' => 'mistral-medium',
173
+ 'choices' => [{ 'index' => 0, 'delta' => { 'role' => 'assistant' }, 'finish_reason' => nil }] },
174
+ { 'id' => 'cmpl-20bc384332d749958251e11427aeeb42',
175
+ 'object' => 'chat.completion.chunk',
176
+ 'created' => 1_703_796_630,
177
+ 'model' => 'mistral-medium',
178
+ 'choices' => [{ 'index' => 0, 'delta' => { 'role' => nil, 'content' => 'Hello! How can I' },
179
+ 'finish_reason' => nil }] },
180
+ { 'id' => 'cmpl-20bc384332d749958251e11427aeeb42',
181
+ 'object' => 'chat.completion.chunk',
182
+ 'created' => 1_703_796_630,
183
+ 'model' => 'mistral-medium',
184
+ 'choices' => [{ 'index' => 0, 'delta' => { 'role' => nil, 'content' => ' assist you today?' },
185
+ 'finish_reason' => nil }] },
186
+ # ...
187
+ { 'id' => 'cmpl-20bc384332d749958251e11427aeeb42',
188
+ 'object' => 'chat.completion.chunk',
189
+ 'created' => 1_703_796_630,
190
+ 'model' => 'mistral-medium',
191
+ 'choices' => [{ 'index' => 0, 'delta' => { 'role' => nil, 'content' => '' },
192
+ 'finish_reason' => 'stop' }] }]
193
+ ```
194
+
195
+ You can mix both as well:
196
+ ```ruby
197
+ result = client.chat_completions(
198
+ { model: 'mistral-medium',
199
+ stream: true,
200
+ messages: [{ role: 'user', content: 'hi!' }] }
201
+ ) do |event, parsed, raw|
202
+ puts event
203
+ end
204
+ ```
205
+
206
+ #### embeddings
207
+
208
+ ```ruby
209
+ result = client.embeddings(
210
+ { model: 'mistral-embed',
211
+ input: [
212
+ 'Embed this sentence.',
213
+ 'As well as this one.'
214
+ ] }
215
+ )
216
+ ```
217
+
218
+ Result:
219
+ ```ruby
220
+ { 'id' => 'embd-03f43eaec35744a3bab6f2ca83418555',
221
+ 'object' => 'list',
222
+ 'data' =>
223
+ [{ 'object' => 'embedding',
224
+ 'embedding' =>
225
+ [-0.0165863037109375,
226
+ 0.07012939453125,
227
+ # ...
228
+ 0.00428009033203125,
229
+ -0.036895751953125],
230
+ 'index' => 0 },
231
+ { 'object' => 'embedding',
232
+ 'embedding' =>
233
+ [-0.0234222412109375,
234
+ 0.039337158203125,
235
+ # ...
236
+ 0.00044846534729003906,
237
+ -0.01065826416015625],
238
+ 'index' => 1 }],
239
+ 'model' => 'mistral-embed',
240
+ 'usage' => { 'prompt_tokens' => 15, 'total_tokens' => 15, 'completion_tokens' => 0 } }
241
+
242
+ ```
243
+
244
+ ### Streaming and Server-Sent Events (SSE)
245
+
246
+ [Server-Sent Events (SSE)](https://en.wikipedia.org/wiki/Server-sent_events) is a technology that allows certain endpoints to offer streaming capabilities, such as creating the impression that "the model is typing along with you," rather than delivering the entire answer all at once.
247
+
248
+ You can set up the client to use Server-Sent Events (SSE) for all supported endpoints:
249
+ ```ruby
250
+ client = Mistral.new(
251
+ credentials: { api_key: ENV['MISTRAL_API_KEY'] },
252
+ options: { server_sent_events: true }
253
+ )
254
+ ```
255
+
256
+ Or, you can decide on a request basis:
257
+ ```ruby
258
+ client.chat_completions(
259
+ { model: 'mistral-medium',
260
+ stream: true,
261
+ messages: [{ role: 'user', content: 'hi!' }] },
262
+ server_sent_events: true
263
+ ) do |event, parsed, raw|
264
+ puts event
265
+ end
266
+ ```
267
+
268
+ With Server-Sent Events (SSE) enabled, you can use a block to receive partial results via events. This feature is particularly useful for methods that offer streaming capabilities, such as `chat_completions`: [Receiving Stream Events](#receiving-stream-events)
269
+
270
+ #### Server-Sent Events (SSE) Hang
271
+
272
+ Method calls will _hang_ until the server-sent events finish, so even without providing a block, you can obtain the final results of the received events: [Receiving Stream Events](#receiving-stream-events)
273
+
274
+ ### System Messages
275
+
276
+ System messages influence how the model answers:
277
+
278
+ ```ruby
279
+ result = client.chat_completions(
280
+ { model: 'mistral-medium',
281
+ messages: [
282
+ { role: 'system', content: 'Only answer strictly using JSON.' },
283
+ { role: 'user', content: 'Calculate 1 + 1.' }
284
+ ] }
285
+ )
286
+ ```
287
+
288
+ Result:
289
+ ```ruby
290
+ { 'id' => 'cmpl-0c6fee44022841728e435ac91416d211',
291
+ 'object' => 'chat.completion',
292
+ 'created' => 1_703_794_201,
293
+ 'model' => 'mistral-medium',
294
+ 'choices' => [{
295
+ 'index' => 0,
296
+ 'message' => { 'role' => 'assistant', 'content' => '{"result": 2}' },
297
+ 'finish_reason' => 'stop'
298
+ }],
299
+ 'usage' => { 'prompt_tokens' => 24, 'total_tokens' => 30, 'completion_tokens' => 6 } }
300
+
301
+ ```
302
+
303
+ ### Back-and-Forth Conversations
304
+
305
+ To maintain a back-and-forth conversation, you need to append the received responses and build a history for your requests:
306
+
307
+ ```rb
308
+ result = client.chat_completions(
309
+ { model: 'mistral-medium',
310
+ messages: [
311
+ { role: 'user',
312
+ content: 'Hi! My name is Purple.' },
313
+ { role: 'assistant',
314
+ content: "Hello Purple! It's nice to meet you. How can I help you today?" },
315
+ { role: 'user', content: "What's my name?" }
316
+ ] }
317
+ )
318
+ ```
319
+
320
+ Result:
321
+ ```ruby
322
+ { 'id' => 'cmpl-cbc4a8db84b347738840e34e46388f1f',
323
+ 'object' => 'chat.completion',
324
+ 'created' => 1_703_793_492,
325
+ 'model' => 'mistral-medium',
326
+ 'choices' =>
327
+ [{ 'index' => 0,
328
+ 'message' => {
329
+ 'role' => 'assistant',
330
+ 'content' => 'Your name is Purple, as you introduced yourself earlier. Is there anything else I can help you with?'
331
+ },
332
+ 'finish_reason' => 'stop' }],
333
+ 'usage' => { 'prompt_tokens' => 49, 'total_tokens' => 71, 'completion_tokens' => 22 } }
334
+ ```
335
+
336
+ ### New Functionalities and APIs
337
+
338
+ Mistral may launch a new endpoint that we haven't covered in the Gem yet. If that's the case, you may still be able to use it through the `request` method. For example, `chat_completions` is just a wrapper for `v1/chat/completions`, which you can call directly like this:
339
+
340
+ ```ruby
341
+ result = client.request(
342
+ 'v1/chat/completions',
343
+ { model: 'mistral-medium',
344
+ messages: [{ role: 'user', content: 'hi!' }] }
345
+ )
346
+ ```
347
+
348
+ ### Request Options
349
+
350
+ #### Timeout
351
+
352
+ You can set the maximum number of seconds to wait for the request to complete with the `timeout` option:
353
+
354
+ ```ruby
355
+ client = Mistral.new(
356
+ credentials: { api_key: ENV['MISTRAL_API_KEY'] },
357
+ options: { connection: { request: { timeout: 5 } } }
358
+ )
359
+ ```
360
+
361
+ You can also have more fine-grained control over [Faraday's Request Options](https://lostisland.github.io/faraday/#/customization/request-options?id=request-options) if you prefer:
362
+
363
+ ```ruby
364
+ client = Mistral.new(
365
+ credentials: { api_key: ENV['MISTRAL_API_KEY'] },
366
+ options: {
367
+ connection: {
368
+ request: {
369
+ timeout: 5,
370
+ open_timeout: 5,
371
+ read_timeout: 5,
372
+ write_timeout: 5
373
+ }
374
+ }
375
+ }
376
+ )
377
+ ```
378
+
379
+ ### Error Handling
380
+
381
+ #### Rescuing
382
+
383
+ ```ruby
384
+ require 'mistral-ai'
385
+
386
+ begin
387
+ client.chat_completions(
388
+ { model: 'mistral-medium',
389
+ messages: [{ role: 'user', content: 'hi!' }] }
390
+ )
391
+ rescue Mistral::Errors::MistralError => error
392
+ puts error.class # Mistral::Errors::RequestError
393
+ puts error.message # 'the server responded with status 500'
394
+
395
+ puts error.payload
396
+ # { model: 'mistral-medium',
397
+ # messages: [{ role: 'user', content: 'hi!' }] },
398
+ # ...
399
+ # }
400
+
401
+ puts error.request
402
+ # #<Faraday::ServerError response={:status=>500, :headers...
403
+ end
404
+ ```
405
+
406
+ #### For Short
407
+
408
+ ```ruby
409
+ require 'mistral-ai/errors'
410
+
411
+ begin
412
+ client.chat_completions(
413
+ { model: 'mistral-medium',
414
+ messages: [{ role: 'user', content: 'hi!' }] }
415
+ )
416
+ rescue MistralError => error
417
+ puts error.class # Mistral::Errors::RequestError
418
+ end
419
+ ```
420
+
421
+ #### Errors
422
+
423
+ ```ruby
424
+ MistralError
425
+
426
+ MissingAPIKeyError
427
+ BlockWithoutServerSentEventsError
428
+ UnsupportedError
429
+
430
+ RequestError
431
+ ```
432
+
433
+ ## Development
434
+
435
+ ```bash
436
+ bundle
437
+ rubocop -A
438
+ ```
439
+
440
+ ### Purpose
441
+
442
+ This Gem is designed to provide low-level access to Mistral, enabling people to build abstractions on top of it. If you are interested in more high-level abstractions or more user-friendly tools, you may want to consider [Nano Bots](https://github.com/icebaker/ruby-nano-bots) 💎 🤖.
443
+
444
+ ### Publish to RubyGems
445
+
446
+ ```bash
447
+ gem build mistral-ai.gemspec
448
+
449
+ gem signin
450
+
451
+ gem push mistral-ai-1.0.0.gem
452
+ ```
453
+
454
+ ### Updating the README
455
+
456
+ Install [Babashka](https://babashka.org):
457
+
458
+ ```sh
459
+ curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | sudo bash
460
+ ```
461
+
462
+ Update the `template.md` file and then:
463
+
464
+ ```sh
465
+ bb tasks/generate-readme.clj
466
+ ```
467
+
468
+ Trick for automatically updating the `README.md` when `template.md` changes:
469
+
470
+ ```sh
471
+ sudo pacman -S inotify-tools # Arch / Manjaro
472
+ sudo apt-get install inotify-tools # Debian / Ubuntu / Raspberry Pi OS
473
+ sudo dnf install inotify-tools # Fedora / CentOS / RHEL
474
+
475
+ while inotifywait -e modify template.md; do bb tasks/generate-readme.clj; done
476
+ ```
477
+
478
+ Trick for Markdown Live Preview:
479
+ ```sh
480
+ pip install -U markdown_live_preview
481
+
482
+ mlp README.md -p 8076
483
+ ```
484
+
485
+ ## Resources and References
486
+
487
+ These resources and references may be useful throughout your learning process.
488
+
489
+ - [Mistral AI Official Website](https://mistral.ai)
490
+ - [Mistral AI Documentation](https://docs.mistral.ai)
491
+ - [Mistral AI API Documentation](https://docs.mistral.ai/api/)
492
+
493
+ ## Disclaimer
494
+
495
+ This is not an official Mistral project, nor is it affiliated with Mistral in any way.
496
+
497
+ This software is distributed under the [MIT License](https://github.com/gbaptista/mistral-ai/blob/main/LICENSE). This license includes a disclaimer of warranty. Moreover, the authors assume no responsibility for any damage or costs that may result from using this project. Use the Mistral AI Ruby Gem at your own risk.
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mistral-ai
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - gbaptista
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-12-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: event_stream_parser
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.8'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 2.8.1
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '2.8'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 2.8.1
47
+ description: A Ruby gem for interacting with Mistral AI's large language models.
48
+ email:
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - ".gitignore"
54
+ - ".rubocop.yml"
55
+ - ".ruby-version"
56
+ - Gemfile
57
+ - Gemfile.lock
58
+ - LICENSE
59
+ - README.md
60
+ - components/errors.rb
61
+ - controllers/client.rb
62
+ - mistral-ai.gemspec
63
+ - ports/dsl/mistral-ai.rb
64
+ - ports/dsl/mistral-ai/errors.rb
65
+ - static/gem.rb
66
+ - tasks/generate-readme.clj
67
+ - template.md
68
+ homepage: https://github.com/gbaptista/mistral-ai
69
+ licenses:
70
+ - MIT
71
+ metadata:
72
+ allowed_push_host: https://rubygems.org
73
+ homepage_uri: https://github.com/gbaptista/mistral-ai
74
+ source_code_uri: https://github.com/gbaptista/mistral-ai
75
+ rubygems_mfa_required: 'true'
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - ports/dsl
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 3.1.0
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubygems_version: 3.4.22
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: Interact with Mistral AI.
95
+ test_files: []