langchainrb 0.5.6 → 0.5.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/langchainrb.svg)](https://badge.fury.io/rb/langchainrb)
|
11
11
|
[![Docs](http://img.shields.io/badge/yard-docs-blue.svg)](http://rubydoc.info/gems/langchainrb)
|
12
12
|
[![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/andreibondarev/langchainrb/blob/main/LICENSE.txt)
|
13
|
-
[![](https://dcbadge.vercel.app/api/server/
|
13
|
+
[![](https://dcbadge.vercel.app/api/server/WDARp7J2n8?compact=true&style=flat)](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
|