langchainrb 0.1.3 → 0.2.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 +4 -4
- data/CHANGELOG.md +12 -1
- data/Gemfile.lock +4 -1
- data/README.md +92 -1
- data/examples/create_and_manage_few_shot_prompt_templates.rb +36 -0
- data/examples/create_and_manage_prompt_templates.rb +21 -0
- data/lib/langchain.rb +8 -0
- data/lib/prompt/base.rb +86 -0
- data/lib/prompt/few_shot_prompt_template.rb +73 -0
- data/lib/prompt/loading.rb +87 -0
- data/lib/prompt/prompt_template.rb +62 -0
- data/lib/vectorsearch/base.rb +17 -20
- data/lib/version.rb +1 -1
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c43d156af4f33487e653c0f72d0a27a327ebe07b1ecc7558409b8d877854318c
|
4
|
+
data.tar.gz: dba1509aa4494e1a35a08a40ca872bcb9f0b3ad03b7f17c6e8c3716c7d5ce805
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b800cf71cb8c9193082383d9994f1f40f61d7479e1db57ad970a089dd26e749be684f8f17b388a704aaba595909acb5babe9fa4ab37836953f0d11dbc55efa66
|
7
|
+
data.tar.gz: 9fdb6337593f3fa5902af104255a3e9f9a06214965b8dcb026d3b914094804b1d546c7b46c0e923d8327a216639ee4eb64e0febeafa9616c73d3706d74032037
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
-
## [0.
|
3
|
+
## [0.2.0] - 2023-05-09
|
4
|
+
|
5
|
+
- Prompt Templating
|
6
|
+
- Ability to create prompt templates and save them to JSON files
|
7
|
+
- Default `Prompt::FewShotPromptTemplate`
|
8
|
+
- New examples added to `examples/`
|
9
|
+
|
10
|
+
## [0.1.4] - 2023-05-02
|
11
|
+
|
12
|
+
- Backfilling missing specs
|
13
|
+
|
14
|
+
## [0.1.3] - 2023-05-01
|
4
15
|
|
5
16
|
- Initial release
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
langchainrb (0.
|
4
|
+
langchainrb (0.2.0)
|
5
5
|
cohere-ruby (~> 0.9.1)
|
6
6
|
milvus (~> 0.9.0)
|
7
7
|
pinecone (~> 0.1.6)
|
@@ -111,6 +111,8 @@ GEM
|
|
111
111
|
multipart-post (2.3.0)
|
112
112
|
nokogiri (1.14.3-x86_64-darwin)
|
113
113
|
racc (~> 1.4)
|
114
|
+
nokogiri (1.14.3-x86_64-linux)
|
115
|
+
racc (~> 1.4)
|
114
116
|
pinecone (0.1.71)
|
115
117
|
dry-struct (~> 1.6.0)
|
116
118
|
dry-validation (~> 1.10.0)
|
@@ -167,6 +169,7 @@ GEM
|
|
167
169
|
|
168
170
|
PLATFORMS
|
169
171
|
x86_64-darwin-19
|
172
|
+
x86_64-linux
|
170
173
|
|
171
174
|
DEPENDENCIES
|
172
175
|
dotenv-rails (~> 2.7.6)
|
data/README.md
CHANGED
@@ -2,11 +2,13 @@
|
|
2
2
|
---
|
3
3
|
⚡ Building applications with LLMs through composability ⚡
|
4
4
|
|
5
|
+
👨💻👩💻 CURRENTLY SEEKING PEOPLE TO FORM THE CORE GROUP OF MAINTAINERS WITH
|
6
|
+
|
5
7
|
:warning: UNDER ACTIVE AND RAPID DEVELOPMENT (MAY BE BUGGY AND UNTESTED)
|
6
8
|
|
7
9
|
 [](https://badge.fury.io/rb/langchainrb)
|
8
10
|
|
9
|
-
|
11
|
+
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.
|
10
12
|
|
11
13
|
## Installation
|
12
14
|
|
@@ -112,12 +114,101 @@ cohere.embed(text: "foo bar")
|
|
112
114
|
cohere.complete(prompt: "What is the meaning of life?")
|
113
115
|
```
|
114
116
|
|
117
|
+
### Using Prompts
|
118
|
+
|
119
|
+
#### Prompt Templates
|
120
|
+
|
121
|
+
Create a prompt with one input variable:
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
prompt = Prompt::PromptTemplate.new(template: "Tell me a {adjective} joke.", input_variables: ["adjective"])
|
125
|
+
prompt.format(adjective: "funny") # "Tell me a funny joke."
|
126
|
+
```
|
127
|
+
|
128
|
+
Create a prompt with multiple input variables:
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
prompt = Prompt::PromptTemplate.new(template: "Tell me a {adjective} joke about {content}.", input_variables: ["adjective", "content"])
|
132
|
+
prompt.format(adjective: "funny", content: "chickens") # "Tell me a funny joke about chickens."
|
133
|
+
```
|
134
|
+
|
135
|
+
Creating a PromptTemplate using just a prompt and no input_variables:
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
prompt = Prompt::PromptTemplate.from_template("Tell me a {adjective} joke about {content}.")
|
139
|
+
prompt.input_variables # ["adjective", "content"]
|
140
|
+
prompt.format(adjective: "funny", content: "chickens") # "Tell me a funny joke about chickens."
|
141
|
+
```
|
142
|
+
|
143
|
+
Save prompt template to JSON file:
|
144
|
+
|
145
|
+
```ruby
|
146
|
+
prompt.save(file_path: "spec/fixtures/prompt/prompt_template.json")
|
147
|
+
```
|
148
|
+
|
149
|
+
Loading a new prompt template using a JSON file:
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
prompt = Prompt.load_from_path(file_path: "spec/fixtures/prompt/prompt_template.json")
|
153
|
+
prompt.input_variables # ["adjective", "content"]
|
154
|
+
```
|
155
|
+
|
156
|
+
#### Few Shot Prompt Templates
|
157
|
+
|
158
|
+
Create a prompt with a few shot examples:
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
prompt = Prompt::FewShotPromptTemplate.new(
|
162
|
+
prefix: "Write antonyms for the following words.",
|
163
|
+
suffix: "Input: {adjective}\nOutput:",
|
164
|
+
example_prompt: Prompt::PromptTemplate.new(
|
165
|
+
input_variables: ["input", "output"],
|
166
|
+
template: "Input: {input}\nOutput: {output}"
|
167
|
+
),
|
168
|
+
examples: [
|
169
|
+
{ "input": "happy", "output": "sad" },
|
170
|
+
{ "input": "tall", "output": "short" }
|
171
|
+
],
|
172
|
+
input_variables: ["adjective"]
|
173
|
+
)
|
174
|
+
|
175
|
+
prompt.format(adjective: "good")
|
176
|
+
|
177
|
+
# Write antonyms for the following words.
|
178
|
+
#
|
179
|
+
# Input: happy
|
180
|
+
# Output: sad
|
181
|
+
#
|
182
|
+
# Input: tall
|
183
|
+
# Output: short
|
184
|
+
#
|
185
|
+
# Input: good
|
186
|
+
# Output:
|
187
|
+
```
|
188
|
+
|
189
|
+
Save prompt template to JSON file:
|
190
|
+
|
191
|
+
```ruby
|
192
|
+
prompt.save(file_path: "spec/fixtures/prompt/few_shot_prompt_template.json")
|
193
|
+
```
|
194
|
+
|
195
|
+
Loading a new prompt template using a JSON file:
|
196
|
+
|
197
|
+
```ruby
|
198
|
+
prompt = Prompt.load_from_path(file_path: "spec/fixtures/prompt/few_shot_prompt_template.json")
|
199
|
+
prompt.prefix # "Write antonyms for the following words."
|
200
|
+
```
|
201
|
+
|
115
202
|
## Development
|
116
203
|
|
117
204
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
118
205
|
|
119
206
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
120
207
|
|
208
|
+
## Honorary Contributors
|
209
|
+
[<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)
|
210
|
+
[<img style="border-radius:50%" alt="Rafael Figueiredo" src="https://avatars.githubusercontent.com/u/35845775?v=4" width="80" height="80" class="avatar">](https://github.com/rafaelqfigueiredo)
|
211
|
+
|
121
212
|
## Contributing
|
122
213
|
|
123
214
|
Bug reports and pull requests are welcome on GitHub at https://github.com/andreibondarev/langchain.
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "langchain"
|
2
|
+
|
3
|
+
# Create a prompt with a few shot examples
|
4
|
+
prompt = Prompt::FewShotPromptTemplate.new(
|
5
|
+
prefix: "Write antonyms for the following words.",
|
6
|
+
suffix: "Input: {adjective}\nOutput:",
|
7
|
+
example_prompt: Prompt::PromptTemplate.new(
|
8
|
+
input_variables: ["input", "output"],
|
9
|
+
template: "Input: {input}\nOutput: {output}"
|
10
|
+
),
|
11
|
+
examples: [
|
12
|
+
{ "input": "happy", "output": "sad" },
|
13
|
+
{ "input": "tall", "output": "short" }
|
14
|
+
],
|
15
|
+
input_variables: ["adjective"]
|
16
|
+
)
|
17
|
+
|
18
|
+
prompt.format(adjective: "good")
|
19
|
+
|
20
|
+
# Write antonyms for the following words.
|
21
|
+
#
|
22
|
+
# Input: happy
|
23
|
+
# Output: sad
|
24
|
+
#
|
25
|
+
# Input: tall
|
26
|
+
# Output: short
|
27
|
+
#
|
28
|
+
# Input: good
|
29
|
+
# Output:
|
30
|
+
|
31
|
+
# Save prompt template to JSON file
|
32
|
+
prompt.save(file_path: "spec/fixtures/prompt/few_shot_prompt_template.json")
|
33
|
+
|
34
|
+
# Loading a new prompt template using a JSON file
|
35
|
+
prompt = Prompt.load_from_path(file_path: "spec/fixtures/prompt/few_shot_prompt_template.json")
|
36
|
+
prompt.prefix # "Write antonyms for the following words."
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "langchain"
|
2
|
+
|
3
|
+
# Create a prompt with one input variable
|
4
|
+
prompt = Prompt::PromptTemplate.new(template: "Tell me a {adjective} joke.", input_variables: ["adjective"])
|
5
|
+
prompt.format(adjective: "funny") # "Tell me a funny joke."
|
6
|
+
|
7
|
+
# Create a prompt with multiple input variables
|
8
|
+
prompt = Prompt::PromptTemplate.new(template: "Tell me a {adjective} joke about {content}.", input_variables: ["adjective", "content"])
|
9
|
+
prompt.format(adjective: "funny", content: "chickens") # "Tell me a funny joke about chickens."
|
10
|
+
|
11
|
+
# Creating a PromptTemplate using just a prompt and no input_variables
|
12
|
+
prompt = Prompt::PromptTemplate.from_template("Tell me a {adjective} joke about {content}.")
|
13
|
+
prompt.input_variables # ["adjective", "content"]
|
14
|
+
prompt.format(adjective: "funny", content: "chickens") # "Tell me a funny joke about chickens."
|
15
|
+
|
16
|
+
# Save prompt template to JSON file
|
17
|
+
prompt.save(file_path: "spec/fixtures/prompt/prompt_template.json")
|
18
|
+
|
19
|
+
# Loading a new prompt template using a JSON file
|
20
|
+
prompt = Prompt.load_from_path(file_path: "spec/fixtures/prompt/prompt_template.json")
|
21
|
+
prompt.input_variables # ["adjective", "content"]
|
data/lib/langchain.rb
CHANGED
@@ -14,4 +14,12 @@ module LLM
|
|
14
14
|
autoload :Base, "llm/base"
|
15
15
|
autoload :Cohere, "llm/cohere"
|
16
16
|
autoload :OpenAI, "llm/openai"
|
17
|
+
end
|
18
|
+
|
19
|
+
module Prompt
|
20
|
+
require_relative "prompt/loading"
|
21
|
+
|
22
|
+
autoload :Base, "prompt/base"
|
23
|
+
autoload :PromptTemplate, "prompt/prompt_template"
|
24
|
+
autoload :FewShotPromptTemplate, "prompt/few_shot_prompt_template"
|
17
25
|
end
|
data/lib/prompt/base.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'strscan'
|
4
|
+
|
5
|
+
module Prompt
|
6
|
+
class Base
|
7
|
+
def format(**kwargs)
|
8
|
+
raise NotImplementedError
|
9
|
+
end
|
10
|
+
|
11
|
+
def prompt_type
|
12
|
+
raise NotImplementedError
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_h
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
# Validate the input variables against the template.
|
21
|
+
#
|
22
|
+
# @param template [String] The template to validate against.
|
23
|
+
# @param input_variables [Array<String>] The input variables to validate.
|
24
|
+
#
|
25
|
+
# @raise [ArgumentError] If there are missing or extra variables.
|
26
|
+
#
|
27
|
+
# @return [void]
|
28
|
+
#
|
29
|
+
def validate(template:, input_variables:)
|
30
|
+
input_variables_set = @input_variables.uniq
|
31
|
+
variables_from_template = Prompt::Base.extract_variables_from_template(template)
|
32
|
+
|
33
|
+
missing_variables = variables_from_template - input_variables_set
|
34
|
+
extra_variables = input_variables_set - variables_from_template
|
35
|
+
|
36
|
+
raise ArgumentError, "Missing variables: #{missing_variables}" if missing_variables.any?
|
37
|
+
raise ArgumentError, "Extra variables: #{extra_variables}" if extra_variables.any?
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Save the object to a file in JSON format.
|
42
|
+
#
|
43
|
+
# @param file_path [String, Pathname] The path to the file to save the object to
|
44
|
+
#
|
45
|
+
# @raise [ArgumentError] If file_path doesn't end with .json
|
46
|
+
#
|
47
|
+
# @return [void]
|
48
|
+
#
|
49
|
+
def save(file_path:)
|
50
|
+
save_path = file_path.is_a?(String) ? Pathname.new(file_path) : file_path
|
51
|
+
directory_path = save_path.dirname
|
52
|
+
FileUtils.mkdir_p(directory_path) unless directory_path.directory?
|
53
|
+
|
54
|
+
if save_path.extname == ".json"
|
55
|
+
File.open(file_path, "w") { |f| f.write(to_h.to_json) }
|
56
|
+
else
|
57
|
+
raise ArgumentError, "#{file_path} must be json"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
#
|
64
|
+
# Extracts variables from a template string.
|
65
|
+
#
|
66
|
+
# This method takes a template string and returns an array of input variable names
|
67
|
+
# contained within the template. Input variables are defined as text enclosed in
|
68
|
+
# curly braces (e.g. "{variable_name}").
|
69
|
+
#
|
70
|
+
# @param template [String] The template string to extract variables from.
|
71
|
+
#
|
72
|
+
# @return [Array<String>] An array of input variable names.
|
73
|
+
#
|
74
|
+
def self.extract_variables_from_template(template)
|
75
|
+
input_variables = []
|
76
|
+
scanner = StringScanner.new(template)
|
77
|
+
|
78
|
+
while scanner.scan_until(/\{([^{}]*)\}/)
|
79
|
+
variable = scanner[1].strip
|
80
|
+
input_variables << variable unless variable.empty?
|
81
|
+
end
|
82
|
+
|
83
|
+
input_variables
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Prompt
|
4
|
+
class FewShotPromptTemplate < Base
|
5
|
+
attr_reader :examples, :example_prompt, :input_variables, :prefix, :suffix, :example_separator
|
6
|
+
|
7
|
+
#
|
8
|
+
# Initializes a new instance of the class.
|
9
|
+
#
|
10
|
+
# @param examples [Array<Hash>] Examples to format into the prompt.
|
11
|
+
# @param example_prompt [PromptTemplate] PromptTemplate used to format an individual example.
|
12
|
+
# @param suffix [String] A prompt template string to put after the examples.
|
13
|
+
# @param input_variables [Array<String>] A list of the names of the variables the prompt template expects.
|
14
|
+
# @param example_separator [String] String separator used to join the prefix, the examples, and suffix.
|
15
|
+
# @param prefix [String] A prompt template string to put before the examples.
|
16
|
+
# @param validate_template [Boolean] Whether or not to try validating the template.
|
17
|
+
#
|
18
|
+
def initialize(
|
19
|
+
examples:,
|
20
|
+
example_prompt:,
|
21
|
+
input_variables:,
|
22
|
+
suffix:,
|
23
|
+
prefix: "",
|
24
|
+
example_separator: "\n\n",
|
25
|
+
validate_template: true
|
26
|
+
)
|
27
|
+
@examples = examples
|
28
|
+
@example_prompt = example_prompt
|
29
|
+
@input_variables = input_variables
|
30
|
+
@prefix = prefix
|
31
|
+
@suffix = suffix
|
32
|
+
@example_separator = example_separator
|
33
|
+
|
34
|
+
validate(template: @prefix + @suffix, input_variables: @input_variables) if @validate_template
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# Format the prompt with the inputs.
|
39
|
+
#
|
40
|
+
# @param kwargs [Hash] Any arguments to be passed to the prompt template.
|
41
|
+
#
|
42
|
+
# @return [String] A formatted string.
|
43
|
+
#
|
44
|
+
def format(**kwargs)
|
45
|
+
example_string = @examples.map { |example| @example_prompt.format(**example) }
|
46
|
+
|
47
|
+
suffix_string = @suffix
|
48
|
+
kwargs.each { |key, value| suffix_string = suffix_string.gsub(/\{#{key}\}/, value.to_s) }
|
49
|
+
|
50
|
+
[@prefix, *example_string, suffix_string].join(@example_separator)
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# Returns the key type of prompt as a string.
|
55
|
+
#
|
56
|
+
# @return [String] the prompt type key
|
57
|
+
#
|
58
|
+
def prompt_type
|
59
|
+
"few_shot"
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_h
|
63
|
+
{
|
64
|
+
_type: prompt_type,
|
65
|
+
input_variables: @input_variables,
|
66
|
+
prefix: @prefix,
|
67
|
+
example_prompt: @example_prompt.to_h,
|
68
|
+
examples: @examples,
|
69
|
+
suffix: @suffix
|
70
|
+
}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'strscan'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
module Prompt
|
7
|
+
TYPE_TO_LOADER = {
|
8
|
+
"prompt" => ->(config) { Prompt.load_prompt(config) },
|
9
|
+
"few_shot" => ->(config) { Prompt.load_few_shot_prompt(config) }
|
10
|
+
}
|
11
|
+
|
12
|
+
class << self
|
13
|
+
#
|
14
|
+
# Load prompt from file.
|
15
|
+
#
|
16
|
+
# @param file_path [String, Pathname] The path of the file to read the configuration data from.
|
17
|
+
#
|
18
|
+
# @return [Object] The loaded prompt loaded.
|
19
|
+
#
|
20
|
+
# @raise [ArgumentError] If the file type of the specified file path is not supported.
|
21
|
+
#
|
22
|
+
def load_from_path(file_path:)
|
23
|
+
file_path = file_path.is_a?(String) ? Pathname.new(file_path) : file_path
|
24
|
+
|
25
|
+
if file_path.extname == ".json"
|
26
|
+
config = JSON.parse(File.read(file_path))
|
27
|
+
else
|
28
|
+
raise ArgumentError, "Got unsupported file type #{file_path.extname}"
|
29
|
+
end
|
30
|
+
|
31
|
+
load_from_config(config)
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Loads a prompt template with the given configuration.
|
36
|
+
#
|
37
|
+
# @param config [Hash] A hash containing the configuration for the prompt.
|
38
|
+
#
|
39
|
+
# @return [PromptTemplate] The loaded prompt loaded.
|
40
|
+
#
|
41
|
+
def load_prompt(config)
|
42
|
+
template, input_variables = config.values_at("template", "input_variables")
|
43
|
+
PromptTemplate.new(template: template, input_variables: input_variables)
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Loads a prompt template with the given configuration.
|
48
|
+
#
|
49
|
+
# @param config [Hash] A hash containing the configuration for the prompt.
|
50
|
+
#
|
51
|
+
# @return [FewShotPromptTemplate] The loaded prompt loaded.
|
52
|
+
#
|
53
|
+
def load_few_shot_prompt(config)
|
54
|
+
prefix, suffix, example_prompt, examples, input_variables = config.values_at("prefix", "suffix", "example_prompt", "examples", "input_variables")
|
55
|
+
example_prompt = load_prompt(example_prompt)
|
56
|
+
FewShotPromptTemplate.new(prefix: prefix, suffix: suffix, example_prompt: example_prompt, examples: examples, input_variables: input_variables)
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
#
|
62
|
+
# Loads the prompt from the given configuration hash
|
63
|
+
#
|
64
|
+
# @param config [Hash] the configuration hash to load from
|
65
|
+
#
|
66
|
+
# @return [Object] the loaded prompt
|
67
|
+
#
|
68
|
+
# @raise [ArgumentError] if the prompt type specified in the config is not supported
|
69
|
+
#
|
70
|
+
def load_from_config(config)
|
71
|
+
# If `_type` key is not present in the configuration hash, add it with a default value of `prompt`
|
72
|
+
unless config.key?("_type")
|
73
|
+
puts "[WARN] No `_type` key found, defaulting to `prompt`"
|
74
|
+
config["_type"] = "prompt"
|
75
|
+
end
|
76
|
+
|
77
|
+
# If the prompt type specified in the configuration hash is not supported, raise an exception
|
78
|
+
unless TYPE_TO_LOADER.key?(config["_type"])
|
79
|
+
raise ArgumentError, "Loading #{config["_type"]} prompt not supported"
|
80
|
+
end
|
81
|
+
|
82
|
+
# Load the prompt using the corresponding loader function from the `TYPE_TO_LOADER` hash
|
83
|
+
prompt_loader = TYPE_TO_LOADER[config["_type"]]
|
84
|
+
prompt_loader.call(config)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Prompt
|
4
|
+
class PromptTemplate < Base
|
5
|
+
attr_reader :template, :input_variables, :validate_template
|
6
|
+
|
7
|
+
#
|
8
|
+
# Initializes a new instance of the class.
|
9
|
+
#
|
10
|
+
# @param template [String] The prompt template.
|
11
|
+
# @param input_variables [Array<String>] A list of the names of the variables the prompt template expects.
|
12
|
+
# @param validate_template [Boolean] Whether or not to try validating the template.
|
13
|
+
#
|
14
|
+
def initialize(template:, input_variables:, validate_template: true)
|
15
|
+
@template = template
|
16
|
+
@input_variables = input_variables
|
17
|
+
@validate_template = validate_template
|
18
|
+
|
19
|
+
validate(template: @template, input_variables: @input_variables) if @validate_template
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# Format the prompt with the inputs.
|
24
|
+
#
|
25
|
+
# @param kwargs [Hash] Any arguments to be passed to the prompt template.
|
26
|
+
# @return [String] A formatted string.
|
27
|
+
#
|
28
|
+
def format(**kwargs)
|
29
|
+
result = @template
|
30
|
+
kwargs.each { |key, value| result = result.gsub(/\{#{key}\}/, value.to_s) }
|
31
|
+
result
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Returns the key type of prompt as a string.
|
36
|
+
#
|
37
|
+
# @return [String] the prompt type key
|
38
|
+
#
|
39
|
+
def prompt_type
|
40
|
+
"prompt"
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_h
|
44
|
+
{
|
45
|
+
_type: prompt_type,
|
46
|
+
input_variables: @input_variables,
|
47
|
+
template: @template
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
# Creates a new instance of the class using the given template.
|
53
|
+
#
|
54
|
+
# @param template [String] The template to use
|
55
|
+
#
|
56
|
+
# @return [Object] A new instance of the class
|
57
|
+
#
|
58
|
+
def self.from_template(template)
|
59
|
+
new(template: template, input_variables: extract_variables_from_template(template))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/vectorsearch/base.rb
CHANGED
@@ -37,33 +37,30 @@ module Vectorsearch
|
|
37
37
|
:generate_completion,
|
38
38
|
:default_dimension
|
39
39
|
|
40
|
-
# def generate_embedding(text:)
|
41
|
-
# llm_client.embed(text: text)
|
42
|
-
# end
|
43
|
-
|
44
|
-
# def generate_completion(prompt:)
|
45
|
-
# llm_client.complete(prompt: prompt)
|
46
|
-
# end
|
47
|
-
|
48
|
-
# def default_dimension
|
49
|
-
# llm_client.default_dimension
|
50
|
-
# end
|
51
|
-
|
52
40
|
def generate_prompt(question:, context:)
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
41
|
+
prompt_template = Prompt::FewShotPromptTemplate.new(
|
42
|
+
prefix: "Context:",
|
43
|
+
suffix: "---\nQuestion: {question}\n---\nAnswer:",
|
44
|
+
example_prompt: Prompt::PromptTemplate.new(
|
45
|
+
template: "{context}",
|
46
|
+
input_variables: ["context"]
|
47
|
+
),
|
48
|
+
examples: [
|
49
|
+
{ context: context }
|
50
|
+
],
|
51
|
+
input_variables: ["question"],
|
52
|
+
example_separator: "\n"
|
53
|
+
)
|
54
|
+
|
55
|
+
prompt_template.format(question: question)
|
59
56
|
end
|
60
57
|
|
61
58
|
private
|
62
59
|
|
63
60
|
def validate_llm!(llm:)
|
64
|
-
# TODO: Fix
|
61
|
+
# TODO: Fix so this works when `llm` value is a string instead of a symbol
|
65
62
|
unless LLM::Base::LLMS.keys.include?(llm)
|
66
|
-
raise ArgumentError, "LLM must be one of #{LLMS}"
|
63
|
+
raise ArgumentError, "LLM must be one of #{LLM::Base::LLMS.keys}"
|
67
64
|
end
|
68
65
|
end
|
69
66
|
end
|
data/lib/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.
|
4
|
+
version: 0.2.0
|
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-05-
|
11
|
+
date: 2023-05-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pry-byebug
|
@@ -137,6 +137,8 @@ files:
|
|
137
137
|
- README.md
|
138
138
|
- Rakefile
|
139
139
|
- examples/.keep
|
140
|
+
- examples/create_and_manage_few_shot_prompt_templates.rb
|
141
|
+
- examples/create_and_manage_prompt_templates.rb
|
140
142
|
- examples/store_and_query_with_pinecone.rb
|
141
143
|
- examples/store_and_query_with_qdrant.rb
|
142
144
|
- examples/store_and_query_with_weaviate.rb
|
@@ -144,6 +146,10 @@ files:
|
|
144
146
|
- lib/llm/base.rb
|
145
147
|
- lib/llm/cohere.rb
|
146
148
|
- lib/llm/openai.rb
|
149
|
+
- lib/prompt/base.rb
|
150
|
+
- lib/prompt/few_shot_prompt_template.rb
|
151
|
+
- lib/prompt/loading.rb
|
152
|
+
- lib/prompt/prompt_template.rb
|
147
153
|
- lib/vectorsearch/base.rb
|
148
154
|
- lib/vectorsearch/milvus.rb
|
149
155
|
- lib/vectorsearch/pinecone.rb
|