langchainrb 0.9.0 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eb443fa9eb8f0f9ee32fcef7b413d6825a4c45779c14551e03e71878215560d9
4
- data.tar.gz: ed70c0b23899598c04fc6c6178466f2bda354f2483f712e83eeb9797f55c38ef
3
+ metadata.gz: cdaafd0889d6666c7aa39d8bee71763f8baf86e0566f9e87312fc6033d07709d
4
+ data.tar.gz: 7acc9f122aed92eab9ab2ac1d50f7ee59c0e24030335dc15878769b7664ffc6b
5
5
  SHA512:
6
- metadata.gz: 1cf9baef16a801a1fd81ab6cb1ee89ab297fb8bc633a15641d125e44b1f4121208ec5e41f1c79ac49f93d27e60be899e030ec2bfb99359d6dc983b99398302ce
7
- data.tar.gz: af0961e7ee973c0fd35f6e44206f66f7f598c0213a4ec71fb5a7608a58cf56336a6a1d700341c53ad6c0c65fb8eebd9bd382b54829821caa5219dda0089ca8f2
6
+ metadata.gz: b76f62411f75eccba98371791e63b18f0f22225de1af7449cde40680acbd1dc09c4b5a6b7eeb1ac667dd9b029c52534fbfbe10a5fa465fa0859059ddb32a400c
7
+ data.tar.gz: 64052a22206ece081a2fd9fbf0233ba47f40539743b1def6d7fc9beeb31102f5559878514cbc0d503fd13681e5efbb34c2755cacbd62b1b01b67876bc9d6237e
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.9.2]
4
+ - Fix vectorsearch#ask methods
5
+ - Bump cohere-ruby gem
6
+
7
+ ## [0.9.1]
8
+ - Add support for new OpenAI models
9
+ - Add Ollama#chat method
10
+ - Fix and refactor of `Langchain::LLM::Ollama`, responses can now be streamed.
11
+
3
12
  ## [0.9.0]
4
13
  - Introducing new `Langchain::Assistant` that will be replacing `Langchain::Conversation` and `Langchain::Agent`s.
5
14
  - `Langchain::Conversation` is deprecated.
data/README.md CHANGED
@@ -42,6 +42,8 @@ If bundler is not being used to manage dependencies, install the gem by executin
42
42
 
43
43
  gem install langchainrb
44
44
 
45
+ Additional gems may be required when loading LLM Providers. These are not included by default so you can include only what you need.
46
+
45
47
  ## Usage
46
48
 
47
49
  ```ruby
@@ -62,7 +64,7 @@ Langchain.rb wraps all supported LLMs in a unified interface allowing you to eas
62
64
  | [GooglePalm](https://ai.google/discover/palm2?utm_source=langchainrb&utm_medium=github) | ✅ | ✅ | ✅ | ✅ | |
63
65
  | [Google Vertex AI](https://cloud.google.com/vertex-ai?utm_source=langchainrb&utm_medium=github) | ✅ | ✅ | ❌ | ✅ | |
64
66
  | [HuggingFace](https://huggingface.co/?utm_source=langchainrb&utm_medium=github) | ✅ | ❌ | ❌ | ❌ | |
65
- | [Ollama](https://ollama.ai/?utm_source=langchainrb&utm_medium=github) | ✅ | ✅ | | ❌ | |
67
+ | [Ollama](https://ollama.ai/?utm_source=langchainrb&utm_medium=github) | ✅ | ✅ | | ❌ | |
66
68
  | [Replicate](https://replicate.com/?utm_source=langchainrb&utm_medium=github) | ✅ | ✅ | ✅ | ✅ | |
67
69
 
68
70
  #### Using standalone LLMs:
@@ -91,7 +93,7 @@ llm.complete(prompt: "What is the meaning of life?").completion
91
93
 
92
94
  Generate a chat completion:
93
95
  ```ruby
94
- llm.chat(prompt: "Hey! How are you?").completion
96
+ llm.chat(messages: [{role: "user", content: "What is the meaning of life?"}]).completion
95
97
  ```
96
98
 
97
99
  Summarize the text:
@@ -5,21 +5,26 @@ module Langchain::LLM
5
5
  # Available models: https://ollama.ai/library
6
6
  #
7
7
  # Usage:
8
- # ollama = Langchain::LLM::Ollama.new(url: ENV["OLLAMA_URL"])
8
+ # ollama = Langchain::LLM::Ollama.new(url: ENV["OLLAMA_URL"], default_options: {})
9
9
  #
10
10
  class Ollama < Base
11
- attr_reader :url
11
+ attr_reader :url, :defaults
12
12
 
13
13
  DEFAULTS = {
14
- temperature: 0.0,
14
+ temperature: 0.8,
15
15
  completion_model_name: "llama2",
16
- embeddings_model_name: "llama2"
16
+ embeddings_model_name: "llama2",
17
+ chat_completion_model_name: "llama2"
17
18
  }.freeze
18
19
 
19
20
  # Initialize the Ollama client
20
21
  # @param url [String] The URL of the Ollama instance
21
- def initialize(url:)
22
+ # @param default_options [Hash] The default options to use
23
+ #
24
+ def initialize(url:, default_options: {})
25
+ depends_on "faraday"
22
26
  @url = url
27
+ @defaults = DEFAULTS.merge(default_options)
23
28
  end
24
29
 
25
30
  #
@@ -27,32 +32,128 @@ module Langchain::LLM
27
32
  #
28
33
  # @param prompt [String] The prompt to complete
29
34
  # @param model [String] The model to use
30
- # @param options [Hash] The options to use (https://github.com/jmorganca/ollama/blob/main/docs/modelfile.md#valid-parameters-and-values)
35
+ # For a list of valid parameters and values, see:
36
+ # https://github.com/jmorganca/ollama/blob/main/docs/modelfile.md#valid-parameters-and-values
31
37
  # @return [Langchain::LLM::OllamaResponse] Response object
32
38
  #
33
- def complete(prompt:, model: nil, **options)
34
- response = +""
39
+ def complete(
40
+ prompt:,
41
+ model: defaults[:completion_model_name],
42
+ images: nil,
43
+ format: nil,
44
+ system: nil,
45
+ template: nil,
46
+ context: nil,
47
+ stream: nil,
48
+ raw: nil,
49
+ mirostat: nil,
50
+ mirostat_eta: nil,
51
+ mirostat_tau: nil,
52
+ num_ctx: nil,
53
+ num_gqa: nil,
54
+ num_gpu: nil,
55
+ num_thread: nil,
56
+ repeat_last_n: nil,
57
+ repeat_penalty: nil,
58
+ temperature: defaults[:temperature],
59
+ seed: nil,
60
+ stop: nil,
61
+ tfs_z: nil,
62
+ num_predict: nil,
63
+ top_k: nil,
64
+ top_p: nil,
65
+ stop_sequences: nil,
66
+ &block
67
+ )
68
+ if stop_sequences
69
+ stop = stop_sequences
70
+ end
35
71
 
36
- model_name = model || DEFAULTS[:completion_model_name]
72
+ parameters = {
73
+ prompt: prompt,
74
+ model: model,
75
+ images: images,
76
+ format: format,
77
+ system: system,
78
+ template: template,
79
+ context: context,
80
+ stream: stream,
81
+ raw: raw
82
+ }.compact
83
+
84
+ llm_parameters = {
85
+ mirostat: mirostat,
86
+ mirostat_eta: mirostat_eta,
87
+ mirostat_tau: mirostat_tau,
88
+ num_ctx: num_ctx,
89
+ num_gqa: num_gqa,
90
+ num_gpu: num_gpu,
91
+ num_thread: num_thread,
92
+ repeat_last_n: repeat_last_n,
93
+ repeat_penalty: repeat_penalty,
94
+ temperature: temperature,
95
+ seed: seed,
96
+ stop: stop,
97
+ tfs_z: tfs_z,
98
+ num_predict: num_predict,
99
+ top_k: top_k,
100
+ top_p: top_p
101
+ }
102
+
103
+ parameters[:options] = llm_parameters.compact
104
+
105
+ response = ""
37
106
 
38
107
  client.post("api/generate") do |req|
39
- req.body = {}
40
- req.body["prompt"] = prompt
41
- req.body["model"] = model_name
42
-
43
- req.body["options"] = options if options.any?
108
+ req.body = parameters
44
109
 
45
- # TODO: Implement streaming support when a &block is passed in
46
110
  req.options.on_data = proc do |chunk, size|
47
111
  json_chunk = JSON.parse(chunk)
48
112
 
49
- unless json_chunk.dig("done")
50
- response.to_s << JSON.parse(chunk).dig("response")
51
- end
113
+ response += json_chunk.dig("response")
114
+
115
+ yield json_chunk, size if block
52
116
  end
53
117
  end
54
118
 
55
- Langchain::LLM::OllamaResponse.new(response, model: model_name)
119
+ Langchain::LLM::OllamaResponse.new(response, model: parameters[:model])
120
+ end
121
+
122
+ # Generate a chat completion
123
+ #
124
+ # @param model [String] Model name
125
+ # @param messages [Array<Hash>] Array of messages
126
+ # @param format [String] Format to return a response in. Currently the only accepted value is `json`
127
+ # @param temperature [Float] The temperature to use
128
+ # @param template [String] The prompt template to use (overrides what is defined in the `Modelfile`)
129
+ # @param stream [Boolean] Streaming the response. If false the response will be returned as a single response object, rather than a stream of objects
130
+ #
131
+ # The message object has the following fields:
132
+ # role: the role of the message, either system, user or assistant
133
+ # content: the content of the message
134
+ # images (optional): a list of images to include in the message (for multimodal models such as llava)
135
+ def chat(
136
+ model: defaults[:chat_completion_model_name],
137
+ messages: [],
138
+ format: nil,
139
+ temperature: defaults[:temperature],
140
+ template: nil,
141
+ stream: false # TODO: Fix streaming.
142
+ )
143
+ parameters = {
144
+ model: model,
145
+ messages: messages,
146
+ format: format,
147
+ temperature: temperature,
148
+ template: template,
149
+ stream: stream
150
+ }.compact
151
+
152
+ response = client.post("api/chat") do |req|
153
+ req.body = parameters
154
+ end
155
+
156
+ Langchain::LLM::OllamaResponse.new(response.body, model: parameters[:model])
56
157
  end
57
158
 
58
159
  #
@@ -63,18 +164,57 @@ module Langchain::LLM
63
164
  # @param options [Hash] The options to use
64
165
  # @return [Langchain::LLM::OllamaResponse] Response object
65
166
  #
66
- def embed(text:, model: nil, **options)
67
- model_name = model || DEFAULTS[:embeddings_model_name]
167
+ def embed(
168
+ text:,
169
+ model: defaults[:embeddings_model_name],
170
+ mirostat: nil,
171
+ mirostat_eta: nil,
172
+ mirostat_tau: nil,
173
+ num_ctx: nil,
174
+ num_gqa: nil,
175
+ num_gpu: nil,
176
+ num_thread: nil,
177
+ repeat_last_n: nil,
178
+ repeat_penalty: nil,
179
+ temperature: defaults[:temperature],
180
+ seed: nil,
181
+ stop: nil,
182
+ tfs_z: nil,
183
+ num_predict: nil,
184
+ top_k: nil,
185
+ top_p: nil
186
+ )
187
+ parameters = {
188
+ prompt: text,
189
+ model: model
190
+ }.compact
191
+
192
+ llm_parameters = {
193
+ mirostat: mirostat,
194
+ mirostat_eta: mirostat_eta,
195
+ mirostat_tau: mirostat_tau,
196
+ num_ctx: num_ctx,
197
+ num_gqa: num_gqa,
198
+ num_gpu: num_gpu,
199
+ num_thread: num_thread,
200
+ repeat_last_n: repeat_last_n,
201
+ repeat_penalty: repeat_penalty,
202
+ temperature: temperature,
203
+ seed: seed,
204
+ stop: stop,
205
+ tfs_z: tfs_z,
206
+ num_predict: num_predict,
207
+ top_k: top_k,
208
+ top_p: top_p
209
+ }
210
+
211
+ parameters[:options] = llm_parameters.compact
68
212
 
69
213
  response = client.post("api/embeddings") do |req|
70
- req.body = {}
71
- req.body["prompt"] = text
72
- req.body["model"] = model_name
73
-
74
- req.body["options"] = options if options.any?
214
+ req.body = parameters
75
215
  end
76
216
 
77
- Langchain::LLM::OllamaResponse.new(response.body, model: model_name)
217
+ Langchain::LLM::OllamaResponse.new(response.body, model: parameters[:model])
78
218
  end
79
219
 
80
220
  private
@@ -13,6 +13,13 @@ module Langchain
13
13
  @model = model
14
14
  end
15
15
 
16
+ # Returns the timestamp when the response was created
17
+ #
18
+ # @return [Time]
19
+ def created_at
20
+ raise NotImplementedError
21
+ end
22
+
16
23
  # Returns the completion text
17
24
  #
18
25
  # @return [String]
@@ -7,6 +7,16 @@ module Langchain::LLM
7
7
  super(raw_response, model: model)
8
8
  end
9
9
 
10
+ def created_at
11
+ if raw_response.dig("created_at")
12
+ Time.parse(raw_response.dig("created_at"))
13
+ end
14
+ end
15
+
16
+ def chat_completion
17
+ raw_response.dig("message", "content")
18
+ end
19
+
10
20
  def completion
11
21
  completions.first
12
22
  end
@@ -26,5 +36,13 @@ module Langchain::LLM
26
36
  def role
27
37
  "assistant"
28
38
  end
39
+
40
+ def prompt_tokens
41
+ raw_response.dig("prompt_eval_count")
42
+ end
43
+
44
+ def completion_tokens
45
+ raw_response.dig("eval_count")
46
+ end
29
47
  end
30
48
  end
@@ -19,10 +19,14 @@ module Langchain
19
19
  "gpt-3.5-turbo-1106" => 4096
20
20
  }
21
21
 
22
+ # NOTE: The gpt-4-turbo-preview is an alias that will always point to the latest GPT 4 Turbo preview
23
+ # the future previews may have a different token limit!
22
24
  TOKEN_LIMITS = {
23
25
  # Source:
24
26
  # https://platform.openai.com/docs/api-reference/embeddings
25
27
  # https://platform.openai.com/docs/models/gpt-4
28
+ "text-embedding-3-large" => 8191,
29
+ "text-embedding-3-small" => 8191,
26
30
  "text-embedding-ada-002" => 8191,
27
31
  "gpt-3.5-turbo" => 4096,
28
32
  "gpt-3.5-turbo-0301" => 4096,
@@ -40,6 +44,8 @@ module Langchain
40
44
  "gpt-4-32k-0314" => 32768,
41
45
  "gpt-4-32k-0613" => 32768,
42
46
  "gpt-4-1106-preview" => 128000,
47
+ "gpt-4-turbo-preview" => 128000,
48
+ "gpt-4-0125-preview" => 128000,
43
49
  "gpt-4-vision-preview" => 128000,
44
50
  "text-curie-001" => 2049,
45
51
  "text-babbage-001" => 2049,
@@ -58,6 +64,11 @@ module Langchain
58
64
  # @return [Integer] The token length of the text
59
65
  #
60
66
  def self.token_length(text, model_name, options = {})
67
+ # tiktoken-ruby doesn't support text-embedding-3-large or text-embedding-3-small yet
68
+ if ["text-embedding-3-large", "text-embedding-3-small"].include?(model_name)
69
+ model_name = "text-embedding-ada-002"
70
+ end
71
+
61
72
  encoder = Tiktoken.encoding_for_model(model_name)
62
73
  encoder.encode(text).length
63
74
  end
@@ -7,7 +7,7 @@ module Langchain
7
7
  attr_reader :token_overflow
8
8
 
9
9
  def initialize(message = "", token_overflow = 0)
10
- super message
10
+ super(message)
11
11
 
12
12
  @token_overflow = token_overflow
13
13
  end
@@ -126,7 +126,9 @@ module Langchain::Vectorsearch
126
126
 
127
127
  prompt = generate_rag_prompt(question: question, context: context)
128
128
 
129
- response = llm.chat(prompt: prompt, &block)
129
+ messages = [{role: "user", content: prompt}]
130
+ response = llm.chat(messages: messages, &block)
131
+
130
132
  response.context = context
131
133
  response
132
134
  end
@@ -141,7 +141,9 @@ module Langchain::Vectorsearch
141
141
 
142
142
  prompt = generate_rag_prompt(question: question, context: context)
143
143
 
144
- response = llm.chat(prompt: prompt, &block)
144
+ messages = [{role: "user", content: prompt}]
145
+ response = llm.chat(messages: messages, &block)
146
+
145
147
  response.context = context
146
148
  response
147
149
  end
@@ -139,7 +139,9 @@ module Langchain::Vectorsearch
139
139
 
140
140
  prompt = generate_rag_prompt(question: question, context: context)
141
141
 
142
- response = llm.chat(prompt: prompt, &block)
142
+ messages = [{role: "user", content: prompt}]
143
+ response = llm.chat(messages: messages, &block)
144
+
143
145
  response.context = context
144
146
  response
145
147
  end
@@ -151,7 +151,9 @@ module Langchain::Vectorsearch
151
151
 
152
152
  prompt = generate_rag_prompt(question: question, context: context)
153
153
 
154
- response = llm.chat(prompt: prompt, &block)
154
+ messages = [{role: "user", content: prompt}]
155
+ response = llm.chat(messages: messages, &block)
156
+
155
157
  response.context = context
156
158
  response
157
159
  end
@@ -148,7 +148,9 @@ module Langchain::Vectorsearch
148
148
 
149
149
  prompt = generate_rag_prompt(question: question, context: context)
150
150
 
151
- response = llm.chat(prompt: prompt, &block)
151
+ messages = [{role: "user", content: prompt}]
152
+ response = llm.chat(messages: messages, &block)
153
+
152
154
  response.context = context
153
155
  response
154
156
  end
@@ -17,12 +17,13 @@ module Langchain::Vectorsearch
17
17
  # @param api_key [String] The API key to use
18
18
  # @param index_name [String] The name of the index to use
19
19
  # @param llm [Object] The LLM client to use
20
- def initialize(environment:, api_key:, index_name:, llm:)
20
+ def initialize(environment:, api_key:, index_name:, llm:, base_uri: nil)
21
21
  depends_on "pinecone"
22
22
 
23
23
  ::Pinecone.configure do |config|
24
24
  config.api_key = api_key
25
25
  config.environment = environment
26
+ config.base_uri = base_uri if base_uri
26
27
  end
27
28
 
28
29
  @client = ::Pinecone::Client.new
@@ -180,7 +181,9 @@ module Langchain::Vectorsearch
180
181
 
181
182
  prompt = generate_rag_prompt(question: question, context: context)
182
183
 
183
- response = llm.chat(prompt: prompt, &block)
184
+ messages = [{role: "user", content: prompt}]
185
+ response = llm.chat(messages: messages, &block)
186
+
184
187
  response.context = context
185
188
  response
186
189
  end
@@ -137,7 +137,9 @@ module Langchain::Vectorsearch
137
137
 
138
138
  prompt = generate_rag_prompt(question: question, context: context)
139
139
 
140
- response = llm.chat(prompt: prompt, &block)
140
+ messages = [{role: "user", content: prompt}]
141
+ response = llm.chat(messages: messages, &block)
142
+
141
143
  response.context = context
142
144
  response
143
145
  end
@@ -137,7 +137,9 @@ module Langchain::Vectorsearch
137
137
 
138
138
  prompt = generate_rag_prompt(question: question, context: context)
139
139
 
140
- response = llm.chat(prompt: prompt, &block)
140
+ messages = [{role: "user", content: prompt}]
141
+ response = llm.chat(messages: messages, &block)
142
+
141
143
  response.context = context
142
144
  response
143
145
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Langchain
4
- VERSION = "0.9.0"
4
+ VERSION = "0.9.2"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: langchainrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrei Bondarev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-01-17 00:00:00.000000000 Z
11
+ date: 2024-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: baran
@@ -240,14 +240,14 @@ dependencies:
240
240
  requirements:
241
241
  - - "~>"
242
242
  - !ruby/object:Gem::Version
243
- version: 0.9.7
243
+ version: 0.9.8
244
244
  type: :development
245
245
  prerelease: false
246
246
  version_requirements: !ruby/object:Gem::Requirement
247
247
  requirements:
248
248
  - - "~>"
249
249
  - !ruby/object:Gem::Version
250
- version: 0.9.7
250
+ version: 0.9.8
251
251
  - !ruby/object:Gem::Dependency
252
252
  name: docx
253
253
  requirement: !ruby/object:Gem::Requirement
@@ -576,14 +576,14 @@ dependencies:
576
576
  requirements:
577
577
  - - "~>"
578
578
  - !ruby/object:Gem::Version
579
- version: 0.8.9
579
+ version: 0.8.10
580
580
  type: :development
581
581
  prerelease: false
582
582
  version_requirements: !ruby/object:Gem::Requirement
583
583
  requirements:
584
584
  - - "~>"
585
585
  - !ruby/object:Gem::Version
586
- version: 0.8.9
586
+ version: 0.8.10
587
587
  - !ruby/object:Gem::Dependency
588
588
  name: wikipedia-client
589
589
  requirement: !ruby/object:Gem::Requirement
@@ -598,6 +598,20 @@ dependencies:
598
598
  - - "~>"
599
599
  - !ruby/object:Gem::Version
600
600
  version: 1.17.0
601
+ - !ruby/object:Gem::Dependency
602
+ name: faraday
603
+ requirement: !ruby/object:Gem::Requirement
604
+ requirements:
605
+ - - ">="
606
+ - !ruby/object:Gem::Version
607
+ version: '0'
608
+ type: :development
609
+ prerelease: false
610
+ version_requirements: !ruby/object:Gem::Requirement
611
+ requirements:
612
+ - - ">="
613
+ - !ruby/object:Gem::Version
614
+ version: '0'
601
615
  description: Build LLM-backed Ruby applications with Ruby's LangChain
602
616
  email:
603
617
  - andrei.bondarev13@gmail.com