cohere-ai 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +6 -0
- data/.ruby-version +1 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +62 -0
- data/LICENSE +9 -0
- data/README.md +765 -0
- data/cohere-ai.gemspec +35 -0
- data/components/errors.rb +25 -0
- data/controllers/client.rb +131 -0
- data/ports/dsl/cohere-ai/errors.rb +5 -0
- data/ports/dsl/cohere-ai.rb +14 -0
- data/static/gem.rb +15 -0
- data/tasks/generate-readme.clj +39 -0
- data/template.md +728 -0
- metadata +81 -0
data/cohere-ai.gemspec
ADDED
@@ -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 = Cohere::GEM[:name]
|
7
|
+
spec.version = Cohere::GEM[:version]
|
8
|
+
spec.authors = [Cohere::GEM[:author]]
|
9
|
+
|
10
|
+
spec.summary = Cohere::GEM[:summary]
|
11
|
+
spec.description = Cohere::GEM[:description]
|
12
|
+
|
13
|
+
spec.homepage = Cohere::GEM[:github]
|
14
|
+
|
15
|
+
spec.license = Cohere::GEM[:license]
|
16
|
+
|
17
|
+
spec.required_ruby_version = Gem::Requirement.new(">= #{Cohere::GEM[:ruby]}")
|
18
|
+
|
19
|
+
spec.metadata['allowed_push_host'] = Cohere::GEM[:gem_server]
|
20
|
+
|
21
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
22
|
+
spec.metadata['source_code_uri'] = Cohere::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,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cohere
|
4
|
+
module Errors
|
5
|
+
class CohereError < StandardError
|
6
|
+
def initialize(message = nil)
|
7
|
+
super(message)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class MissingAPIKeyError < CohereError; end
|
12
|
+
class BlockWithoutServerSentEventsError < CohereError; end
|
13
|
+
|
14
|
+
class RequestError < CohereError
|
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,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
require_relative '../ports/dsl/cohere-ai/errors'
|
7
|
+
|
8
|
+
module Cohere
|
9
|
+
module Controllers
|
10
|
+
class Client
|
11
|
+
DEFAULT_ADDRESS = 'https://api.cohere.ai'
|
12
|
+
|
13
|
+
ALLOWED_REQUEST_OPTIONS = %i[timeout open_timeout read_timeout write_timeout].freeze
|
14
|
+
|
15
|
+
def initialize(config)
|
16
|
+
@api_key = config.dig(:credentials, :api_key)
|
17
|
+
@server_sent_events = config.dig(:options, :server_sent_events)
|
18
|
+
|
19
|
+
@address = if config[:credentials][:address].nil? || config[:credentials][:address].to_s.strip.empty?
|
20
|
+
"#{DEFAULT_ADDRESS}/"
|
21
|
+
else
|
22
|
+
"#{config[:credentials][:address].to_s.sub(%r{/$}, '')}/"
|
23
|
+
end
|
24
|
+
|
25
|
+
if @api_key.nil? && @address == "#{DEFAULT_ADDRESS}/"
|
26
|
+
raise MissingAPIKeyError, 'Missing API Key, which is required.'
|
27
|
+
end
|
28
|
+
|
29
|
+
@request_options = config.dig(:options, :connection, :request)
|
30
|
+
|
31
|
+
@request_options = if @request_options.is_a?(Hash)
|
32
|
+
@request_options.select do |key, _|
|
33
|
+
ALLOWED_REQUEST_OPTIONS.include?(key)
|
34
|
+
end
|
35
|
+
else
|
36
|
+
{}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def chat(payload, server_sent_events: nil, &callback)
|
41
|
+
server_sent_events = false if payload[:stream] != true
|
42
|
+
request('v1/chat', payload, server_sent_events:, &callback)
|
43
|
+
end
|
44
|
+
|
45
|
+
def generate(payload, server_sent_events: nil, &callback)
|
46
|
+
server_sent_events = false if payload[:stream] != true
|
47
|
+
request('v1/generate', payload, server_sent_events:, &callback)
|
48
|
+
end
|
49
|
+
|
50
|
+
def embed(payload, _server_sent_events: nil, &callback)
|
51
|
+
request('v1/embed', payload, server_sent_events: false, &callback)
|
52
|
+
end
|
53
|
+
|
54
|
+
def rerank(payload, _server_sent_events: nil, &callback)
|
55
|
+
request('v1/rerank', payload, server_sent_events: false, &callback)
|
56
|
+
end
|
57
|
+
|
58
|
+
def classify(payload, _server_sent_events: nil, &callback)
|
59
|
+
request('v1/classify', payload, server_sent_events: false, &callback)
|
60
|
+
end
|
61
|
+
|
62
|
+
def detect_language(payload, _server_sent_events: nil, &callback)
|
63
|
+
request('v1/detect-language', payload, server_sent_events: false, &callback)
|
64
|
+
end
|
65
|
+
|
66
|
+
def summarize(payload, _server_sent_events: nil, &callback)
|
67
|
+
request('v1/summarize', payload, server_sent_events: false, &callback)
|
68
|
+
end
|
69
|
+
|
70
|
+
def tokenize(payload, _server_sent_events: nil, &callback)
|
71
|
+
request('v1/tokenize', payload, server_sent_events: false, &callback)
|
72
|
+
end
|
73
|
+
|
74
|
+
def detokenize(payload, _server_sent_events: nil, &callback)
|
75
|
+
request('v1/detokenize', payload, server_sent_events: false, &callback)
|
76
|
+
end
|
77
|
+
|
78
|
+
def request(path, payload = nil, server_sent_events: nil, request_method: 'POST', &callback)
|
79
|
+
server_sent_events_enabled = server_sent_events.nil? ? @server_sent_events : server_sent_events
|
80
|
+
url = "#{@address}#{path}"
|
81
|
+
|
82
|
+
if !callback.nil? && !server_sent_events_enabled
|
83
|
+
raise BlockWithoutServerSentEventsError,
|
84
|
+
'You are trying to use a block without Server Sent Events (SSE) enabled.'
|
85
|
+
end
|
86
|
+
|
87
|
+
results = []
|
88
|
+
|
89
|
+
method_to_call = request_method.to_s.strip.downcase.to_sym
|
90
|
+
|
91
|
+
response = Faraday.new(request: @request_options) do |faraday|
|
92
|
+
faraday.response :raise_error
|
93
|
+
end.send(method_to_call) do |request|
|
94
|
+
request.url url
|
95
|
+
request.headers['Content-Type'] = 'application/json'
|
96
|
+
|
97
|
+
request.headers['Authorization'] = "Bearer #{@api_key}" unless @api_key.nil?
|
98
|
+
|
99
|
+
request.body = payload.to_json unless payload.nil?
|
100
|
+
|
101
|
+
if server_sent_events_enabled
|
102
|
+
request.options.on_data = proc do |chunk, bytes, env|
|
103
|
+
if env && env.status != 200
|
104
|
+
raise_error = Faraday::Response::RaiseError.new
|
105
|
+
raise_error.on_complete(env.merge(body: chunk))
|
106
|
+
end
|
107
|
+
|
108
|
+
result = { event: safe_parse_json(chunk), raw: { chunk:, bytes:, env: } }
|
109
|
+
|
110
|
+
callback.call(result[:event], result[:raw]) unless callback.nil?
|
111
|
+
|
112
|
+
results << result
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
return safe_parse_json(response.body) unless server_sent_events_enabled
|
118
|
+
|
119
|
+
results.map { |result| result[:event] }
|
120
|
+
rescue Faraday::ServerError => e
|
121
|
+
raise RequestError.new(e.message, request: e, payload:)
|
122
|
+
end
|
123
|
+
|
124
|
+
def safe_parse_json(raw)
|
125
|
+
raw.start_with?('{', '[') ? JSON.parse(raw) : raw
|
126
|
+
rescue JSON::ParserError
|
127
|
+
raw
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
data/static/gem.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cohere
|
4
|
+
GEM = {
|
5
|
+
name: 'cohere-ai',
|
6
|
+
version: '1.0.0',
|
7
|
+
author: 'gbaptista',
|
8
|
+
summary: 'Interact with Cohere AI.',
|
9
|
+
description: "A Ruby gem for interacting with Cohere AI platform.",
|
10
|
+
github: 'https://github.com/gbaptista/cohere-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."))
|