langchainrb 0.16.1 → 0.17.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +6 -1
- data/lib/langchain/assistants/assistant.rb +25 -17
- data/lib/langchain/assistants/messages/base.rb +5 -1
- data/lib/langchain/assistants/messages/mistral_ai_message.rb +30 -8
- data/lib/langchain/assistants/messages/openai_message.rb +37 -8
- data/lib/langchain/llm/base.rb +1 -2
- data/lib/langchain/vectorsearch/elasticsearch.rb +1 -1
- data/lib/langchain/vectorsearch/milvus.rb +45 -61
- data/lib/langchain/vectorsearch/qdrant.rb +3 -2
- data/lib/langchain/vectorsearch/weaviate.rb +3 -2
- data/lib/langchain/version.rb +1 -1
- metadata +8 -24
- data/lib/langchain/llm/google_palm.rb +0 -177
- data/lib/langchain/llm/response/google_palm_response.rb +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c125e87218ae9ce233711968edf212e128b50910f118951296593d141c9b7a68
|
4
|
+
data.tar.gz: a8e0890d5eef171709068ee19e4e0955929035d732225916e28debd03cfebcbf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ae228197ef8be183cf9f36dc46bb523033fcfd1c563246e3f49bec081822b819d3ca1b93a0b5a780af276cb80ef3ce6ef6734e87f7cf3fad335d0e57e186e965
|
7
|
+
data.tar.gz: fd17a2caabbce6d6b006831e3eb51c6c3c174f178536991f6c0477aadc4d5ea64c2dae317cf59be9691908c0d0908cca6fac681eedc413b69588883cb6494a50
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.17.0] - 2024-10-02
|
4
|
+
- [BREAKING] Langchain::Vectorsearch::Milvus was rewritten to work with newer milvus 0.10.0 gem
|
5
|
+
- [BREAKING] Removing Langchain::LLM::GooglePalm
|
6
|
+
- Assistant can now process image_urls in the messages (currently only for OpenAI and Mistral AI)
|
7
|
+
- Vectorsearch providers utilize the global Langchain.logger
|
8
|
+
- Update required milvus, qdrant and weaviate versions
|
9
|
+
|
3
10
|
## [0.16.1] - 2024-09-30
|
4
11
|
- Deprecate Langchain::LLM::GooglePalm
|
5
12
|
- Allow setting response_object: {} parameter when initializing supported Langchain::LLM::* classes
|
data/README.md
CHANGED
@@ -63,7 +63,6 @@ The `Langchain::LLM` module provides a unified interface for interacting with va
|
|
63
63
|
- Azure OpenAI
|
64
64
|
- Cohere
|
65
65
|
- Google Gemini
|
66
|
-
- Google PaLM (deprecated)
|
67
66
|
- Google Vertex AI
|
68
67
|
- HuggingFace
|
69
68
|
- LlamaCpp
|
@@ -501,6 +500,12 @@ assistant = Langchain::Assistant.new(
|
|
501
500
|
# Add a user message and run the assistant
|
502
501
|
assistant.add_message_and_run!(content: "What's the latest news about AI?")
|
503
502
|
|
503
|
+
# Supply an image to the assistant
|
504
|
+
assistant.add_message_and_run!(
|
505
|
+
content: "Show me a picture of a cat",
|
506
|
+
image: "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"
|
507
|
+
)
|
508
|
+
|
504
509
|
# Access the conversation thread
|
505
510
|
messages = assistant.messages
|
506
511
|
|
@@ -63,13 +63,14 @@ module Langchain
|
|
63
63
|
|
64
64
|
# Add a user message to the messages array
|
65
65
|
#
|
66
|
-
# @param content [String] The content of the message
|
67
66
|
# @param role [String] The role attribute of the message. Default: "user"
|
67
|
+
# @param content [String] The content of the message
|
68
|
+
# @param image_url [String] The URL of the image to include in the message
|
68
69
|
# @param tool_calls [Array<Hash>] The tool calls to include in the message
|
69
70
|
# @param tool_call_id [String] The ID of the tool call to include in the message
|
70
71
|
# @return [Array<Langchain::Message>] The messages
|
71
|
-
def add_message(content: nil,
|
72
|
-
message = build_message(role: role, content: content, tool_calls: tool_calls, tool_call_id: tool_call_id)
|
72
|
+
def add_message(role: "user", content: nil, image_url: nil, tool_calls: [], tool_call_id: nil)
|
73
|
+
message = build_message(role: role, content: content, image_url: image_url, tool_calls: tool_calls, tool_call_id: tool_call_id)
|
73
74
|
|
74
75
|
# Call the callback with the message
|
75
76
|
add_message_callback.call(message) if add_message_callback # rubocop:disable Style/SafeNavigation
|
@@ -145,8 +146,8 @@ module Langchain
|
|
145
146
|
# @param content [String] The content of the message
|
146
147
|
# @param auto_tool_execution [Boolean] Whether or not to automatically run tools
|
147
148
|
# @return [Array<Langchain::Message>] The messages
|
148
|
-
def add_message_and_run(content
|
149
|
-
add_message(content: content, role: "user")
|
149
|
+
def add_message_and_run(content: nil, image_url: nil, auto_tool_execution: false)
|
150
|
+
add_message(content: content, image_url: image_url, role: "user")
|
150
151
|
run(auto_tool_execution: auto_tool_execution)
|
151
152
|
end
|
152
153
|
|
@@ -154,8 +155,8 @@ module Langchain
|
|
154
155
|
#
|
155
156
|
# @param content [String] The content of the message
|
156
157
|
# @return [Array<Langchain::Message>] The messages
|
157
|
-
def add_message_and_run!(content:)
|
158
|
-
add_message_and_run(content: content, auto_tool_execution: true)
|
158
|
+
def add_message_and_run!(content: nil, image_url: nil)
|
159
|
+
add_message_and_run(content: content, image_url: image_url, auto_tool_execution: true)
|
159
160
|
end
|
160
161
|
|
161
162
|
# Submit tool output
|
@@ -388,11 +389,12 @@ module Langchain
|
|
388
389
|
#
|
389
390
|
# @param role [String] The role of the message
|
390
391
|
# @param content [String] The content of the message
|
392
|
+
# @param image_url [String] The URL of the image to include in the message
|
391
393
|
# @param tool_calls [Array<Hash>] The tool calls to include in the message
|
392
394
|
# @param tool_call_id [String] The ID of the tool call to include in the message
|
393
395
|
# @return [Langchain::Message] The Message object
|
394
|
-
def build_message(role:, content: nil, tool_calls: [], tool_call_id: nil)
|
395
|
-
@llm_adapter.build_message(role: role, content: content, tool_calls: tool_calls, tool_call_id: tool_call_id)
|
396
|
+
def build_message(role:, content: nil, image_url: nil, tool_calls: [], tool_call_id: nil)
|
397
|
+
@llm_adapter.build_message(role: role, content: content, image_url: image_url, tool_calls: tool_calls, tool_call_id: tool_call_id)
|
396
398
|
end
|
397
399
|
|
398
400
|
# Increment the tokens count based on the last interaction with the LLM
|
@@ -443,7 +445,7 @@ module Langchain
|
|
443
445
|
raise NotImplementedError, "Subclasses must implement extract_tool_call_args"
|
444
446
|
end
|
445
447
|
|
446
|
-
def build_message(role:, content: nil, tool_calls: [], tool_call_id: nil)
|
448
|
+
def build_message(role:, content: nil, image_url: nil, tool_calls: [], tool_call_id: nil)
|
447
449
|
raise NotImplementedError, "Subclasses must implement build_message"
|
448
450
|
end
|
449
451
|
end
|
@@ -457,7 +459,9 @@ module Langchain
|
|
457
459
|
params
|
458
460
|
end
|
459
461
|
|
460
|
-
def build_message(role:, content: nil, tool_calls: [], tool_call_id: nil)
|
462
|
+
def build_message(role:, content: nil, image_url: nil, tool_calls: [], tool_call_id: nil)
|
463
|
+
warn "Image URL is not supported by Ollama currently" if image_url
|
464
|
+
|
461
465
|
Langchain::Messages::OllamaMessage.new(role: role, content: content, tool_calls: tool_calls, tool_call_id: tool_call_id)
|
462
466
|
end
|
463
467
|
|
@@ -506,8 +510,8 @@ module Langchain
|
|
506
510
|
params
|
507
511
|
end
|
508
512
|
|
509
|
-
def build_message(role:, content: nil, tool_calls: [], tool_call_id: nil)
|
510
|
-
Langchain::Messages::OpenAIMessage.new(role: role, content: content, tool_calls: tool_calls, tool_call_id: tool_call_id)
|
513
|
+
def build_message(role:, content: nil, image_url: nil, tool_calls: [], tool_call_id: nil)
|
514
|
+
Langchain::Messages::OpenAIMessage.new(role: role, content: content, image_url: image_url, tool_calls: tool_calls, tool_call_id: tool_call_id)
|
511
515
|
end
|
512
516
|
|
513
517
|
# Extract the tool call information from the OpenAI tool call hash
|
@@ -564,8 +568,8 @@ module Langchain
|
|
564
568
|
params
|
565
569
|
end
|
566
570
|
|
567
|
-
def build_message(role:, content: nil, tool_calls: [], tool_call_id: nil)
|
568
|
-
Langchain::Messages::MistralAIMessage.new(role: role, content: content, tool_calls: tool_calls, tool_call_id: tool_call_id)
|
571
|
+
def build_message(role:, content: nil, image_url: nil, tool_calls: [], tool_call_id: nil)
|
572
|
+
Langchain::Messages::MistralAIMessage.new(role: role, content: content, image_url: image_url, tool_calls: tool_calls, tool_call_id: tool_call_id)
|
569
573
|
end
|
570
574
|
|
571
575
|
# Extract the tool call information from the OpenAI tool call hash
|
@@ -623,7 +627,9 @@ module Langchain
|
|
623
627
|
params
|
624
628
|
end
|
625
629
|
|
626
|
-
def build_message(role:, content: nil, tool_calls: [], tool_call_id: nil)
|
630
|
+
def build_message(role:, content: nil, image_url: nil, tool_calls: [], tool_call_id: nil)
|
631
|
+
warn "Image URL is not supported by Google Gemini" if image_url
|
632
|
+
|
627
633
|
Langchain::Messages::GoogleGeminiMessage.new(role: role, content: content, tool_calls: tool_calls, tool_call_id: tool_call_id)
|
628
634
|
end
|
629
635
|
|
@@ -676,7 +682,9 @@ module Langchain
|
|
676
682
|
params
|
677
683
|
end
|
678
684
|
|
679
|
-
def build_message(role:, content: nil, tool_calls: [], tool_call_id: nil)
|
685
|
+
def build_message(role:, content: nil, image_url: nil, tool_calls: [], tool_call_id: nil)
|
686
|
+
warn "Image URL is not supported by Anthropic currently" if image_url
|
687
|
+
|
680
688
|
Langchain::Messages::AnthropicMessage.new(role: role, content: content, tool_calls: tool_calls, tool_call_id: tool_call_id)
|
681
689
|
end
|
682
690
|
|
@@ -15,17 +15,20 @@ module Langchain
|
|
15
15
|
|
16
16
|
# Initialize a new MistralAI message
|
17
17
|
#
|
18
|
-
# @param [String] The role of the message
|
19
|
-
# @param [String] The content of the message
|
20
|
-
# @param [
|
21
|
-
# @param [
|
22
|
-
|
18
|
+
# @param role [String] The role of the message
|
19
|
+
# @param content [String] The content of the message
|
20
|
+
# @param image_url [String] The URL of the image
|
21
|
+
# @param tool_calls [Array<Hash>] The tool calls made in the message
|
22
|
+
# @param tool_call_id [String] The ID of the tool call
|
23
|
+
def initialize(role:, content: nil, image_url: nil, tool_calls: [], tool_call_id: nil) # TODO: Implement image_file: reference (https://platform.openai.com/docs/api-reference/messages/object#messages/object-content)
|
23
24
|
raise ArgumentError, "Role must be one of #{ROLES.join(", ")}" unless ROLES.include?(role)
|
24
25
|
raise ArgumentError, "Tool calls must be an array of hashes" unless tool_calls.is_a?(Array) && tool_calls.all? { |tool_call| tool_call.is_a?(Hash) }
|
25
26
|
|
26
27
|
@role = role
|
27
28
|
# Some Tools return content as a JSON hence `.to_s`
|
28
29
|
@content = content.to_s
|
30
|
+
# Make sure you're using the Pixtral model if you want to send image_url
|
31
|
+
@image_url = image_url
|
29
32
|
@tool_calls = tool_calls
|
30
33
|
@tool_call_id = tool_call_id
|
31
34
|
end
|
@@ -43,9 +46,28 @@ module Langchain
|
|
43
46
|
def to_hash
|
44
47
|
{}.tap do |h|
|
45
48
|
h[:role] = role
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
+
|
50
|
+
if tool_calls.any?
|
51
|
+
h[:tool_calls] = tool_calls
|
52
|
+
else
|
53
|
+
h[:tool_call_id] = tool_call_id if tool_call_id
|
54
|
+
|
55
|
+
h[:content] = []
|
56
|
+
|
57
|
+
if content && !content.empty?
|
58
|
+
h[:content] << {
|
59
|
+
type: "text",
|
60
|
+
text: content
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
64
|
+
if image_url
|
65
|
+
h[:content] << {
|
66
|
+
type: "image_url",
|
67
|
+
image_url: image_url
|
68
|
+
}
|
69
|
+
end
|
70
|
+
end
|
49
71
|
end
|
50
72
|
end
|
51
73
|
|
@@ -15,17 +15,25 @@ module Langchain
|
|
15
15
|
|
16
16
|
# Initialize a new OpenAI message
|
17
17
|
#
|
18
|
-
# @param [String] The role of the message
|
19
|
-
# @param [String] The content of the message
|
20
|
-
# @param [
|
21
|
-
# @param [
|
22
|
-
|
18
|
+
# @param role [String] The role of the message
|
19
|
+
# @param content [String] The content of the message
|
20
|
+
# @param image_url [String] The URL of the image
|
21
|
+
# @param tool_calls [Array<Hash>] The tool calls made in the message
|
22
|
+
# @param tool_call_id [String] The ID of the tool call
|
23
|
+
def initialize(
|
24
|
+
role:,
|
25
|
+
content: nil,
|
26
|
+
image_url: nil,
|
27
|
+
tool_calls: [],
|
28
|
+
tool_call_id: nil
|
29
|
+
)
|
23
30
|
raise ArgumentError, "Role must be one of #{ROLES.join(", ")}" unless ROLES.include?(role)
|
24
31
|
raise ArgumentError, "Tool calls must be an array of hashes" unless tool_calls.is_a?(Array) && tool_calls.all? { |tool_call| tool_call.is_a?(Hash) }
|
25
32
|
|
26
33
|
@role = role
|
27
34
|
# Some Tools return content as a JSON hence `.to_s`
|
28
35
|
@content = content.to_s
|
36
|
+
@image_url = image_url
|
29
37
|
@tool_calls = tool_calls
|
30
38
|
@tool_call_id = tool_call_id
|
31
39
|
end
|
@@ -43,9 +51,30 @@ module Langchain
|
|
43
51
|
def to_hash
|
44
52
|
{}.tap do |h|
|
45
53
|
h[:role] = role
|
46
|
-
|
47
|
-
|
48
|
-
|
54
|
+
|
55
|
+
if tool_calls.any?
|
56
|
+
h[:tool_calls] = tool_calls
|
57
|
+
else
|
58
|
+
h[:tool_call_id] = tool_call_id if tool_call_id
|
59
|
+
|
60
|
+
h[:content] = []
|
61
|
+
|
62
|
+
if content && !content.empty?
|
63
|
+
h[:content] << {
|
64
|
+
type: "text",
|
65
|
+
text: content
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
if image_url
|
70
|
+
h[:content] << {
|
71
|
+
type: "image_url",
|
72
|
+
image_url: {
|
73
|
+
url: image_url
|
74
|
+
}
|
75
|
+
}
|
76
|
+
end
|
77
|
+
end
|
49
78
|
end
|
50
79
|
end
|
51
80
|
|
data/lib/langchain/llm/base.rb
CHANGED
@@ -11,9 +11,8 @@ module Langchain::LLM
|
|
11
11
|
# - {Langchain::LLM::Anthropic}
|
12
12
|
# - {Langchain::LLM::Azure}
|
13
13
|
# - {Langchain::LLM::Cohere}
|
14
|
-
# - {Langchain::LLM::GooglePalm}
|
15
|
-
# - {Langchain::LLM::GoogleVertexAI}
|
16
14
|
# - {Langchain::LLM::GoogleGemini}
|
15
|
+
# - {Langchain::LLM::GoogleVertexAI}
|
17
16
|
# - {Langchain::LLM::HuggingFace}
|
18
17
|
# - {Langchain::LLM::LlamaCpp}
|
19
18
|
# - {Langchain::LLM::OpenAI}
|
@@ -6,16 +6,18 @@ module Langchain::Vectorsearch
|
|
6
6
|
# Wrapper around Milvus REST APIs.
|
7
7
|
#
|
8
8
|
# Gem requirements:
|
9
|
-
# gem "milvus", "~> 0.
|
9
|
+
# gem "milvus", "~> 0.10.3"
|
10
10
|
#
|
11
11
|
# Usage:
|
12
|
-
#
|
12
|
+
# milvus = Langchain::Vectorsearch::Milvus.new(url:, index_name:, llm:, api_key:)
|
13
13
|
#
|
14
|
-
|
15
14
|
def initialize(url:, index_name:, llm:, api_key: nil)
|
16
15
|
depends_on "milvus"
|
17
16
|
|
18
|
-
@client = ::Milvus::Client.new(
|
17
|
+
@client = ::Milvus::Client.new(
|
18
|
+
url: url,
|
19
|
+
logger: Langchain.logger
|
20
|
+
)
|
19
21
|
@index_name = index_name
|
20
22
|
|
21
23
|
super(llm: llm)
|
@@ -24,33 +26,24 @@ module Langchain::Vectorsearch
|
|
24
26
|
def add_texts(texts:)
|
25
27
|
client.entities.insert(
|
26
28
|
collection_name: index_name,
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
field_name: "content",
|
31
|
-
type: ::Milvus::DATA_TYPES["varchar"],
|
32
|
-
field: Array(texts)
|
33
|
-
}, {
|
34
|
-
field_name: "vectors",
|
35
|
-
type: ::Milvus::DATA_TYPES["float_vector"],
|
36
|
-
field: Array(texts).map { |text| llm.embed(text: text).embedding }
|
37
|
-
}
|
38
|
-
]
|
29
|
+
data: texts.map do |text|
|
30
|
+
{content: text, vector: llm.embed(text: text).embedding}
|
31
|
+
end
|
39
32
|
)
|
40
33
|
end
|
41
34
|
|
35
|
+
# TODO: Add update_texts method
|
36
|
+
|
42
37
|
# Deletes a list of texts in the index
|
43
38
|
#
|
44
39
|
# @param ids [Array<Integer>] The ids of texts to delete
|
45
40
|
# @return [Boolean] The response from the server
|
46
41
|
def remove_texts(ids:)
|
47
42
|
raise ArgumentError, "ids must be an array" unless ids.is_a?(Array)
|
48
|
-
# Convert ids to integers if strings are passed
|
49
|
-
ids = ids.map(&:to_i)
|
50
43
|
|
51
44
|
client.entities.delete(
|
52
45
|
collection_name: index_name,
|
53
|
-
|
46
|
+
filter: "id in #{ids}"
|
54
47
|
)
|
55
48
|
end
|
56
49
|
|
@@ -62,33 +55,25 @@ module Langchain::Vectorsearch
|
|
62
55
|
client.collections.create(
|
63
56
|
auto_id: true,
|
64
57
|
collection_name: index_name,
|
65
|
-
description: "Default schema created by langchain.rb",
|
66
58
|
fields: [
|
67
59
|
{
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
data_type: ::Milvus::DATA_TYPES["int64"]
|
60
|
+
fieldName: "id",
|
61
|
+
isPrimary: true,
|
62
|
+
dataType: "Int64"
|
72
63
|
}, {
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
value: "32768" # Largest allowed value
|
80
|
-
}
|
81
|
-
]
|
64
|
+
fieldName: "content",
|
65
|
+
isPrimary: false,
|
66
|
+
dataType: "VarChar",
|
67
|
+
elementTypeParams: {
|
68
|
+
max_length: "32768" # Largest allowed value
|
69
|
+
}
|
82
70
|
}, {
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
value: llm.default_dimensions.to_s
|
90
|
-
}
|
91
|
-
]
|
71
|
+
fieldName: "vector",
|
72
|
+
isPrimary: false,
|
73
|
+
dataType: "FloatVector",
|
74
|
+
elementTypeParams: {
|
75
|
+
dim: llm.default_dimensions.to_s
|
76
|
+
}
|
92
77
|
}
|
93
78
|
]
|
94
79
|
)
|
@@ -97,13 +82,17 @@ module Langchain::Vectorsearch
|
|
97
82
|
# Create the default index
|
98
83
|
# @return [Boolean] The response from the server
|
99
84
|
def create_default_index
|
100
|
-
client.
|
85
|
+
client.indexes.create(
|
101
86
|
collection_name: index_name,
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
87
|
+
index_params: [
|
88
|
+
{
|
89
|
+
metricType: "L2",
|
90
|
+
fieldName: "vector",
|
91
|
+
indexName: "vector_idx",
|
92
|
+
indexConfig: {
|
93
|
+
index_type: "AUTOINDEX"
|
94
|
+
}
|
95
|
+
}
|
107
96
|
]
|
108
97
|
)
|
109
98
|
end
|
@@ -111,13 +100,13 @@ module Langchain::Vectorsearch
|
|
111
100
|
# Get the default schema
|
112
101
|
# @return [Hash] The response from the server
|
113
102
|
def get_default_schema
|
114
|
-
client.collections.
|
103
|
+
client.collections.describe(collection_name: index_name)
|
115
104
|
end
|
116
105
|
|
117
106
|
# Delete default schema
|
118
107
|
# @return [Hash] The response from the server
|
119
108
|
def destroy_default_schema
|
120
|
-
client.collections.
|
109
|
+
client.collections.drop(collection_name: index_name)
|
121
110
|
end
|
122
111
|
|
123
112
|
# Load default schema into memory
|
@@ -138,16 +127,12 @@ module Langchain::Vectorsearch
|
|
138
127
|
def similarity_search_by_vector(embedding:, k: 4)
|
139
128
|
load_default_schema
|
140
129
|
|
141
|
-
client.search(
|
130
|
+
client.entities.search(
|
142
131
|
collection_name: index_name,
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
params: "{\"nprobe\": 10}",
|
148
|
-
anns_field: "vectors",
|
149
|
-
metric_type: "L2",
|
150
|
-
vector_type: ::Milvus::DATA_TYPES["float_vector"]
|
132
|
+
anns_field: "vector",
|
133
|
+
data: [embedding],
|
134
|
+
limit: k,
|
135
|
+
output_fields: ["content", "id", "vector"]
|
151
136
|
)
|
152
137
|
end
|
153
138
|
|
@@ -159,8 +144,7 @@ module Langchain::Vectorsearch
|
|
159
144
|
def ask(question:, k: 4, &block)
|
160
145
|
search_results = similarity_search(query: question, k: k)
|
161
146
|
|
162
|
-
|
163
|
-
content_data = content_field.first.dig("Field", "Scalars", "Data", "StringData", "data")
|
147
|
+
content_data = search_results.dig("data").map { |result| result.dig("content") }
|
164
148
|
|
165
149
|
context = content_data.join("\n---\n")
|
166
150
|
|
@@ -6,7 +6,7 @@ module Langchain::Vectorsearch
|
|
6
6
|
# Wrapper around Qdrant
|
7
7
|
#
|
8
8
|
# Gem requirements:
|
9
|
-
# gem "qdrant-ruby", "~> 0.9.
|
9
|
+
# gem "qdrant-ruby", "~> 0.9.8"
|
10
10
|
#
|
11
11
|
# Usage:
|
12
12
|
# qdrant = Langchain::Vectorsearch::Qdrant.new(url:, api_key:, index_name:, llm:)
|
@@ -22,7 +22,8 @@ module Langchain::Vectorsearch
|
|
22
22
|
|
23
23
|
@client = ::Qdrant::Client.new(
|
24
24
|
url: url,
|
25
|
-
api_key: api_key
|
25
|
+
api_key: api_key,
|
26
|
+
logger: Langchain.logger
|
26
27
|
)
|
27
28
|
@index_name = index_name
|
28
29
|
|
@@ -6,7 +6,7 @@ module Langchain::Vectorsearch
|
|
6
6
|
# Wrapper around Weaviate
|
7
7
|
#
|
8
8
|
# Gem requirements:
|
9
|
-
# gem "weaviate-ruby", "~> 0.9.
|
9
|
+
# gem "weaviate-ruby", "~> 0.9.2"
|
10
10
|
#
|
11
11
|
# Usage:
|
12
12
|
# weaviate = Langchain::Vectorsearch::Weaviate.new(url: ENV["WEAVIATE_URL"], api_key: ENV["WEAVIATE_API_KEY"], index_name: "Docs", llm: llm)
|
@@ -22,7 +22,8 @@ module Langchain::Vectorsearch
|
|
22
22
|
|
23
23
|
@client = ::Weaviate::Client.new(
|
24
24
|
url: url,
|
25
|
-
api_key: api_key
|
25
|
+
api_key: api_key,
|
26
|
+
logger: Langchain.logger
|
26
27
|
)
|
27
28
|
|
28
29
|
# Weaviate requires the class name to be Capitalized: https://weaviate.io/developers/weaviate/configuration/schema-configuration#create-a-class
|
data/lib/langchain/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: langchainrb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.17.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrei Bondarev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-10-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: baran
|
@@ -318,20 +318,6 @@ dependencies:
|
|
318
318
|
- - ">="
|
319
319
|
- !ruby/object:Gem::Version
|
320
320
|
version: '0'
|
321
|
-
- !ruby/object:Gem::Dependency
|
322
|
-
name: google_palm_api
|
323
|
-
requirement: !ruby/object:Gem::Requirement
|
324
|
-
requirements:
|
325
|
-
- - "~>"
|
326
|
-
- !ruby/object:Gem::Version
|
327
|
-
version: 0.1.3
|
328
|
-
type: :development
|
329
|
-
prerelease: false
|
330
|
-
version_requirements: !ruby/object:Gem::Requirement
|
331
|
-
requirements:
|
332
|
-
- - "~>"
|
333
|
-
- !ruby/object:Gem::Version
|
334
|
-
version: 0.1.3
|
335
321
|
- !ruby/object:Gem::Dependency
|
336
322
|
name: google_search_results
|
337
323
|
requirement: !ruby/object:Gem::Requirement
|
@@ -380,14 +366,14 @@ dependencies:
|
|
380
366
|
requirements:
|
381
367
|
- - "~>"
|
382
368
|
- !ruby/object:Gem::Version
|
383
|
-
version: 0.
|
369
|
+
version: 0.10.3
|
384
370
|
type: :development
|
385
371
|
prerelease: false
|
386
372
|
version_requirements: !ruby/object:Gem::Requirement
|
387
373
|
requirements:
|
388
374
|
- - "~>"
|
389
375
|
- !ruby/object:Gem::Version
|
390
|
-
version: 0.
|
376
|
+
version: 0.10.3
|
391
377
|
- !ruby/object:Gem::Dependency
|
392
378
|
name: llama_cpp
|
393
379
|
requirement: !ruby/object:Gem::Requirement
|
@@ -520,14 +506,14 @@ dependencies:
|
|
520
506
|
requirements:
|
521
507
|
- - "~>"
|
522
508
|
- !ruby/object:Gem::Version
|
523
|
-
version: 0.9.
|
509
|
+
version: 0.9.8
|
524
510
|
type: :development
|
525
511
|
prerelease: false
|
526
512
|
version_requirements: !ruby/object:Gem::Requirement
|
527
513
|
requirements:
|
528
514
|
- - "~>"
|
529
515
|
- !ruby/object:Gem::Version
|
530
|
-
version: 0.9.
|
516
|
+
version: 0.9.8
|
531
517
|
- !ruby/object:Gem::Dependency
|
532
518
|
name: roo
|
533
519
|
requirement: !ruby/object:Gem::Requirement
|
@@ -604,14 +590,14 @@ dependencies:
|
|
604
590
|
requirements:
|
605
591
|
- - "~>"
|
606
592
|
- !ruby/object:Gem::Version
|
607
|
-
version: 0.
|
593
|
+
version: 0.9.2
|
608
594
|
type: :development
|
609
595
|
prerelease: false
|
610
596
|
version_requirements: !ruby/object:Gem::Requirement
|
611
597
|
requirements:
|
612
598
|
- - "~>"
|
613
599
|
- !ruby/object:Gem::Version
|
614
|
-
version: 0.
|
600
|
+
version: 0.9.2
|
615
601
|
- !ruby/object:Gem::Dependency
|
616
602
|
name: wikipedia-client
|
617
603
|
requirement: !ruby/object:Gem::Requirement
|
@@ -683,7 +669,6 @@ files:
|
|
683
669
|
- lib/langchain/llm/base.rb
|
684
670
|
- lib/langchain/llm/cohere.rb
|
685
671
|
- lib/langchain/llm/google_gemini.rb
|
686
|
-
- lib/langchain/llm/google_palm.rb
|
687
672
|
- lib/langchain/llm/google_vertex_ai.rb
|
688
673
|
- lib/langchain/llm/hugging_face.rb
|
689
674
|
- lib/langchain/llm/llama_cpp.rb
|
@@ -701,7 +686,6 @@ files:
|
|
701
686
|
- lib/langchain/llm/response/base_response.rb
|
702
687
|
- lib/langchain/llm/response/cohere_response.rb
|
703
688
|
- lib/langchain/llm/response/google_gemini_response.rb
|
704
|
-
- lib/langchain/llm/response/google_palm_response.rb
|
705
689
|
- lib/langchain/llm/response/hugging_face_response.rb
|
706
690
|
- lib/langchain/llm/response/llama_cpp_response.rb
|
707
691
|
- lib/langchain/llm/response/mistral_ai_response.rb
|
@@ -1,177 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Langchain::LLM
|
4
|
-
#
|
5
|
-
# Wrapper around the Google PaLM (Pathways Language Model) APIs: https://ai.google/build/machine-learning/
|
6
|
-
#
|
7
|
-
# Gem requirements:
|
8
|
-
# gem "google_palm_api", "~> 0.1.3"
|
9
|
-
#
|
10
|
-
# Usage:
|
11
|
-
# google_palm = Langchain::LLM::GooglePalm.new(api_key: ENV["GOOGLE_PALM_API_KEY"])
|
12
|
-
#
|
13
|
-
class GooglePalm < Base
|
14
|
-
extend Gem::Deprecate
|
15
|
-
|
16
|
-
DEFAULTS = {
|
17
|
-
temperature: 0.0,
|
18
|
-
dimensions: 768, # This is what the `embedding-gecko-001` model generates
|
19
|
-
completion_model_name: "text-bison-001",
|
20
|
-
chat_completion_model_name: "chat-bison-001",
|
21
|
-
embeddings_model_name: "embedding-gecko-001"
|
22
|
-
}.freeze
|
23
|
-
|
24
|
-
ROLE_MAPPING = {
|
25
|
-
"assistant" => "ai"
|
26
|
-
}
|
27
|
-
|
28
|
-
attr_reader :defaults
|
29
|
-
|
30
|
-
# @deprecated Please use Langchain::LLM::GoogleGemini instead
|
31
|
-
#
|
32
|
-
# @param api_key [String] The API key for the Google PaLM API
|
33
|
-
def initialize(api_key:, default_options: {})
|
34
|
-
depends_on "google_palm_api"
|
35
|
-
|
36
|
-
@client = ::GooglePalmApi::Client.new(api_key: api_key)
|
37
|
-
@defaults = DEFAULTS.merge(default_options)
|
38
|
-
end
|
39
|
-
deprecate :initialize, "Langchain::LLM::GoogleGemini.new(api_key:)", 2024, 10
|
40
|
-
|
41
|
-
#
|
42
|
-
# Generate an embedding for a given text
|
43
|
-
#
|
44
|
-
# @param text [String] The text to generate an embedding for
|
45
|
-
# @return [Langchain::LLM::GooglePalmResponse] Response object
|
46
|
-
#
|
47
|
-
def embed(text:)
|
48
|
-
response = client.embed(text: text)
|
49
|
-
|
50
|
-
Langchain::LLM::GooglePalmResponse.new response,
|
51
|
-
model: @defaults[:embeddings_model_name]
|
52
|
-
end
|
53
|
-
|
54
|
-
#
|
55
|
-
# Generate a completion for a given prompt
|
56
|
-
#
|
57
|
-
# @param prompt [String] The prompt to generate a completion for
|
58
|
-
# @param params extra parameters passed to GooglePalmAPI::Client#generate_text
|
59
|
-
# @return [Langchain::LLM::GooglePalmResponse] Response object
|
60
|
-
#
|
61
|
-
def complete(prompt:, **params)
|
62
|
-
default_params = {
|
63
|
-
prompt: prompt,
|
64
|
-
temperature: @defaults[:temperature],
|
65
|
-
model: @defaults[:completion_model_name]
|
66
|
-
}
|
67
|
-
|
68
|
-
if params[:stop_sequences]
|
69
|
-
default_params[:stop_sequences] = params.delete(:stop_sequences)
|
70
|
-
end
|
71
|
-
|
72
|
-
if params[:max_tokens]
|
73
|
-
default_params[:max_output_tokens] = params.delete(:max_tokens)
|
74
|
-
end
|
75
|
-
|
76
|
-
default_params.merge!(params)
|
77
|
-
|
78
|
-
response = client.generate_text(**default_params)
|
79
|
-
|
80
|
-
Langchain::LLM::GooglePalmResponse.new response,
|
81
|
-
model: default_params[:model]
|
82
|
-
end
|
83
|
-
|
84
|
-
#
|
85
|
-
# Generate a chat completion for a given prompt
|
86
|
-
#
|
87
|
-
# @param prompt [String] The prompt to generate a chat completion for
|
88
|
-
# @param messages [Array<Hash>] The messages that have been sent in the conversation
|
89
|
-
# @param context [String] An initial context to provide as a system message, ie "You are RubyGPT, a helpful chat bot for helping people learn Ruby"
|
90
|
-
# @param examples [Array<Hash>] Examples of messages to provide to the model. Useful for Few-Shot Prompting
|
91
|
-
# @param options [Hash] extra parameters passed to GooglePalmAPI::Client#generate_chat_message
|
92
|
-
# @return [Langchain::LLM::GooglePalmResponse] Response object
|
93
|
-
#
|
94
|
-
def chat(prompt: "", messages: [], context: "", examples: [], **options)
|
95
|
-
raise ArgumentError.new(":prompt or :messages argument is expected") if prompt.empty? && messages.empty?
|
96
|
-
|
97
|
-
default_params = {
|
98
|
-
temperature: @defaults[:temperature],
|
99
|
-
model: @defaults[:chat_completion_model_name],
|
100
|
-
context: context,
|
101
|
-
messages: compose_chat_messages(prompt: prompt, messages: messages),
|
102
|
-
examples: compose_examples(examples)
|
103
|
-
}
|
104
|
-
|
105
|
-
if options[:stop_sequences]
|
106
|
-
default_params[:stop] = options.delete(:stop_sequences)
|
107
|
-
end
|
108
|
-
|
109
|
-
if options[:max_tokens]
|
110
|
-
default_params[:max_output_tokens] = options.delete(:max_tokens)
|
111
|
-
end
|
112
|
-
|
113
|
-
default_params.merge!(options)
|
114
|
-
|
115
|
-
response = client.generate_chat_message(**default_params)
|
116
|
-
raise "GooglePalm API returned an error: #{response}" if response.dig("error")
|
117
|
-
|
118
|
-
Langchain::LLM::GooglePalmResponse.new response,
|
119
|
-
model: default_params[:model]
|
120
|
-
# TODO: Pass in prompt_tokens: prompt_tokens
|
121
|
-
end
|
122
|
-
|
123
|
-
#
|
124
|
-
# Generate a summarization for a given text
|
125
|
-
#
|
126
|
-
# @param text [String] The text to generate a summarization for
|
127
|
-
# @return [String] The summarization
|
128
|
-
#
|
129
|
-
def summarize(text:)
|
130
|
-
prompt_template = Langchain::Prompt.load_from_path(
|
131
|
-
file_path: Langchain.root.join("langchain/llm/prompts/summarize_template.yaml")
|
132
|
-
)
|
133
|
-
prompt = prompt_template.format(text: text)
|
134
|
-
|
135
|
-
complete(
|
136
|
-
prompt: prompt,
|
137
|
-
temperature: @defaults[:temperature],
|
138
|
-
# Most models have a context length of 2048 tokens (except for the newest models, which support 4096).
|
139
|
-
max_tokens: 256
|
140
|
-
)
|
141
|
-
end
|
142
|
-
|
143
|
-
private
|
144
|
-
|
145
|
-
def compose_chat_messages(prompt:, messages:)
|
146
|
-
history = []
|
147
|
-
history.concat transform_messages(messages) unless messages.empty?
|
148
|
-
|
149
|
-
unless prompt.empty?
|
150
|
-
if history.last && history.last[:role] == "user"
|
151
|
-
history.last[:content] += "\n#{prompt}"
|
152
|
-
else
|
153
|
-
history.append({author: "user", content: prompt})
|
154
|
-
end
|
155
|
-
end
|
156
|
-
history
|
157
|
-
end
|
158
|
-
|
159
|
-
def compose_examples(examples)
|
160
|
-
examples.each_slice(2).map do |example|
|
161
|
-
{
|
162
|
-
input: {content: example.first[:content]},
|
163
|
-
output: {content: example.last[:content]}
|
164
|
-
}
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
def transform_messages(messages)
|
169
|
-
messages.map do |message|
|
170
|
-
{
|
171
|
-
author: ROLE_MAPPING.fetch(message[:role], message[:role]),
|
172
|
-
content: message[:content]
|
173
|
-
}
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Langchain::LLM
|
4
|
-
class GooglePalmResponse < BaseResponse
|
5
|
-
attr_reader :prompt_tokens
|
6
|
-
|
7
|
-
def initialize(raw_response, model: nil, prompt_tokens: nil)
|
8
|
-
@prompt_tokens = prompt_tokens
|
9
|
-
super(raw_response, model: model)
|
10
|
-
end
|
11
|
-
|
12
|
-
def completion
|
13
|
-
completions&.dig(0, "output")
|
14
|
-
end
|
15
|
-
|
16
|
-
def embedding
|
17
|
-
embeddings.first
|
18
|
-
end
|
19
|
-
|
20
|
-
def completions
|
21
|
-
raw_response.dig("candidates")
|
22
|
-
end
|
23
|
-
|
24
|
-
def chat_completion
|
25
|
-
chat_completions&.dig(0, "content")
|
26
|
-
end
|
27
|
-
|
28
|
-
def chat_completions
|
29
|
-
raw_response.dig("candidates")
|
30
|
-
end
|
31
|
-
|
32
|
-
def embeddings
|
33
|
-
[raw_response.dig("embedding", "value")]
|
34
|
-
end
|
35
|
-
|
36
|
-
def role
|
37
|
-
"assistant"
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|