Skip to content

Commit a2b6b6a

Browse files
Fix zeitwerk error when eager_load is turned on (#822)
* Fix zeitwerk error when eager_load is turned on * Rename /assistants directory to /assistant * Move Langchain::Messages namespace to Langchain::Assistant::Messages * Clean up zeitwerk configuration * Add code comments * fixes
1 parent cb783d6 commit a2b6b6a

30 files changed

+681
-557
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
## [Unreleased]
2+
- [BREAKING] `Langchain::Messages::*` namespace had migrated to `Langchain::Assistant::Messages::*`
23
- [BREAKING] Modify `Langchain::LLM::AwsBedrock` constructor to pass model options via default_options: {...}
34
- Added support for streaming with Anthropic
45
- Bump anthropic gem

lib/langchain.rb

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,12 @@
2222
"mistral_ai_response" => "MistralAIResponse",
2323
"mistral_ai_message" => "MistralAIMessage",
2424
"openai" => "OpenAI",
25-
"openai_validator" => "OpenAIValidator",
2625
"openai_response" => "OpenAIResponse",
2726
"openai_message" => "OpenAIMessage",
2827
"pdf" => "PDF"
2928
)
29+
3030
loader.collapse("#{__dir__}/langchain/llm/response")
31-
loader.collapse("#{__dir__}/langchain/assistants")
32-
33-
loader.collapse("#{__dir__}/langchain/tool/calculator")
34-
loader.collapse("#{__dir__}/langchain/tool/database")
35-
loader.collapse("#{__dir__}/langchain/tool/docs_tool")
36-
loader.collapse("#{__dir__}/langchain/tool/file_system")
37-
loader.collapse("#{__dir__}/langchain/tool/google_search")
38-
loader.collapse("#{__dir__}/langchain/tool/ruby_code_interpreter")
39-
loader.collapse("#{__dir__}/langchain/tool/news_retriever")
40-
loader.collapse("#{__dir__}/langchain/tool/tavily")
41-
loader.collapse("#{__dir__}/langchain/tool/vectorsearch")
42-
loader.collapse("#{__dir__}/langchain/tool/weather")
43-
loader.collapse("#{__dir__}/langchain/tool/wikipedia")
4431

4532
# RubyCodeInterpreter does not work with Ruby 3.3;
4633
# https://github.com/ukutaht/safe_ruby/issues/4

lib/langchain/assistants/assistant.rb renamed to lib/langchain/assistant.rb

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# frozen_string_literal: true
22

3-
require_relative "llm/adapter"
4-
53
module Langchain
64
# Assistants are Agent-like objects that leverage helpful instructions, LLMs, tools and knowledge to respond to user queries.
75
# Assistants can be configured with an LLM of your choice, any vector search database and easily extended with additional tools.
@@ -104,7 +102,7 @@ def prompt_of_concatenated_messages
104102
# @param messages [Array<Langchain::Message>] The messages to set
105103
# @return [Array<Langchain::Message>] The messages
106104
def messages=(messages)
107-
raise ArgumentError, "messages array must only contain Langchain::Message instance(s)" unless messages.is_a?(Array) && messages.all? { |m| m.is_a?(Langchain::Messages::Base) }
105+
raise ArgumentError, "messages array must only contain Langchain::Message instance(s)" unless messages.is_a?(Array) && messages.all? { |m| m.is_a?(Messages::Base) }
108106

109107
@messages = messages
110108
end
@@ -336,15 +334,15 @@ def execute_tools
336334
def determine_tool_role
337335
case llm
338336
when Langchain::LLM::Anthropic
339-
Langchain::Messages::AnthropicMessage::TOOL_ROLE
337+
Messages::AnthropicMessage::TOOL_ROLE
340338
when Langchain::LLM::GoogleGemini, Langchain::LLM::GoogleVertexAI
341-
Langchain::Messages::GoogleGeminiMessage::TOOL_ROLE
339+
Messages::GoogleGeminiMessage::TOOL_ROLE
342340
when Langchain::LLM::MistralAI
343-
Langchain::Messages::MistralAIMessage::TOOL_ROLE
341+
Messages::MistralAIMessage::TOOL_ROLE
344342
when Langchain::LLM::Ollama
345-
Langchain::Messages::OllamaMessage::TOOL_ROLE
343+
Messages::OllamaMessage::TOOL_ROLE
346344
when Langchain::LLM::OpenAI
347-
Langchain::Messages::OpenAIMessage::TOOL_ROLE
345+
Messages::OpenAIMessage::TOOL_ROLE
348346
end
349347
end
350348

lib/langchain/assistants/llm/adapter.rb renamed to lib/langchain/assistant/llm/adapter.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Dir[Pathname.new(__FILE__).dirname.join("adapters", "*.rb")].sort.each { |file| require file }
1+
# frozen_string_literal: true
22

33
module Langchain
44
class Assistant

lib/langchain/assistants/llm/adapters/anthropic.rb renamed to lib/langchain/assistant/llm/adapters/anthropic.rb

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
1+
# frozen_string_literal: true
2+
13
module Langchain
24
class Assistant
35
module LLM
46
module Adapters
57
class Anthropic < Base
8+
# Build the chat parameters for the Anthropic API
9+
#
10+
# @param tools [Array<Hash>] The tools to use
11+
# @param instructions [String] The system instructions
12+
# @param messages [Array<Hash>] The messages
13+
# @param tool_choice [String] The tool choice
14+
# @return [Hash] The chat parameters
615
def build_chat_params(tools:, instructions:, messages:, tool_choice:)
716
params = {messages: messages}
817
if tools.any?
@@ -13,10 +22,18 @@ def build_chat_params(tools:, instructions:, messages:, tool_choice:)
1322
params
1423
end
1524

25+
# Build an Anthropic message
26+
#
27+
# @param role [String] The role of the message
28+
# @param content [String] The content of the message
29+
# @param image_url [String] The image URL
30+
# @param tool_calls [Array<Hash>] The tool calls
31+
# @param tool_call_id [String] The tool call ID
32+
# @return [Messages::AnthropicMessage] The Anthropic message
1633
def build_message(role:, content: nil, image_url: nil, tool_calls: [], tool_call_id: nil)
1734
warn "Image URL is not supported by Anthropic currently" if image_url
1835

19-
Langchain::Messages::AnthropicMessage.new(role: role, content: content, tool_calls: tool_calls, tool_call_id: tool_call_id)
36+
Messages::AnthropicMessage.new(role: role, content: content, tool_calls: tool_calls, tool_call_id: tool_call_id)
2037
end
2138

2239
# Extract the tool call information from the Anthropic tool call hash
@@ -31,14 +48,20 @@ def extract_tool_call_args(tool_call:)
3148
[tool_call_id, tool_name, method_name, tool_arguments]
3249
end
3350

51+
# Build the tools for the Anthropic API
3452
def build_tools(tools)
3553
tools.map { |tool| tool.class.function_schemas.to_anthropic_format }.flatten
3654
end
3755

56+
# Get the allowed assistant.tool_choice values for Anthropic
3857
def allowed_tool_choices
3958
["auto", "any"]
4059
end
4160

61+
# Get the available tool function names for Anthropic
62+
#
63+
# @param tools [Array<Hash>] The tools
64+
# @return [Array<String>] The tool function names
4265
def available_tool_names(tools)
4366
build_tools(tools).map { |tool| tool.dig(:name) }
4467
end
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# frozen_string_literal: true
2+
3+
module Langchain
4+
class Assistant
5+
module LLM
6+
module Adapters
7+
class Base
8+
# Build the chat parameters for the LLM
9+
#
10+
# @param tools [Array] The tools to use
11+
# @param instructions [String] The system instructions
12+
# @param messages [Array] The messages
13+
# @param tool_choice [String] The tool choice
14+
# @return [Hash] The chat parameters
15+
def build_chat_params(tools:, instructions:, messages:, tool_choice:)
16+
raise NotImplementedError, "Subclasses must implement build_chat_params"
17+
end
18+
19+
# Extract the tool call information from the tool call hash
20+
#
21+
# @param tool_call [Hash] The tool call hash
22+
# @return [Array] The tool call information
23+
def extract_tool_call_args(tool_call:)
24+
raise NotImplementedError, "Subclasses must implement extract_tool_call_args"
25+
end
26+
27+
# Build a message for the LLM
28+
#
29+
# @param role [String] The role of the message
30+
# @param content [String] The content of the message
31+
# @param image_url [String] The image URL
32+
# @param tool_calls [Array] The tool calls
33+
# @param tool_call_id [String] The tool call ID
34+
# @return [Messages::Base] The message
35+
def build_message(role:, content: nil, image_url: nil, tool_calls: [], tool_call_id: nil)
36+
raise NotImplementedError, "Subclasses must implement build_message"
37+
end
38+
end
39+
end
40+
end
41+
end
42+
end

lib/langchain/assistants/llm/adapters/google_gemini.rb renamed to lib/langchain/assistant/llm/adapters/google_gemini.rb

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
1+
# frozen_string_literal: true
2+
13
module Langchain
24
class Assistant
35
module LLM
46
module Adapters
57
class GoogleGemini < Base
8+
# Build the chat parameters for the Google Gemini LLM
9+
#
10+
# @param tools [Array] The tools to use
11+
# @param instructions [String] The system instructions
12+
# @param messages [Array] The messages
13+
# @param tool_choice [String] The tool choice
14+
# @return [Hash] The chat parameters
615
def build_chat_params(tools:, instructions:, messages:, tool_choice:)
716
params = {messages: messages}
817
if tools.any?
@@ -13,10 +22,18 @@ def build_chat_params(tools:, instructions:, messages:, tool_choice:)
1322
params
1423
end
1524

25+
# Build a Google Gemini message
26+
#
27+
# @param role [String] The role of the message
28+
# @param content [String] The content of the message
29+
# @param image_url [String] The image URL
30+
# @param tool_calls [Array] The tool calls
31+
# @param tool_call_id [String] The tool call ID
32+
# @return [Messages::GoogleGeminiMessage] The Google Gemini message
1633
def build_message(role:, content: nil, image_url: nil, tool_calls: [], tool_call_id: nil)
1734
warn "Image URL is not supported by Google Gemini" if image_url
1835

19-
Langchain::Messages::GoogleGeminiMessage.new(role: role, content: content, tool_calls: tool_calls, tool_call_id: tool_call_id)
36+
Messages::GoogleGeminiMessage.new(role: role, content: content, tool_calls: tool_calls, tool_call_id: tool_call_id)
2037
end
2138

2239
# Extract the tool call information from the Google Gemini tool call hash
@@ -31,14 +48,20 @@ def extract_tool_call_args(tool_call:)
3148
[tool_call_id, tool_name, method_name, tool_arguments]
3249
end
3350

51+
# Build the tools for the Google Gemini LLM
52+
#
53+
# @param tools [Array<Langchain::Tool::Base>] The tools
54+
# @return [Array] The tools in Google Gemini format
3455
def build_tools(tools)
3556
tools.map { |tool| tool.class.function_schemas.to_google_gemini_format }.flatten
3657
end
3758

59+
# Get the allowed assistant.tool_choice values for Google Gemini
3860
def allowed_tool_choices
3961
["auto", "none"]
4062
end
4163

64+
# Get the available tool names for Google Gemini
4265
def available_tool_names(tools)
4366
build_tools(tools).map { |tool| tool.dig(:name) }
4467
end

lib/langchain/assistants/llm/adapters/mistral_ai.rb renamed to lib/langchain/assistant/llm/adapters/mistral_ai.rb

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
1+
# frozen_string_literal: true
2+
13
module Langchain
24
class Assistant
35
module LLM
46
module Adapters
57
class MistralAI < Base
8+
# Build the chat parameters for the Mistral AI LLM
9+
#
10+
# @param tools [Array] The tools to use
11+
# @param instructions [String] The system instructions
12+
# @param messages [Array] The messages
13+
# @param tool_choice [String] The tool choice
14+
# @return [Hash] The chat parameters
615
def build_chat_params(tools:, instructions:, messages:, tool_choice:)
716
params = {messages: messages}
817
if tools.any?
@@ -12,8 +21,16 @@ def build_chat_params(tools:, instructions:, messages:, tool_choice:)
1221
params
1322
end
1423

24+
# Build a Mistral AI message
25+
#
26+
# @param role [String] The role of the message
27+
# @param content [String] The content of the message
28+
# @param image_url [String] The image URL
29+
# @param tool_calls [Array] The tool calls
30+
# @param tool_call_id [String] The tool call ID
31+
# @return [Messages::MistralAIMessage] The Mistral AI message
1532
def build_message(role:, content: nil, image_url: nil, tool_calls: [], tool_call_id: nil)
16-
Langchain::Messages::MistralAIMessage.new(role: role, content: content, image_url: image_url, tool_calls: tool_calls, tool_call_id: tool_call_id)
33+
Messages::MistralAIMessage.new(role: role, content: content, image_url: image_url, tool_calls: tool_calls, tool_call_id: tool_call_id)
1734
end
1835

1936
# Extract the tool call information from the OpenAI tool call hash
@@ -36,14 +53,17 @@ def extract_tool_call_args(tool_call:)
3653
[tool_call_id, tool_name, method_name, tool_arguments]
3754
end
3855

56+
# Build the tools for the Mistral AI LLM
3957
def build_tools(tools)
4058
tools.map { |tool| tool.class.function_schemas.to_openai_format }.flatten
4159
end
4260

61+
# Get the allowed assistant.tool_choice values for Mistral AI
4362
def allowed_tool_choices
4463
["auto", "none"]
4564
end
4665

66+
# Get the available tool names for Mistral AI
4767
def available_tool_names(tools)
4868
build_tools(tools).map { |tool| tool.dig(:function, :name) }
4969
end

lib/langchain/assistants/llm/adapters/ollama.rb renamed to lib/langchain/assistant/llm/adapters/ollama.rb

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
1+
# frozen_string_literal: true
2+
13
module Langchain
24
class Assistant
35
module LLM
46
module Adapters
57
class Ollama < Base
8+
# Build the chat parameters for the Ollama LLM
9+
#
10+
# @param tools [Array] The tools to use
11+
# @param instructions [String] The system instructions
12+
# @param messages [Array] The messages
13+
# @param tool_choice [String] The tool choice
14+
# @return [Hash] The chat parameters
615
def build_chat_params(tools:, instructions:, messages:, tool_choice:)
716
params = {messages: messages}
817
if tools.any?
@@ -11,10 +20,18 @@ def build_chat_params(tools:, instructions:, messages:, tool_choice:)
1120
params
1221
end
1322

23+
# Build an Ollama message
24+
#
25+
# @param role [String] The role of the message
26+
# @param content [String] The content of the message
27+
# @param image_url [String] The image URL
28+
# @param tool_calls [Array] The tool calls
29+
# @param tool_call_id [String] The tool call ID
30+
# @return [Messages::OllamaMessage] The Ollama message
1431
def build_message(role:, content: nil, image_url: nil, tool_calls: [], tool_call_id: nil)
1532
warn "Image URL is not supported by Ollama currently" if image_url
1633

17-
Langchain::Messages::OllamaMessage.new(role: role, content: content, tool_calls: tool_calls, tool_call_id: tool_call_id)
34+
Messages::OllamaMessage.new(role: role, content: content, tool_calls: tool_calls, tool_call_id: tool_call_id)
1835
end
1936

2037
# Extract the tool call information from the OpenAI tool call hash
@@ -37,10 +54,12 @@ def extract_tool_call_args(tool_call:)
3754
[tool_call_id, tool_name, method_name, tool_arguments]
3855
end
3956

57+
# Build the tools for the Ollama LLM
4058
def available_tool_names(tools)
4159
build_tools(tools).map { |tool| tool.dig(:function, :name) }
4260
end
4361

62+
# Get the allowed assistant.tool_choice values for Ollama
4463
def allowed_tool_choices
4564
["auto", "none"]
4665
end

0 commit comments

Comments
 (0)