langchainrb 0.13.5 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -0
  3. data/README.md +2 -17
  4. data/lib/langchain/assistants/assistant.rb +207 -92
  5. data/lib/langchain/assistants/messages/ollama_message.rb +74 -0
  6. data/lib/langchain/assistants/thread.rb +8 -1
  7. data/lib/langchain/contextual_logger.rb +2 -2
  8. data/lib/langchain/llm/ai21.rb +0 -4
  9. data/lib/langchain/llm/anthropic.rb +15 -6
  10. data/lib/langchain/llm/azure.rb +3 -3
  11. data/lib/langchain/llm/base.rb +1 -0
  12. data/lib/langchain/llm/cohere.rb +0 -2
  13. data/lib/langchain/llm/google_gemini.rb +1 -1
  14. data/lib/langchain/llm/google_palm.rb +1 -4
  15. data/lib/langchain/llm/ollama.rb +24 -18
  16. data/lib/langchain/llm/openai.rb +1 -1
  17. data/lib/langchain/llm/response/google_gemini_response.rb +1 -1
  18. data/lib/langchain/llm/response/ollama_response.rb +5 -1
  19. data/lib/langchain/llm/unified_parameters.rb +2 -2
  20. data/lib/langchain/tool/calculator.rb +38 -0
  21. data/lib/langchain/tool/{database/database.rb → database.rb} +24 -12
  22. data/lib/langchain/tool/file_system.rb +44 -0
  23. data/lib/langchain/tool/{google_search/google_search.rb → google_search.rb} +17 -23
  24. data/lib/langchain/tool/{news_retriever/news_retriever.rb → news_retriever.rb} +41 -14
  25. data/lib/langchain/tool/ruby_code_interpreter.rb +41 -0
  26. data/lib/langchain/tool/{tavily/tavily.rb → tavily.rb} +24 -10
  27. data/lib/langchain/tool/vectorsearch.rb +40 -0
  28. data/lib/langchain/tool/{weather/weather.rb → weather.rb} +21 -17
  29. data/lib/langchain/tool/{wikipedia/wikipedia.rb → wikipedia.rb} +17 -13
  30. data/lib/langchain/tool_definition.rb +212 -0
  31. data/lib/langchain/utils/hash_transformer.rb +9 -17
  32. data/lib/langchain/vectorsearch/chroma.rb +2 -2
  33. data/lib/langchain/vectorsearch/elasticsearch.rb +2 -2
  34. data/lib/langchain/vectorsearch/epsilla.rb +3 -3
  35. data/lib/langchain/vectorsearch/milvus.rb +3 -3
  36. data/lib/langchain/vectorsearch/pgvector.rb +2 -2
  37. data/lib/langchain/vectorsearch/pinecone.rb +2 -2
  38. data/lib/langchain/vectorsearch/qdrant.rb +2 -2
  39. data/lib/langchain/vectorsearch/weaviate.rb +4 -4
  40. data/lib/langchain/version.rb +1 -1
  41. metadata +16 -45
  42. data/lib/langchain/tool/base.rb +0 -107
  43. data/lib/langchain/tool/calculator/calculator.json +0 -19
  44. data/lib/langchain/tool/calculator/calculator.rb +0 -34
  45. data/lib/langchain/tool/database/database.json +0 -46
  46. data/lib/langchain/tool/file_system/file_system.json +0 -57
  47. data/lib/langchain/tool/file_system/file_system.rb +0 -32
  48. data/lib/langchain/tool/google_search/google_search.json +0 -19
  49. data/lib/langchain/tool/news_retriever/news_retriever.json +0 -122
  50. data/lib/langchain/tool/ruby_code_interpreter/ruby_code_interpreter.json +0 -19
  51. data/lib/langchain/tool/ruby_code_interpreter/ruby_code_interpreter.rb +0 -37
  52. data/lib/langchain/tool/tavily/tavily.json +0 -54
  53. data/lib/langchain/tool/vectorsearch/vectorsearch.json +0 -24
  54. data/lib/langchain/tool/vectorsearch/vectorsearch.rb +0 -36
  55. data/lib/langchain/tool/weather/weather.json +0 -19
  56. data/lib/langchain/tool/wikipedia/wikipedia.json +0 -19
  57. data/lib/langchain/utils/token_length/ai21_validator.rb +0 -41
  58. data/lib/langchain/utils/token_length/base_validator.rb +0 -42
  59. data/lib/langchain/utils/token_length/cohere_validator.rb +0 -49
  60. data/lib/langchain/utils/token_length/google_palm_validator.rb +0 -57
  61. data/lib/langchain/utils/token_length/openai_validator.rb +0 -138
  62. data/lib/langchain/utils/token_length/token_limit_exceeded.rb +0 -17
@@ -8,6 +8,7 @@ module Langchain::LLM
8
8
  # Langchain.rb provides a common interface to interact with all supported LLMs:
9
9
  #
10
10
  # - {Langchain::LLM::AI21}
11
+ # - {Langchain::LLM::Anthropic}
11
12
  # - {Langchain::LLM::Azure}
12
13
  # - {Langchain::LLM::Cohere}
13
14
  # - {Langchain::LLM::GooglePalm}
@@ -74,8 +74,6 @@ module Langchain::LLM
74
74
 
75
75
  default_params.merge!(params)
76
76
 
77
- default_params[:max_tokens] = Langchain::Utils::TokenLength::CohereValidator.validate_max_tokens!(prompt, default_params[:model], llm: client)
78
-
79
77
  response = client.generate(**default_params)
80
78
  Langchain::LLM::CohereResponse.new response, model: @defaults[:completion_model_name]
81
79
  end
@@ -62,7 +62,7 @@ module Langchain::LLM
62
62
 
63
63
  request = Net::HTTP::Post.new(uri)
64
64
  request.content_type = "application/json"
65
- request.body = Langchain::Utils::HashTransformer.deep_transform_keys(parameters) { |key| Langchain::Utils::HashTransformer.camelize_lower(key.to_s).to_sym }.to_json
65
+ request.body = parameters.to_json
66
66
 
67
67
  response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
68
68
  http.request(request)
@@ -18,7 +18,7 @@ module Langchain::LLM
18
18
  chat_completion_model_name: "chat-bison-001",
19
19
  embeddings_model_name: "embedding-gecko-001"
20
20
  }.freeze
21
- LENGTH_VALIDATOR = Langchain::Utils::TokenLength::GooglePalmValidator
21
+
22
22
  ROLE_MAPPING = {
23
23
  "assistant" => "ai"
24
24
  }
@@ -96,9 +96,6 @@ module Langchain::LLM
96
96
  examples: compose_examples(examples)
97
97
  }
98
98
 
99
- # chat-bison-001 is the only model that currently supports countMessageTokens functions
100
- LENGTH_VALIDATOR.validate_max_tokens!(default_params[:messages], "chat-bison-001", llm: self)
101
-
102
99
  if options[:stop_sequences]
103
100
  default_params[:stop] = options.delete(:stop_sequences)
104
101
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/hash"
4
-
5
3
  module Langchain::LLM
6
4
  # Interface to Ollama API.
7
5
  # Available models: https://ollama.ai/library
@@ -14,10 +12,10 @@ module Langchain::LLM
14
12
  attr_reader :url, :defaults
15
13
 
16
14
  DEFAULTS = {
17
- temperature: 0.8,
18
- completion_model_name: "llama3",
19
- embeddings_model_name: "llama3",
20
- chat_completion_model_name: "llama3"
15
+ temperature: 0.0,
16
+ completion_model_name: "llama3.1",
17
+ embeddings_model_name: "llama3.1",
18
+ chat_completion_model_name: "llama3.1"
21
19
  }.freeze
22
20
 
23
21
  EMBEDDING_SIZES = {
@@ -25,20 +23,24 @@ module Langchain::LLM
25
23
  "dolphin-mixtral": 4_096,
26
24
  llama2: 4_096,
27
25
  llama3: 4_096,
26
+ "llama3.1": 4_096,
28
27
  llava: 4_096,
29
28
  mistral: 4_096,
30
29
  "mistral-openorca": 4_096,
31
- mixtral: 4_096
30
+ mixtral: 4_096,
31
+ tinydolphin: 2_048
32
32
  }.freeze
33
33
 
34
34
  # Initialize the Ollama client
35
35
  # @param url [String] The URL of the Ollama instance
36
+ # @param api_key [String] The API key to use. This is optional and used when you expose Ollama API using Open WebUI
36
37
  # @param default_options [Hash] The default options to use
37
38
  #
38
- def initialize(url: "http://localhost:11434", default_options: {})
39
+ def initialize(url: "http://localhost:11434", api_key: nil, default_options: {})
39
40
  depends_on "faraday"
40
41
  @url = url
41
- @defaults = DEFAULTS.deep_merge(default_options)
42
+ @api_key = api_key
43
+ @defaults = DEFAULTS.merge(default_options)
42
44
  chat_parameters.update(
43
45
  model: {default: @defaults[:chat_completion_model_name]},
44
46
  temperature: {default: @defaults[:temperature]},
@@ -113,7 +115,7 @@ module Langchain::LLM
113
115
  system: system,
114
116
  template: template,
115
117
  context: context,
116
- stream: block.present?,
118
+ stream: block_given?, # rubocop:disable Performance/BlockGivenWithExplicitBlock
117
119
  raw: raw
118
120
  }.compact
119
121
 
@@ -173,7 +175,7 @@ module Langchain::LLM
173
175
  # content: the content of the message
174
176
  # images (optional): a list of images to include in the message (for multimodal models such as llava)
175
177
  def chat(messages:, model: nil, **params, &block)
176
- parameters = chat_parameters.to_params(params.merge(messages:, model:, stream: block.present?))
178
+ parameters = chat_parameters.to_params(params.merge(messages:, model:, stream: block_given?)) # rubocop:disable Performance/BlockGivenWithExplicitBlock
177
179
  responses_stream = []
178
180
 
179
181
  client.post("api/chat", parameters) do |req|
@@ -264,13 +266,20 @@ module Langchain::LLM
264
266
  private
265
267
 
266
268
  def client
267
- @client ||= Faraday.new(url: url) do |conn|
269
+ @client ||= Faraday.new(url: url, headers: auth_headers) do |conn|
268
270
  conn.request :json
269
271
  conn.response :json
270
272
  conn.response :raise_error
273
+ conn.response :logger, nil, {headers: true, bodies: true, errors: true}
271
274
  end
272
275
  end
273
276
 
277
+ def auth_headers
278
+ return unless @api_key
279
+
280
+ {"Authorization" => "Bearer #{@api_key}"}
281
+ end
282
+
274
283
  def json_responses_chunk_handler(&block)
275
284
  proc do |chunk, _size|
276
285
  chunk.split("\n").each do |chunk_line|
@@ -288,13 +297,10 @@ module Langchain::LLM
288
297
  OllamaResponse.new(final_response, model: parameters[:model])
289
298
  end
290
299
 
300
+ # BUG: If streamed, this method does not currently return the tool_calls response.
291
301
  def generate_final_chat_completion_response(responses_stream, parameters)
292
- final_response = responses_stream.last.merge(
293
- "message" => {
294
- "role" => "assistant",
295
- "content" => responses_stream.map { |resp| resp.dig("message", "content") }.join
296
- }
297
- )
302
+ final_response = responses_stream.last
303
+ final_response["message"]["content"] = responses_stream.map { |resp| resp.dig("message", "content") }.join
298
304
 
299
305
  OllamaResponse.new(final_response, model: parameters[:model])
300
306
  end
@@ -16,7 +16,7 @@ module Langchain::LLM
16
16
  DEFAULTS = {
17
17
  n: 1,
18
18
  temperature: 0.0,
19
- chat_completion_model_name: "gpt-3.5-turbo",
19
+ chat_completion_model_name: "gpt-4o-mini",
20
20
  embeddings_model_name: "text-embedding-3-small"
21
21
  }.freeze
22
22
 
@@ -3,7 +3,7 @@
3
3
  module Langchain::LLM
4
4
  class GoogleGeminiResponse < BaseResponse
5
5
  def initialize(raw_response, model: nil)
6
- super(raw_response, model: model)
6
+ super
7
7
  end
8
8
 
9
9
  def chat_completion
@@ -36,7 +36,7 @@ module Langchain::LLM
36
36
  end
37
37
 
38
38
  def prompt_tokens
39
- raw_response.dig("prompt_eval_count") if done?
39
+ raw_response.fetch("prompt_eval_count", 0) if done?
40
40
  end
41
41
 
42
42
  def completion_tokens
@@ -47,6 +47,10 @@ module Langchain::LLM
47
47
  prompt_tokens + completion_tokens if done?
48
48
  end
49
49
 
50
+ def tool_calls
51
+ Array(raw_response.dig("message", "tool_calls"))
52
+ end
53
+
50
54
  private
51
55
 
52
56
  def done?
@@ -77,8 +77,8 @@ module Langchain::LLM
77
77
  @parameters.to_h
78
78
  end
79
79
 
80
- def each(&)
81
- to_params.each(&)
80
+ def each(&block)
81
+ to_params.each(&block)
82
82
  end
83
83
 
84
84
  def <=>(other)
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Langchain::Tool
4
+ #
5
+ # A calculator tool that falls back to the Google calculator widget
6
+ #
7
+ # Gem requirements:
8
+ # gem "eqn", "~> 1.6.5"
9
+ # gem "google_search_results", "~> 2.0.0"
10
+ #
11
+ # Usage:
12
+ # calculator = Langchain::Tool::Calculator.new
13
+ #
14
+ class Calculator
15
+ extend Langchain::ToolDefinition
16
+ include Langchain::DependencyHelper
17
+
18
+ define_function :execute, description: "Evaluates a pure math expression or if equation contains non-math characters (e.g.: \"12F in Celsius\") then it uses the google search calculator to evaluate the expression" do
19
+ property :input, type: "string", description: "Math expression", required: true
20
+ end
21
+
22
+ def initialize
23
+ depends_on "eqn"
24
+ end
25
+
26
+ # Evaluates a pure math expression or if equation contains non-math characters (e.g.: "12F in Celsius") then it uses the google search calculator to evaluate the expression
27
+ #
28
+ # @param input [String] math expression
29
+ # @return [String] Answer
30
+ def execute(input:)
31
+ Langchain.logger.info("Executing \"#{input}\"", for: self.class)
32
+
33
+ Eqn::Calculator.calc(input)
34
+ rescue Eqn::ParseError, Eqn::NoVariableValueError
35
+ "\"#{input}\" is an invalid mathematical expression"
36
+ end
37
+ end
38
+ end
@@ -1,16 +1,28 @@
1
1
  module Langchain::Tool
2
- class Database < Base
3
- #
4
- # Connects to a database, executes SQL queries, and outputs DB schema for Agents to use
5
- #
6
- # Gem requirements:
7
- # gem "sequel", "~> 5.68.0"
8
- #
9
- # Usage:
10
- # database = Langchain::Tool::Database.new(connection_string: "postgres://user:password@localhost:5432/db_name")
11
- #
12
- NAME = "database"
13
- ANNOTATIONS_PATH = Langchain.root.join("./langchain/tool/#{NAME}/#{NAME}.json").to_path
2
+ #
3
+ # Connects to a database, executes SQL queries, and outputs DB schema for Agents to use
4
+ #
5
+ # Gem requirements:
6
+ # gem "sequel", "~> 5.68.0"
7
+ #
8
+ # Usage:
9
+ # database = Langchain::Tool::Database.new(connection_string: "postgres://user:password@localhost:5432/db_name")
10
+ #
11
+ class Database
12
+ extend Langchain::ToolDefinition
13
+ include Langchain::DependencyHelper
14
+
15
+ define_function :list_tables, description: "Database Tool: Returns a list of tables in the database"
16
+
17
+ define_function :describe_tables, description: "Database Tool: Returns the schema for a list of tables" do
18
+ property :tables, type: "string", description: "The tables to describe", required: true
19
+ end
20
+
21
+ define_function :dump_schema, description: "Database Tool: Returns the database schema"
22
+
23
+ define_function :execute, description: "Database Tool: Executes a SQL query and returns the results" do
24
+ property :input, type: "string", description: "SQL query to be executed", required: true
25
+ end
14
26
 
15
27
  attr_reader :db, :requested_tables, :excluded_tables
16
28
 
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Langchain::Tool
4
+ #
5
+ # A tool that wraps the Ruby file system classes.
6
+ #
7
+ # Usage:
8
+ # file_system = Langchain::Tool::FileSystem.new
9
+ #
10
+ class FileSystem
11
+ extend Langchain::ToolDefinition
12
+
13
+ define_function :list_directory, description: "File System Tool: Lists out the content of a specified directory" do
14
+ property :directory_path, type: "string", description: "Directory path to list", required: true
15
+ end
16
+
17
+ define_function :read_file, description: "File System Tool: Reads the contents of a file" do
18
+ property :file_path, type: "string", description: "Path to the file to read from", required: true
19
+ end
20
+
21
+ define_function :write_to_file, description: "File System Tool: Write content to a file" do
22
+ property :file_path, type: "string", description: "Path to the file to write", required: true
23
+ property :content, type: "string", description: "Content to write to the file", required: true
24
+ end
25
+
26
+ def list_directory(directory_path:)
27
+ Dir.entries(directory_path)
28
+ rescue Errno::ENOENT
29
+ "No such directory: #{directory_path}"
30
+ end
31
+
32
+ def read_file(file_path:)
33
+ File.read(file_path)
34
+ rescue Errno::ENOENT
35
+ "No such file: #{file_path}"
36
+ end
37
+
38
+ def write_to_file(file_path:, content:)
39
+ File.write(file_path, content)
40
+ rescue Errno::EACCES
41
+ "Permission denied: #{file_path}"
42
+ end
43
+ end
44
+ end
@@ -1,19 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Langchain::Tool
4
- class GoogleSearch < Base
5
- #
6
- # Wrapper around SerpApi's Google Search API
7
- #
8
- # Gem requirements:
9
- # gem "google_search_results", "~> 2.0.0"
10
- #
11
- # Usage:
12
- # search = Langchain::Tool::GoogleSearch.new(api_key: "YOUR_API_KEY")
13
- # search.execute(input: "What is the capital of France?")
14
- #
15
- NAME = "google_search"
16
- ANNOTATIONS_PATH = Langchain.root.join("./langchain/tool/#{NAME}/#{NAME}.json").to_path
4
+ #
5
+ # Wrapper around SerpApi's Google Search API
6
+ #
7
+ # Gem requirements:
8
+ # gem "google_search_results", "~> 2.0.0"
9
+ #
10
+ # Usage:
11
+ # search = Langchain::Tool::GoogleSearch.new(api_key: "YOUR_API_KEY")
12
+ # search.execute(input: "What is the capital of France?")
13
+ #
14
+ class GoogleSearch
15
+ extend Langchain::ToolDefinition
16
+ include Langchain::DependencyHelper
17
+
18
+ define_function :execute, description: "Executes Google Search and returns the result" do
19
+ property :input, type: "string", description: "Search query", required: true
20
+ end
17
21
 
18
22
  attr_reader :api_key
19
23
 
@@ -29,16 +33,6 @@ module Langchain::Tool
29
33
  @api_key = api_key
30
34
  end
31
35
 
32
- #
33
- # Executes Google Search and returns hash_results JSON
34
- #
35
- # @param input [String] search query
36
- # @return [Hash] hash_results JSON
37
- #
38
- def self.execute_search(input:)
39
- new.execute_search(input: input)
40
- end
41
-
42
36
  # Executes Google Search and returns the result
43
37
  #
44
38
  # @param input [String] search query
@@ -1,16 +1,43 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Langchain::Tool
4
- class NewsRetriever < Base
5
- #
6
- # A tool that retrieves latest news from various sources via https://newsapi.org/.
7
- # An API key needs to be obtained from https://newsapi.org/ to use this tool.
8
- #
9
- # Usage:
10
- # news_retriever = Langchain::Tool::NewsRetriever.new(api_key: ENV["NEWS_API_KEY"])
11
- #
12
- NAME = "news_retriever"
13
- ANNOTATIONS_PATH = Langchain.root.join("./langchain/tool/#{NAME}/#{NAME}.json").to_path
4
+ #
5
+ # A tool that retrieves latest news from various sources via https://newsapi.org/.
6
+ # An API key needs to be obtained from https://newsapi.org/ to use this tool.
7
+ #
8
+ # Usage:
9
+ # news_retriever = Langchain::Tool::NewsRetriever.new(api_key: ENV["NEWS_API_KEY"])
10
+ #
11
+ class NewsRetriever
12
+ extend Langchain::ToolDefinition
13
+
14
+ define_function :get_everything, description: "News Retriever: Search through millions of articles from over 150,000 large and small news sources and blogs" do
15
+ property :q, type: "string", description: 'Keywords or phrases to search for in the article title and body. Surround phrases with quotes (") for exact match. Alternatively you can use the AND / OR / NOT keywords, and optionally group these with parenthesis. Must be URL-encoded'
16
+ property :search_in, type: "string", description: "The fields to restrict your q search to", enum: ["title", "description", "content"]
17
+ property :sources, type: "string", description: "A comma-separated string of identifiers (maximum 20) for the news sources or blogs you want headlines from. Use the /sources endpoint to locate these programmatically or look at the sources index"
18
+ property :domains, type: "string", description: "A comma-separated string of domains (eg bbc.co.uk, techcrunch.com, engadget.com) to restrict the search to"
19
+ property :exclude_domains, type: "string", description: "A comma-separated string of domains (eg bbc.co.uk, techcrunch.com, engadget.com) to remove from the results"
20
+ property :from, type: "string", description: "A date and optional time for the oldest article allowed. This should be in ISO 8601 format"
21
+ property :to, type: "string", description: "A date and optional time for the newest article allowed. This should be in ISO 8601 format"
22
+ property :language, type: "string", description: "The 2-letter ISO-639-1 code of the language you want to get headlines for", enum: ["ar", "de", "en", "es", "fr", "he", "it", "nl", "no", "pt", "ru", "sv", "ud", "zh"]
23
+ property :sort_by, type: "string", description: "The order to sort the articles in", enum: ["relevancy", "popularity", "publishedAt"]
24
+ property :page_size, type: "integer", description: "The number of results to return per page (request). 5 is the default, 100 is the maximum"
25
+ property :page, type: "integer", description: "Use this to page through the results if the total results found is greater than the page size"
26
+ end
27
+
28
+ define_function :get_top_headlines, description: "News Retriever: Provides live top and breaking headlines for a country, specific category in a country, single source, or multiple sources. You can also search with keywords. Articles are sorted by the earliest date published first" do
29
+ property :country, type: "string", description: "The 2-letter ISO 3166-1 code of the country you want to get headlines for", enum: ["ae", "ar", "at", "au", "be", "bg", "br", "ca", "ch", "cn", "co", "cu", "cz", "de", "eg", "fr", "gb", "gr", "hk", "hu", "id", "ie", "il", "in", "it", "jp", "kr", "lt", "lv", "ma", "mx", "my", "ng", "nl", "no", "nz", "ph", "pl", "pt", "ro", "rs", "ru", "sa", "se", "sg", "si", "sk", "th", "tr", "tw", "ua", "us", "ve", "za"]
30
+ property :category, type: "string", description: "The category you want to get headlines for", enum: ["business", "entertainment", "general", "health", "science", "sports", "technology"]
31
+ property :q, type: "string", description: "Keywords or a phrase to search for"
32
+ property :page_size, type: "integer", description: "The number of results to return per page (request). 5 is the default, 100 is the maximum"
33
+ property :page, type: "integer", description: "Use this to page through the results if the total results found is greater than the page size"
34
+ end
35
+
36
+ define_function :get_sources, description: "News Retriever: This endpoint returns the subset of news publishers that top headlines (/v2/top-headlines) are available from. It's mainly a convenience endpoint that you can use to keep track of the publishers available on the API, and you can pipe it straight through to your users" do
37
+ property :country, type: "string", description: "The 2-letter ISO 3166-1 code of the country you want to get headlines for. Default: all countries", enum: ["ae", "ar", "at", "au", "be", "bg", "br", "ca", "ch", "cn", "co", "cu", "cz", "de", "eg", "fr", "gb", "gr", "hk", "hu", "id", "ie", "il", "in", "it", "jp", "kr", "lt", "lv", "ma", "mx", "my", "ng", "nl", "no", "nz", "ph", "pl", "pt", "ro", "rs", "ru", "sa", "se", "sg", "si", "sk", "th", "tr", "tw", "ua", "us", "ve", "za"]
38
+ property :category, type: "string", description: "The category you want to get headlines for. Default: all categories", enum: ["business", "entertainment", "general", "health", "science", "sports", "technology"]
39
+ property :language, type: "string", description: "The 2-letter ISO-639-1 code of the language you want to get headlines for", enum: ["ar", "de", "en", "es", "fr", "he", "it", "nl", "no", "pt", "ru", "sv", "ud", "zh"]
40
+ end
14
41
 
15
42
  def initialize(api_key: ENV["NEWS_API_KEY"])
16
43
  @api_key = api_key
@@ -20,9 +47,9 @@ module Langchain::Tool
20
47
  #
21
48
  # @param q [String] Keywords or phrases to search for in the article title and body.
22
49
  # @param search_in [String] The fields to restrict your q search to. The possible options are: title, description, content.
23
- # @param sources [String] A comma-seperated string of identifiers (maximum 20) for the news sources or blogs you want headlines from. Use the /sources endpoint to locate these programmatically or look at the sources index.
24
- # @param domains [String] A comma-seperated string of domains (eg bbc.co.uk, techcrunch.com, engadget.com) to restrict the search to.
25
- # @param exclude_domains [String] A comma-seperated string of domains (eg bbc.co.uk, techcrunch.com, engadget.com) to remove from the results.
50
+ # @param sources [String] A comma-separated string of identifiers (maximum 20) for the news sources or blogs you want headlines from. Use the /sources endpoint to locate these programmatically or look at the sources index.
51
+ # @param domains [String] A comma-separated string of domains (eg bbc.co.uk, techcrunch.com, engadget.com) to restrict the search to.
52
+ # @param exclude_domains [String] A comma-separated string of domains (eg bbc.co.uk, techcrunch.com, engadget.com) to remove from the results.
26
53
  # @param from [String] A date and optional time for the oldest article allowed. This should be in ISO 8601 format.
27
54
  # @param to [String] A date and optional time for the newest article allowed. This should be in ISO 8601 format.
28
55
  # @param language [String] The 2-letter ISO-639-1 code of the language you want to get headlines for. Possible options: ar, de, en, es, fr, he, it, nl, no, pt, ru, se, ud, zh.
@@ -66,7 +93,7 @@ module Langchain::Tool
66
93
  #
67
94
  # @param country [String] The 2-letter ISO 3166-1 code of the country you want to get headlines for. Possible options: ae, ar, at, au, be, bg, br, ca, ch, cn, co, cu, cz, de, eg, fr, gb, gr, hk, hu, id, ie, il, in, it, jp, kr, lt, lv, ma, mx, my, ng, nl, no, nz, ph, pl, pt, ro, rs, ru, sa, se, sg, si, sk, th, tr, tw, ua, us, ve, za.
68
95
  # @param category [String] The category you want to get headlines for. Possible options: business, entertainment, general, health, science, sports, technology.
69
- # @param sources [String] A comma-seperated string of identifiers for the news sources or blogs you want headlines from. Use the /sources endpoint to locate these programmatically.
96
+ # @param sources [String] A comma-separated string of identifiers for the news sources or blogs you want headlines from. Use the /sources endpoint to locate these programmatically.
70
97
  # @param q [String] Keywords or a phrase to search for.
71
98
  # @param page_size [Integer] The number of results to return per page. 20 is the API's default, 100 is the maximum. Our default is 5.
72
99
  # @param page [Integer] Use this to page through the results.
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Langchain::Tool
4
+ #
5
+ # A tool that execute Ruby code in a sandboxed environment.
6
+ #
7
+ # Gem requirements:
8
+ # gem "safe_ruby", "~> 1.0.4"
9
+ #
10
+ # Usage:
11
+ # interpreter = Langchain::Tool::RubyCodeInterpreter.new
12
+ #
13
+ class RubyCodeInterpreter
14
+ extend Langchain::ToolDefinition
15
+ include Langchain::DependencyHelper
16
+
17
+ define_function :execute, description: "Executes Ruby code in a sandboxes environment" do
18
+ property :input, type: "string", description: "Ruby code expression", required: true
19
+ end
20
+
21
+ def initialize(timeout: 30)
22
+ depends_on "safe_ruby"
23
+
24
+ @timeout = timeout
25
+ end
26
+
27
+ # Executes Ruby code in a sandboxes environment.
28
+ #
29
+ # @param input [String] ruby code expression
30
+ # @return [String] Answer
31
+ def execute(input:)
32
+ Langchain.logger.info("Executing \"#{input}\"", for: self.class)
33
+
34
+ safe_eval(input)
35
+ end
36
+
37
+ def safe_eval(code)
38
+ SafeRuby.eval(code, timeout: @timeout)
39
+ end
40
+ end
41
+ end
@@ -1,16 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Langchain::Tool
4
- class Tavily < Base
5
- #
6
- # Tavily Search is a robust search API tailored specifically for LLM Agents.
7
- # It seamlessly integrates with diverse data sources to ensure a superior, relevant search experience.
8
- #
9
- # Usage:
10
- # tavily = Langchain::Tool::Tavily.new(api_key: ENV["TAVILY_API_KEY"])
11
- #
12
- NAME = "tavily"
13
- ANNOTATIONS_PATH = Langchain.root.join("./langchain/tool/#{NAME}/#{NAME}.json").to_path
4
+ #
5
+ # Tavily Search is a robust search API tailored specifically for LLM Agents.
6
+ # It seamlessly integrates with diverse data sources to ensure a superior, relevant search experience.
7
+ #
8
+ # Usage:
9
+ # tavily = Langchain::Tool::Tavily.new(api_key: ENV["TAVILY_API_KEY"])
10
+ #
11
+ class Tavily
12
+ extend Langchain::ToolDefinition
13
+
14
+ define_function :search, description: "Tavily Tool: Robust search API" do
15
+ property :query, type: "string", description: "The search query string", required: true
16
+ property :search_depth, type: "string", description: "The depth of the search: basic for quick results and advanced for indepth high quality results but longer response time", enum: ["basic", "advanced"]
17
+ property :include_images, type: "boolean", description: "Include a list of query related images in the response"
18
+ property :include_answer, type: "boolean", description: "Include answers in the search results"
19
+ property :include_raw_content, type: "boolean", description: "Include raw content in the search results"
20
+ property :max_results, type: "integer", description: "The number of maximum search results to return"
21
+ property :include_domains, type: "array", description: "A list of domains to specifically include in the search results" do
22
+ item type: "string"
23
+ end
24
+ property :exclude_domains, type: "array", description: "A list of domains to specifically exclude from the search results" do
25
+ item type: "string"
26
+ end
27
+ end
14
28
 
15
29
  def initialize(api_key:)
16
30
  @api_key = api_key
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Langchain::Tool
4
+ #
5
+ # A tool wraps vectorsearch classes
6
+ #
7
+ # Usage:
8
+ # # Initialize the LLM that will be used to generate embeddings
9
+ # ollama = Langchain::LLM::Ollama.new(url: ENV["OLLAMA_URL"]
10
+ # chroma = Langchain::Vectorsearch::Chroma.new(url: ENV["CHROMA_URL"], index_name: "my_index", llm: ollama)
11
+ #
12
+ # # This tool can now be used by the Assistant
13
+ # vectorsearch_tool = Langchain::Tool::Vectorsearch.new(vectorsearch: chroma)
14
+ #
15
+ class Vectorsearch
16
+ extend Langchain::ToolDefinition
17
+
18
+ define_function :similarity_search, description: "Vectorsearch: Retrieves relevant document for the query" do
19
+ property :query, type: "string", description: "Query to find similar documents for", required: true
20
+ property :k, type: "integer", description: "Number of similar documents to retrieve. Default value: 4"
21
+ end
22
+
23
+ attr_reader :vectorsearch
24
+
25
+ # Initializes the Vectorsearch tool
26
+ #
27
+ # @param vectorsearch [Langchain::Vectorsearch::Base] Vectorsearch instance to use
28
+ def initialize(vectorsearch:)
29
+ @vectorsearch = vectorsearch
30
+ end
31
+
32
+ # Executes the vector search and returns the results
33
+ #
34
+ # @param query [String] The query to search for
35
+ # @param k [Integer] The number of results to return
36
+ def similarity_search(query:, k: 4)
37
+ vectorsearch.similarity_search(query:, k: 4)
38
+ end
39
+ end
40
+ end
@@ -1,23 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Langchain::Tool
4
- class Weather < Base
5
- #
6
- # A weather tool that gets current weather data
7
- #
8
- # Current weather data is free for 1000 calls per day (https://home.openweathermap.org/api_keys)
9
- # Forecast and historical data require registration with credit card, so not supported yet.
10
- #
11
- # Gem requirements:
12
- # gem "open-weather-ruby-client", "~> 0.3.0"
13
- # api_key: https://home.openweathermap.org/api_keys
14
- #
15
- # Usage:
16
- # weather = Langchain::Tool::Weather.new(api_key: ENV["OPEN_WEATHER_API_KEY"])
17
- # weather.execute(input: "Boston, MA; imperial")
18
- #
19
- NAME = "weather"
20
- ANNOTATIONS_PATH = Langchain.root.join("./langchain/tool/#{NAME}/#{NAME}.json").to_path
4
+ #
5
+ # A weather tool that gets current weather data
6
+ #
7
+ # Current weather data is free for 1000 calls per day (https://home.openweathermap.org/api_keys)
8
+ # Forecast and historical data require registration with credit card, so not supported yet.
9
+ #
10
+ # Gem requirements:
11
+ # gem "open-weather-ruby-client", "~> 0.3.0"
12
+ # api_key: https://home.openweathermap.org/api_keys
13
+ #
14
+ # Usage:
15
+ # weather = Langchain::Tool::Weather.new(api_key: ENV["OPEN_WEATHER_API_KEY"])
16
+ # weather.execute(input: "Boston, MA; imperial")
17
+ #
18
+ class Weather
19
+ extend Langchain::ToolDefinition
20
+ include Langchain::DependencyHelper
21
+
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
24
+ end
21
25
 
22
26
  attr_reader :client, :units
23
27