langchainrb 0.4.0 → 0.4.2
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 +4 -4
- data/CHANGELOG.md +11 -0
- data/Gemfile.lock +13 -1
- data/README.md +10 -3
- data/Rakefile +5 -0
- data/lib/langchain/agent/chain_of_thought_agent/chain_of_thought_agent.rb +5 -6
- data/lib/langchain/dependency_helper.rb +34 -0
- data/lib/langchain/llm/ai21.rb +45 -0
- data/lib/langchain/llm/base.rb +2 -1
- data/lib/langchain/llm/cohere.rb +9 -0
- data/lib/langchain/llm/google_palm.rb +7 -0
- data/lib/langchain/llm/hugging_face.rb +9 -0
- data/lib/langchain/llm/openai.rb +33 -41
- data/lib/langchain/llm/replicate.rb +4 -0
- data/lib/langchain/processors/base.rb +2 -0
- data/lib/langchain/prompt/base.rb +2 -2
- data/lib/langchain/prompt/loading.rb +1 -0
- data/lib/langchain/prompt/prompt_template.rb +1 -1
- data/lib/langchain/tool/base.rb +2 -0
- data/lib/langchain/tool/calculator.rb +11 -0
- data/lib/langchain/tool/ruby_code_interpreter.rb +33 -0
- data/lib/langchain/tool/serp_api.rb +7 -1
- data/lib/langchain/tool/wikipedia.rb +6 -0
- data/lib/langchain/vectorsearch/base.rb +1 -0
- data/lib/langchain/vectorsearch/chroma.rb +9 -0
- data/lib/langchain/vectorsearch/milvus.rb +9 -0
- data/lib/langchain/vectorsearch/pgvector.rb +9 -1
- data/lib/langchain/vectorsearch/pinecone.rb +9 -0
- data/lib/langchain/vectorsearch/qdrant.rb +9 -0
- data/lib/langchain/vectorsearch/weaviate.rb +9 -0
- data/lib/{version.rb → langchain/version.rb} +1 -1
- data/lib/langchain.rb +6 -3
- metadata +76 -4
- data/lib/dependency_helper.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6e84f50b6e12bd94f5fa8de956549537f5d34b8a901bc6af3fbc5d392fc2e0a
|
4
|
+
data.tar.gz: '08c01f481d64b0c35f7e86491d1115d975497c8561f50408516fad388f084c3e'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a1d29180f3c0cf89307413bc99e22accc6875d458b3ae12ea72d30146cf5ff172fba7047fe00b385d324057638115254c8dcc6f01459a75f96dccb9a99a301b
|
7
|
+
data.tar.gz: 070a0b6836cdb7dd356c99186964f61926498d5f585910bbb30449d4b2a12d50797797dc34c6fe3eb6a4e64c156230d23606c2ac0cf131eeccc942c6231ab3c9
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.4.2] - 2023-06-03
|
4
|
+
- 🗣️ LLMs
|
5
|
+
- Introducing support for AI21
|
6
|
+
- Better docs generation
|
7
|
+
- Refactors
|
8
|
+
|
9
|
+
## [0.4.1] - 2023-06-02
|
10
|
+
- Beautiful colored log messages
|
11
|
+
- 🛠️ Tools
|
12
|
+
- Introducing `Langchain::Tool::RubyCodeInterpreter`, a tool executes sandboxed Ruby code
|
13
|
+
|
3
14
|
## [0.4.0] - 2023-06-01
|
4
15
|
- [BREAKING] Everything is namespaced under `Langchain::` now
|
5
16
|
- Pgvector similarity search uses the cosine distance by default now
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
langchainrb (0.4.
|
4
|
+
langchainrb (0.4.2)
|
5
|
+
colorize (~> 0.8.1)
|
5
6
|
tiktoken_ruby (~> 0.0.5)
|
6
7
|
|
7
8
|
GEM
|
@@ -29,9 +30,11 @@ GEM
|
|
29
30
|
addressable (2.8.4)
|
30
31
|
public_suffix (>= 2.0.2, < 6.0)
|
31
32
|
afm (0.2.2)
|
33
|
+
ai21 (0.2.0)
|
32
34
|
ast (2.4.2)
|
33
35
|
builder (3.2.4)
|
34
36
|
byebug (11.1.3)
|
37
|
+
childprocess (4.1.0)
|
35
38
|
chroma-db (0.3.0)
|
36
39
|
dry-monads (~> 1.6)
|
37
40
|
ruby-next-core (>= 0.15.0)
|
@@ -39,6 +42,7 @@ GEM
|
|
39
42
|
cohere-ruby (0.9.4)
|
40
43
|
faraday (>= 1.0.0)
|
41
44
|
faraday_middleware (>= 1.0.0)
|
45
|
+
colorize (0.8.1)
|
42
46
|
concurrent-ruby (1.2.2)
|
43
47
|
crass (1.0.6)
|
44
48
|
diff-lcs (1.5.0)
|
@@ -207,6 +211,7 @@ GEM
|
|
207
211
|
rainbow (3.1.1)
|
208
212
|
rake (13.0.6)
|
209
213
|
rb_sys (0.9.78)
|
214
|
+
rdiscount (2.2.7)
|
210
215
|
regexp_parser (2.8.0)
|
211
216
|
replicate-ruby (0.2.2)
|
212
217
|
addressable
|
@@ -250,6 +255,8 @@ GEM
|
|
250
255
|
ruby-rc4 (0.1.5)
|
251
256
|
ruby2_keywords (0.0.5)
|
252
257
|
rubyzip (2.3.2)
|
258
|
+
safe_ruby (1.0.4)
|
259
|
+
childprocess (>= 0.3.9)
|
253
260
|
standard (1.28.2)
|
254
261
|
language_server-protocol (~> 3.17.0.2)
|
255
262
|
lint_roller (~> 1.0)
|
@@ -281,6 +288,7 @@ GEM
|
|
281
288
|
graphlient (~> 0.6.0)
|
282
289
|
wikipedia-client (1.17.0)
|
283
290
|
addressable (~> 2.7)
|
291
|
+
yard (0.9.34)
|
284
292
|
zeitwerk (2.6.8)
|
285
293
|
|
286
294
|
PLATFORMS
|
@@ -292,6 +300,7 @@ PLATFORMS
|
|
292
300
|
x86_64-linux
|
293
301
|
|
294
302
|
DEPENDENCIES
|
303
|
+
ai21 (~> 0.2.0)
|
295
304
|
chroma-db (~> 0.3.0)
|
296
305
|
cohere-ruby (~> 0.9.4)
|
297
306
|
docx (~> 0.8.0)
|
@@ -310,12 +319,15 @@ DEPENDENCIES
|
|
310
319
|
pry-byebug (~> 3.10.0)
|
311
320
|
qdrant-ruby (~> 0.9.0)
|
312
321
|
rake (~> 13.0)
|
322
|
+
rdiscount
|
313
323
|
replicate-ruby (~> 0.2.2)
|
314
324
|
rspec (~> 3.0)
|
315
325
|
ruby-openai (~> 4.0.0)
|
326
|
+
safe_ruby (~> 1.0.4)
|
316
327
|
standardrb
|
317
328
|
weaviate-ruby (~> 0.8.0)
|
318
329
|
wikipedia-client (~> 1.17.0)
|
330
|
+
yard
|
319
331
|
|
320
332
|
BUNDLED WITH
|
321
333
|
2.4.0
|
data/README.md
CHANGED
@@ -109,6 +109,10 @@ Add `gem "ruby-openai", "~> 4.0.0"` to your Gemfile.
|
|
109
109
|
```ruby
|
110
110
|
openai = Langchain::LLM::OpenAI.new(api_key: ENV["OPENAI_API_KEY"])
|
111
111
|
```
|
112
|
+
You can pass additional parameters to the constructor, it will be passed to the OpenAI client:
|
113
|
+
```ruby
|
114
|
+
openai = Langchain::LLM::OpenAI.new(api_key: ENV["OPENAI_API_KEY"], llm_options: {uri_base: "http://localhost:1234"}) )
|
115
|
+
```
|
112
116
|
```ruby
|
113
117
|
openai.embed(text: "foo bar")
|
114
118
|
```
|
@@ -260,10 +264,10 @@ agent.run(question: "How many full soccer fields would be needed to cover the di
|
|
260
264
|
| Name | Description | ENV Requirements | Gem Requirements |
|
261
265
|
| ------------ | :------------------------------------------------: | :-----------------------------------------------------------: | :---------------------------------------: |
|
262
266
|
| "calculator" | Useful for getting the result of a math expression | | `gem "eqn", "~> 1.6.5"` |
|
263
|
-
| "
|
267
|
+
| "ruby_code_interpreter" | Interprets Ruby expressions | | `gem "safe_ruby", "~> 1.0.4"` |
|
268
|
+
| "search" | A wrapper around Google Search | `ENV["SERPAPI_API_KEY"]` (https://serpapi.com/manage-api-key) | `gem "google_search_results", "~> 2.0.0"` |
|
264
269
|
| "wikipedia" | Calls Wikipedia API to retrieve the summary | | `gem "wikipedia-client", "~> 1.17.0"` |
|
265
270
|
|
266
|
-
|
267
271
|
#### Loaders 🚚
|
268
272
|
|
269
273
|
Need to read data from various sources? Load it up.
|
@@ -300,7 +304,7 @@ Additional examples available: [/examples](https://github.com/andreibondarev/lan
|
|
300
304
|
|
301
305
|
## Logging
|
302
306
|
|
303
|
-
LangChain.rb uses standard logging mechanisms and defaults to `:
|
307
|
+
LangChain.rb uses standard logging mechanisms and defaults to `:warn` level. Most messages are at info level, but we will add debug or warn statements as needed.
|
304
308
|
To show all log messages:
|
305
309
|
|
306
310
|
```ruby
|
@@ -314,6 +318,9 @@ Langchain.logger.level = :info
|
|
314
318
|
3. `bundle exec rake` to ensure that the tests pass and to run standardrb
|
315
319
|
4. `bin/console` to load the gem in a REPL session. Feel free to add your own instances of LLMs, Tools, Agents, etc. and experiment with them.
|
316
320
|
|
321
|
+
## Community
|
322
|
+
Join us in the [Ruby AI Builders](https://discord.gg/SBmjAnKT) Discord community in #langchainrb
|
323
|
+
|
317
324
|
## Core Contributors
|
318
325
|
[<img style="border-radius:50%" alt="Andrei Bondarev" src="https://avatars.githubusercontent.com/u/541665?v=4" width="80" height="80" class="avatar">](https://github.com/andreibondarev)
|
319
326
|
|
data/Rakefile
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require "bundler/gem_tasks"
|
4
4
|
require "rspec/core/rake_task"
|
5
5
|
require "standard/rake"
|
6
|
+
require "yard"
|
6
7
|
|
7
8
|
RSpec::Core::RakeTask.new(:spec)
|
8
9
|
|
@@ -11,3 +12,7 @@ task default: :spec
|
|
11
12
|
Rake::Task["spec"].enhance do
|
12
13
|
Rake::Task["standard:fix"].invoke
|
13
14
|
end
|
15
|
+
|
16
|
+
YARD::Rake::YardocTask.new do |t|
|
17
|
+
t.options = ["--fail-on-warning"]
|
18
|
+
end
|
@@ -42,7 +42,7 @@ module Langchain::Agent
|
|
42
42
|
)
|
43
43
|
|
44
44
|
loop do
|
45
|
-
Langchain.logger.info("
|
45
|
+
Langchain.logger.info("[#{self.class.name}]".red + ": Sending the prompt to the #{llm} LLM")
|
46
46
|
response = llm_client.complete(
|
47
47
|
prompt: prompt,
|
48
48
|
stop_sequences: ["Observation:"],
|
@@ -59,12 +59,11 @@ module Langchain::Agent
|
|
59
59
|
# Find the input to the action in the "Action Input: [action_input]" format
|
60
60
|
action_input = response.match(/Action Input: "?(.*)"?/)&.send(:[], -1)
|
61
61
|
|
62
|
-
Langchain.logger.info("Agent: Using the \"#{action}\" Tool with \"#{action_input}\"")
|
63
|
-
|
64
62
|
# Retrieve the Tool::[ToolName] class and call `execute`` with action_input as the input
|
65
|
-
|
66
|
-
|
67
|
-
|
63
|
+
tool = Langchain::Tool.const_get(Langchain::Tool::Base::TOOLS[action.strip])
|
64
|
+
Langchain.logger.info("[#{self.class.name}]".red + ": Invoking \"#{tool}\" Tool with \"#{action_input}\"")
|
65
|
+
|
66
|
+
result = tool.execute(input: action_input)
|
68
67
|
|
69
68
|
# Append the Observation to the prompt
|
70
69
|
prompt += if prompt.end_with?("Observation:")
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Langchain
|
4
|
+
module DependencyHelper
|
5
|
+
class VersionError < ScriptError; end
|
6
|
+
|
7
|
+
# This method requires and loads the given gem, and then checks to see if the version of the gem meets the requirements listed in `langchain.gemspec`
|
8
|
+
# This solution was built to avoid auto-loading every single gem in the Gemfile when the developer will mostly likely be only using a few of them.
|
9
|
+
#
|
10
|
+
# @param gem_name [String] The name of the gem to load
|
11
|
+
# @return [Boolean] Whether or not the gem was loaded successfully
|
12
|
+
# @raise [LoadError] If the gem is not installed
|
13
|
+
# @raise [VersionError] If the gem is installed, but the version does not meet the requirements
|
14
|
+
#
|
15
|
+
def depends_on(gem_name)
|
16
|
+
gem(gem_name) # require the gem
|
17
|
+
|
18
|
+
return(true) unless defined?(Bundler) # If we're in a non-bundler environment, we're no longer able to determine if we'll meet requirements
|
19
|
+
|
20
|
+
gem_version = Gem.loaded_specs[gem_name].version
|
21
|
+
gem_requirement = Bundler.load.dependencies.find { |g| g.name == gem_name }&.requirement
|
22
|
+
|
23
|
+
raise LoadError unless gem_requirement
|
24
|
+
|
25
|
+
unless gem_requirement.satisfied_by?(gem_version)
|
26
|
+
raise VersionError, "The #{gem_name} gem is installed, but version #{gem_requirement} is required. You have #{gem_version}."
|
27
|
+
end
|
28
|
+
|
29
|
+
true
|
30
|
+
rescue LoadError
|
31
|
+
raise LoadError, "Could not load #{gem_name}. Please ensure that the #{gem_name} gem is installed."
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Langchain::LLM
|
4
|
+
class AI21 < Base
|
5
|
+
#
|
6
|
+
# Wrapper around AI21 Studio APIs.
|
7
|
+
#
|
8
|
+
# Gem requirements: gem "ai21", "~> 0.2.0"
|
9
|
+
#
|
10
|
+
# Usage:
|
11
|
+
# ai21 = Langchain::LLM::AI21.new(api_key:)
|
12
|
+
#
|
13
|
+
|
14
|
+
def initialize(api_key:)
|
15
|
+
depends_on "ai21"
|
16
|
+
require "ai21"
|
17
|
+
|
18
|
+
@client = ::AI21::Client.new(api_key)
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Generate a completion for a given prompt
|
23
|
+
#
|
24
|
+
# @param prompt [String] The prompt to generate a completion for
|
25
|
+
# @param params [Hash] The parameters to pass to the API
|
26
|
+
# @return [String] The completion
|
27
|
+
#
|
28
|
+
def complete(prompt:, **params)
|
29
|
+
response = client.complete(prompt, params)
|
30
|
+
response.dig(:completions, 0, :data, :text)
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# Generate a summary for a given text
|
35
|
+
#
|
36
|
+
# @param text [String] The text to generate a summary for
|
37
|
+
# @param params [Hash] The parameters to pass to the API
|
38
|
+
# @return [String] The summary
|
39
|
+
#
|
40
|
+
def summarize(text:, **params)
|
41
|
+
response = client.summarize(text, "TEXT", params)
|
42
|
+
response.dig(:summary)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/langchain/llm/base.rb
CHANGED
data/lib/langchain/llm/cohere.rb
CHANGED
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
module Langchain::LLM
|
4
4
|
class Cohere < Base
|
5
|
+
#
|
6
|
+
# Wrapper around the Cohere API.
|
7
|
+
#
|
8
|
+
# Gem requirements: gem "cohere-ruby", "~> 0.9.4"
|
9
|
+
#
|
10
|
+
# Usage:
|
11
|
+
# cohere = Langchain::LLM::Cohere.new(api_key: "YOUR_API_KEY")
|
12
|
+
#
|
13
|
+
|
5
14
|
DEFAULTS = {
|
6
15
|
temperature: 0.0,
|
7
16
|
completion_model_name: "base",
|
@@ -2,7 +2,14 @@
|
|
2
2
|
|
3
3
|
module Langchain::LLM
|
4
4
|
class GooglePalm < Base
|
5
|
+
#
|
5
6
|
# Wrapper around the Google PaLM (Pathways Language Model) APIs.
|
7
|
+
#
|
8
|
+
# Gem requirements: gem "google_palm_api", "~> 0.1.0"
|
9
|
+
#
|
10
|
+
# Usage:
|
11
|
+
# google_palm = Langchain::LLM::GooglePalm.new(api_key: "YOUR_API_KEY")
|
12
|
+
#
|
6
13
|
|
7
14
|
DEFAULTS = {
|
8
15
|
temperature: 0.0,
|
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
module Langchain::LLM
|
4
4
|
class HuggingFace < Base
|
5
|
+
#
|
6
|
+
# Wrapper around the HuggingFace Inference API.
|
7
|
+
#
|
8
|
+
# Gem requirements: gem "hugging-face", "~> 0.3.4"
|
9
|
+
#
|
10
|
+
# Usage:
|
11
|
+
# hf = Langchain::LLM::HuggingFace.new(api_key: "YOUR_API_KEY")
|
12
|
+
#
|
13
|
+
|
5
14
|
# The gem does not currently accept other models:
|
6
15
|
# https://github.com/alchaplinsky/hugging-face/blob/main/lib/hugging_face/inference_api.rb#L32-L34
|
7
16
|
DEFAULTS = {
|
data/lib/langchain/llm/openai.rb
CHANGED
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
module Langchain::LLM
|
4
4
|
class OpenAI < Base
|
5
|
+
#
|
6
|
+
# Wrapper around OpenAI APIs.
|
7
|
+
#
|
8
|
+
# Gem requirements: gem "ruby-openai", "~> 4.0.0"
|
9
|
+
#
|
10
|
+
# Usage:
|
11
|
+
# openai = Langchain::LLM::OpenAI.new(api_key:, llm_options: {})
|
12
|
+
#
|
13
|
+
|
5
14
|
DEFAULTS = {
|
6
15
|
temperature: 0.0,
|
7
16
|
completion_model_name: "text-davinci-003",
|
@@ -10,12 +19,11 @@ module Langchain::LLM
|
|
10
19
|
dimension: 1536
|
11
20
|
}.freeze
|
12
21
|
|
13
|
-
def initialize(api_key:)
|
22
|
+
def initialize(api_key:, llm_options: {})
|
14
23
|
depends_on "ruby-openai"
|
15
24
|
require "openai"
|
16
25
|
|
17
|
-
|
18
|
-
@client = ::OpenAI::Client.new(access_token: api_key)
|
26
|
+
@client = ::OpenAI::Client.new(access_token: api_key, **llm_options)
|
19
27
|
end
|
20
28
|
|
21
29
|
#
|
@@ -24,17 +32,12 @@ module Langchain::LLM
|
|
24
32
|
# @param text [String] The text to generate an embedding for
|
25
33
|
# @return [Array] The embedding
|
26
34
|
#
|
27
|
-
def embed(text
|
28
|
-
|
35
|
+
def embed(text:, **params)
|
36
|
+
parameters = {model: DEFAULTS[:embeddings_model_name], input: text}
|
29
37
|
|
30
|
-
Langchain::Utils::TokenLengthValidator.validate!(text, model)
|
38
|
+
Langchain::Utils::TokenLengthValidator.validate!(text, parameters[:model])
|
31
39
|
|
32
|
-
response = client.embeddings(
|
33
|
-
parameters: {
|
34
|
-
model: model,
|
35
|
-
input: text
|
36
|
-
}
|
37
|
-
)
|
40
|
+
response = client.embeddings(parameters: parameters.merge(params))
|
38
41
|
response.dig("data").first.dig("embedding")
|
39
42
|
end
|
40
43
|
|
@@ -45,23 +48,13 @@ module Langchain::LLM
|
|
45
48
|
# @return [String] The completion
|
46
49
|
#
|
47
50
|
def complete(prompt:, **params)
|
48
|
-
|
49
|
-
|
50
|
-
Langchain::Utils::TokenLengthValidator.validate!(prompt, model)
|
51
|
-
|
52
|
-
default_params = {
|
53
|
-
model: model,
|
54
|
-
temperature: DEFAULTS[:temperature],
|
55
|
-
prompt: prompt
|
56
|
-
}
|
51
|
+
parameters = compose_parameters DEFAULTS[:completion_model_name], params
|
57
52
|
|
58
|
-
|
59
|
-
default_params[:stop] = params.delete(:stop_sequences)
|
60
|
-
end
|
53
|
+
Langchain::Utils::TokenLengthValidator.validate!(prompt, parameters[:model])
|
61
54
|
|
62
|
-
|
55
|
+
parameters[:prompt] = prompt
|
63
56
|
|
64
|
-
response = client.completions(parameters:
|
57
|
+
response = client.completions(parameters: parameters)
|
65
58
|
response.dig("choices", 0, "text")
|
66
59
|
end
|
67
60
|
|
@@ -72,24 +65,13 @@ module Langchain::LLM
|
|
72
65
|
# @return [String] The chat completion
|
73
66
|
#
|
74
67
|
def chat(prompt:, **params)
|
75
|
-
|
68
|
+
parameters = compose_parameters DEFAULTS[:chat_completion_model_name], params
|
76
69
|
|
77
|
-
Langchain::Utils::TokenLengthValidator.validate!(prompt, model)
|
70
|
+
Langchain::Utils::TokenLengthValidator.validate!(prompt, parameters[:model])
|
78
71
|
|
79
|
-
|
80
|
-
model: model,
|
81
|
-
temperature: DEFAULTS[:temperature],
|
82
|
-
# TODO: Figure out how to introduce persisted conversations
|
83
|
-
messages: [{role: "user", content: prompt}]
|
84
|
-
}
|
85
|
-
|
86
|
-
if params[:stop_sequences]
|
87
|
-
default_params[:stop] = params.delete(:stop_sequences)
|
88
|
-
end
|
72
|
+
parameters[:messages] = [{role: "user", content: prompt}]
|
89
73
|
|
90
|
-
|
91
|
-
|
92
|
-
response = client.chat(parameters: default_params)
|
74
|
+
response = client.chat(parameters: parameters)
|
93
75
|
response.dig("choices", 0, "message", "content")
|
94
76
|
end
|
95
77
|
|
@@ -112,5 +94,15 @@ module Langchain::LLM
|
|
112
94
|
max_tokens: 2048
|
113
95
|
)
|
114
96
|
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def compose_parameters(model, params)
|
101
|
+
default_params = {model: model, temperature: DEFAULTS[:temperature]}
|
102
|
+
|
103
|
+
default_params[:stop] = params.delete(:stop_sequences) if params[:stop_sequences]
|
104
|
+
|
105
|
+
default_params.merge(params)
|
106
|
+
end
|
115
107
|
end
|
116
108
|
end
|
@@ -2,7 +2,11 @@
|
|
2
2
|
|
3
3
|
module Langchain::LLM
|
4
4
|
class Replicate < Base
|
5
|
+
#
|
5
6
|
# Wrapper around Replicate.com LLM provider
|
7
|
+
#
|
8
|
+
# Gem requirements: gem "replicate-ruby", "~> 0.2.2"
|
9
|
+
#
|
6
10
|
# Use it directly:
|
7
11
|
# replicate = LLM::Replicate.new(api_key: ENV["REPLICATE_API_KEY"])
|
8
12
|
#
|
@@ -64,9 +64,9 @@ module Langchain::Prompt
|
|
64
64
|
#
|
65
65
|
# This method takes a template string and returns an array of input variable names
|
66
66
|
# contained within the template. Input variables are defined as text enclosed in
|
67
|
-
# curly braces (e.g.
|
67
|
+
# curly braces (e.g. <code>\{variable_name\}</code>).
|
68
68
|
#
|
69
|
-
# Content within two consecutive curly braces (e.g.
|
69
|
+
# Content within two consecutive curly braces (e.g. <code>\{\{ignore_me}}</code>) are ignored.
|
70
70
|
#
|
71
71
|
# @param template [String] The template string to extract variables from.
|
72
72
|
#
|
@@ -20,7 +20,7 @@ module Langchain::Prompt
|
|
20
20
|
end
|
21
21
|
|
22
22
|
#
|
23
|
-
# Format the prompt with the inputs. Double {{}} replaced with single {} to adhere to f-string spec.
|
23
|
+
# Format the prompt with the inputs. Double <code>{{}}</code> replaced with single <code>{}</code> to adhere to f-string spec.
|
24
24
|
#
|
25
25
|
# @param kwargs [Hash] Any arguments to be passed to the prompt template.
|
26
26
|
# @return [String] A formatted string.
|
data/lib/langchain/tool/base.rb
CHANGED
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
module Langchain::Tool
|
4
4
|
class Calculator < Base
|
5
|
+
#
|
6
|
+
# A calculator tool that falls back to the Google calculator widget
|
7
|
+
#
|
8
|
+
# Gem requirements:
|
9
|
+
# gem "eqn", "~> 1.6.5"
|
10
|
+
# gem "google_search_results", "~> 2.0.0"
|
11
|
+
# ENV requirements: ENV["SERPAPI_API_KEY"]
|
12
|
+
#
|
13
|
+
|
5
14
|
description <<~DESC
|
6
15
|
Useful for getting the result of a math expression.
|
7
16
|
|
@@ -18,6 +27,8 @@ module Langchain::Tool
|
|
18
27
|
# @param input [String] math expression
|
19
28
|
# @return [String] Answer
|
20
29
|
def execute(input:)
|
30
|
+
Langchain.logger.info("[#{self.class.name}]".light_blue + ": Executing \"#{input}\"")
|
31
|
+
|
21
32
|
Eqn::Calculator.calc(input)
|
22
33
|
rescue Eqn::ParseError, Eqn::NoVariableValueError
|
23
34
|
# Sometimes the input is not a pure math expression, e.g: "12F in Celsius"
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Langchain::Tool
|
4
|
+
class RubyCodeInterpreter < Base
|
5
|
+
#
|
6
|
+
# A tool that execute Ruby code in a sandboxed environment.
|
7
|
+
#
|
8
|
+
# Gem requirements: gem "safe_ruby", "~> 1.0.4"
|
9
|
+
#
|
10
|
+
|
11
|
+
description <<~DESC
|
12
|
+
A Ruby code interpreter. Use this to execute ruby expressions. Input should be a valid ruby expression. If you want to see the output of the tool, make sure to return a value.
|
13
|
+
DESC
|
14
|
+
|
15
|
+
def initialize(timeout: 30)
|
16
|
+
@timeout = timeout
|
17
|
+
depends_on "safe_ruby"
|
18
|
+
require "safe_ruby"
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param input [String] ruby code expression
|
22
|
+
# @return [String] Answer
|
23
|
+
def execute(input:)
|
24
|
+
Langchain.logger.info("[#{self.class.name}]".light_blue + ": Executing \"#{input}\"")
|
25
|
+
|
26
|
+
safe_eval(input)
|
27
|
+
end
|
28
|
+
|
29
|
+
def safe_eval(code)
|
30
|
+
SafeRuby.eval(code, timeout: @timeout)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -2,8 +2,12 @@
|
|
2
2
|
|
3
3
|
module Langchain::Tool
|
4
4
|
class SerpApi < Base
|
5
|
+
#
|
5
6
|
# Wrapper around SerpAPI
|
6
|
-
#
|
7
|
+
#
|
8
|
+
# Gem requirements: gem "google_search_results", "~> 2.0.0"
|
9
|
+
# ENV requirements: ENV["SERPAPI_API_KEY"] # https://serpapi.com/manage-api-key)
|
10
|
+
#
|
7
11
|
|
8
12
|
description <<~DESC
|
9
13
|
A wrapper around Google Search.
|
@@ -33,6 +37,8 @@ module Langchain::Tool
|
|
33
37
|
# TODO: Glance at all of the fields that langchain Python looks through: https://github.com/hwchase17/langchain/blob/v0.0.166/langchain/utilities/serpapi.py#L128-L156
|
34
38
|
# We may need to do the same thing here.
|
35
39
|
def execute(input:)
|
40
|
+
Langchain.logger.info("[#{self.class.name}]".light_blue + ": Executing \"#{input}\"")
|
41
|
+
|
36
42
|
hash_results = execute_search(input: input)
|
37
43
|
|
38
44
|
hash_results.dig(:answer_box, :answer) ||
|
@@ -2,7 +2,11 @@
|
|
2
2
|
|
3
3
|
module Langchain::Tool
|
4
4
|
class Wikipedia < Base
|
5
|
+
#
|
5
6
|
# Tool that adds the capability to search using the Wikipedia API
|
7
|
+
#
|
8
|
+
# Gem requirements: gem "wikipedia-client", "~> 1.17.0"
|
9
|
+
#
|
6
10
|
|
7
11
|
description <<~DESC
|
8
12
|
A wrapper around Wikipedia.
|
@@ -22,6 +26,8 @@ module Langchain::Tool
|
|
22
26
|
# @param input [String] search query
|
23
27
|
# @return [String] Answer
|
24
28
|
def execute(input:)
|
29
|
+
Langchain.logger.info("[#{self.class.name}]".light_blue + ": Executing \"#{input}\"")
|
30
|
+
|
25
31
|
page = ::Wikipedia.find(input)
|
26
32
|
# It would be nice to figure out a way to provide page.content but the LLM token limit is an issue
|
27
33
|
page.summary
|
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
module Langchain::Vectorsearch
|
4
4
|
class Chroma < Base
|
5
|
+
#
|
6
|
+
# Wrapper around Chroma DB
|
7
|
+
#
|
8
|
+
# Gem requirements: gem "chroma-db", "~> 0.3.0"
|
9
|
+
#
|
10
|
+
# Usage:
|
11
|
+
# chroma = Langchain::Vectorsearch::Chroma.new(url:, index_name:, llm:, llm_api_key:, api_key: nil)
|
12
|
+
#
|
13
|
+
|
5
14
|
# Initialize the Chroma client
|
6
15
|
# @param url [String] The URL of the Qdrant server
|
7
16
|
# @param api_key [String] The API key to use
|
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
module Langchain::Vectorsearch
|
4
4
|
class Milvus < Base
|
5
|
+
#
|
6
|
+
# Wrapper around Milvus REST APIs.
|
7
|
+
#
|
8
|
+
# Gem requirements: gem "milvus", "~> 0.9.0"
|
9
|
+
#
|
10
|
+
# Usage:
|
11
|
+
# milvus = Langchain::Vectorsearch::Milvus.new(url:, index_name:, llm:, llm_api_key:)
|
12
|
+
#
|
13
|
+
|
5
14
|
def initialize(url:, index_name:, llm:, llm_api_key:, api_key: nil)
|
6
15
|
depends_on "milvus"
|
7
16
|
require "milvus"
|
@@ -1,8 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Langchain::Vectorsearch
|
4
|
-
# The PostgreSQL vector search adapter
|
5
4
|
class Pgvector < Base
|
5
|
+
#
|
6
|
+
# The PostgreSQL vector search adapter
|
7
|
+
#
|
8
|
+
# Gem requirements: gem "pgvector", "~> 0.2"
|
9
|
+
#
|
10
|
+
# Usage:
|
11
|
+
# pgvector = Langchain::Vectorsearch::Pgvector.new(url:, index_name:, llm:, llm_api_key:)
|
12
|
+
#
|
13
|
+
|
6
14
|
# The operators supported by the PostgreSQL vector search adapter
|
7
15
|
OPERATORS = {
|
8
16
|
"cosine_distance" => "<=>",
|
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
module Langchain::Vectorsearch
|
4
4
|
class Pinecone < Base
|
5
|
+
#
|
6
|
+
# Wrapper around Pinecone API.
|
7
|
+
#
|
8
|
+
# Gem requirements: gem "pinecone", "~> 0.1.6"
|
9
|
+
#
|
10
|
+
# Usage:
|
11
|
+
# pinecone = Langchain::Vectorsearch::Pinecone.new(environment:, api_key:, index_name:, llm:, llm_api_key:)
|
12
|
+
#
|
13
|
+
|
5
14
|
# Initialize the Pinecone client
|
6
15
|
# @param environment [String] The environment to use
|
7
16
|
# @param api_key [String] The API key to use
|
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
module Langchain::Vectorsearch
|
4
4
|
class Qdrant < Base
|
5
|
+
#
|
6
|
+
# Wrapper around Qdrant
|
7
|
+
#
|
8
|
+
# Gem requirements: gem "qdrant-ruby", "~> 0.9.0"
|
9
|
+
#
|
10
|
+
# Usage:
|
11
|
+
# qdrant = Langchain::Vectorsearch::Qdrant.new(url:, api_key:, index_name:, llm:, llm_api_key:)
|
12
|
+
#
|
13
|
+
|
5
14
|
# Initialize the Qdrant client
|
6
15
|
# @param url [String] The URL of the Qdrant server
|
7
16
|
# @param api_key [String] The API key to use
|
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
module Langchain::Vectorsearch
|
4
4
|
class Weaviate < Base
|
5
|
+
#
|
6
|
+
# Wrapper around Weaviate
|
7
|
+
#
|
8
|
+
# Gem requirements: gem "weaviate-ruby", "~> 0.8.0"
|
9
|
+
#
|
10
|
+
# Usage:
|
11
|
+
# weaviate = Langchain::Vectorsearch::Weaviate.new(url:, api_key:, index_name:, llm:, llm_api_key:)
|
12
|
+
#
|
13
|
+
|
5
14
|
# Initialize the Weaviate adapter
|
6
15
|
# @param url [String] The URL of the Weaviate instance
|
7
16
|
# @param api_key [String] The API key to use
|
data/lib/langchain.rb
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
require "logger"
|
4
4
|
require "pathname"
|
5
|
+
require "colorize"
|
5
6
|
|
6
|
-
require_relative "./version"
|
7
|
-
require_relative "./dependency_helper"
|
7
|
+
require_relative "./langchain/version"
|
8
8
|
|
9
9
|
module Langchain
|
10
10
|
class << self
|
@@ -13,12 +13,13 @@ module Langchain
|
|
13
13
|
attr_reader :root
|
14
14
|
end
|
15
15
|
|
16
|
-
@logger ||= ::Logger.new($stdout, level: :warn, formatter: ->(severity, datetime, progname, msg) { "[LangChain.rb] #{msg}\n" })
|
16
|
+
@logger ||= ::Logger.new($stdout, level: :warn, formatter: ->(severity, datetime, progname, msg) { "[LangChain.rb]".yellow + " #{msg}\n" })
|
17
17
|
|
18
18
|
@root = Pathname.new(__dir__)
|
19
19
|
|
20
20
|
autoload :Loader, "langchain/loader"
|
21
21
|
autoload :Data, "langchain/data"
|
22
|
+
autoload :DependencyHelper, "langchain/dependency_helper"
|
22
23
|
|
23
24
|
module Agent
|
24
25
|
autoload :Base, "langchain/agent/base"
|
@@ -28,6 +29,7 @@ module Langchain
|
|
28
29
|
module Tool
|
29
30
|
autoload :Base, "langchain/tool/base"
|
30
31
|
autoload :Calculator, "langchain/tool/calculator"
|
32
|
+
autoload :RubyCodeInterpreter, "langchain/tool/ruby_code_interpreter"
|
31
33
|
autoload :SerpApi, "langchain/tool/serp_api"
|
32
34
|
autoload :Wikipedia, "langchain/tool/wikipedia"
|
33
35
|
end
|
@@ -58,6 +60,7 @@ module Langchain
|
|
58
60
|
end
|
59
61
|
|
60
62
|
module LLM
|
63
|
+
autoload :AI21, "langchain/llm/ai21"
|
61
64
|
autoload :Base, "langchain/llm/base"
|
62
65
|
autoload :Cohere, "langchain/llm/cohere"
|
63
66
|
autoload :GooglePalm, "langchain/llm/google_palm"
|
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.4.
|
4
|
+
version: 0.4.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: 2023-06-
|
11
|
+
date: 2023-06-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tiktoken_ruby
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.0.5
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: colorize
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.8.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.8.1
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: dotenv-rails
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +66,48 @@ dependencies:
|
|
52
66
|
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: 3.10.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: yard
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rdiscount
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: ai21
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.2.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.2.0
|
55
111
|
- !ruby/object:Gem::Dependency
|
56
112
|
name: chroma-db
|
57
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -276,6 +332,20 @@ dependencies:
|
|
276
332
|
- - "~>"
|
277
333
|
- !ruby/object:Gem::Version
|
278
334
|
version: 4.0.0
|
335
|
+
- !ruby/object:Gem::Dependency
|
336
|
+
name: safe_ruby
|
337
|
+
requirement: !ruby/object:Gem::Requirement
|
338
|
+
requirements:
|
339
|
+
- - "~>"
|
340
|
+
- !ruby/object:Gem::Version
|
341
|
+
version: 1.0.4
|
342
|
+
type: :development
|
343
|
+
prerelease: false
|
344
|
+
version_requirements: !ruby/object:Gem::Requirement
|
345
|
+
requirements:
|
346
|
+
- - "~>"
|
347
|
+
- !ruby/object:Gem::Version
|
348
|
+
version: 1.0.4
|
279
349
|
- !ruby/object:Gem::Dependency
|
280
350
|
name: weaviate-ruby
|
281
351
|
requirement: !ruby/object:Gem::Requirement
|
@@ -325,12 +395,13 @@ files:
|
|
325
395
|
- examples/store_and_query_with_pinecone.rb
|
326
396
|
- examples/store_and_query_with_qdrant.rb
|
327
397
|
- examples/store_and_query_with_weaviate.rb
|
328
|
-
- lib/dependency_helper.rb
|
329
398
|
- lib/langchain.rb
|
330
399
|
- lib/langchain/agent/base.rb
|
331
400
|
- lib/langchain/agent/chain_of_thought_agent/chain_of_thought_agent.rb
|
332
401
|
- lib/langchain/agent/chain_of_thought_agent/chain_of_thought_agent_prompt.json
|
333
402
|
- lib/langchain/data.rb
|
403
|
+
- lib/langchain/dependency_helper.rb
|
404
|
+
- lib/langchain/llm/ai21.rb
|
334
405
|
- lib/langchain/llm/base.rb
|
335
406
|
- lib/langchain/llm/cohere.rb
|
336
407
|
- lib/langchain/llm/google_palm.rb
|
@@ -353,6 +424,7 @@ files:
|
|
353
424
|
- lib/langchain/prompt/prompt_template.rb
|
354
425
|
- lib/langchain/tool/base.rb
|
355
426
|
- lib/langchain/tool/calculator.rb
|
427
|
+
- lib/langchain/tool/ruby_code_interpreter.rb
|
356
428
|
- lib/langchain/tool/serp_api.rb
|
357
429
|
- lib/langchain/tool/wikipedia.rb
|
358
430
|
- lib/langchain/utils/token_length_validator.rb
|
@@ -363,8 +435,8 @@ files:
|
|
363
435
|
- lib/langchain/vectorsearch/pinecone.rb
|
364
436
|
- lib/langchain/vectorsearch/qdrant.rb
|
365
437
|
- lib/langchain/vectorsearch/weaviate.rb
|
438
|
+
- lib/langchain/version.rb
|
366
439
|
- lib/langchainrb.rb
|
367
|
-
- lib/version.rb
|
368
440
|
- sig/langchain.rbs
|
369
441
|
homepage: https://rubygems.org/gems/langchainrb
|
370
442
|
licenses:
|
data/lib/dependency_helper.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
VersionError = Class.new(ScriptError)
|
4
|
-
|
5
|
-
# This method requires and loads the given gem, and then checks to see if the version of the gem meets the requirements listed in `langchain.gemspec`
|
6
|
-
# This solution was built to avoid auto-loading every single gem in the Gemfile when the developer will mostly likely be only using a few of them.
|
7
|
-
#
|
8
|
-
# @param gem_name [String] The name of the gem to load
|
9
|
-
# @return [Boolean] Whether or not the gem was loaded successfully
|
10
|
-
# @raise [LoadError] If the gem is not installed
|
11
|
-
# @raise [VersionError] If the gem is installed, but the version does not meet the requirements
|
12
|
-
#
|
13
|
-
def depends_on(gem_name)
|
14
|
-
gem(gem_name) # require the gem
|
15
|
-
|
16
|
-
return(true) unless defined?(Bundler) # If we're in a non-bundler environment, we're no longer able to determine if we'll meet requirements
|
17
|
-
|
18
|
-
gem_version = Gem.loaded_specs[gem_name].version
|
19
|
-
gem_requirement = Bundler.load.dependencies.find { |g| g.name == gem_name }&.requirement
|
20
|
-
|
21
|
-
raise LoadError unless gem_requirement
|
22
|
-
|
23
|
-
unless gem_requirement.satisfied_by?(gem_version)
|
24
|
-
raise VersionError, "The #{gem_name} gem is installed, but version #{gem_requirement} is required. You have #{gem_version}."
|
25
|
-
end
|
26
|
-
|
27
|
-
true
|
28
|
-
rescue LoadError
|
29
|
-
raise LoadError, "Could not load #{gem_name}. Please ensure that the #{gem_name} gem is installed."
|
30
|
-
end
|