langchainrb 0.12.0 → 0.12.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/lib/langchain/llm/anthropic.rb +27 -49
- data/lib/langchain/llm/aws_bedrock.rb +30 -34
- data/lib/langchain/llm/azure.rb +6 -0
- data/lib/langchain/llm/base.rb +18 -0
- data/lib/langchain/llm/cohere.rb +38 -6
- data/lib/langchain/llm/mistral_ai.rb +10 -19
- data/lib/langchain/llm/ollama.rb +23 -27
- data/lib/langchain/llm/openai.rb +20 -48
- data/lib/langchain/llm/parameters/chat.rb +51 -0
- data/lib/langchain/llm/response/base_response.rb +2 -2
- data/lib/langchain/llm/response/cohere_response.rb +16 -0
- data/lib/langchain/llm/unified_parameters.rb +98 -0
- data/lib/langchain/loader.rb +6 -0
- data/lib/langchain/tool/base.rb +5 -5
- data/lib/langchain/utils/token_length/openai_validator.rb +6 -1
- data/lib/langchain/version.rb +1 -1
- metadata +10 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6f106f178a5641f17ca723eec7272d120fbdd0e3046e44152eaf575af2985724
|
4
|
+
data.tar.gz: 417d5b671a6783d0854c05c43871b1e931133eaf65e6d39ac6ac4989a0124e36
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 184b139d3e9d54fcd42665e25692d9fdb14e92c3d0bb23713647dfa2f1a87854215b13cc9573f10872d3e2e09d042e8c05640356276bc69a32423119e99c129b
|
7
|
+
data.tar.gz: 4503a8498018b53a9068345186efe03a72da4340d82a0f7806d4007e220c748814ab2da49194e09fd11ef33de3a35f38048e835dd43cee2c0b967bb810bfb512
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.12.1] - 2024-05-13
|
4
|
+
- Langchain::LLM::Ollama now uses `llama3` by default
|
5
|
+
- Langchain::LLM::Anthropic#complete() now uses `claude-2.1` by default
|
6
|
+
- Updated with new OpenAI models, including `gpt-4o`
|
7
|
+
- New `Langchain::LLM::Cohere#chat()` method.
|
8
|
+
- Introducing `UnifiedParameters` to unify parameters across LLM classes
|
9
|
+
|
3
10
|
## [0.12.0] - 2024-04-22
|
4
11
|
- [BREAKING] Rename `dimension` parameter to `dimensions` everywhere
|
5
12
|
|
@@ -13,7 +13,7 @@ module Langchain::LLM
|
|
13
13
|
class Anthropic < Base
|
14
14
|
DEFAULTS = {
|
15
15
|
temperature: 0.0,
|
16
|
-
completion_model_name: "claude-2",
|
16
|
+
completion_model_name: "claude-2.1",
|
17
17
|
chat_completion_model_name: "claude-3-sonnet-20240229",
|
18
18
|
max_tokens_to_sample: 256
|
19
19
|
}.freeze
|
@@ -32,6 +32,15 @@ module Langchain::LLM
|
|
32
32
|
|
33
33
|
@client = ::Anthropic::Client.new(access_token: api_key, **llm_options)
|
34
34
|
@defaults = DEFAULTS.merge(default_options)
|
35
|
+
chat_parameters.update(
|
36
|
+
model: {default: @defaults[:chat_completion_model_name]},
|
37
|
+
temperature: {default: @defaults[:temperature]},
|
38
|
+
max_tokens: {default: @defaults[:max_tokens_to_sample]},
|
39
|
+
metadata: {},
|
40
|
+
system: {}
|
41
|
+
)
|
42
|
+
chat_parameters.ignore(:n, :user)
|
43
|
+
chat_parameters.remap(stop: :stop_sequences)
|
35
44
|
end
|
36
45
|
|
37
46
|
# Generate a completion for a given prompt
|
@@ -72,66 +81,35 @@ module Langchain::LLM
|
|
72
81
|
parameters[:metadata] = metadata if metadata
|
73
82
|
parameters[:stream] = stream if stream
|
74
83
|
|
75
|
-
# TODO: Implement token length validator for Anthropic
|
76
|
-
# parameters[:max_tokens_to_sample] = validate_max_tokens(prompt, parameters[:completion_model_name])
|
77
|
-
|
78
84
|
response = client.complete(parameters: parameters)
|
79
85
|
Langchain::LLM::AnthropicResponse.new(response)
|
80
86
|
end
|
81
87
|
|
82
88
|
# Generate a chat completion for given messages
|
83
89
|
#
|
84
|
-
# @param
|
85
|
-
# @
|
86
|
-
# @
|
87
|
-
# @
|
88
|
-
# @
|
89
|
-
# @
|
90
|
-
# @
|
91
|
-
# @
|
92
|
-
# @
|
93
|
-
# @
|
94
|
-
# @
|
90
|
+
# @param [Hash] params unified chat parmeters from [Langchain::LLM::Parameters::Chat::SCHEMA]
|
91
|
+
# @option params [Array<String>] :messages Input messages
|
92
|
+
# @option params [String] :model The model that will complete your prompt
|
93
|
+
# @option params [Integer] :max_tokens Maximum number of tokens to generate before stopping
|
94
|
+
# @option params [Hash] :metadata Object describing metadata about the request
|
95
|
+
# @option params [Array<String>] :stop_sequences Custom text sequences that will cause the model to stop generating
|
96
|
+
# @option params [Boolean] :stream Whether to incrementally stream the response using server-sent events
|
97
|
+
# @option params [String] :system System prompt
|
98
|
+
# @option params [Float] :temperature Amount of randomness injected into the response
|
99
|
+
# @option params [Array<String>] :tools Definitions of tools that the model may use
|
100
|
+
# @option params [Integer] :top_k Only sample from the top K options for each subsequent token
|
101
|
+
# @option params [Float] :top_p Use nucleus sampling.
|
95
102
|
# @return [Langchain::LLM::AnthropicResponse] The chat completion
|
96
|
-
def chat(
|
97
|
-
|
98
|
-
model: @defaults[:chat_completion_model_name],
|
99
|
-
max_tokens: @defaults[:max_tokens_to_sample],
|
100
|
-
metadata: nil,
|
101
|
-
stop_sequences: nil,
|
102
|
-
stream: nil,
|
103
|
-
system: nil,
|
104
|
-
temperature: @defaults[:temperature],
|
105
|
-
tools: [],
|
106
|
-
top_k: nil,
|
107
|
-
top_p: nil
|
108
|
-
)
|
109
|
-
raise ArgumentError.new("messages argument is required") if messages.empty?
|
110
|
-
raise ArgumentError.new("model argument is required") if model.empty?
|
111
|
-
raise ArgumentError.new("max_tokens argument is required") if max_tokens.nil?
|
103
|
+
def chat(params = {})
|
104
|
+
parameters = chat_parameters.to_params(params)
|
112
105
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
max_tokens: max_tokens,
|
117
|
-
temperature: temperature
|
118
|
-
}
|
119
|
-
parameters[:metadata] = metadata if metadata
|
120
|
-
parameters[:stop_sequences] = stop_sequences if stop_sequences
|
121
|
-
parameters[:stream] = stream if stream
|
122
|
-
parameters[:system] = system if system
|
123
|
-
parameters[:tools] = tools if tools.any?
|
124
|
-
parameters[:top_k] = top_k if top_k
|
125
|
-
parameters[:top_p] = top_p if top_p
|
106
|
+
raise ArgumentError.new("messages argument is required") if Array(parameters[:messages]).empty?
|
107
|
+
raise ArgumentError.new("model argument is required") if parameters[:model].empty?
|
108
|
+
raise ArgumentError.new("max_tokens argument is required") if parameters[:max_tokens].nil?
|
126
109
|
|
127
110
|
response = client.messages(parameters: parameters)
|
128
111
|
|
129
112
|
Langchain::LLM::AnthropicResponse.new(response)
|
130
113
|
end
|
131
|
-
|
132
|
-
# TODO: Implement token length validator for Anthropic
|
133
|
-
# def validate_max_tokens(messages, model)
|
134
|
-
# LENGTH_VALIDATOR.validate_max_tokens!(messages, model)
|
135
|
-
# end
|
136
114
|
end
|
137
115
|
end
|
@@ -59,6 +59,17 @@ module Langchain::LLM
|
|
59
59
|
@defaults = DEFAULTS.merge(default_options)
|
60
60
|
.merge(completion_model_name: completion_model)
|
61
61
|
.merge(embedding_model_name: embedding_model)
|
62
|
+
|
63
|
+
chat_parameters.update(
|
64
|
+
model: {default: @defaults[:chat_completion_model_name]},
|
65
|
+
temperature: {},
|
66
|
+
max_tokens: {default: @defaults[:max_tokens_to_sample]},
|
67
|
+
metadata: {},
|
68
|
+
system: {},
|
69
|
+
anthropic_version: {default: "bedrock-2023-05-31"}
|
70
|
+
)
|
71
|
+
chat_parameters.ignore(:n, :user)
|
72
|
+
chat_parameters.remap(stop: :stop_sequences)
|
62
73
|
end
|
63
74
|
|
64
75
|
#
|
@@ -113,43 +124,28 @@ module Langchain::LLM
|
|
113
124
|
# Generate a chat completion for a given prompt
|
114
125
|
# Currently only configured to work with the Anthropic provider and
|
115
126
|
# the claude-3 model family
|
116
|
-
#
|
117
|
-
# @param
|
118
|
-
# @
|
119
|
-
# @
|
120
|
-
# @
|
121
|
-
# @
|
122
|
-
# @
|
123
|
-
# @
|
127
|
+
#
|
128
|
+
# @param [Hash] params unified chat parmeters from [Langchain::LLM::Parameters::Chat::SCHEMA]
|
129
|
+
# @option params [Array<String>] :messages The messages to generate a completion for
|
130
|
+
# @option params [String] :system The system prompt to provide instructions
|
131
|
+
# @option params [String] :model The model to use for completion defaults to @defaults[:chat_completion_model_name]
|
132
|
+
# @option params [Integer] :max_tokens The maximum number of tokens to generate defaults to @defaults[:max_tokens_to_sample]
|
133
|
+
# @option params [Array<String>] :stop The stop sequences to use for completion
|
134
|
+
# @option params [Array<String>] :stop_sequences The stop sequences to use for completion
|
135
|
+
# @option params [Float] :temperature The temperature to use for completion
|
136
|
+
# @option params [Float] :top_p Use nucleus sampling.
|
137
|
+
# @option params [Integer] :top_k Only sample from the top K options for each subsequent token
|
124
138
|
# @return [Langchain::LLM::AnthropicMessagesResponse] Response object
|
125
|
-
def chat(
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
temperature: nil,
|
132
|
-
top_p: nil,
|
133
|
-
top_k: nil
|
134
|
-
)
|
135
|
-
raise ArgumentError.new("messages argument is required") if messages.empty?
|
136
|
-
|
137
|
-
raise "Model #{model} does not support chat completions." unless Langchain::LLM::AwsBedrock::SUPPORTED_CHAT_COMPLETION_PROVIDERS.include?(completion_provider)
|
138
|
-
|
139
|
-
inference_parameters = {
|
140
|
-
messages: messages,
|
141
|
-
max_tokens: max_tokens,
|
142
|
-
anthropic_version: @defaults[:anthropic_version]
|
143
|
-
}
|
144
|
-
inference_parameters[:system] = system if system
|
145
|
-
inference_parameters[:stop_sequences] = stop_sequences if stop_sequences
|
146
|
-
inference_parameters[:temperature] = temperature if temperature
|
147
|
-
inference_parameters[:top_p] = top_p if top_p
|
148
|
-
inference_parameters[:top_k] = top_k if top_k
|
139
|
+
def chat(params = {})
|
140
|
+
parameters = chat_parameters.to_params(params)
|
141
|
+
|
142
|
+
raise ArgumentError.new("messages argument is required") if Array(parameters[:messages]).empty?
|
143
|
+
|
144
|
+
raise "Model #{parameters[:model]} does not support chat completions." unless Langchain::LLM::AwsBedrock::SUPPORTED_CHAT_COMPLETION_PROVIDERS.include?(completion_provider)
|
149
145
|
|
150
146
|
response = client.invoke_model({
|
151
|
-
model_id: model,
|
152
|
-
body:
|
147
|
+
model_id: parameters[:model],
|
148
|
+
body: parameters.except(:model).to_json,
|
153
149
|
content_type: "application/json",
|
154
150
|
accept: "application/json"
|
155
151
|
})
|
data/lib/langchain/llm/azure.rb
CHANGED
data/lib/langchain/llm/base.rb
CHANGED
@@ -24,6 +24,15 @@ module Langchain::LLM
|
|
24
24
|
# A client for communicating with the LLM
|
25
25
|
attr_reader :client
|
26
26
|
|
27
|
+
# Ensuring backward compatibility after https://github.com/patterns-ai-core/langchainrb/pull/586
|
28
|
+
# TODO: Delete this method later
|
29
|
+
def default_dimension
|
30
|
+
default_dimensions
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns the number of vector dimensions used by DEFAULTS[:chat_completion_model_name]
|
34
|
+
#
|
35
|
+
# @return [Integer] Vector dimensions
|
27
36
|
def default_dimensions
|
28
37
|
self.class.const_get(:DEFAULTS).dig(:dimensions)
|
29
38
|
end
|
@@ -61,5 +70,14 @@ module Langchain::LLM
|
|
61
70
|
def summarize(...)
|
62
71
|
raise NotImplementedError, "#{self.class.name} does not support summarization"
|
63
72
|
end
|
73
|
+
|
74
|
+
#
|
75
|
+
# Returns an instance of Langchain::LLM::Parameters::Chat
|
76
|
+
#
|
77
|
+
def chat_parameters(params = {})
|
78
|
+
@chat_parameters ||= Langchain::LLM::Parameters::Chat.new(
|
79
|
+
parameters: params
|
80
|
+
)
|
81
|
+
end
|
64
82
|
end
|
65
83
|
end
|
data/lib/langchain/llm/cohere.rb
CHANGED
@@ -8,22 +8,34 @@ module Langchain::LLM
|
|
8
8
|
# gem "cohere-ruby", "~> 0.9.6"
|
9
9
|
#
|
10
10
|
# Usage:
|
11
|
-
#
|
11
|
+
# llm = Langchain::LLM::Cohere.new(api_key: ENV["COHERE_API_KEY"])
|
12
12
|
#
|
13
13
|
class Cohere < Base
|
14
14
|
DEFAULTS = {
|
15
15
|
temperature: 0.0,
|
16
16
|
completion_model_name: "command",
|
17
|
+
chat_completion_model_name: "command-r-plus",
|
17
18
|
embeddings_model_name: "small",
|
18
19
|
dimensions: 1024,
|
19
20
|
truncate: "START"
|
20
21
|
}.freeze
|
21
22
|
|
22
|
-
def initialize(api_key
|
23
|
+
def initialize(api_key:, default_options: {})
|
23
24
|
depends_on "cohere-ruby", req: "cohere"
|
24
25
|
|
25
|
-
@client = ::Cohere::Client.new(api_key)
|
26
|
+
@client = ::Cohere::Client.new(api_key: api_key)
|
26
27
|
@defaults = DEFAULTS.merge(default_options)
|
28
|
+
chat_parameters.update(
|
29
|
+
model: {default: @defaults[:chat_completion_model_name]},
|
30
|
+
temperature: {default: @defaults[:temperature]}
|
31
|
+
)
|
32
|
+
chat_parameters.remap(
|
33
|
+
system: :preamble,
|
34
|
+
messages: :chat_history,
|
35
|
+
stop: :stop_sequences,
|
36
|
+
top_k: :k,
|
37
|
+
top_p: :p
|
38
|
+
)
|
27
39
|
end
|
28
40
|
|
29
41
|
#
|
@@ -68,9 +80,29 @@ module Langchain::LLM
|
|
68
80
|
Langchain::LLM::CohereResponse.new response, model: @defaults[:completion_model_name]
|
69
81
|
end
|
70
82
|
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
83
|
+
# Generate a chat completion for given messages
|
84
|
+
#
|
85
|
+
# @param [Hash] params unified chat parmeters from [Langchain::LLM::Parameters::Chat::SCHEMA]
|
86
|
+
# @option params [Array<String>] :messages Input messages
|
87
|
+
# @option params [String] :model The model that will complete your prompt
|
88
|
+
# @option params [Integer] :max_tokens Maximum number of tokens to generate before stopping
|
89
|
+
# @option params [Array<String>] :stop Custom text sequences that will cause the model to stop generating
|
90
|
+
# @option params [Boolean] :stream Whether to incrementally stream the response using server-sent events
|
91
|
+
# @option params [String] :system System prompt
|
92
|
+
# @option params [Float] :temperature Amount of randomness injected into the response
|
93
|
+
# @option params [Array<String>] :tools Definitions of tools that the model may use
|
94
|
+
# @option params [Integer] :top_k Only sample from the top K options for each subsequent token
|
95
|
+
# @option params [Float] :top_p Use nucleus sampling.
|
96
|
+
# @return [Langchain::LLM::CohereResponse] The chat completion
|
97
|
+
def chat(params = {})
|
98
|
+
raise ArgumentError.new("messages argument is required") if Array(params[:messages]).empty?
|
99
|
+
|
100
|
+
parameters = chat_parameters.to_params(params)
|
101
|
+
|
102
|
+
response = client.chat(**parameters)
|
103
|
+
|
104
|
+
Langchain::LLM::CohereResponse.new(response)
|
105
|
+
end
|
74
106
|
|
75
107
|
# Generate a summary in English for a given text
|
76
108
|
#
|
@@ -23,28 +23,19 @@ module Langchain::LLM
|
|
23
23
|
)
|
24
24
|
|
25
25
|
@defaults = DEFAULTS.merge(default_options)
|
26
|
+
chat_parameters.update(
|
27
|
+
model: {default: @defaults[:chat_completion_model_name]},
|
28
|
+
n: {default: @defaults[:n]},
|
29
|
+
safe_prompt: {}
|
30
|
+
)
|
31
|
+
chat_parameters.remap(seed: :random_seed)
|
32
|
+
chat_parameters.ignore(:n, :top_k)
|
26
33
|
end
|
27
34
|
|
28
|
-
def chat(
|
29
|
-
|
30
|
-
model: defaults[:chat_completion_model_name],
|
31
|
-
temperature: nil,
|
32
|
-
top_p: nil,
|
33
|
-
max_tokens: nil,
|
34
|
-
safe_prompt: nil,
|
35
|
-
random_seed: nil
|
36
|
-
)
|
37
|
-
params = {
|
38
|
-
messages: messages,
|
39
|
-
model: model
|
40
|
-
}
|
41
|
-
params[:temperature] = temperature if temperature
|
42
|
-
params[:top_p] = top_p if top_p
|
43
|
-
params[:max_tokens] = max_tokens if max_tokens
|
44
|
-
params[:safe_prompt] = safe_prompt if safe_prompt
|
45
|
-
params[:random_seed] = random_seed if random_seed
|
35
|
+
def chat(params = {})
|
36
|
+
parameters = chat_parameters.to_params(params)
|
46
37
|
|
47
|
-
response = client.chat_completions(
|
38
|
+
response = client.chat_completions(parameters)
|
48
39
|
|
49
40
|
Langchain::LLM::MistralAIResponse.new(response.to_h)
|
50
41
|
end
|
data/lib/langchain/llm/ollama.rb
CHANGED
@@ -7,22 +7,24 @@ module Langchain::LLM
|
|
7
7
|
# Available models: https://ollama.ai/library
|
8
8
|
#
|
9
9
|
# Usage:
|
10
|
-
#
|
10
|
+
# llm = Langchain::LLM::Ollama.new
|
11
|
+
# llm = Langchain::LLM::Ollama.new(url: ENV["OLLAMA_URL"], default_options: {})
|
11
12
|
#
|
12
13
|
class Ollama < Base
|
13
14
|
attr_reader :url, :defaults
|
14
15
|
|
15
16
|
DEFAULTS = {
|
16
17
|
temperature: 0.8,
|
17
|
-
completion_model_name: "
|
18
|
-
embeddings_model_name: "
|
19
|
-
chat_completion_model_name: "
|
18
|
+
completion_model_name: "llama3",
|
19
|
+
embeddings_model_name: "llama3",
|
20
|
+
chat_completion_model_name: "llama3"
|
20
21
|
}.freeze
|
21
22
|
|
22
23
|
EMBEDDING_SIZES = {
|
23
24
|
codellama: 4_096,
|
24
25
|
"dolphin-mixtral": 4_096,
|
25
26
|
llama2: 4_096,
|
27
|
+
llama3: 4_096,
|
26
28
|
llava: 4_096,
|
27
29
|
mistral: 4_096,
|
28
30
|
"mistral-openorca": 4_096,
|
@@ -33,10 +35,17 @@ module Langchain::LLM
|
|
33
35
|
# @param url [String] The URL of the Ollama instance
|
34
36
|
# @param default_options [Hash] The default options to use
|
35
37
|
#
|
36
|
-
def initialize(url
|
38
|
+
def initialize(url: "http://localhost:11434", default_options: {})
|
37
39
|
depends_on "faraday"
|
38
40
|
@url = url
|
39
41
|
@defaults = DEFAULTS.deep_merge(default_options)
|
42
|
+
chat_parameters.update(
|
43
|
+
model: {default: @defaults[:chat_completion_model_name]},
|
44
|
+
temperature: {default: @defaults[:temperature]},
|
45
|
+
template: {},
|
46
|
+
stream: {default: false}
|
47
|
+
)
|
48
|
+
chat_parameters.remap(response_format: :format)
|
40
49
|
end
|
41
50
|
|
42
51
|
# Returns the # of vector dimensions for the embeddings
|
@@ -150,33 +159,20 @@ module Langchain::LLM
|
|
150
159
|
|
151
160
|
# Generate a chat completion
|
152
161
|
#
|
153
|
-
# @param
|
154
|
-
# @
|
155
|
-
# @
|
156
|
-
# @
|
157
|
-
# @
|
158
|
-
# @
|
162
|
+
# @param [Hash] params unified chat parmeters from [Langchain::LLM::Parameters::Chat::SCHEMA]
|
163
|
+
# @option params [String] :model Model name
|
164
|
+
# @option params [Array<Hash>] :messages Array of messages
|
165
|
+
# @option params [String] :format Format to return a response in. Currently the only accepted value is `json`
|
166
|
+
# @option params [Float] :temperature The temperature to use
|
167
|
+
# @option params [String] :template The prompt template to use (overrides what is defined in the `Modelfile`)
|
168
|
+
# @option params [Boolean] :stream Streaming the response. If false the response will be returned as a single response object, rather than a stream of objects
|
159
169
|
#
|
160
170
|
# The message object has the following fields:
|
161
171
|
# role: the role of the message, either system, user or assistant
|
162
172
|
# content: the content of the message
|
163
173
|
# images (optional): a list of images to include in the message (for multimodal models such as llava)
|
164
|
-
def chat(
|
165
|
-
|
166
|
-
messages: [],
|
167
|
-
format: nil,
|
168
|
-
temperature: defaults[:temperature],
|
169
|
-
template: nil,
|
170
|
-
stream: false # TODO: Fix streaming.
|
171
|
-
)
|
172
|
-
parameters = {
|
173
|
-
model: model,
|
174
|
-
messages: messages,
|
175
|
-
format: format,
|
176
|
-
temperature: temperature,
|
177
|
-
template: template,
|
178
|
-
stream: stream
|
179
|
-
}.compact
|
174
|
+
def chat(params = {})
|
175
|
+
parameters = chat_parameters.to_params(params)
|
180
176
|
|
181
177
|
response = client.post("api/chat") do |req|
|
182
178
|
req.body = parameters
|
data/lib/langchain/llm/openai.rb
CHANGED
@@ -40,6 +40,15 @@ module Langchain::LLM
|
|
40
40
|
@client = ::OpenAI::Client.new(access_token: api_key, **llm_options)
|
41
41
|
|
42
42
|
@defaults = DEFAULTS.merge(default_options)
|
43
|
+
chat_parameters.update(
|
44
|
+
model: {default: @defaults[:chat_completion_model_name]},
|
45
|
+
logprobs: {},
|
46
|
+
top_logprobs: {},
|
47
|
+
n: {default: @defaults[:n]},
|
48
|
+
temperature: {default: @defaults[:temperature]},
|
49
|
+
user: {}
|
50
|
+
)
|
51
|
+
chat_parameters.ignore(:top_k)
|
43
52
|
end
|
44
53
|
|
45
54
|
# Generate an embedding for a given text
|
@@ -102,54 +111,17 @@ module Langchain::LLM
|
|
102
111
|
|
103
112
|
# Generate a chat completion for given messages.
|
104
113
|
#
|
105
|
-
# @param
|
106
|
-
# @
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
presence_penalty: nil,
|
117
|
-
response_format: nil,
|
118
|
-
seed: nil,
|
119
|
-
stop: nil,
|
120
|
-
stream: nil,
|
121
|
-
temperature: defaults[:temperature],
|
122
|
-
top_p: nil,
|
123
|
-
tools: [],
|
124
|
-
tool_choice: nil,
|
125
|
-
user: nil,
|
126
|
-
&block
|
127
|
-
)
|
128
|
-
raise ArgumentError.new("messages argument is required") if messages.empty?
|
129
|
-
raise ArgumentError.new("model argument is required") if model.empty?
|
130
|
-
raise ArgumentError.new("'tool_choice' is only allowed when 'tools' are specified.") if tool_choice && tools.empty?
|
131
|
-
|
132
|
-
parameters = {
|
133
|
-
messages: messages,
|
134
|
-
model: model
|
135
|
-
}
|
136
|
-
parameters[:frequency_penalty] = frequency_penalty if frequency_penalty
|
137
|
-
parameters[:logit_bias] = logit_bias if logit_bias
|
138
|
-
parameters[:logprobs] = logprobs if logprobs
|
139
|
-
parameters[:top_logprobs] = top_logprobs if top_logprobs
|
140
|
-
# TODO: Fix max_tokens validation to account for tools/functions
|
141
|
-
parameters[:max_tokens] = max_tokens if max_tokens # || validate_max_tokens(parameters[:messages], parameters[:model])
|
142
|
-
parameters[:n] = n if n
|
143
|
-
parameters[:presence_penalty] = presence_penalty if presence_penalty
|
144
|
-
parameters[:response_format] = response_format if response_format
|
145
|
-
parameters[:seed] = seed if seed
|
146
|
-
parameters[:stop] = stop if stop
|
147
|
-
parameters[:stream] = stream if stream
|
148
|
-
parameters[:temperature] = temperature if temperature
|
149
|
-
parameters[:top_p] = top_p if top_p
|
150
|
-
parameters[:tools] = tools if tools.any?
|
151
|
-
parameters[:tool_choice] = tool_choice if tool_choice
|
152
|
-
parameters[:user] = user if user
|
114
|
+
# @param [Hash] params unified chat parmeters from [Langchain::LLM::Parameters::Chat::SCHEMA]
|
115
|
+
# @option params [Array<Hash>] :messages List of messages comprising the conversation so far
|
116
|
+
# @option params [String] :model ID of the model to use
|
117
|
+
def chat(params = {}, &block)
|
118
|
+
parameters = chat_parameters.to_params(params)
|
119
|
+
|
120
|
+
raise ArgumentError.new("messages argument is required") if Array(parameters[:messages]).empty?
|
121
|
+
raise ArgumentError.new("model argument is required") if parameters[:model].to_s.empty?
|
122
|
+
if parameters[:tool_choice] && Array(parameters[:tools]).empty?
|
123
|
+
raise ArgumentError.new("'tool_choice' is only allowed when 'tools' are specified.")
|
124
|
+
end
|
153
125
|
|
154
126
|
# TODO: Clean this part up
|
155
127
|
if block
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "delegate"
|
4
|
+
|
5
|
+
module Langchain::LLM::Parameters
|
6
|
+
class Chat < SimpleDelegator
|
7
|
+
# TODO: At the moment, the UnifiedParamters only considers keys. In the
|
8
|
+
# future, we may consider ActiveModel-style validations and further typed
|
9
|
+
# options here.
|
10
|
+
SCHEMA = {
|
11
|
+
# Either "messages" or "prompt" is required
|
12
|
+
messages: {},
|
13
|
+
model: {},
|
14
|
+
prompt: {},
|
15
|
+
|
16
|
+
# System instructions. Used by Cohere, Anthropic and Google Gemini.
|
17
|
+
system: {},
|
18
|
+
|
19
|
+
# Allows to force the model to produce specific output format.
|
20
|
+
response_format: {},
|
21
|
+
|
22
|
+
stop: {}, # multiple types (e.g. OpenAI also allows Array, null)
|
23
|
+
stream: {}, # Enable streaming
|
24
|
+
|
25
|
+
max_tokens: {}, # Range: [1, context_length)
|
26
|
+
temperature: {}, # Range: [0, 2]
|
27
|
+
top_p: {}, # Range: (0, 1]
|
28
|
+
top_k: {}, # Range: [1, Infinity) Not available for OpenAI models
|
29
|
+
frequency_penalty: {}, # Range: [-2, 2]
|
30
|
+
presence_penalty: {}, # Range: [-2, 2]
|
31
|
+
repetition_penalty: {}, # Range: (0, 2]
|
32
|
+
seed: {}, # OpenAI only
|
33
|
+
|
34
|
+
# Function-calling
|
35
|
+
tools: {default: []},
|
36
|
+
tool_choice: {},
|
37
|
+
|
38
|
+
# Additional optional parameters
|
39
|
+
logit_bias: {}
|
40
|
+
}
|
41
|
+
|
42
|
+
def initialize(parameters: {})
|
43
|
+
super(
|
44
|
+
::Langchain::LLM::UnifiedParameters.new(
|
45
|
+
schema: SCHEMA.dup,
|
46
|
+
parameters: parameters
|
47
|
+
)
|
48
|
+
)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -45,14 +45,14 @@ module Langchain
|
|
45
45
|
|
46
46
|
# Return the completion candidates
|
47
47
|
#
|
48
|
-
# @return [Array]
|
48
|
+
# @return [Array<String>]
|
49
49
|
def completions
|
50
50
|
raise NotImplementedError
|
51
51
|
end
|
52
52
|
|
53
53
|
# Return the chat completion candidates
|
54
54
|
#
|
55
|
-
# @return [Array]
|
55
|
+
# @return [Array<String>]
|
56
56
|
def chat_completions
|
57
57
|
raise NotImplementedError
|
58
58
|
end
|
@@ -17,5 +17,21 @@ module Langchain::LLM
|
|
17
17
|
def completion
|
18
18
|
completions&.dig(0, "text")
|
19
19
|
end
|
20
|
+
|
21
|
+
def chat_completion
|
22
|
+
raw_response.dig("text")
|
23
|
+
end
|
24
|
+
|
25
|
+
def role
|
26
|
+
raw_response.dig("chat_history").last["role"]
|
27
|
+
end
|
28
|
+
|
29
|
+
def prompt_tokens
|
30
|
+
raw_response.dig("meta", "billed_units", "input_tokens")
|
31
|
+
end
|
32
|
+
|
33
|
+
def completion_tokens
|
34
|
+
raw_response.dig("meta", "billed_units", "output_tokens")
|
35
|
+
end
|
20
36
|
end
|
21
37
|
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Langchain::LLM
|
4
|
+
class UnifiedParameters
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
attr_reader :schema, :aliases, :parameters, :ignored, :remapped
|
8
|
+
|
9
|
+
class Null < self
|
10
|
+
def initialize(parameters: {})
|
11
|
+
super(schema: {}, parameters: parameters)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(schema:, parameters: {})
|
16
|
+
@schema = schema || {}
|
17
|
+
@aliases = {}
|
18
|
+
@remapped = {}
|
19
|
+
@ignored = Set.new
|
20
|
+
@schema.each do |name, param|
|
21
|
+
@aliases[name] = Set.new(Array(param[:aliases])) if param[:aliases]
|
22
|
+
end
|
23
|
+
@parameters = to_params(parameters.to_h) if !parameters.to_h.empty?
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_params(params = {})
|
27
|
+
# if params are provided, reset any previously initialized
|
28
|
+
@parameters = params if !params.empty?
|
29
|
+
@parameters = (@parameters || {}).merge!(params).slice(*schema.keys)
|
30
|
+
@aliases.each do |field, aliased_keys|
|
31
|
+
# favor existing keys in case of conflicts,
|
32
|
+
# and check for multiples
|
33
|
+
aliased_keys.each do |alias_key|
|
34
|
+
@parameters[field] ||= params[alias_key] if value_present?(params[alias_key])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
@schema.each do |field, param_options|
|
38
|
+
param_options ||= {}
|
39
|
+
default = param_options[:default]
|
40
|
+
@parameters[field] ||= default if value_present?(default)
|
41
|
+
end
|
42
|
+
@remapped.each do |field, renamed_field|
|
43
|
+
@parameters[renamed_field] = @parameters[field] if value_present?(@parameters[field])
|
44
|
+
end
|
45
|
+
@parameters = @parameters.except(*@ignored + @remapped.keys)
|
46
|
+
end
|
47
|
+
|
48
|
+
def remap(field_map)
|
49
|
+
@remapped ||= {}
|
50
|
+
@remapped.merge!(field_map)
|
51
|
+
field_map.each do |field, renamed_field|
|
52
|
+
@schema[renamed_field] = @schema[field]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def update(schema = {})
|
57
|
+
@schema.merge!(schema)
|
58
|
+
schema.each do |name, param|
|
59
|
+
if param[:aliases]
|
60
|
+
@aliases[name] ||= Set.new
|
61
|
+
@aliases[name] << param[:aliases]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
67
|
+
def ignore(*field_names)
|
68
|
+
@ignored.merge(field_names)
|
69
|
+
end
|
70
|
+
|
71
|
+
def alias_field(field_name, as:)
|
72
|
+
@aliases[field_name] ||= Set.new
|
73
|
+
@aliases[field_name] << as
|
74
|
+
end
|
75
|
+
|
76
|
+
def to_h
|
77
|
+
@parameters.to_h
|
78
|
+
end
|
79
|
+
|
80
|
+
def each(&)
|
81
|
+
to_params.each(&)
|
82
|
+
end
|
83
|
+
|
84
|
+
def <=>(other)
|
85
|
+
to_params.<=>(other.to_params)
|
86
|
+
end
|
87
|
+
|
88
|
+
def [](key)
|
89
|
+
to_params[key]
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def value_present?(value)
|
95
|
+
!value.nil? && (!value.is_a?(Enumerable) || !value.empty?)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/langchain/loader.rb
CHANGED
@@ -29,9 +29,11 @@ module Langchain
|
|
29
29
|
# @param path [String | Pathname] path to file or URL
|
30
30
|
# @param options [Hash] options passed to the processor class used to process the data
|
31
31
|
# @return [Data] data loaded from path
|
32
|
+
# rubocop:disable Style/ArgumentsForwarding
|
32
33
|
def self.load(path, options = {}, &block)
|
33
34
|
new(path, options).load(&block)
|
34
35
|
end
|
36
|
+
# rubocop:enable Style/ArgumentsForwarding
|
35
37
|
|
36
38
|
# Initialize Langchain::Loader
|
37
39
|
# @param path [String | Pathname] path to file or URL
|
@@ -76,12 +78,14 @@ module Langchain
|
|
76
78
|
# @yieldreturn [String] parsed data, as a String
|
77
79
|
#
|
78
80
|
# @return [Data] data that was loaded
|
81
|
+
# rubocop:disable Style/ArgumentsForwarding
|
79
82
|
def load(&block)
|
80
83
|
return process_data(load_from_url, &block) if url?
|
81
84
|
return load_from_directory(&block) if directory?
|
82
85
|
|
83
86
|
process_data(load_from_path, &block)
|
84
87
|
end
|
88
|
+
# rubocop:enable Style/ArgumentsForwarding
|
85
89
|
|
86
90
|
private
|
87
91
|
|
@@ -95,6 +99,7 @@ module Langchain
|
|
95
99
|
raise FileNotFound, "File #{@path} does not exist"
|
96
100
|
end
|
97
101
|
|
102
|
+
# rubocop:disable Style/ArgumentsForwarding
|
98
103
|
def load_from_directory(&block)
|
99
104
|
Dir.glob(File.join(@path, "**/*")).map do |file|
|
100
105
|
# Only load and add to result files with supported extensions
|
@@ -103,6 +108,7 @@ module Langchain
|
|
103
108
|
UnknownFormatError nil
|
104
109
|
end.flatten.compact
|
105
110
|
end
|
111
|
+
# rubocop:enable Style/ArgumentsForwarding
|
106
112
|
|
107
113
|
def process_data(data, &block)
|
108
114
|
@raw_data = data
|
data/lib/langchain/tool/base.rb
CHANGED
@@ -3,13 +3,13 @@
|
|
3
3
|
module Langchain::Tool
|
4
4
|
# = Tools
|
5
5
|
#
|
6
|
-
# Tools are used by Agents to perform specific tasks.
|
6
|
+
# Tools are used by Agents to perform specific tasks. A 'Tool' is a collection of functions ("methods").
|
7
7
|
#
|
8
8
|
# == Available Tools
|
9
9
|
#
|
10
10
|
# - {Langchain::Tool::Calculator}: calculate the result of a math expression
|
11
11
|
# - {Langchain::Tool::Database}: executes SQL queries
|
12
|
-
# - {Langchain::Tool::FileSystem}: interacts with
|
12
|
+
# - {Langchain::Tool::FileSystem}: interacts with the file system
|
13
13
|
# - {Langchain::Tool::GoogleSearch}: search on Google (via SerpAPI)
|
14
14
|
# - {Langchain::Tool::RubyCodeInterpreter}: runs ruby code
|
15
15
|
# - {Langchain::Tool::Weather}: gets current weather data
|
@@ -42,10 +42,10 @@ module Langchain::Tool
|
|
42
42
|
#
|
43
43
|
# == Adding Tools
|
44
44
|
#
|
45
|
-
# 1. Create a new
|
46
|
-
# 2.
|
45
|
+
# 1. Create a new folder in lib/langchain/tool/your_tool_name/
|
46
|
+
# 2. Inside of this folder create a file with a class YourToolName that inherits from {Langchain::Tool::Base}
|
47
47
|
# 3. Add `NAME=` and `ANNOTATIONS_PATH=` constants in your Tool class
|
48
|
-
# 4. Implement various methods in your tool class
|
48
|
+
# 4. Implement various public methods in your tool class
|
49
49
|
# 5. Create a sidecar .json file in the same directory as your tool file annotating the methods in the Open API format
|
50
50
|
# 6. Add your tool to the {file:README.md}
|
51
51
|
class Base
|
@@ -28,10 +28,11 @@ module Langchain
|
|
28
28
|
"text-embedding-3-large" => 8191,
|
29
29
|
"text-embedding-3-small" => 8191,
|
30
30
|
"text-embedding-ada-002" => 8191,
|
31
|
-
"gpt-3.5-turbo" =>
|
31
|
+
"gpt-3.5-turbo" => 16385,
|
32
32
|
"gpt-3.5-turbo-0301" => 4096,
|
33
33
|
"gpt-3.5-turbo-0613" => 4096,
|
34
34
|
"gpt-3.5-turbo-1106" => 16385,
|
35
|
+
"gpt-3.5-turbo-0125" => 16385,
|
35
36
|
"gpt-3.5-turbo-16k" => 16384,
|
36
37
|
"gpt-3.5-turbo-16k-0613" => 16384,
|
37
38
|
"text-davinci-003" => 4097,
|
@@ -44,9 +45,13 @@ module Langchain
|
|
44
45
|
"gpt-4-32k-0314" => 32768,
|
45
46
|
"gpt-4-32k-0613" => 32768,
|
46
47
|
"gpt-4-1106-preview" => 128000,
|
48
|
+
"gpt-4-turbo" => 128000,
|
49
|
+
"gpt-4-turbo-2024-04-09" => 128000,
|
47
50
|
"gpt-4-turbo-preview" => 128000,
|
48
51
|
"gpt-4-0125-preview" => 128000,
|
49
52
|
"gpt-4-vision-preview" => 128000,
|
53
|
+
"gpt-4o" => 128000,
|
54
|
+
"gpt-4o-2024-05-13" => 128000,
|
50
55
|
"text-curie-001" => 2049,
|
51
56
|
"text-babbage-001" => 2049,
|
52
57
|
"text-ada-001" => 2049,
|
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.12.
|
4
|
+
version: 0.12.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrei Bondarev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-05-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -238,16 +238,16 @@ dependencies:
|
|
238
238
|
name: anthropic
|
239
239
|
requirement: !ruby/object:Gem::Requirement
|
240
240
|
requirements:
|
241
|
-
- - "
|
241
|
+
- - "~>"
|
242
242
|
- !ruby/object:Gem::Version
|
243
|
-
version: '0'
|
243
|
+
version: '0.2'
|
244
244
|
type: :development
|
245
245
|
prerelease: false
|
246
246
|
version_requirements: !ruby/object:Gem::Requirement
|
247
247
|
requirements:
|
248
|
-
- - "
|
248
|
+
- - "~>"
|
249
249
|
- !ruby/object:Gem::Version
|
250
|
-
version: '0'
|
250
|
+
version: '0.2'
|
251
251
|
- !ruby/object:Gem::Dependency
|
252
252
|
name: aws-sdk-bedrockruntime
|
253
253
|
requirement: !ruby/object:Gem::Requirement
|
@@ -282,14 +282,14 @@ dependencies:
|
|
282
282
|
requirements:
|
283
283
|
- - "~>"
|
284
284
|
- !ruby/object:Gem::Version
|
285
|
-
version: 0.9.
|
285
|
+
version: 0.9.10
|
286
286
|
type: :development
|
287
287
|
prerelease: false
|
288
288
|
version_requirements: !ruby/object:Gem::Requirement
|
289
289
|
requirements:
|
290
290
|
- - "~>"
|
291
291
|
- !ruby/object:Gem::Version
|
292
|
-
version: 0.9.
|
292
|
+
version: 0.9.10
|
293
293
|
- !ruby/object:Gem::Dependency
|
294
294
|
name: docx
|
295
295
|
requirement: !ruby/object:Gem::Requirement
|
@@ -742,6 +742,7 @@ files:
|
|
742
742
|
- lib/langchain/llm/mistral_ai.rb
|
743
743
|
- lib/langchain/llm/ollama.rb
|
744
744
|
- lib/langchain/llm/openai.rb
|
745
|
+
- lib/langchain/llm/parameters/chat.rb
|
745
746
|
- lib/langchain/llm/prompts/ollama/summarize_template.yaml
|
746
747
|
- lib/langchain/llm/prompts/summarize_template.yaml
|
747
748
|
- lib/langchain/llm/replicate.rb
|
@@ -758,6 +759,7 @@ files:
|
|
758
759
|
- lib/langchain/llm/response/ollama_response.rb
|
759
760
|
- lib/langchain/llm/response/openai_response.rb
|
760
761
|
- lib/langchain/llm/response/replicate_response.rb
|
762
|
+
- lib/langchain/llm/unified_parameters.rb
|
761
763
|
- lib/langchain/loader.rb
|
762
764
|
- lib/langchain/output_parsers/base.rb
|
763
765
|
- lib/langchain/output_parsers/output_fixing_parser.rb
|