langchainrb 0.15.0 → 0.15.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: dde504e05b1cbb32c857569bf71301537fed2deb468f1bdd69a7ef900a41c085
4
- data.tar.gz: '08659cddd6f0bb285e167c7a35dbd2f83c2e9bb51a69206217ea91649e99839c'
3
+ metadata.gz: a8a7ebf84076b609719daddc97e448f4d4fe987e8ee1eeaddb70df667f163d02
4
+ data.tar.gz: d52a9619b5913e8ce51563697e38841f9798e04f3caf294d7f331ff159eb70cb
5
5
  SHA512:
6
- metadata.gz: ce4dd091498659a2d8dda4b54e9e9584dc19be5f390dc5f1d98efa054a264134dc3510f2f83c65bdf23edfbd7344587b91113e69c2ea1fea2cdc157317735799
7
- data.tar.gz: a6df110aa7d96c87402164f67aadab0a97e2a62b68b7466cf630fe79dd0611a1740ae11163361eef9c98fc816f7ba12d7bfc0aa2225759cc8191f59fead8fcbd
6
+ metadata.gz: 2354d82608942a1744be426f23277b18fee508f539613327c9ed6f784d7da18f317d2266d356f3124eef93ea5052fe237f3fc639ff56db4b86060b08f16df1d2
7
+ data.tar.gz: 282873b85e832e9a872f007a5a6bf35400e22639c5c7f26ac535da4f06370f35d6de35a44d434ec81fedfcff1143a448440cf8bf76ae38e01d0ad5ec15f08dc7
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.15.1] - 2024-08-19
4
+ - Drop `to_bool` gem in favour of custom util class
5
+ - Drop `colorize` which is GPL-licensed in favour of `rainbow`
6
+ - Improve Langchain::Tool::Weather tool
7
+
3
8
  ## [0.15.0] - 2024-08-14
4
9
  - Fix Langchain::Assistant when llm is Anthropic
5
10
  - Fix GoogleGemini#chat method
@@ -135,7 +140,7 @@
135
140
  - AWS Bedrock is available as an LLM provider. Available models from AI21, Cohere, AWS, and Anthropic.
136
141
 
137
142
  ## [0.7.3] - 2023-11-08
138
- - LLM response passes through the context in RAG cases
143
+ - LLM response passes through the context in RAG cases
139
144
  - Fix gpt-4 token length validation
140
145
 
141
146
  ## [0.7.2] - 2023-11-02
@@ -180,7 +185,7 @@
180
185
 
181
186
  ## [0.6.13] - 2023-08-23
182
187
  - Add `k:` parameter to all `ask()` vector search methods
183
- - Bump Faraday to 2.x
188
+ - Bump Faraday to 2.x
184
189
 
185
190
  ## [0.6.12] - 2023-08-13
186
191
 
@@ -42,13 +42,13 @@ module Langchain
42
42
  for_class_name = for_class&.name
43
43
 
44
44
  log_line_parts = []
45
- log_line_parts << "[Langchain.rb]".colorize(color: :yellow)
45
+ log_line_parts << colorize("[Langchain.rb]", color: :yellow)
46
46
  log_line_parts << if for_class.respond_to?(:logger_options)
47
- "[#{for_class_name}]".colorize(for_class.logger_options) + ":"
47
+ colorize("[#{for_class_name}]", for_class.logger_options) + ":"
48
48
  elsif for_class_name
49
49
  "[#{for_class_name}]:"
50
50
  end
51
- log_line_parts << args.first.colorize(MESSAGE_COLOR_OPTIONS[method])
51
+ log_line_parts << colorize(args.first, MESSAGE_COLOR_OPTIONS[method])
52
52
  log_line = log_line_parts.compact.join(" ")
53
53
 
54
54
  @logger.send(
@@ -56,5 +56,11 @@ module Langchain
56
56
  log_line
57
57
  )
58
58
  end
59
+
60
+ private
61
+
62
+ def colorize(line, options)
63
+ Langchain::Utils::Colorizer.colorize(line, options)
64
+ end
59
65
  end
60
66
  end
@@ -47,7 +47,7 @@ module Langchain
47
47
  verdicts = match.captures.first
48
48
  verdicts
49
49
  .split(".")
50
- .count { |value| value.strip.to_boolean }
50
+ .count { |value| to_boolean(value.strip) }
51
51
  end
52
52
 
53
53
  def statements_verification(statements:, context:)
@@ -79,6 +79,10 @@ module Langchain
79
79
  file_path: Langchain.root.join("langchain/evals/ragas/prompts/faithfulness_statements_extraction.yml")
80
80
  )
81
81
  end
82
+
83
+ def to_boolean(value)
84
+ Langchain::Utils::ToBoolean.new.to_bool(value)
85
+ end
82
86
  end
83
87
  end
84
88
  end
@@ -7,53 +7,103 @@ module Langchain::Tool
7
7
  # Current weather data is free for 1000 calls per day (https://home.openweathermap.org/api_keys)
8
8
  # Forecast and historical data require registration with credit card, so not supported yet.
9
9
  #
10
- # Gem requirements:
11
- # gem "open-weather-ruby-client", "~> 0.3.0"
12
- # api_key: https://home.openweathermap.org/api_keys
13
- #
14
10
  # Usage:
15
11
  # weather = Langchain::Tool::Weather.new(api_key: ENV["OPEN_WEATHER_API_KEY"])
16
- # weather.execute(input: "Boston, MA; imperial")
12
+ # assistant = Langchain::Assistant.new(
13
+ # llm: llm,
14
+ # tools: [weather]
15
+ # )
17
16
  #
18
17
  class Weather
19
18
  extend Langchain::ToolDefinition
20
- include Langchain::DependencyHelper
21
19
 
22
- define_function :execute, description: "Returns current weather for a city" do
23
- property :input, type: "string", description: "Comma separated city and unit (optional: imperial, metric, or standard)", required: true
20
+ define_function :get_current_weather, description: "Returns current weather for a city" do
21
+ property :city,
22
+ type: "string",
23
+ description: "City name",
24
+ required: true
25
+ property :state_code,
26
+ type: "string",
27
+ description: "State code",
28
+ required: true
29
+ property :country_code,
30
+ type: "string",
31
+ description: "Country code",
32
+ required: false
33
+ property :units,
34
+ type: "string",
35
+ description: "Units for temperature (imperial or metric). Default: \"imperial\"",
36
+ enum: ["imperial", "metric", "standard"],
37
+ required: false
24
38
  end
25
39
 
26
- attr_reader :client, :units
40
+ def initialize(api_key:)
41
+ @api_key = api_key
42
+ end
27
43
 
28
- # Initializes the Weather tool
29
- #
30
- # @param api_key [String] Open Weather API key
31
- # @return [Langchain::Tool::Weather] Weather tool
32
- def initialize(api_key:, units: "metric")
33
- depends_on "open-weather-ruby-client"
34
- require "open-weather-ruby-client"
44
+ def get_current_weather(city:, state_code:, country_code: nil, units: "imperial")
45
+ validate_input(city: city, state_code: state_code, country_code: country_code, units: units)
35
46
 
36
- OpenWeather::Client.configure do |config|
37
- config.api_key = api_key
38
- config.user_agent = "Langchainrb Ruby Client"
39
- end
47
+ Langchain.logger.info("get_current_weather", for: self.class, city:, state_code:, country_code:, units:)
40
48
 
41
- @client = OpenWeather::Client.new
49
+ fetch_current_weather(city: city, state_code: state_code, country_code: country_code, units: units)
42
50
  end
43
51
 
44
- # Returns current weather for a city
45
- #
46
- # @param input [String] comma separated city and unit (optional: imperial, metric, or standard)
47
- # @return [String] Answer
48
- def execute(input:)
49
- Langchain.logger.info("Executing for \"#{input}\"", for: self.class)
52
+ private
53
+
54
+ def fetch_current_weather(city:, state_code:, country_code:, units:)
55
+ params = {appid: @api_key, q: [city, state_code, country_code].compact.join(","), units: units}
56
+
57
+ location_response = send_request(path: "geo/1.0/direct", params: params.except(:units))
58
+ return location_response if location_response.is_a?(String) # Error occurred
59
+
60
+ location = location_response.first
61
+ return "Location not found" unless location
62
+
63
+ params = params.merge(lat: location["lat"], lon: location["lon"]).except(:q)
64
+ weather_data = send_request(path: "data/2.5/weather", params: params)
65
+
66
+ parse_weather_response(weather_data, units)
67
+ end
50
68
 
51
- input_array = input.split(";")
52
- city, units = *input_array.map(&:strip)
69
+ def send_request(path:, params:)
70
+ uri = URI.parse("https://api.openweathermap.org/#{path}?#{URI.encode_www_form(params)}")
71
+ http = Net::HTTP.new(uri.host, uri.port)
72
+ http.use_ssl = true
53
73
 
54
- data = client.current_weather(city: city, units: units)
55
- weather = data.main.map { |key, value| "#{key} #{value}" }.join(", ")
56
- "The current weather in #{data.name} is #{weather}"
74
+ request = Net::HTTP::Get.new(uri.request_uri)
75
+ request["Content-Type"] = "application/json"
76
+
77
+ Langchain.logger.info("Sending request to OpenWeatherMap API", path: path, params: params.except(:appid))
78
+ response = http.request(request)
79
+ Langchain.logger.info("Received response from OpenWeatherMap API", status: response.code)
80
+
81
+ if response.code == "200"
82
+ JSON.parse(response.body)
83
+ else
84
+ "API request failed: #{response.code} - #{response.message}"
85
+ end
86
+ end
87
+
88
+ def validate_input(city:, state_code:, country_code:, units:)
89
+ raise ArgumentError, "City name cannot be empty" if city.to_s.strip.empty?
90
+ raise ArgumentError, "State code cannot be empty" if state_code.to_s.strip.empty?
91
+ raise ArgumentError, "Invalid units. Use \"imperial\", \"standard\" or \"metric\"" unless ["imperial", "metric", "standard"].include?(units)
92
+ end
93
+
94
+ def parse_weather_response(response, units)
95
+ temp_unit = case units
96
+ when "standard" then "K"
97
+ when "metric" then "°C"
98
+ when "imperial" then "°F"
99
+ end
100
+ speed_unit = (units == "imperial") ? "mph" : "m/s"
101
+ {
102
+ temperature: "#{response["main"]["temp"]} #{temp_unit}",
103
+ humidity: "#{response["main"]["humidity"]}%",
104
+ description: response["weather"][0]["description"],
105
+ wind_speed: "#{response["wind"]["speed"]} #{speed_unit}"
106
+ }
57
107
  end
58
108
  end
59
109
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Langchain
4
+ module Utils
5
+ class Colorizer
6
+ def self.colorize(line, options)
7
+ decorated_line = Rainbow(line)
8
+ options.each_pair.each do |modifier, value|
9
+ decorated_line = if modifier == :mode
10
+ decorated_line.public_send(value)
11
+ else
12
+ decorated_line.public_send(modifier, value)
13
+ end
14
+ end
15
+ decorated_line
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Langchain
4
+ module Utils
5
+ class ToBoolean
6
+ TRUTHABLE_STRINGS = %w[1 true t yes y]
7
+ private_constant :TRUTHABLE_STRINGS
8
+
9
+ def to_bool(value)
10
+ case value
11
+ when String
12
+ TRUTHABLE_STRINGS.include?(value.downcase)
13
+ when Integer
14
+ value == 1
15
+ when TrueClass
16
+ true
17
+ when FalseClass
18
+ false
19
+ when Symbol
20
+ to_bool(value.to_s)
21
+ else
22
+ false
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Langchain
4
- VERSION = "0.15.0"
4
+ VERSION = "0.15.1"
5
5
  end
data/lib/langchain.rb CHANGED
@@ -2,8 +2,7 @@
2
2
 
3
3
  require "logger"
4
4
  require "pathname"
5
- require "colorize"
6
- require "to_bool"
5
+ require "rainbow"
7
6
  require "zeitwerk"
8
7
  loader = Zeitwerk::Loader.for_gem
9
8
  loader.ignore("#{__dir__}/langchainrb.rb")
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.15.0
4
+ version: 0.15.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-08-14 00:00:00.000000000 Z
11
+ date: 2024-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: baran
@@ -25,19 +25,19 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.1.9
27
27
  - !ruby/object:Gem::Dependency
28
- name: colorize
28
+ name: rainbow
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.1.0
33
+ version: 3.1.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 1.1.0
40
+ version: 3.1.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: json-schema
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -80,20 +80,6 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: 0.3.0
83
- - !ruby/object:Gem::Dependency
84
- name: to_bool
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: 2.0.0
90
- type: :runtime
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: 2.0.0
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: matrix
99
85
  requirement: !ruby/object:Gem::Requirement
@@ -472,20 +458,6 @@ dependencies:
472
458
  - - ">="
473
459
  - !ruby/object:Gem::Version
474
460
  version: '0'
475
- - !ruby/object:Gem::Dependency
476
- name: open-weather-ruby-client
477
- requirement: !ruby/object:Gem::Requirement
478
- requirements:
479
- - - "~>"
480
- - !ruby/object:Gem::Version
481
- version: 0.4.0
482
- type: :development
483
- prerelease: false
484
- version_requirements: !ruby/object:Gem::Requirement
485
- requirements:
486
- - - "~>"
487
- - !ruby/object:Gem::Version
488
- version: 0.4.0
489
461
  - !ruby/object:Gem::Dependency
490
462
  name: pg
491
463
  requirement: !ruby/object:Gem::Requirement
@@ -785,8 +757,10 @@ files:
785
757
  - lib/langchain/tool/weather.rb
786
758
  - lib/langchain/tool/wikipedia.rb
787
759
  - lib/langchain/tool_definition.rb
760
+ - lib/langchain/utils/colorizer.rb
788
761
  - lib/langchain/utils/cosine_similarity.rb
789
762
  - lib/langchain/utils/hash_transformer.rb
763
+ - lib/langchain/utils/to_boolean.rb
790
764
  - lib/langchain/vectorsearch/base.rb
791
765
  - lib/langchain/vectorsearch/chroma.rb
792
766
  - lib/langchain/vectorsearch/elasticsearch.rb