langchainrb 0.13.5 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
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