langchainrb 0.5.6 → 0.5.7
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 +4 -0
- data/Gemfile.lock +1 -1
- data/README.md +2 -2
- data/lib/langchain/agent/sql_query_agent/sql_query_agent.rb +1 -1
- data/lib/langchain/llm/ai21.rb +16 -2
- data/lib/langchain/llm/cohere.rb +5 -4
- data/lib/langchain/llm/google_palm.rb +12 -5
- data/lib/langchain/llm/openai.rb +52 -12
- data/lib/langchain/llm/replicate.rb +5 -4
- data/lib/langchain/tool/calculator.rb +6 -8
- data/lib/langchain/tool/database.rb +27 -6
- data/lib/langchain/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ba5e9e8257d18c0940fdaf4fe84c03d594d8f1151e40e1bb35de059f8e6e5094
|
4
|
+
data.tar.gz: 11310635819502b9bfbd66bc45dc7aa1ce500d4a874dcc5ab550d6c5edf7194f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b97e21bcbc0c5f1d842271b64949c07d6d78190cd97c22fd0dab735d6b6ae2f2e6328ba2631dfc77ed0a5dd227573e3f84f064e8dd9332701848a798747ac9a
|
7
|
+
data.tar.gz: 267b2029de10acf45bb97a040d174102f666e048aaaf03ab76218cd5281574c1ae977ba8e975faf4b690e677611daba2fb0fc975801c0e41072f050ec2ac2e34
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.5.7] - 2023-06-19
|
4
|
+
- Developer can modify models used when initiliazing `Langchain::LLM::*` clients
|
5
|
+
- Improvements to the `SQLQueryAgent` and the database tool
|
6
|
+
|
3
7
|
## [0.5.6] - 2023-06-18
|
4
8
|
- If used with OpenAI, Langchain::Conversation responses can now be streamed.
|
5
9
|
- Improved logging
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
[](https://badge.fury.io/rb/langchainrb)
|
11
11
|
[](http://rubydoc.info/gems/langchainrb)
|
12
12
|
[](https://github.com/andreibondarev/langchainrb/blob/main/LICENSE.txt)
|
13
|
-
[](https://discord.gg/WDARp7J2n8)
|
14
14
|
|
15
15
|
|
16
16
|
Langchain.rb is a library that's an abstraction layer on top many emergent AI, ML and other DS tools. The goal is to abstract complexity and difficult concepts to make building AI/ML-supercharged applications approachable for traditional software engineers.
|
@@ -367,7 +367,7 @@ Langchain.logger.level = :info
|
|
367
367
|
5. Optionally, install lefthook git hooks for pre-commit to auto lint: `gem install lefthook && lefthook install -f`
|
368
368
|
|
369
369
|
## Discord
|
370
|
-
Join us in the [Langchain.rb](https://discord.gg/
|
370
|
+
Join us in the [Langchain.rb](https://discord.gg/WDARp7J2n8) Discord server.
|
371
371
|
|
372
372
|
## Core Contributors
|
373
373
|
[<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)
|
data/lib/langchain/llm/ai21.rb
CHANGED
@@ -11,11 +11,17 @@ module Langchain::LLM
|
|
11
11
|
# ai21 = Langchain::LLM::AI21.new(api_key:)
|
12
12
|
#
|
13
13
|
class AI21 < Base
|
14
|
-
|
14
|
+
DEFAULTS = {
|
15
|
+
temperature: 0.0,
|
16
|
+
model: "j2-large"
|
17
|
+
}.freeze
|
18
|
+
|
19
|
+
def initialize(api_key:, default_options: {})
|
15
20
|
depends_on "ai21"
|
16
21
|
require "ai21"
|
17
22
|
|
18
23
|
@client = ::AI21::Client.new(api_key)
|
24
|
+
@defaults = DEFAULTS.merge(default_options)
|
19
25
|
end
|
20
26
|
|
21
27
|
#
|
@@ -26,7 +32,9 @@ module Langchain::LLM
|
|
26
32
|
# @return [String] The completion
|
27
33
|
#
|
28
34
|
def complete(prompt:, **params)
|
29
|
-
|
35
|
+
parameters = complete_parameters params
|
36
|
+
|
37
|
+
response = client.complete(prompt, parameters)
|
30
38
|
response.dig(:completions, 0, :data, :text)
|
31
39
|
end
|
32
40
|
|
@@ -41,5 +49,11 @@ module Langchain::LLM
|
|
41
49
|
response = client.summarize(text, "TEXT", params)
|
42
50
|
response.dig(:summary)
|
43
51
|
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def complete_parameters(params)
|
56
|
+
@defaults.dup.merge(params)
|
57
|
+
end
|
44
58
|
end
|
45
59
|
end
|
data/lib/langchain/llm/cohere.rb
CHANGED
@@ -18,11 +18,12 @@ module Langchain::LLM
|
|
18
18
|
dimension: 1024
|
19
19
|
}.freeze
|
20
20
|
|
21
|
-
def initialize(api_key:)
|
21
|
+
def initialize(api_key:, default_options: {})
|
22
22
|
depends_on "cohere-ruby"
|
23
23
|
require "cohere"
|
24
24
|
|
25
25
|
@client = ::Cohere::Client.new(api_key: api_key)
|
26
|
+
@defaults = DEFAULTS.merge(default_options)
|
26
27
|
end
|
27
28
|
|
28
29
|
#
|
@@ -34,7 +35,7 @@ module Langchain::LLM
|
|
34
35
|
def embed(text:)
|
35
36
|
response = client.embed(
|
36
37
|
texts: [text],
|
37
|
-
model:
|
38
|
+
model: @defaults[:embeddings_model_name]
|
38
39
|
)
|
39
40
|
response.dig("embeddings").first
|
40
41
|
end
|
@@ -49,8 +50,8 @@ module Langchain::LLM
|
|
49
50
|
def complete(prompt:, **params)
|
50
51
|
default_params = {
|
51
52
|
prompt: prompt,
|
52
|
-
temperature:
|
53
|
-
model:
|
53
|
+
temperature: @defaults[:temperature],
|
54
|
+
model: @defaults[:completion_model_name]
|
54
55
|
}
|
55
56
|
|
56
57
|
if params[:stop_sequences]
|
@@ -22,15 +22,19 @@ module Langchain::LLM
|
|
22
22
|
|
23
23
|
DEFAULTS = {
|
24
24
|
temperature: 0.0,
|
25
|
-
dimension: 768 # This is what the `embedding-gecko-001` model generates
|
25
|
+
dimension: 768, # This is what the `embedding-gecko-001` model generates
|
26
|
+
completion_model_name: "text-bison-001",
|
27
|
+
chat_completion_model_name: "chat-bison-001",
|
28
|
+
embeddings_model_name: "embedding-gecko-001"
|
26
29
|
}.freeze
|
27
30
|
LENGTH_VALIDATOR = Langchain::Utils::TokenLength::GooglePalmValidator
|
28
31
|
|
29
|
-
def initialize(api_key:)
|
32
|
+
def initialize(api_key:, default_options: {})
|
30
33
|
depends_on "google_palm_api"
|
31
34
|
require "google_palm_api"
|
32
35
|
|
33
36
|
@client = ::GooglePalmApi::Client.new(api_key: api_key)
|
37
|
+
@defaults = DEFAULTS.merge(default_options)
|
34
38
|
end
|
35
39
|
|
36
40
|
#
|
@@ -56,7 +60,8 @@ module Langchain::LLM
|
|
56
60
|
def complete(prompt:, **params)
|
57
61
|
default_params = {
|
58
62
|
prompt: prompt,
|
59
|
-
temperature:
|
63
|
+
temperature: @defaults[:temperature],
|
64
|
+
completion_model_name: @defaults[:completion_model_name]
|
60
65
|
}
|
61
66
|
|
62
67
|
if params[:stop_sequences]
|
@@ -85,12 +90,14 @@ module Langchain::LLM
|
|
85
90
|
raise ArgumentError.new(":prompt or :messages argument is expected") if prompt.empty? && messages.empty?
|
86
91
|
|
87
92
|
default_params = {
|
88
|
-
temperature:
|
93
|
+
temperature: @defaults[:temperature],
|
94
|
+
chat_completion_model_name: @defaults[:chat_completion_model_name],
|
89
95
|
context: context,
|
90
96
|
messages: compose_chat_messages(prompt: prompt, messages: messages),
|
91
97
|
examples: compose_examples(examples)
|
92
98
|
}
|
93
99
|
|
100
|
+
# chat-bison-001 is the only model that currently supports countMessageTokens functions
|
94
101
|
LENGTH_VALIDATOR.validate_max_tokens!(default_params[:messages], "chat-bison-001", llm: self)
|
95
102
|
|
96
103
|
if options[:stop_sequences]
|
@@ -123,7 +130,7 @@ module Langchain::LLM
|
|
123
130
|
|
124
131
|
complete(
|
125
132
|
prompt: prompt,
|
126
|
-
temperature:
|
133
|
+
temperature: @defaults[:temperature],
|
127
134
|
# Most models have a context length of 2048 tokens (except for the newest models, which support 4096).
|
128
135
|
max_tokens: 2048
|
129
136
|
)
|
data/lib/langchain/llm/openai.rb
CHANGED
@@ -19,11 +19,12 @@ module Langchain::LLM
|
|
19
19
|
}.freeze
|
20
20
|
LENGTH_VALIDATOR = Langchain::Utils::TokenLength::OpenAIValidator
|
21
21
|
|
22
|
-
def initialize(api_key:, llm_options: {})
|
22
|
+
def initialize(api_key:, llm_options: {}, default_options: {})
|
23
23
|
depends_on "ruby-openai"
|
24
24
|
require "openai"
|
25
25
|
|
26
26
|
@client = ::OpenAI::Client.new(access_token: api_key, **llm_options)
|
27
|
+
@defaults = DEFAULTS.merge(default_options)
|
27
28
|
end
|
28
29
|
|
29
30
|
#
|
@@ -34,7 +35,7 @@ module Langchain::LLM
|
|
34
35
|
# @return [Array] The embedding
|
35
36
|
#
|
36
37
|
def embed(text:, **params)
|
37
|
-
parameters = {model:
|
38
|
+
parameters = {model: @defaults[:embeddings_model_name], input: text}
|
38
39
|
|
39
40
|
validate_max_tokens(text, parameters[:model])
|
40
41
|
|
@@ -50,7 +51,7 @@ module Langchain::LLM
|
|
50
51
|
# @return [String] The completion
|
51
52
|
#
|
52
53
|
def complete(prompt:, **params)
|
53
|
-
parameters = compose_parameters
|
54
|
+
parameters = compose_parameters @defaults[:completion_model_name], params
|
54
55
|
|
55
56
|
parameters[:prompt] = prompt
|
56
57
|
parameters[:max_tokens] = validate_max_tokens(prompt, parameters[:model])
|
@@ -60,20 +61,59 @@ module Langchain::LLM
|
|
60
61
|
end
|
61
62
|
|
62
63
|
#
|
63
|
-
# Generate a chat completion for a given prompt
|
64
|
+
# Generate a chat completion for a given prompt or messages.
|
65
|
+
#
|
66
|
+
# == Examples
|
67
|
+
#
|
68
|
+
# # simplest case, just give a prompt
|
69
|
+
# openai.chat prompt: "When was Ruby first released?"
|
70
|
+
#
|
71
|
+
# # prompt plus some context about how to respond
|
72
|
+
# openai.chat context: "You are RubyGPT, a helpful chat bot for helping people learn Ruby", prompt: "Does Ruby have a REPL like IPython?"
|
73
|
+
#
|
74
|
+
# # full control over messages that get sent, equivilent to the above
|
75
|
+
# openai.chat messages: [
|
76
|
+
# {
|
77
|
+
# role: "system",
|
78
|
+
# content: "You are RubyGPT, a helpful chat bot for helping people learn Ruby", prompt: "Does Ruby have a REPL like IPython?"
|
79
|
+
# },
|
80
|
+
# {
|
81
|
+
# role: "user",
|
82
|
+
# content: "When was Ruby first released?"
|
83
|
+
# }
|
84
|
+
# ]
|
85
|
+
#
|
86
|
+
# # few-short prompting with examples
|
87
|
+
# openai.chat prompt: "When was factory_bot released?",
|
88
|
+
# examples: [
|
89
|
+
# {
|
90
|
+
# role: "user",
|
91
|
+
# content: "When was Ruby on Rails released?"
|
92
|
+
# }
|
93
|
+
# {
|
94
|
+
# role: "assistant",
|
95
|
+
# content: "2004"
|
96
|
+
# },
|
97
|
+
# ]
|
64
98
|
#
|
65
99
|
# @param prompt [String] The prompt to generate a chat completion for
|
66
|
-
# @param messages [Array] The messages that have been sent in the conversation
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
# @param
|
100
|
+
# @param messages [Array<Hash>] The messages that have been sent in the conversation
|
101
|
+
# Each message should be a Hash with the following keys:
|
102
|
+
# - :content [String] The content of the message
|
103
|
+
# - :role [String] The role of the sender (system, user, assistant, or function)
|
104
|
+
# @param context [String] An initial context to provide as a system message, ie "You are RubyGPT, a helpful chat bot for helping people learn Ruby"
|
105
|
+
# @param examples [Array<Hash>] Examples of messages to provide to the model. Useful for Few-Shot Prompting
|
106
|
+
# Each message should be a Hash with the following keys:
|
107
|
+
# - :content [String] The content of the message
|
108
|
+
# - :role [String] The role of the sender (system, user, assistant, or function)
|
109
|
+
# @param options <Hash> extra parameters passed to OpenAI::Client#chat
|
110
|
+
# @yield [String] Stream responses back one String at a time
|
71
111
|
# @return [String] The chat completion
|
72
112
|
#
|
73
113
|
def chat(prompt: "", messages: [], context: "", examples: [], **options)
|
74
114
|
raise ArgumentError.new(":prompt or :messages argument is expected") if prompt.empty? && messages.empty?
|
75
115
|
|
76
|
-
parameters = compose_parameters
|
116
|
+
parameters = compose_parameters @defaults[:chat_completion_model_name], options
|
77
117
|
parameters[:messages] = compose_chat_messages(prompt: prompt, messages: messages, context: context, examples: examples)
|
78
118
|
parameters[:max_tokens] = validate_max_tokens(parameters[:messages], parameters[:model])
|
79
119
|
|
@@ -104,13 +144,13 @@ module Langchain::LLM
|
|
104
144
|
)
|
105
145
|
prompt = prompt_template.format(text: text)
|
106
146
|
|
107
|
-
complete(prompt: prompt, temperature:
|
147
|
+
complete(prompt: prompt, temperature: @defaults[:temperature])
|
108
148
|
end
|
109
149
|
|
110
150
|
private
|
111
151
|
|
112
152
|
def compose_parameters(model, params)
|
113
|
-
default_params = {model: model, temperature:
|
153
|
+
default_params = {model: model, temperature: @defaults[:temperature]}
|
114
154
|
|
115
155
|
default_params[:stop] = params.delete(:stop_sequences) if params[:stop_sequences]
|
116
156
|
|
@@ -32,7 +32,7 @@ module Langchain::LLM
|
|
32
32
|
#
|
33
33
|
# @param api_key [String] The API key to use
|
34
34
|
#
|
35
|
-
def initialize(api_key:)
|
35
|
+
def initialize(api_key:, default_options: {})
|
36
36
|
depends_on "replicate-ruby"
|
37
37
|
require "replicate"
|
38
38
|
|
@@ -41,6 +41,7 @@ module Langchain::LLM
|
|
41
41
|
end
|
42
42
|
|
43
43
|
@client = ::Replicate.client
|
44
|
+
@defaults = DEFAULTS.merge(default_options)
|
44
45
|
end
|
45
46
|
|
46
47
|
#
|
@@ -100,7 +101,7 @@ module Langchain::LLM
|
|
100
101
|
|
101
102
|
complete(
|
102
103
|
prompt: prompt,
|
103
|
-
temperature:
|
104
|
+
temperature: @defaults[:temperature],
|
104
105
|
# Most models have a context length of 2048 tokens (except for the newest models, which support 4096).
|
105
106
|
max_tokens: 2048
|
106
107
|
)
|
@@ -111,11 +112,11 @@ module Langchain::LLM
|
|
111
112
|
private
|
112
113
|
|
113
114
|
def completion_model
|
114
|
-
@completion_model ||= client.retrieve_model(
|
115
|
+
@completion_model ||= client.retrieve_model(@defaults[:completion_model_name]).latest_version
|
115
116
|
end
|
116
117
|
|
117
118
|
def embeddings_model
|
118
|
-
@embeddings_model ||= client.retrieve_model(
|
119
|
+
@embeddings_model ||= client.retrieve_model(@defaults[:embeddings_model_name]).latest_version
|
119
120
|
end
|
120
121
|
end
|
121
122
|
end
|
@@ -16,6 +16,11 @@ module Langchain::Tool
|
|
16
16
|
Useful for getting the result of a math expression.
|
17
17
|
|
18
18
|
The input to this tool should be a valid mathematical expression that could be executed by a simple calculator.
|
19
|
+
Usage:
|
20
|
+
Action Input: 1 + 1
|
21
|
+
Action Input: 3 * 2 / 4
|
22
|
+
Action Input: 9 - 7
|
23
|
+
Action Input: (4.1 + 2.3) / (2.0 - 5.6) * 3
|
19
24
|
DESC
|
20
25
|
|
21
26
|
def initialize
|
@@ -32,14 +37,7 @@ module Langchain::Tool
|
|
32
37
|
|
33
38
|
Eqn::Calculator.calc(input)
|
34
39
|
rescue Eqn::ParseError, Eqn::NoVariableValueError
|
35
|
-
#
|
36
|
-
# We can use the google answer box to evaluate this expression
|
37
|
-
# TODO: Figure out to find a better way to evaluate these language expressions.
|
38
|
-
hash_results = Langchain::Tool::GoogleSearch
|
39
|
-
.new(api_key: ENV["SERPAPI_API_KEY"])
|
40
|
-
.execute_search(input: input)
|
41
|
-
hash_results.dig(:answer_box, :to) ||
|
42
|
-
hash_results.dig(:answer_box, :result)
|
40
|
+
"\"#{input}\" is an invalid mathematical expression"
|
43
41
|
end
|
44
42
|
end
|
45
43
|
end
|
@@ -14,15 +14,18 @@ module Langchain::Tool
|
|
14
14
|
The input to this tool should be valid SQL.
|
15
15
|
DESC
|
16
16
|
|
17
|
-
attr_reader :db
|
17
|
+
attr_reader :db, :requested_tables, :except_tables
|
18
18
|
|
19
19
|
#
|
20
20
|
# Establish a database connection
|
21
21
|
#
|
22
22
|
# @param connection_string [String] Database connection info, e.g. 'postgres://user:password@localhost:5432/db_name'
|
23
|
+
# @param tables [Array<Symbol>] The tables to use. Will use all if empty.
|
24
|
+
# @param except_tables [Array<Symbol>] The tables to exclude. Will exclude none if empty.
|
25
|
+
|
23
26
|
# @return [Database] Database object
|
24
27
|
#
|
25
|
-
def initialize(connection_string:)
|
28
|
+
def initialize(connection_string:, tables: [], except_tables: [])
|
26
29
|
depends_on "sequel"
|
27
30
|
require "sequel"
|
28
31
|
require "sequel/extensions/schema_dumper"
|
@@ -30,7 +33,8 @@ module Langchain::Tool
|
|
30
33
|
raise StandardError, "connection_string parameter cannot be blank" if connection_string.empty?
|
31
34
|
|
32
35
|
@db = Sequel.connect(connection_string)
|
33
|
-
@
|
36
|
+
@requested_tables = tables
|
37
|
+
@except_tables = except_tables
|
34
38
|
end
|
35
39
|
|
36
40
|
#
|
@@ -38,9 +42,26 @@ module Langchain::Tool
|
|
38
42
|
#
|
39
43
|
# @return [String] schema
|
40
44
|
#
|
41
|
-
def
|
42
|
-
Langchain.logger.info("Dumping schema", for: self.class)
|
43
|
-
|
45
|
+
def dump_schema
|
46
|
+
Langchain.logger.info("Dumping schema tables and keys", for: self.class)
|
47
|
+
schema = ""
|
48
|
+
db.tables.each do |table|
|
49
|
+
next if except_tables.include?(table)
|
50
|
+
next unless requested_tables.empty? || requested_tables.include?(table)
|
51
|
+
|
52
|
+
schema << "CREATE TABLE #{table}(\n"
|
53
|
+
db.schema(table).each do |column|
|
54
|
+
schema << "#{column[0]} #{column[1][:type]}"
|
55
|
+
schema << " PRIMARY KEY" if column[1][:primary_key] == true
|
56
|
+
schema << "," unless column == db.schema(table).last
|
57
|
+
schema << "\n"
|
58
|
+
end
|
59
|
+
schema << ");\n"
|
60
|
+
db.foreign_key_list(table).each do |fk|
|
61
|
+
schema << "ALTER TABLE #{table} ADD FOREIGN KEY (#{fk[:columns][0]}) REFERENCES #{fk[:table]}(#{fk[:key][0]});\n"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
schema
|
44
65
|
end
|
45
66
|
|
46
67
|
#
|
data/lib/langchain/version.rb
CHANGED
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.5.
|
4
|
+
version: 0.5.7
|
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-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: baran
|