diff --git a/lib/langchain/vectorsearch/weaviate.rb b/lib/langchain/vectorsearch/weaviate.rb index 46d25458d..5d7545488 100644 --- a/lib/langchain/vectorsearch/weaviate.rb +++ b/lib/langchain/vectorsearch/weaviate.rb @@ -9,7 +9,7 @@ class Weaviate < Base # gem "weaviate-ruby", "~> 0.8.9" # # Usage: - # weaviate = Langchain::Vectorsearch::Weaviate.new(url:, api_key:, index_name:, llm:) + # weaviate = Langchain::Vectorsearch::Weaviate.new(url: ENV["WEAVIATE_URL"], api_key: ENV["WEAVIATE_API_KEY"], index_name: "Docs", llm: llm) # # Initialize the Weaviate adapter @@ -71,6 +71,22 @@ def update_texts(texts:, ids:) end end + # Deletes a list of texts in the index + # @param ids [Array] The ids of texts to delete + # @return [Hash] The response from the server + def remove_texts(ids:) + raise ArgumentError, "ids must be an array" unless ids.is_a?(Array) + + client.objects.batch_delete( + class_name: index_name, + where: { + path: ["__id"], + operator: "ContainsAny", + valueTextArray: ids + } + ) + end + # Create default schema # @return [Hash] The response from the server def create_default_schema diff --git a/spec/fixtures/vectorsearch/weaviate/batch_delete.json b/spec/fixtures/vectorsearch/weaviate/batch_delete.json new file mode 100644 index 000000000..e09eff96d --- /dev/null +++ b/spec/fixtures/vectorsearch/weaviate/batch_delete.json @@ -0,0 +1,20 @@ +{ + "dryRun": false, + "match": { + "class": "Products", + "where": { + "operands": null, + "operator": "ContainsAny", + "path": ["__id"], + "valueTextArray": ["999"] + } + }, + "output": "minimal", + "results": { + "failed": 0, + "limit": 100000, + "matches": 1, + "objects": null, + "successful": 1 + } +} diff --git a/spec/langchain/vectorsearch/weaviate_spec.rb b/spec/langchain/vectorsearch/weaviate_spec.rb index c40f92f59..c09a74fb7 100644 --- a/spec/langchain/vectorsearch/weaviate_spec.rb +++ b/spec/langchain/vectorsearch/weaviate_spec.rb @@ -7,7 +7,7 @@ described_class.new( url: "http://localhost:8080", api_key: "123", - index_name: "products", + index_name: "Products", llm: Langchain::LLM::OpenAI.new(api_key: "123") ) } @@ -55,7 +55,7 @@ def stub(id) ).to receive(:batch_create) .with( objects: [{ - class: "products", + class: "Products", properties: {__id: id.to_s, content: "Hello World"}, vector: [-0.0018150936, 0.0017554426, -0.022715086] }] @@ -120,6 +120,23 @@ def stub(id) end end + describe "#remove_texts" do + let(:fixture) { JSON.parse(File.read("spec/fixtures/vectorsearch/weaviate/batch_delete.json")) } + + let(:record) { + [{"_additional" => {"id" => "372ba500-01af-4448-aa03-21f3dd25a456"}}] + } + + before do + allow(subject.client.query).to receive(:get).and_return(record) + allow(subject.client.objects).to receive(:batch_delete).and_return(fixture) + end + + it "removes texts" do + expect(subject.remove_texts(ids: [1]).dig("results", "successful")).to eq(1) + end + end + describe "#similarity_search" do let(:fixture) { JSON.parse(File.read("spec/fixtures/vectorsearch/weaviate/search.json")) } @@ -128,7 +145,7 @@ def stub(id) subject.client.query ).to receive(:get) .with( - class_name: "products", + class_name: "Products", near_vector: "{ vector: [-0.0018150936, 0.0017554426, -0.022715086] }", limit: "4", fields: "__id content _additional { id }" @@ -158,7 +175,7 @@ def stub(id) subject.client.query ).to receive(:get) .with( - class_name: "products", + class_name: "Products", near_vector: "{ vector: [0.1, 0.2, 0.3] }", limit: "4", fields: "__id content _additional { id }"