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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7f29aad35bc35dc95eb8673b11578b51c7449a19818989d9da5e640c6fb219c7
4
- data.tar.gz: 4d0c4d3d424a82c7f02fb9e49ca52a5bdca5dfbce19fbfa22f2d74ef46d81eb7
3
+ metadata.gz: 6f106f178a5641f17ca723eec7272d120fbdd0e3046e44152eaf575af2985724
4
+ data.tar.gz: 417d5b671a6783d0854c05c43871b1e931133eaf65e6d39ac6ac4989a0124e36
5
5
  SHA512:
6
- metadata.gz: 91b6f4fc5056308eab9119dcfda1be16857e6e9e6e531977148b1e8f31b72090794b67e6855afb95633b8f836b8d20921bc5a069afdc745d1114892143a177e1
7
- data.tar.gz: f7a7949ab2efd960eacf3a93f7beaa9104403a93619b8c95ea094901c2d3d19b89980c81d293ae16035c5ff51fe021a09f2e81e2c0ed6854bff87d30e6def925
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 messages [Array<String>] Input messages
85
- # @param model [String] The model that will complete your prompt
86
- # @param max_tokens [Integer] Maximum number of tokens to generate before stopping
87
- # @param metadata [Hash] Object describing metadata about the request
88
- # @param stop_sequences [Array<String>] Custom text sequences that will cause the model to stop generating
89
- # @param stream [Boolean] Whether to incrementally stream the response using server-sent events
90
- # @param system [String] System prompt
91
- # @param temperature [Float] Amount of randomness injected into the response
92
- # @param tools [Array<String>] Definitions of tools that the model may use
93
- # @param top_k [Integer] Only sample from the top K options for each subsequent token
94
- # @param top_p [Float] Use nucleus sampling.
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
- messages: [],
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
- parameters = {
114
- messages: messages,
115
- model: model,
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
- # @param messages [Array] The messages to generate a completion for
117
- # @param system [String] The system prompt to provide instructions
118
- # @param model [String] The model to use for completion defaults to @defaults[:chat_completion_model_name]
119
- # @param max_tokens [Integer] The maximum number of tokens to generate
120
- # @param stop_sequences [Array] The stop sequences to use for completion
121
- # @param temperature [Float] The temperature to use for completion
122
- # @param top_p [Float] The top p to use for completion
123
- # @param top_k [Integer] The top k to use for completion
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
- messages: [],
127
- system: nil,
128
- model: defaults[:completion_model_name],
129
- max_tokens: defaults[:max_tokens_to_sample],
130
- stop_sequences: nil,
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: inference_parameters.to_json,
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
  })
@@ -32,6 +32,12 @@ module Langchain::LLM
32
32
  **llm_options
33
33
  )
34
34
  @defaults = DEFAULTS.merge(default_options)
35
+ chat_parameters.update(
36
+ logprobs: {},
37
+ top_logprobs: {},
38
+ user: {}
39
+ )
40
+ chat_parameters.ignore(:top_k)
35
41
  end
36
42
 
37
43
  def embed(...)
@@ -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
@@ -8,22 +8,34 @@ module Langchain::LLM
8
8
  # gem "cohere-ruby", "~> 0.9.6"
9
9
  #
10
10
  # Usage:
11
- # cohere = Langchain::LLM::Cohere.new(api_key: ENV["COHERE_API_KEY"])
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, default_options = {})
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
- # TODO: Implement chat method: https://github.com/andreibondarev/cohere-ruby/issues/11
72
- # def chat
73
- # end
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
- messages:,
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(params)
38
+ response = client.chat_completions(parameters)
48
39
 
49
40
  Langchain::LLM::MistralAIResponse.new(response.to_h)
50
41
  end
@@ -7,22 +7,24 @@ module Langchain::LLM
7
7
  # Available models: https://ollama.ai/library
8
8
  #
9
9
  # Usage:
10
- # ollama = Langchain::LLM::Ollama.new(url: ENV["OLLAMA_URL"], default_options: {})
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: "llama2",
18
- embeddings_model_name: "llama2",
19
- chat_completion_model_name: "llama2"
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:, default_options: {})
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 model [String] Model name
154
- # @param messages [Array<Hash>] Array of messages
155
- # @param format [String] Format to return a response in. Currently the only accepted value is `json`
156
- # @param temperature [Float] The temperature to use
157
- # @param template [String] The prompt template to use (overrides what is defined in the `Modelfile`)
158
- # @param stream [Boolean] Streaming the response. If false the response will be returned as a single response object, rather than a stream of objects
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
- model: defaults[:chat_completion_model_name],
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
@@ -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 messages [Array<Hash>] List of messages comprising the conversation so far
106
- # @param model [String] ID of the model to use
107
- def chat(
108
- messages: [],
109
- model: defaults[:chat_completion_model_name],
110
- frequency_penalty: nil,
111
- logit_bias: nil,
112
- logprobs: nil,
113
- top_logprobs: nil,
114
- max_tokens: nil,
115
- n: defaults[:n],
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
@@ -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
@@ -3,13 +3,13 @@
3
3
  module Langchain::Tool
4
4
  # = Tools
5
5
  #
6
- # Tools are used by Agents to perform specific tasks. Basically anything is possible with enough code!
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 files
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 file in lib/langchain/tool/your_tool_name.rb
46
- # 2. Create a class in the file that inherits from {Langchain::Tool::Base}
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" => 4096,
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,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Langchain
4
- VERSION = "0.12.0"
4
+ VERSION = "0.12.1"
5
5
  end
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.0
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-04-22 00:00:00.000000000 Z
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.8
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.8
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