maritaca-ai 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d09d3d7f30a05367ba9488b60754235fb4ecd4ad204e699aa7b7035a75329d4b
4
+ data.tar.gz: f235d41d277a28ca87c6dca8037e8bb706145cf75e46386ac40e39ba28f945cf
5
+ SHA512:
6
+ metadata.gz: 7b2ef8109622f102f41f2a14b1c21177c5ffa0af47417b5b0d17b61f334fe32e336ae25a5fb6cc9d08c31d60f6055cde42f9ac2503169abaa0bc6ee097bc4bca
7
+ data.tar.gz: 5da080135ef573549d4948c4b242dd4bc840be4db30b0313a5608f36613cd8e1cd00a1b5db503d65f2dad7ac195a411617ad8c43bae5ebd998d582fb8f374ad1
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ *.gem
2
+ .devcontainer
data/.rubocop.yml ADDED
@@ -0,0 +1,6 @@
1
+ AllCops:
2
+ TargetRubyVersion: 3.1.0
3
+ NewCops: enable
4
+
5
+ Style/Documentation:
6
+ Enabled: false
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.1.0
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
7
+ group :test, :development do
8
+ gem 'pry-byebug', '~> 3.10', '>= 3.10.1'
9
+ gem 'rubocop', '~> 1.58'
10
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,62 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ maritaca-ai (1.0.0)
5
+ faraday (~> 2.8, >= 2.8.1)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ ast (2.4.2)
11
+ base64 (0.2.0)
12
+ byebug (11.1.3)
13
+ coderay (1.1.3)
14
+ faraday (2.8.1)
15
+ base64
16
+ faraday-net_http (>= 2.0, < 3.1)
17
+ ruby2_keywords (>= 0.0.4)
18
+ faraday-net_http (3.0.2)
19
+ json (2.7.1)
20
+ language_server-protocol (3.17.0.3)
21
+ method_source (1.0.0)
22
+ parallel (1.24.0)
23
+ parser (3.2.2.4)
24
+ ast (~> 2.4.1)
25
+ racc
26
+ pry (0.14.2)
27
+ coderay (~> 1.1)
28
+ method_source (~> 1.0)
29
+ pry-byebug (3.10.1)
30
+ byebug (~> 11.0)
31
+ pry (>= 0.13, < 0.15)
32
+ racc (1.7.3)
33
+ rainbow (3.1.1)
34
+ regexp_parser (2.8.3)
35
+ rexml (3.2.6)
36
+ rubocop (1.59.0)
37
+ json (~> 2.3)
38
+ language_server-protocol (>= 3.17.0)
39
+ parallel (~> 1.10)
40
+ parser (>= 3.2.2.4)
41
+ rainbow (>= 2.2.2, < 4.0)
42
+ regexp_parser (>= 1.8, < 3.0)
43
+ rexml (>= 3.2.5, < 4.0)
44
+ rubocop-ast (>= 1.30.0, < 2.0)
45
+ ruby-progressbar (~> 1.7)
46
+ unicode-display_width (>= 2.4.0, < 3.0)
47
+ rubocop-ast (1.30.0)
48
+ parser (>= 3.2.1.0)
49
+ ruby-progressbar (1.13.0)
50
+ ruby2_keywords (0.0.5)
51
+ unicode-display_width (2.5.0)
52
+
53
+ PLATFORMS
54
+ x86_64-linux
55
+
56
+ DEPENDENCIES
57
+ maritaca-ai!
58
+ pry-byebug (~> 3.10, >= 3.10.1)
59
+ rubocop (~> 1.58)
60
+
61
+ BUNDLED WITH
62
+ 2.4.22
data/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright 2023 Guilherme Baptista
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,337 @@
1
+ # Maritaca AI
2
+
3
+ A Ruby gem for interacting with [MariTalk](https://chat.maritaca.ai) from [Maritaca AI](https://www.maritaca.ai).
4
+
5
+ ![The image features a minimalist logo combining a red ruby and a green Brazilian maritaca bird. The left side shows a flat, smooth red ruby, while the right side transitions to a vibrant green maritaca bird, both depicted in a simple, stylized manner. The background is a subtle gradient, enhancing the logo's modern and clean design..](https://raw.githubusercontent.com/gbaptista/assets/main/maritaca-ai/maritaca-ai-canvas.png)
6
+
7
+ > _This Gem is designed to provide low-level access to MariTalk, 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 'maritaca-ai', '~> 1.0.0'
13
+ ```
14
+
15
+ ```ruby
16
+ require 'maritaca-ai'
17
+
18
+ client = Maritaca.new(
19
+ credentials: { api_key: ENV['MARITACA_API_KEY'] }
20
+ )
21
+
22
+ result = client.chat_inference(
23
+ { model: 'maritalk',
24
+ chat_mode: true,
25
+ messages: [ { role: 'user', content: 'Oi!' } ] }
26
+ )
27
+ ```
28
+
29
+ Result:
30
+ ```ruby
31
+ { 'answer' => 'Oi! Como posso ajudá-lo(a) hoje?' }
32
+ ```
33
+
34
+ ## Index
35
+
36
+ - [TL;DR and Quick Start](#tldr-and-quick-start)
37
+ - [Index](#index)
38
+ - [Setup](#setup)
39
+ - [Installing](#installing)
40
+ - [Credentials](#credentials)
41
+ - [Usage](#usage)
42
+ - [Client](#client)
43
+ - [Custom Address](#custom-address)
44
+ - [Methods](#methods)
45
+ - [chat_inference](#chat_inference)
46
+ - [Chat](#chat)
47
+ - [Back-and-Forth Conversations](#back-and-forth-conversations)
48
+ - [Without Chat](#without-chat)
49
+ - [New Functionalities and APIs](#new-functionalities-and-apis)
50
+ - [Request Options](#request-options)
51
+ - [Timeout](#timeout)
52
+ - [Error Handling](#error-handling)
53
+ - [Rescuing](#rescuing)
54
+ - [For Short](#for-short)
55
+ - [Errors](#errors)
56
+ - [Development](#development)
57
+ - [Purpose](#purpose)
58
+ - [Publish to RubyGems](#publish-to-rubygems)
59
+ - [Updating the README](#updating-the-readme)
60
+ - [Resources and References](#resources-and-references)
61
+ - [Disclaimer](#disclaimer)
62
+
63
+ ## Setup
64
+
65
+ ### Installing
66
+
67
+ ```sh
68
+ gem install maritaca-ai -v 1.0.0
69
+ ```
70
+
71
+ ```sh
72
+ gem 'maritaca-ai', '~> 1.0.0'
73
+ ```
74
+
75
+ ### Credentials
76
+
77
+ You can obtain your API key at [MariTalk](https://chat.maritaca.ai).
78
+
79
+ Enclose credentials in single quotes when using environment variables to prevent issues with the `$` character in the API key:
80
+
81
+ ```sh
82
+ MARITACA_API_KEY='123...$a12...'
83
+ ```
84
+
85
+ ## Usage
86
+
87
+ ### Client
88
+
89
+ Ensure that you have an [API Key](#credentials) for authentication.
90
+
91
+ Create a new client:
92
+ ```ruby
93
+ require 'maritaca-ai'
94
+
95
+ client = Maritaca.new(
96
+ credentials: { api_key: ENV['MARITACA_API_KEY'] }
97
+ )
98
+ ```
99
+
100
+ #### Custom Address
101
+
102
+ You can use a custom address:
103
+
104
+ ```ruby
105
+ require 'maritaca-ai'
106
+
107
+ client = Maritaca.new(
108
+ credentials: {
109
+ address: 'https://chat.maritaca.ai',
110
+ api_key: ENV['MARITACA_API_KEY']
111
+ }
112
+ )
113
+ ```
114
+
115
+ ### Methods
116
+
117
+ #### chat_inference
118
+
119
+ #### Chat
120
+
121
+ ```ruby
122
+ result = client.chat_inference(
123
+ { model: 'maritalk',
124
+ chat_mode: true,
125
+ messages: [ { role: 'user', content: 'Oi!' } ] }
126
+ )
127
+ ```
128
+
129
+ Result:
130
+ ```ruby
131
+ { 'answer' => 'Oi! Como posso ajudá-lo(a) hoje?' }
132
+ ```
133
+
134
+ #### Back-and-Forth Conversations
135
+
136
+ To maintain a back-and-forth conversation, you need to append the received responses and build a history for your requests:
137
+
138
+ ```rb
139
+ result = client.chat_inference(
140
+ { model: 'maritalk',
141
+ chat_mode: true,
142
+ messages: [
143
+ { role: 'user', content: 'Oi, meu nome é Tamanduá.' },
144
+ { role: 'assistant', content: 'Oi Tamanduá, como posso ajudá-lo hoje?' },
145
+ { role: 'user', content: 'Qual é o meu nome?' }
146
+ ] }
147
+ )
148
+ ```
149
+
150
+ Result:
151
+ ```ruby
152
+ { 'answer' => 'Seu nome é Tamanduá.' }
153
+ ```
154
+
155
+ #### Without Chat
156
+
157
+ You can prompt the model without using chat mode:
158
+
159
+ ```ruby
160
+ result = client.chat_inference(
161
+ { model: 'maritalk',
162
+ chat_mode: false,
163
+ messages: "Minha terra tem palmeiras,\nOnde canta o Sabiá;\n" }
164
+ )
165
+ ```
166
+
167
+ Result:
168
+ ```ruby
169
+ { 'answer' =>
170
+ "As aves, que aqui gorjeiam,\n" \
171
+ 'Não gorjeiam como lá.' }
172
+ ```
173
+
174
+ ### New Functionalities and APIs
175
+
176
+ Maritaca 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_inference` is just a wrapper for `api/chat/inference`, which you can call directly like this:
177
+
178
+ ```ruby
179
+ result = client.request(
180
+ 'api/chat/inference',
181
+ { model: 'maritalk',
182
+ chat_mode: true,
183
+ messages: [{ role: 'user', content: 'Oi!' }] },
184
+ request_method: 'POST'
185
+ )
186
+ ```
187
+
188
+ ### Request Options
189
+
190
+ #### Timeout
191
+
192
+ You can set the maximum number of seconds to wait for the request to complete with the `timeout` option:
193
+
194
+ ```ruby
195
+ client = Maritaca.new(
196
+ credentials: { api_key: ENV['MARITACA_API_KEY'] },
197
+ options: { connection: { request: { timeout: 5 } } }
198
+ )
199
+ ```
200
+
201
+ 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:
202
+
203
+ ```ruby
204
+ client = Maritaca.new(
205
+ credentials: { api_key: ENV['MARITACA_API_KEY'] },
206
+ options: {
207
+ connection: {
208
+ request: {
209
+ timeout: 5,
210
+ open_timeout: 5,
211
+ read_timeout: 5,
212
+ write_timeout: 5
213
+ }
214
+ }
215
+ }
216
+ )
217
+ ```
218
+
219
+ ### Error Handling
220
+
221
+ #### Rescuing
222
+
223
+ ```ruby
224
+ require 'maritaca-ai'
225
+
226
+ begin
227
+ client.chat_inference(
228
+ { model: 'maritalk',
229
+ chat_mode: true,
230
+ messages: [ { role: 'user', content: 'Oi!' } ] }
231
+ )
232
+ rescue Maritaca::Errors::MaritacaError => error
233
+ puts error.class # Maritaca::Errors::RequestError
234
+ puts error.message # 'the server responded with status 500'
235
+
236
+ puts error.payload
237
+ # { model: 'maritalk',
238
+ # chat_mode: true,
239
+ # ...
240
+ # }
241
+
242
+ puts error.request
243
+ # #<Faraday::ServerError response={:status=>500, :headers...
244
+ end
245
+ ```
246
+
247
+ #### For Short
248
+
249
+ ```ruby
250
+ require 'maritaca-ai/errors'
251
+
252
+ begin
253
+ client.chat_inference(
254
+ { model: 'maritalk',
255
+ chat_mode: true,
256
+ messages: [ { role: 'user', content: 'Oi!' } ] }
257
+ )
258
+ rescue MaritacaError => error
259
+ puts error.class # Maritaca::Errors::RequestError
260
+ end
261
+ ```
262
+
263
+ #### Errors
264
+
265
+ ```ruby
266
+ MaritacaError
267
+
268
+ MissingAPIKeyError
269
+
270
+ RequestError
271
+ ```
272
+
273
+ ## Development
274
+
275
+ ```bash
276
+ bundle
277
+ rubocop -A
278
+ ```
279
+
280
+ ### Purpose
281
+
282
+ This Gem is designed to provide low-level access to MariTalk, 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) 💎 🤖.
283
+
284
+ ### Publish to RubyGems
285
+
286
+ ```bash
287
+ gem build maritaca-ai.gemspec
288
+
289
+ gem signin
290
+
291
+ gem push maritaca-ai-1.0.0.gem
292
+ ```
293
+
294
+ ### Updating the README
295
+
296
+ Install [Babashka](https://babashka.org):
297
+
298
+ ```sh
299
+ curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | sudo bash
300
+ ```
301
+
302
+ Update the `template.md` file and then:
303
+
304
+ ```sh
305
+ bb tasks/generate-readme.clj
306
+ ```
307
+
308
+ Trick for automatically updating the `README.md` when `template.md` changes:
309
+
310
+ ```sh
311
+ sudo pacman -S inotify-tools # Arch / Manjaro
312
+ sudo apt-get install inotify-tools # Debian / Ubuntu / Raspberry Pi OS
313
+ sudo dnf install inotify-tools # Fedora / CentOS / RHEL
314
+
315
+ while inotifywait -e modify template.md; do bb tasks/generate-readme.clj; done
316
+ ```
317
+
318
+ Trick for Markdown Live Preview:
319
+ ```sh
320
+ pip install -U markdown_live_preview
321
+
322
+ mlp README.md -p 8076
323
+ ```
324
+
325
+ ## Resources and References
326
+
327
+ These resources and references may be useful throughout your learning process.
328
+
329
+ - [Maritaca AI Official Website](https://www.maritaca.ai)
330
+ - [MariTalk Documentation](https://maritaca-ai.github.io/maritalk-api/maritalk.html)
331
+ - [Maritaca AI API Documentation](https://chat.maritaca.ai/docs)
332
+
333
+ ## Disclaimer
334
+
335
+ This is not an official Maritaca AI project, nor is it affiliated with Maritaca AI in any way.
336
+
337
+ This software is distributed under the [MIT License](https://github.com/gbaptista/maritaca-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 Maritaca AI Ruby Gem at your own risk.
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Maritaca
4
+ module Errors
5
+ class MaritacaError < StandardError
6
+ def initialize(message = nil)
7
+ super(message)
8
+ end
9
+ end
10
+
11
+ class MissingAPIKeyError < MaritacaError; end
12
+ class BlockWithoutServerSentEventsError < MaritacaError; end
13
+
14
+ class RequestError < MaritacaError
15
+ attr_reader :request, :payload
16
+
17
+ def initialize(message = nil, request: nil, payload: nil)
18
+ @request = request
19
+ @payload = payload
20
+
21
+ super(message)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'event_stream_parser'
4
+ require 'faraday'
5
+ require 'json'
6
+
7
+ require_relative '../ports/dsl/maritaca-ai/errors'
8
+
9
+ module Maritaca
10
+ module Controllers
11
+ class Client
12
+ DEFAULT_ADDRESS = 'https://chat.maritaca.ai'
13
+
14
+ ALLOWED_REQUEST_OPTIONS = %i[timeout open_timeout read_timeout write_timeout].freeze
15
+
16
+ def initialize(config)
17
+ @api_key = config.dig(:credentials, :api_key)
18
+ @server_sent_events = config.dig(:options, :server_sent_events)
19
+
20
+ @address = if config[:credentials][:address].nil? || config[:credentials][:address].to_s.strip.empty?
21
+ "#{DEFAULT_ADDRESS}/"
22
+ else
23
+ "#{config[:credentials][:address].to_s.sub(%r{/$}, '')}/"
24
+ end
25
+
26
+ if @api_key.nil? && @address == "#{DEFAULT_ADDRESS}/"
27
+ raise MissingAPIKeyError, 'Missing API Key, which is required.'
28
+ end
29
+
30
+ @request_options = config.dig(:options, :connection, :request)
31
+
32
+ @request_options = if @request_options.is_a?(Hash)
33
+ @request_options.select do |key, _|
34
+ ALLOWED_REQUEST_OPTIONS.include?(key)
35
+ end
36
+ else
37
+ {}
38
+ end
39
+ end
40
+
41
+ def chat_inference(payload, server_sent_events: nil, &callback)
42
+ request('api/chat/inference', payload, server_sent_events:, &callback)
43
+ end
44
+
45
+ def request(path, payload = nil, server_sent_events: nil, request_method: 'POST', &callback)
46
+ server_sent_events_enabled = server_sent_events.nil? ? @server_sent_events : server_sent_events
47
+ url = "#{@address}#{path}"
48
+
49
+ if !callback.nil? && !server_sent_events_enabled
50
+ raise BlockWithoutServerSentEventsError,
51
+ 'You are trying to use a block without Server Sent Events (SSE) enabled.'
52
+ end
53
+
54
+ results = []
55
+
56
+ method_to_call = request_method.to_s.strip.downcase.to_sym
57
+
58
+ partial_json = ''
59
+
60
+ response = Faraday.new(request: @request_options) do |faraday|
61
+ faraday.response :raise_error
62
+ end.send(method_to_call) do |request|
63
+ request.url url
64
+ request.headers['Content-Type'] = 'application/json'
65
+
66
+ request.headers['authorization'] = "Key #{@api_key}" unless @api_key.nil?
67
+
68
+ request.body = payload.to_json unless payload.nil?
69
+
70
+ if server_sent_events_enabled
71
+ request.options.on_data = proc do |chunk, bytes, env|
72
+ if env && env.status != 200
73
+ raise_error = Faraday::Response::RaiseError.new
74
+ raise_error.on_complete(env.merge(body: chunk))
75
+ end
76
+
77
+ partial_json += chunk
78
+
79
+ parsed_json = safe_parse_json(partial_json)
80
+
81
+ if parsed_json
82
+ result = { event: parsed_json, raw: { chunk:, bytes:, env: } }
83
+
84
+ callback.call(result[:event], result[:raw]) unless callback.nil?
85
+
86
+ results << result
87
+
88
+ partial_json = ''
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ return safe_parse_json_with_fallback_to_raw(response.body) unless server_sent_events_enabled
95
+
96
+ results.map { |result| result[:event] }
97
+ rescue Faraday::ServerError => e
98
+ raise RequestError.new(e.message, request: e, payload:)
99
+ end
100
+
101
+ def safe_parse_json_with_fallback_to_raw(raw)
102
+ raw.to_s.lstrip.start_with?('{', '[') ? JSON.parse(raw) : raw
103
+ rescue JSON::ParserError
104
+ raw
105
+ end
106
+
107
+ def safe_parse_json(raw)
108
+ raw.to_s.lstrip.start_with?('{', '[') ? JSON.parse(raw) : nil
109
+ rescue JSON::ParserError
110
+ nil
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'static/gem'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = Maritaca::GEM[:name]
7
+ spec.version = Maritaca::GEM[:version]
8
+ spec.authors = [Maritaca::GEM[:author]]
9
+
10
+ spec.summary = Maritaca::GEM[:summary]
11
+ spec.description = Maritaca::GEM[:description]
12
+
13
+ spec.homepage = Maritaca::GEM[:github]
14
+
15
+ spec.license = Maritaca::GEM[:license]
16
+
17
+ spec.required_ruby_version = Gem::Requirement.new(">= #{Maritaca::GEM[:ruby]}")
18
+
19
+ spec.metadata['allowed_push_host'] = Maritaca::GEM[:gem_server]
20
+
21
+ spec.metadata['homepage_uri'] = spec.homepage
22
+ spec.metadata['source_code_uri'] = Maritaca::GEM[:github]
23
+
24
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
+ `git ls-files -z`.split("\x0").reject do |f|
26
+ f.match(%r{\A(?:test|spec|features)/})
27
+ end
28
+ end
29
+
30
+ spec.require_paths = ['ports/dsl']
31
+
32
+ spec.add_dependency 'faraday', '~> 2.8', '>= 2.8.1'
33
+
34
+ spec.metadata['rubygems_mfa_required'] = 'true'
35
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../components/errors'
4
+
5
+ include Maritaca::Errors
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../static/gem'
4
+ require_relative '../../controllers/client'
5
+
6
+ module Maritaca
7
+ def self.new(...)
8
+ Controllers::Client.new(...)
9
+ end
10
+
11
+ def self.version
12
+ Maritaca::GEM[:version]
13
+ end
14
+ end
data/static/gem.rb ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Maritaca
4
+ GEM = {
5
+ name: 'maritaca-ai',
6
+ version: '1.0.0',
7
+ author: 'gbaptista',
8
+ summary: 'Interact with Maritaca AI.',
9
+ description: "A Ruby gem for interacting with Maritaca AI's large language models.",
10
+ github: 'https://github.com/gbaptista/maritaca-ai',
11
+ gem_server: 'https://rubygems.org',
12
+ license: 'MIT',
13
+ ruby: '3.1.0'
14
+ }.freeze
15
+ end
@@ -0,0 +1,39 @@
1
+ (require '[clojure.string :as str])
2
+
3
+ (defn slugify [text]
4
+ (-> text
5
+ (clojure.string/lower-case)
6
+ (clojure.string/replace " " "-")
7
+ (clojure.string/replace #"[^a-z0-9\-_]" "")))
8
+
9
+ (defn remove-code-blocks [content]
10
+ (let [code-block-regex #"(?s)```.*?```"]
11
+ (clojure.string/replace content code-block-regex "")))
12
+
13
+ (defn process-line [line]
14
+ (when-let [[_ hashes title] (re-find #"^(\#{2,}) (.+)" line)]
15
+ (let [link (slugify title)]
16
+ {:level (count hashes) :title title :link link})))
17
+
18
+ (defn create-index [content]
19
+ (let [processed-content (remove-code-blocks content)
20
+ processed-lines (->> processed-content
21
+ clojure.string/split-lines
22
+ (map process-line)
23
+ (remove nil?))]
24
+ (->> processed-lines
25
+ (map (fn [{:keys [level title link]}]
26
+ (str (apply str (repeat (* 4 (- level 2)) " "))
27
+ "- ["
28
+ title
29
+ "](#"
30
+ link
31
+ ")")))
32
+ (clojure.string/join "\n"))))
33
+
34
+
35
+ (let [content (slurp "template.md")
36
+ index (create-index content)
37
+ updated-content (clojure.string/replace content "{index}" index)]
38
+ (spit "README.md" updated-content)
39
+ (println "README.md successfully generated."))
data/template.md ADDED
@@ -0,0 +1,312 @@
1
+ # Maritaca AI
2
+
3
+ A Ruby gem for interacting with [MariTalk](https://chat.maritaca.ai) from [Maritaca AI](https://www.maritaca.ai).
4
+
5
+ ![The image features a minimalist logo combining a red ruby and a green Brazilian maritaca bird. The left side shows a flat, smooth red ruby, while the right side transitions to a vibrant green maritaca bird, both depicted in a simple, stylized manner. The background is a subtle gradient, enhancing the logo's modern and clean design..](https://raw.githubusercontent.com/gbaptista/assets/main/maritaca-ai/maritaca-ai-canvas.png)
6
+
7
+ > _This Gem is designed to provide low-level access to MariTalk, 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 'maritaca-ai', '~> 1.0.0'
13
+ ```
14
+
15
+ ```ruby
16
+ require 'maritaca-ai'
17
+
18
+ client = Maritaca.new(
19
+ credentials: { api_key: ENV['MARITACA_API_KEY'] }
20
+ )
21
+
22
+ result = client.chat_inference(
23
+ { model: 'maritalk',
24
+ chat_mode: true,
25
+ messages: [ { role: 'user', content: 'Oi!' } ] }
26
+ )
27
+ ```
28
+
29
+ Result:
30
+ ```ruby
31
+ { 'answer' => 'Oi! Como posso ajudá-lo(a) hoje?' }
32
+ ```
33
+
34
+ ## Index
35
+
36
+ {index}
37
+
38
+ ## Setup
39
+
40
+ ### Installing
41
+
42
+ ```sh
43
+ gem install maritaca-ai -v 1.0.0
44
+ ```
45
+
46
+ ```sh
47
+ gem 'maritaca-ai', '~> 1.0.0'
48
+ ```
49
+
50
+ ### Credentials
51
+
52
+ You can obtain your API key at [MariTalk](https://chat.maritaca.ai).
53
+
54
+ Enclose credentials in single quotes when using environment variables to prevent issues with the `$` character in the API key:
55
+
56
+ ```sh
57
+ MARITACA_API_KEY='123...$a12...'
58
+ ```
59
+
60
+ ## Usage
61
+
62
+ ### Client
63
+
64
+ Ensure that you have an [API Key](#credentials) for authentication.
65
+
66
+ Create a new client:
67
+ ```ruby
68
+ require 'maritaca-ai'
69
+
70
+ client = Maritaca.new(
71
+ credentials: { api_key: ENV['MARITACA_API_KEY'] }
72
+ )
73
+ ```
74
+
75
+ #### Custom Address
76
+
77
+ You can use a custom address:
78
+
79
+ ```ruby
80
+ require 'maritaca-ai'
81
+
82
+ client = Maritaca.new(
83
+ credentials: {
84
+ address: 'https://chat.maritaca.ai',
85
+ api_key: ENV['MARITACA_API_KEY']
86
+ }
87
+ )
88
+ ```
89
+
90
+ ### Methods
91
+
92
+ #### chat_inference
93
+
94
+ #### Chat
95
+
96
+ ```ruby
97
+ result = client.chat_inference(
98
+ { model: 'maritalk',
99
+ chat_mode: true,
100
+ messages: [ { role: 'user', content: 'Oi!' } ] }
101
+ )
102
+ ```
103
+
104
+ Result:
105
+ ```ruby
106
+ { 'answer' => 'Oi! Como posso ajudá-lo(a) hoje?' }
107
+ ```
108
+
109
+ #### Back-and-Forth Conversations
110
+
111
+ To maintain a back-and-forth conversation, you need to append the received responses and build a history for your requests:
112
+
113
+ ```rb
114
+ result = client.chat_inference(
115
+ { model: 'maritalk',
116
+ chat_mode: true,
117
+ messages: [
118
+ { role: 'user', content: 'Oi, meu nome é Tamanduá.' },
119
+ { role: 'assistant', content: 'Oi Tamanduá, como posso ajudá-lo hoje?' },
120
+ { role: 'user', content: 'Qual é o meu nome?' }
121
+ ] }
122
+ )
123
+ ```
124
+
125
+ Result:
126
+ ```ruby
127
+ { 'answer' => 'Seu nome é Tamanduá.' }
128
+ ```
129
+
130
+ #### Without Chat
131
+
132
+ You can prompt the model without using chat mode:
133
+
134
+ ```ruby
135
+ result = client.chat_inference(
136
+ { model: 'maritalk',
137
+ chat_mode: false,
138
+ messages: "Minha terra tem palmeiras,\nOnde canta o Sabiá;\n" }
139
+ )
140
+ ```
141
+
142
+ Result:
143
+ ```ruby
144
+ { 'answer' =>
145
+ "As aves, que aqui gorjeiam,\n" \
146
+ 'Não gorjeiam como lá.' }
147
+ ```
148
+
149
+ ### New Functionalities and APIs
150
+
151
+ Maritaca 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_inference` is just a wrapper for `api/chat/inference`, which you can call directly like this:
152
+
153
+ ```ruby
154
+ result = client.request(
155
+ 'api/chat/inference',
156
+ { model: 'maritalk',
157
+ chat_mode: true,
158
+ messages: [{ role: 'user', content: 'Oi!' }] },
159
+ request_method: 'POST'
160
+ )
161
+ ```
162
+
163
+ ### Request Options
164
+
165
+ #### Timeout
166
+
167
+ You can set the maximum number of seconds to wait for the request to complete with the `timeout` option:
168
+
169
+ ```ruby
170
+ client = Maritaca.new(
171
+ credentials: { api_key: ENV['MARITACA_API_KEY'] },
172
+ options: { connection: { request: { timeout: 5 } } }
173
+ )
174
+ ```
175
+
176
+ 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:
177
+
178
+ ```ruby
179
+ client = Maritaca.new(
180
+ credentials: { api_key: ENV['MARITACA_API_KEY'] },
181
+ options: {
182
+ connection: {
183
+ request: {
184
+ timeout: 5,
185
+ open_timeout: 5,
186
+ read_timeout: 5,
187
+ write_timeout: 5
188
+ }
189
+ }
190
+ }
191
+ )
192
+ ```
193
+
194
+ ### Error Handling
195
+
196
+ #### Rescuing
197
+
198
+ ```ruby
199
+ require 'maritaca-ai'
200
+
201
+ begin
202
+ client.chat_inference(
203
+ { model: 'maritalk',
204
+ chat_mode: true,
205
+ messages: [ { role: 'user', content: 'Oi!' } ] }
206
+ )
207
+ rescue Maritaca::Errors::MaritacaError => error
208
+ puts error.class # Maritaca::Errors::RequestError
209
+ puts error.message # 'the server responded with status 500'
210
+
211
+ puts error.payload
212
+ # { model: 'maritalk',
213
+ # chat_mode: true,
214
+ # ...
215
+ # }
216
+
217
+ puts error.request
218
+ # #<Faraday::ServerError response={:status=>500, :headers...
219
+ end
220
+ ```
221
+
222
+ #### For Short
223
+
224
+ ```ruby
225
+ require 'maritaca-ai/errors'
226
+
227
+ begin
228
+ client.chat_inference(
229
+ { model: 'maritalk',
230
+ chat_mode: true,
231
+ messages: [ { role: 'user', content: 'Oi!' } ] }
232
+ )
233
+ rescue MaritacaError => error
234
+ puts error.class # Maritaca::Errors::RequestError
235
+ end
236
+ ```
237
+
238
+ #### Errors
239
+
240
+ ```ruby
241
+ MaritacaError
242
+
243
+ MissingAPIKeyError
244
+
245
+ RequestError
246
+ ```
247
+
248
+ ## Development
249
+
250
+ ```bash
251
+ bundle
252
+ rubocop -A
253
+ ```
254
+
255
+ ### Purpose
256
+
257
+ This Gem is designed to provide low-level access to MariTalk, 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) 💎 🤖.
258
+
259
+ ### Publish to RubyGems
260
+
261
+ ```bash
262
+ gem build maritaca-ai.gemspec
263
+
264
+ gem signin
265
+
266
+ gem push maritaca-ai-1.0.0.gem
267
+ ```
268
+
269
+ ### Updating the README
270
+
271
+ Install [Babashka](https://babashka.org):
272
+
273
+ ```sh
274
+ curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | sudo bash
275
+ ```
276
+
277
+ Update the `template.md` file and then:
278
+
279
+ ```sh
280
+ bb tasks/generate-readme.clj
281
+ ```
282
+
283
+ Trick for automatically updating the `README.md` when `template.md` changes:
284
+
285
+ ```sh
286
+ sudo pacman -S inotify-tools # Arch / Manjaro
287
+ sudo apt-get install inotify-tools # Debian / Ubuntu / Raspberry Pi OS
288
+ sudo dnf install inotify-tools # Fedora / CentOS / RHEL
289
+
290
+ while inotifywait -e modify template.md; do bb tasks/generate-readme.clj; done
291
+ ```
292
+
293
+ Trick for Markdown Live Preview:
294
+ ```sh
295
+ pip install -U markdown_live_preview
296
+
297
+ mlp README.md -p 8076
298
+ ```
299
+
300
+ ## Resources and References
301
+
302
+ These resources and references may be useful throughout your learning process.
303
+
304
+ - [Maritaca AI Official Website](https://www.maritaca.ai)
305
+ - [MariTalk Documentation](https://maritaca-ai.github.io/maritalk-api/maritalk.html)
306
+ - [Maritaca AI API Documentation](https://chat.maritaca.ai/docs)
307
+
308
+ ## Disclaimer
309
+
310
+ This is not an official Maritaca AI project, nor is it affiliated with Maritaca AI in any way.
311
+
312
+ This software is distributed under the [MIT License](https://github.com/gbaptista/maritaca-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 Maritaca AI Ruby Gem at your own risk.
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: maritaca-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-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.8'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.8.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '2.8'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.8.1
33
+ description: A Ruby gem for interacting with Maritaca AI's large language models.
34
+ email:
35
+ executables: []
36
+ extensions: []
37
+ extra_rdoc_files: []
38
+ files:
39
+ - ".gitignore"
40
+ - ".rubocop.yml"
41
+ - ".ruby-version"
42
+ - Gemfile
43
+ - Gemfile.lock
44
+ - LICENSE
45
+ - README.md
46
+ - components/errors.rb
47
+ - controllers/client.rb
48
+ - maritaca-ai.gemspec
49
+ - ports/dsl/maritaca-ai.rb
50
+ - ports/dsl/maritaca-ai/errors.rb
51
+ - static/gem.rb
52
+ - tasks/generate-readme.clj
53
+ - template.md
54
+ homepage: https://github.com/gbaptista/maritaca-ai
55
+ licenses:
56
+ - MIT
57
+ metadata:
58
+ allowed_push_host: https://rubygems.org
59
+ homepage_uri: https://github.com/gbaptista/maritaca-ai
60
+ source_code_uri: https://github.com/gbaptista/maritaca-ai
61
+ rubygems_mfa_required: 'true'
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - ports/dsl
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 3.1.0
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubygems_version: 3.5.3
78
+ signing_key:
79
+ specification_version: 4
80
+ summary: Interact with Maritaca AI.
81
+ test_files: []