langchainrb 0.12.0 → 0.12.1

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 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