langchainrb 0.14.0 → 0.15.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -2
- data/lib/langchain/assistants/assistant.rb +175 -131
- data/lib/langchain/assistants/messages/ollama_message.rb +9 -21
- data/lib/langchain/contextual_logger.rb +11 -5
- data/lib/langchain/evals/ragas/faithfulness.rb +5 -1
- data/lib/langchain/llm/google_gemini.rb +1 -1
- data/lib/langchain/llm/ollama.rb +23 -17
- data/lib/langchain/llm/openai.rb +1 -1
- data/lib/langchain/llm/response/ollama_response.rb +1 -15
- data/lib/langchain/llm/unified_parameters.rb +2 -2
- data/lib/langchain/tool/calculator.rb +38 -0
- data/lib/langchain/tool/{database/database.rb → database.rb} +24 -12
- data/lib/langchain/tool/file_system.rb +44 -0
- data/lib/langchain/tool/{google_search/google_search.rb → google_search.rb} +17 -23
- data/lib/langchain/tool/{news_retriever/news_retriever.rb → news_retriever.rb} +41 -14
- data/lib/langchain/tool/ruby_code_interpreter.rb +41 -0
- data/lib/langchain/tool/{tavily/tavily.rb → tavily.rb} +24 -10
- data/lib/langchain/tool/vectorsearch.rb +40 -0
- data/lib/langchain/tool/weather.rb +109 -0
- data/lib/langchain/tool/{wikipedia/wikipedia.rb → wikipedia.rb} +17 -13
- data/lib/langchain/tool_definition.rb +212 -0
- data/lib/langchain/utils/colorizer.rb +19 -0
- data/lib/langchain/utils/hash_transformer.rb +9 -17
- data/lib/langchain/utils/to_boolean.rb +27 -0
- data/lib/langchain/vectorsearch/chroma.rb +2 -2
- data/lib/langchain/vectorsearch/elasticsearch.rb +2 -2
- data/lib/langchain/vectorsearch/epsilla.rb +3 -3
- data/lib/langchain/vectorsearch/milvus.rb +2 -2
- data/lib/langchain/vectorsearch/pgvector.rb +2 -2
- data/lib/langchain/vectorsearch/pinecone.rb +2 -2
- data/lib/langchain/vectorsearch/qdrant.rb +2 -2
- data/lib/langchain/vectorsearch/weaviate.rb +4 -4
- data/lib/langchain/version.rb +1 -1
- data/lib/langchain.rb +1 -2
- metadata +18 -54
- data/lib/langchain/tool/base.rb +0 -107
- data/lib/langchain/tool/calculator/calculator.json +0 -19
- data/lib/langchain/tool/calculator/calculator.rb +0 -34
- data/lib/langchain/tool/database/database.json +0 -46
- data/lib/langchain/tool/file_system/file_system.json +0 -57
- data/lib/langchain/tool/file_system/file_system.rb +0 -32
- data/lib/langchain/tool/google_search/google_search.json +0 -19
- data/lib/langchain/tool/news_retriever/news_retriever.json +0 -122
- data/lib/langchain/tool/ruby_code_interpreter/ruby_code_interpreter.json +0 -19
- data/lib/langchain/tool/ruby_code_interpreter/ruby_code_interpreter.rb +0 -37
- data/lib/langchain/tool/tavily/tavily.json +0 -54
- data/lib/langchain/tool/vectorsearch/vectorsearch.json +0 -24
- data/lib/langchain/tool/vectorsearch/vectorsearch.rb +0 -36
- data/lib/langchain/tool/weather/weather.json +0 -19
- data/lib/langchain/tool/weather/weather.rb +0 -55
- data/lib/langchain/tool/wikipedia/wikipedia.json +0 -19
@@ -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
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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-
|
24
|
-
# @param domains [String] A comma-
|
25
|
-
# @param exclude_domains [String] A comma-
|
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-
|
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
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Langchain::Tool
|
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
|
+
# Usage:
|
11
|
+
# weather = Langchain::Tool::Weather.new(api_key: ENV["OPEN_WEATHER_API_KEY"])
|
12
|
+
# assistant = Langchain::Assistant.new(
|
13
|
+
# llm: llm,
|
14
|
+
# tools: [weather]
|
15
|
+
# )
|
16
|
+
#
|
17
|
+
class Weather
|
18
|
+
extend Langchain::ToolDefinition
|
19
|
+
|
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
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize(api_key:)
|
41
|
+
@api_key = api_key
|
42
|
+
end
|
43
|
+
|
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)
|
46
|
+
|
47
|
+
Langchain.logger.info("get_current_weather", for: self.class, city:, state_code:, country_code:, units:)
|
48
|
+
|
49
|
+
fetch_current_weather(city: city, state_code: state_code, country_code: country_code, units: units)
|
50
|
+
end
|
51
|
+
|
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
|
68
|
+
|
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
|
73
|
+
|
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
|
+
}
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -1,19 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Langchain::Tool
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
4
|
+
#
|
5
|
+
# Tool that adds the capability to search using the Wikipedia API
|
6
|
+
#
|
7
|
+
# Gem requirements:
|
8
|
+
# gem "wikipedia-client", "~> 1.17.0"
|
9
|
+
#
|
10
|
+
# Usage:
|
11
|
+
# wikipedia = Langchain::Tool::Wikipedia.new
|
12
|
+
# wikipedia.execute(input: "The Roman Empire")
|
13
|
+
#
|
14
|
+
class Wikipedia
|
15
|
+
extend Langchain::ToolDefinition
|
16
|
+
include Langchain::DependencyHelper
|
17
|
+
|
18
|
+
define_function :execute, description: "Executes Wikipedia API search and returns the answer" do
|
19
|
+
property :input, type: "string", description: "Search query", required: true
|
20
|
+
end
|
17
21
|
|
18
22
|
# Initializes the Wikipedia tool
|
19
23
|
def initialize
|