This is an automated email from the ASF dual-hosted git repository.
ishan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/main by this push:
new cba99d5735d SOLR-17892: Add support for cuVS-Lucene as a pluggable
codec in Solr (#3615)
cba99d5735d is described below
commit cba99d5735db0ae42fe6bc48b900dc853caff2ca
Author: Vivek Narang <[email protected]>
AuthorDate: Mon Sep 29 09:01:17 2025 -0400
SOLR-17892: Add support for cuVS-Lucene as a pluggable codec in Solr (#3615)
Co-authored-by: Ishan Chattopadhyaya <[email protected]>
---
gradle/globals.gradle | 5 +
gradle/libs.versions.toml | 2 +
.../randomization/policies/solr-tests.policy | 2 +
settings.gradle | 1 +
solr/CHANGES.txt | 2 +
solr/licenses/cuvs-java-25.10.0.jar.sha1 | 1 +
solr/licenses/cuvs-java-LICENSE-ASL.txt | 201 +++++++++++++++
solr/licenses/cuvs-java-NOTICE.txt | 0
solr/licenses/cuvs-lucene-25.10.0.jar.sha1 | 1 +
solr/licenses/cuvs-lucene-LICENSE-ASL.txt | 201 +++++++++++++++
solr/licenses/cuvs-lucene-NOTICE.txt | 0
solr/modules/cuvs/README.md | 26 ++
solr/modules/cuvs/build.gradle | 34 +++
solr/modules/cuvs/gradle.lockfile | 162 ++++++++++++
.../src/java/org/apache/solr/cuvs/CuVSCodec.java | 124 +++++++++
.../org/apache/solr/cuvs/CuVSCodecFactory.java | 59 +++++
.../java/org/apache/solr/cuvs/package-info.java | 21 ++
solr/modules/cuvs/src/java/overview.html | 21 ++
solr/modules/cuvs/src/test-files/log4j2.xml | 40 +++
.../test-files/solr/collection1/conf/schema.xml | 34 +++
.../solr/collection1/conf/solrconfig.xml | 41 +++
solr/modules/cuvs/src/test-files/solr/solr.xml | 41 +++
.../apache/solr/cuvs/TestCuVSCodecSupportIT.java | 164 ++++++++++++
solr/server/etc/security.policy | 3 +
.../query-guide/pages/dense-vector-search.adoc | 279 ++++++++++++++++++++-
25 files changed, 1464 insertions(+), 1 deletion(-)
diff --git a/gradle/globals.gradle b/gradle/globals.gradle
index 70aa7ef3ab5..4834c5a4cce 100644
--- a/gradle/globals.gradle
+++ b/gradle/globals.gradle
@@ -25,6 +25,11 @@ allprojects {
// Repositories to fetch dependencies from.
repositories {
mavenCentral()
+ // Note: The maven repository below is temorary and will be removed
eventually.
+ maven {
+ name "SearchScale"
+ url "https://maven.searchscale.com/snapshots"
+ }
/* Reenable this if we need it again in future
maven {
name "LucenePrerelease${lucenePrereleaseBuild}"
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index a3783feaac1..985722ff5e8 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -75,6 +75,7 @@ commons-codec = "1.19.0"
commons-io = "2.15.1"
compose = "1.8.2"
cutterslade-analyze = "1.10.0"
+cuvs-lucene = "25.10.0"
cybozulabs-langdetect = "1.1-20120112"
decompose = "3.3.0"
diffplug-spotless = "7.2.1"
@@ -314,6 +315,7 @@ codehaus-woodstox-stax2api = { module =
"org.codehaus.woodstox:stax2-api", versi
commonscli-commonscli = { module = "commons-cli:commons-cli", version.ref =
"commons-cli" }
commonscodec-commonscodec = { module = "commons-codec:commons-codec",
version.ref = "commons-codec" }
commonsio-commonsio = { module = "commons-io:commons-io", version.ref =
"commons-io" }
+cuvs-lucene = { module = "com.nvidia.cuvs.lucene:cuvs-lucene", version.ref =
"cuvs-lucene" }
cybozulabs-langdetect = { module = "com.cybozu.labs:langdetect", version.ref =
"cybozulabs-langdetect" }
decompose-decompose = { module = "com.arkivanov.decompose:decompose",
version.ref = "decompose" }
decompose-extensions-compose = { module =
"com.arkivanov.decompose:extensions-compose", version.ref = "decompose" }
diff --git a/gradle/testing/randomization/policies/solr-tests.policy
b/gradle/testing/randomization/policies/solr-tests.policy
index 2d3246c6d9b..5dbd7f3449f 100644
--- a/gradle/testing/randomization/policies/solr-tests.policy
+++ b/gradle/testing/randomization/policies/solr-tests.policy
@@ -276,4 +276,6 @@ grant {
permission java.io.FilePermission "${lucene-dev-path.dir}${/}-", "read";
// Allow testing effects of customized or bug-fixed dependencies locally
(also need to add mavenLocal() to build)
permission java.io.FilePermission "${user.home}${/}.m2${/}repository${/}-",
"read";
+
+ permission java.lang.RuntimePermission "loadLibrary.cudart";
};
diff --git a/settings.gradle b/settings.gradle
index 4a16234cc52..3f1737a45ea 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -46,6 +46,7 @@ include "solr:server"
include "solr:modules:analysis-extras"
include "solr:modules:clustering"
include "solr:modules:cross-dc"
+include "solr:modules:cuvs"
include "solr:modules:opentelemetry"
include "solr:modules:extraction"
include "solr:modules:gcs-repository"
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 3dccd4cd69e..5d068539073 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -21,6 +21,8 @@ New Features
* SOLR-17780: Add support for scalar quantized dense vectors (Kevin Liang via
Alessandro Benedetti)
+* SOLR-17892: Add support for cuVS-Lucene as a pluggable codec in Solr (Vivek
Narang, Ishan Chattopadhyaya)
+
* SOLR-17812: Add support for binary quantized dense vectors (Kevin Liang via
Alessandro Benedetti)
* SOLR-17023: Use Modern NLP Models from Apache OpenNLP with Solr (Jeff
Zemerick, Eric Pugh)
diff --git a/solr/licenses/cuvs-java-25.10.0.jar.sha1
b/solr/licenses/cuvs-java-25.10.0.jar.sha1
new file mode 100644
index 00000000000..0ebe3a3840e
--- /dev/null
+++ b/solr/licenses/cuvs-java-25.10.0.jar.sha1
@@ -0,0 +1 @@
+61f3a3ce565a659d296775a7b06fc20dabccee41
diff --git a/solr/licenses/cuvs-java-LICENSE-ASL.txt
b/solr/licenses/cuvs-java-LICENSE-ASL.txt
new file mode 100644
index 00000000000..261eeb9e9f8
--- /dev/null
+++ b/solr/licenses/cuvs-java-LICENSE-ASL.txt
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/solr/licenses/cuvs-java-NOTICE.txt
b/solr/licenses/cuvs-java-NOTICE.txt
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/solr/licenses/cuvs-lucene-25.10.0.jar.sha1
b/solr/licenses/cuvs-lucene-25.10.0.jar.sha1
new file mode 100644
index 00000000000..cee312df718
--- /dev/null
+++ b/solr/licenses/cuvs-lucene-25.10.0.jar.sha1
@@ -0,0 +1 @@
+b5a458458255bfdfa6688a571b5bee032428f2d4
diff --git a/solr/licenses/cuvs-lucene-LICENSE-ASL.txt
b/solr/licenses/cuvs-lucene-LICENSE-ASL.txt
new file mode 100644
index 00000000000..261eeb9e9f8
--- /dev/null
+++ b/solr/licenses/cuvs-lucene-LICENSE-ASL.txt
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/solr/licenses/cuvs-lucene-NOTICE.txt
b/solr/licenses/cuvs-lucene-NOTICE.txt
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/solr/modules/cuvs/README.md b/solr/modules/cuvs/README.md
new file mode 100644
index 00000000000..a3d69fddb16
--- /dev/null
+++ b/solr/modules/cuvs/README.md
@@ -0,0 +1,26 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+Welcome to Apache Solr's cuVS module!
+========
+
+> [!CAUTION]
+> This feature is currently experimental.
+
+This module provides the codecs for enabling GPU-based accelerated vector
search capability.
+
+For more information please refer to the Query Guide / Query Syntax and
Parsers / Dense Vector Search in the ref guide.
\ No newline at end of file
diff --git a/solr/modules/cuvs/build.gradle b/solr/modules/cuvs/build.gradle
new file mode 100644
index 00000000000..d00eed9b1a3
--- /dev/null
+++ b/solr/modules/cuvs/build.gradle
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+apply plugin: 'java-library'
+
+description = 'cuVS plugin'
+
+dependencies {
+ implementation libs.cuvs.lucene
+ implementation project(':solr:core')
+ implementation project(':solr:solrj')
+ implementation libs.apache.lucene.core
+ implementation libs.slf4j.api
+
+ testImplementation project(':solr:test-framework')
+ testImplementation libs.apache.lucene.testframework
+ testImplementation libs.junit.junit
+ testImplementation libs.commonsio.commonsio
+}
+
diff --git a/solr/modules/cuvs/gradle.lockfile
b/solr/modules/cuvs/gradle.lockfile
new file mode 100644
index 00000000000..37d36a3d639
--- /dev/null
+++ b/solr/modules/cuvs/gradle.lockfile
@@ -0,0 +1,162 @@
+# This is a Gradle generated file for dependency locking.
+# Manual edits can break the build and are not advised.
+# This file is expected to be part of source control.
+com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.3=jarValidation,testCompileClasspath,testRuntimeClasspath
+com.carrotsearch:hppc:0.10.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+com.fasterxml.jackson.core:jackson-annotations:2.20=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+com.fasterxml.jackson.core:jackson-core:2.20.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+com.fasterxml.jackson.core:jackson-databind:2.20.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.20.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.20.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+com.fasterxml.jackson.module:jackson-module-jakarta-xmlbind-annotations:2.20.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+com.fasterxml.jackson:jackson-bom:2.20.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+com.fasterxml.woodstox:woodstox-core:7.0.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+com.github.ben-manes.caffeine:caffeine:3.2.2=annotationProcessor,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testRuntimeClasspath
+com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.auto.value:auto-value-annotations:1.11.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_annotations:2.41.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
+com.google.errorprone:error_prone_check_api:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.errorprone:error_prone_core:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.googlejavaformat:google-java-format:1.27.0=annotationProcessor,errorprone,testAnnotationProcessor
+com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
+com.google.guava:guava:33.4.8-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
+com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
+com.google.j2objc:j2objc-annotations:3.1=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
+com.google.protobuf:protobuf-java:3.25.8=annotationProcessor,errorprone,testAnnotationProcessor
+com.j256.simplemagic:simplemagic:1.17=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+com.jayway.jsonpath:json-path:2.9.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+com.lmax:disruptor:3.4.4=solrPlatformLibs
+com.nvidia.cuvs.lucene:cuvs-lucene:25.10.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath
+com.nvidia.cuvs:cuvs-java:25.10.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath
+com.tdunning:t-digest:3.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+commons-cli:commons-cli:1.10.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+commons-codec:commons-codec:1.19.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+commons-io:commons-io:2.17.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+io.dropwizard.metrics:metrics-annotation:4.2.26=jarValidation,solrPlatformLibs,testRuntimeClasspath
+io.dropwizard.metrics:metrics-core:4.2.26=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+io.dropwizard.metrics:metrics-graphite:4.2.26=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+io.dropwizard.metrics:metrics-jetty12-ee10:4.2.26=jarValidation,solrPlatformLibs,testRuntimeClasspath
+io.dropwizard.metrics:metrics-jetty12:4.2.26=jarValidation,solrPlatformLibs,testRuntimeClasspath
+io.dropwizard.metrics:metrics-jmx:4.2.26=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+io.dropwizard.metrics:metrics-jvm:4.2.26=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+io.github.eisop:dataflow-errorprone:3.41.0-eisop1=annotationProcessor,errorprone,testAnnotationProcessor
+io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,errorprone,testAnnotationProcessor
+io.netty:netty-buffer:4.2.4.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+io.netty:netty-codec-base:4.2.4.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+io.netty:netty-common:4.2.4.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+io.netty:netty-handler:4.2.4.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+io.netty:netty-resolver:4.2.4.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+io.netty:netty-tcnative-boringssl-static:2.0.70.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+io.netty:netty-tcnative-classes:2.0.70.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+io.netty:netty-transport-classes-epoll:4.2.4.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+io.netty:netty-transport-native-epoll:4.2.4.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+io.netty:netty-transport-native-unix-common:4.2.4.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+io.netty:netty-transport:4.2.4.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+io.opentelemetry:opentelemetry-api:1.53.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+io.opentelemetry:opentelemetry-common:1.53.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+io.opentelemetry:opentelemetry-context:1.53.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+io.prometheus:prometheus-metrics-exposition-formats:1.1.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+io.prometheus:prometheus-metrics-model:1.1.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+io.sgr:s2-geometry-library-java:1.0.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.22=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+jakarta.annotation:jakarta.annotation-api:2.1.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+jakarta.inject:jakarta.inject-api:2.0.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+jakarta.servlet:jakarta.servlet-api:6.0.0=jarValidation,testCompileClasspath,testRuntimeClasspath
+jakarta.validation:jakarta.validation-api:3.0.2=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+jakarta.ws.rs:jakarta.ws.rs-api:3.1.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+javax.inject:javax.inject:1=annotationProcessor,errorprone,testAnnotationProcessor
+junit:junit:4.13.2=jarValidation,testCompileClasspath,testRuntimeClasspath
+org.antlr:antlr4-runtime:4.13.2=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.commons:commons-exec:1.5.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.commons:commons-lang3:3.18.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.commons:commons-math3:3.6.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.curator:curator-client:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+org.apache.curator:curator-framework:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath
+org.apache.httpcomponents:httpclient:4.5.14=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.httpcomponents:httpcore:4.4.16=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.httpcomponents:httpmime:4.5.14=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.logging.log4j:log4j-1.2-api:2.21.0=solrPlatformLibs
+org.apache.logging.log4j:log4j-api:2.21.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.logging.log4j:log4j-core:2.21.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.logging.log4j:log4j-layout-template-json:2.21.0=solrPlatformLibs
+org.apache.logging.log4j:log4j-slf4j2-impl:2.21.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.logging.log4j:log4j-web:2.21.0=solrPlatformLibs
+org.apache.lucene:lucene-analysis-common:10.2.1=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+org.apache.lucene:lucene-analysis-kuromoji:10.2.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.lucene:lucene-analysis-nori:10.2.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.lucene:lucene-analysis-phonetic:10.2.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.lucene:lucene-backward-codecs:10.2.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.lucene:lucene-classification:10.2.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.lucene:lucene-codecs:10.2.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.lucene:lucene-core:10.2.1=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+org.apache.lucene:lucene-expressions:10.2.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.lucene:lucene-facet:10.2.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.lucene:lucene-grouping:10.2.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.lucene:lucene-highlighter:10.2.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.lucene:lucene-join:10.2.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.lucene:lucene-memory:10.2.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.lucene:lucene-misc:10.2.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.lucene:lucene-queries:10.2.1=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+org.apache.lucene:lucene-queryparser:10.2.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.lucene:lucene-sandbox:10.2.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.lucene:lucene-spatial-extras:10.2.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.lucene:lucene-spatial3d:10.2.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.lucene:lucene-suggest:10.2.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.apache.lucene:lucene-test-framework:10.2.1=jarValidation,testCompileClasspath,testRuntimeClasspath
+org.apache.zookeeper:zookeeper-jute:3.9.4=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+org.apache.zookeeper:zookeeper:3.9.4=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+org.apiguardian:apiguardian-api:1.1.2=jarValidation,testRuntimeClasspath
+org.codehaus.woodstox:stax2-api:4.2.2=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.eclipse.jetty.ee10:jetty-ee10-servlet:12.0.19=jarValidation,testCompileClasspath,testRuntimeClasspath
+org.eclipse.jetty.http2:jetty-http2-client-transport:12.0.19=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.eclipse.jetty.http2:jetty-http2-client:12.0.19=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+org.eclipse.jetty.http2:jetty-http2-common:12.0.19=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+org.eclipse.jetty.http2:jetty-http2-hpack:12.0.19=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+org.eclipse.jetty.http2:jetty-http2-server:12.0.19=jarValidation,testRuntimeClasspath
+org.eclipse.jetty.toolchain:jetty-jakarta-servlet-api:5.0.2=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.eclipse.jetty:jetty-alpn-client:12.0.19=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+org.eclipse.jetty:jetty-alpn-java-client:12.0.19=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.eclipse.jetty:jetty-alpn-java-server:12.0.19=jarValidation,testRuntimeClasspath
+org.eclipse.jetty:jetty-alpn-server:12.0.19=jarValidation,testRuntimeClasspath
+org.eclipse.jetty:jetty-client:12.0.19=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.eclipse.jetty:jetty-http:12.0.19=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+org.eclipse.jetty:jetty-io:12.0.19=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+org.eclipse.jetty:jetty-rewrite:12.0.19=jarValidation,testRuntimeClasspath
+org.eclipse.jetty:jetty-security:12.0.19=jarValidation,testCompileClasspath,testRuntimeClasspath
+org.eclipse.jetty:jetty-server:12.0.19=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+org.eclipse.jetty:jetty-session:12.0.19=jarValidation,testCompileClasspath,testRuntimeClasspath
+org.eclipse.jetty:jetty-util:12.0.19=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+org.glassfish.hk2.external:aopalliance-repackaged:3.1.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.glassfish.hk2:hk2-api:3.1.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.glassfish.hk2:hk2-locator:3.1.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.glassfish.hk2:hk2-utils:3.1.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.glassfish.hk2:osgi-resource-locator:1.0.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.glassfish.jersey.containers:jersey-container-jetty-http:2.39.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.glassfish.jersey.core:jersey-client:3.1.11=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.glassfish.jersey.core:jersey-common:3.1.11=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.glassfish.jersey.core:jersey-server:3.1.11=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.glassfish.jersey.ext:jersey-entity-filtering:3.1.11=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.glassfish.jersey.inject:jersey-hk2:3.1.11=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.glassfish.jersey.media:jersey-media-json-jackson:3.1.11=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.hamcrest:hamcrest:3.0=jarValidation,testCompileClasspath,testRuntimeClasspath
+org.javassist:javassist:3.30.2-GA=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.jspecify:jspecify:1.0.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
+org.junit.jupiter:junit-jupiter-api:5.6.2=jarValidation,testRuntimeClasspath
+org.junit.platform:junit-platform-commons:1.6.2=jarValidation,testRuntimeClasspath
+org.junit:junit-bom:5.6.2=jarValidation,testRuntimeClasspath
+org.locationtech.spatial4j:spatial4j:0.8=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.opentest4j:opentest4j:1.2.0=jarValidation,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.8=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.ow2.asm:asm-tree:9.8=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.ow2.asm:asm:9.8=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.pcollections:pcollections:4.0.1=annotationProcessor,errorprone,testAnnotationProcessor
+org.semver4j:semver4j:6.0.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.slf4j:jcl-over-slf4j:2.0.17=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+org.slf4j:jul-to-slf4j:2.0.17=solrPlatformLibs
+org.slf4j:slf4j-api:2.0.17=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
+org.xerial.snappy:snappy-java:1.1.10.8=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
+empty=apiHelper,apiHelperTest,compileOnlyHelper,compileOnlyHelperTest,generatedPythonClient,localPythonClientCopy,missingdoclet,packaging,permitAggregatorUse,permitTestAggregatorUse,permitTestUnusedDeclared,permitTestUsedUndeclared,permitUnusedDeclared,permitUsedUndeclared,signatures
diff --git a/solr/modules/cuvs/src/java/org/apache/solr/cuvs/CuVSCodec.java
b/solr/modules/cuvs/src/java/org/apache/solr/cuvs/CuVSCodec.java
new file mode 100644
index 00000000000..0c451bc863d
--- /dev/null
+++ b/solr/modules/cuvs/src/java/org/apache/solr/cuvs/CuVSCodec.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.cuvs;
+
+import com.nvidia.cuvs.lucene.Lucene99AcceleratedHNSWVectorsFormat;
+import java.lang.invoke.MethodHandles;
+import org.apache.lucene.codecs.FilterCodec;
+import org.apache.lucene.codecs.KnnVectorsFormat;
+import org.apache.lucene.codecs.lucene101.Lucene101Codec;
+import org.apache.lucene.codecs.perfield.PerFieldKnnVectorsFormat;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.schema.DenseVectorField;
+import org.apache.solr.schema.FieldType;
+import org.apache.solr.schema.SchemaField;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This codec utilizes the Lucene99AcceleratedHNSWVectorsFormat from the
lucene-cuvs library to
+ * enable GPU-based accelerated vector search.
+ *
+ * @since 10.0.0
+ */
+public class CuVSCodec extends FilterCodec {
+
+ private static final Logger log =
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ private static final int DEFAULT_CUVS_WRITER_THREADS = 32;
+ private static final int DEFAULT_INT_GRAPH_DEGREE = 128;
+ private static final int DEFAULT_GRAPH_DEGREE = 64;
+ private static final int DEFAULT_HNSW_LAYERS = 1;
+ private static final int DEFAULT_MAX_CONN = 16;
+ private static final int DEFAULT_BEAM_WIDTH = 100;
+
+ private static final String CAGRA_HNSW = "cagra_hnsw";
+ private static final String FALLBACK_CODEC = "Lucene101";
+
+ private final SolrCore core;
+ private final Lucene101Codec fallbackCodec;
+ private final Lucene99AcceleratedHNSWVectorsFormat cuvsHNSWVectorsFormat;
+
+ public CuVSCodec(SolrCore core, Lucene101Codec fallback, NamedList<?> args) {
+ super(FALLBACK_CODEC, fallback);
+ this.core = core;
+ this.fallbackCodec = fallback;
+
+ String cwt = args._getStr("cuvsWriterThreads");
+ int cuvsWriterThreads = cwt != null ? Integer.parseInt(cwt) :
DEFAULT_CUVS_WRITER_THREADS;
+ String igd = args._getStr("intGraphDegree");
+ int intGraphDegree = igd != null ? Integer.parseInt(igd) :
DEFAULT_INT_GRAPH_DEGREE;
+ String gd = args._getStr("graphDegree");
+ int graphDegree = gd != null ? Integer.parseInt(gd) : DEFAULT_GRAPH_DEGREE;
+ String hl = args._getStr("hnswLayers");
+ int hnswLayers = hl != null ? Integer.parseInt(hl) : DEFAULT_HNSW_LAYERS;
+ String mc = args._getStr("maxConn");
+ int maxConn = mc != null ? Integer.parseInt(mc) : DEFAULT_MAX_CONN;
+ String bw = args._getStr("beamWidth");
+ int beamWidth = bw != null ? Integer.parseInt(bw) : DEFAULT_BEAM_WIDTH;
+
+ assert cuvsWriterThreads > 0 : "cuvsWriterThreads cannot be less then or
equal to 0";
+ assert intGraphDegree > 0 : "intGraphDegree cannot be less then or equal
to 0";
+ assert graphDegree > 0 : "graphDegree cannot be less then or equal to 0";
+ assert hnswLayers > 0 : "hnswLayers cannot be less then or equal to 0";
+ assert maxConn > 0 : "max connections cannot be less then or equal to 0";
+ assert beamWidth > 0 : "beam width cannot be less then or equal to 0";
+
+ cuvsHNSWVectorsFormat =
+ new Lucene99AcceleratedHNSWVectorsFormat(
+ cuvsWriterThreads, intGraphDegree, graphDegree, hnswLayers,
maxConn, beamWidth);
+
+ if (log.isInfoEnabled()) {
+ log.info(
+ "Lucene99AcceleratedHNSWVectorsFormat initialized with parameter
values: cuvsWriterThreads {}, intGraphDegree {}, graphDegree {}, hnswLayers {},
maxConn {}, beamWidth {}",
+ cuvsWriterThreads,
+ intGraphDegree,
+ graphDegree,
+ hnswLayers,
+ maxConn,
+ beamWidth);
+ }
+ }
+
+ @Override
+ public KnnVectorsFormat knnVectorsFormat() {
+ return perFieldKnnVectorsFormat;
+ }
+
+ private PerFieldKnnVectorsFormat perFieldKnnVectorsFormat =
+ new PerFieldKnnVectorsFormat() {
+ @Override
+ public KnnVectorsFormat getKnnVectorsFormatForField(String field) {
+ final SchemaField schemaField =
core.getLatestSchema().getFieldOrNull(field);
+ FieldType fieldType = (schemaField == null ? null :
schemaField.getType());
+ if (fieldType instanceof DenseVectorField vectorType) {
+ String knnAlgorithm = vectorType.getKnnAlgorithm();
+ if (CAGRA_HNSW.equals(knnAlgorithm)) {
+ return cuvsHNSWVectorsFormat;
+ } else if (DenseVectorField.HNSW_ALGORITHM.equals(knnAlgorithm)) {
+ return fallbackCodec.getKnnVectorsFormatForField(field);
+ } else {
+ throw new SolrException(
+ SolrException.ErrorCode.SERVER_ERROR,
+ knnAlgorithm + " KNN algorithm is not supported");
+ }
+ }
+ return fallbackCodec.getKnnVectorsFormatForField(field);
+ }
+ };
+}
diff --git
a/solr/modules/cuvs/src/java/org/apache/solr/cuvs/CuVSCodecFactory.java
b/solr/modules/cuvs/src/java/org/apache/solr/cuvs/CuVSCodecFactory.java
new file mode 100644
index 00000000000..8356d4784de
--- /dev/null
+++ b/solr/modules/cuvs/src/java/org/apache/solr/cuvs/CuVSCodecFactory.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.cuvs;
+
+import org.apache.lucene.codecs.Codec;
+import org.apache.lucene.codecs.lucene101.Lucene101Codec;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.CodecFactory;
+import org.apache.solr.core.SchemaCodecFactory;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.util.plugin.SolrCoreAware;
+
+public class CuVSCodecFactory extends CodecFactory implements SolrCoreAware {
+
+ private final SchemaCodecFactory fallback;
+ private SolrCore core;
+ NamedList<?> args;
+ Lucene101Codec fallbackCodec;
+ CuVSCodec codec;
+
+ public CuVSCodecFactory() {
+ this.fallback = new SchemaCodecFactory();
+ }
+
+ @Override
+ public Codec getCodec() {
+ if (codec == null) {
+ fallbackCodec = (Lucene101Codec) fallback.getCodec();
+ codec = new CuVSCodec(core, fallbackCodec, args);
+ }
+ return codec;
+ }
+
+ @Override
+ public void inform(SolrCore solrCore) {
+ fallback.inform(solrCore);
+ this.core = solrCore;
+ }
+
+ @Override
+ public void init(NamedList<?> args) {
+ fallback.init(args);
+ this.args = args;
+ }
+}
diff --git a/solr/modules/cuvs/src/java/org/apache/solr/cuvs/package-info.java
b/solr/modules/cuvs/src/java/org/apache/solr/cuvs/package-info.java
new file mode 100644
index 00000000000..af510147775
--- /dev/null
+++ b/solr/modules/cuvs/src/java/org/apache/solr/cuvs/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Contains the {@link org.apache.solr.cuvs.CuVSCodec} to enable GPU-based
accelerated vector search
+ */
+package org.apache.solr.cuvs;
diff --git a/solr/modules/cuvs/src/java/overview.html
b/solr/modules/cuvs/src/java/overview.html
new file mode 100644
index 00000000000..32baf7f2f84
--- /dev/null
+++ b/solr/modules/cuvs/src/java/overview.html
@@ -0,0 +1,21 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<html>
+<body>
+Apache Solr Search Server: Cuvs module
+</body>
+</html>
diff --git a/solr/modules/cuvs/src/test-files/log4j2.xml
b/solr/modules/cuvs/src/test-files/log4j2.xml
new file mode 100644
index 00000000000..528299e3e0b
--- /dev/null
+++ b/solr/modules/cuvs/src/test-files/log4j2.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<!-- We're configuring testing to be synchronous due to "logging polution",
see SOLR-13268 -->
+<Configuration>
+ <Appenders>
+ <Console name="STDERR" target="SYSTEM_ERR">
+ <PatternLayout>
+ <Pattern>
+ %maxLen{%-4r %-5p (%t) [%notEmpty{n:%X{node_name}}%notEmpty{
c:%X{collection}}%notEmpty{ s:%X{shard}}%notEmpty{ r:%X{replica}}%notEmpty{
x:%X{core}}%notEmpty{ t:%X{trace_id}}] %c{1.} %m%notEmpty{
+ =>%ex{short}}}{10240}%n
+ </Pattern>
+ </PatternLayout>
+ </Console>
+ </Appenders>
+ <Loggers>
+ <!-- Use <AsyncLogger/<AsyncRoot and <Logger/<Root for asynchronous
logging or synchonous logging respectively -->
+ <Logger name="org.apache.zookeeper" level="WARN"/>
+ <Logger name="org.apache.directory" level="WARN"/>
+ <Logger name="org.eclipse.jetty" level="INFO"/>
+
+ <Root level="INFO">
+ <AppenderRef ref="STDERR"/>
+ </Root>
+ </Loggers>
+</Configuration>
diff --git a/solr/modules/cuvs/src/test-files/solr/collection1/conf/schema.xml
b/solr/modules/cuvs/src/test-files/solr/collection1/conf/schema.xml
new file mode 100644
index 00000000000..122eed5c464
--- /dev/null
+++ b/solr/modules/cuvs/src/test-files/solr/collection1/conf/schema.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Test schema file for DenseVectorField -->
+
+<schema name="schema-densevector" version="1.7">
+ <fieldType name="string" class="solr.StrField" multiValued="true"/>
+ <fieldType name="knn_vector1" class="solr.DenseVectorField"
vectorDimension="8" knnAlgorithm="cagra_hnsw" similarityFunction="cosine"/>
+ <fieldType name="knn_vector2" class="solr.DenseVectorField"
vectorDimension="8" similarityFunction="cosine"/>
+
+ <fieldType name="plong" class="solr.LongPointField"
useDocValuesAsStored="false"/>
+
+ <field name="id" type="string" indexed="true" stored="true"
multiValued="false" required="false"/>
+ <field name="vector_field1" type="knn_vector1" indexed="true"
stored="true"/>
+ <field name="vector_field2" type="knn_vector2" indexed="true"
stored="true"/>
+
+ <field name="_version_" type="plong" indexed="true" stored="true"
multiValued="false"/>
+ <uniqueKey>id</uniqueKey>
+</schema>
diff --git
a/solr/modules/cuvs/src/test-files/solr/collection1/conf/solrconfig.xml
b/solr/modules/cuvs/src/test-files/solr/collection1/conf/solrconfig.xml
new file mode 100644
index 00000000000..38551201f6f
--- /dev/null
+++ b/solr/modules/cuvs/src/test-files/solr/collection1/conf/solrconfig.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" ?>
+<!--
+ This software was produced for the U. S. Government
+ under Contract No. W15P7T-11-C-F600, and is
+ subject to the Rights in Noncommercial Computer Software
+ and Noncommercial Computer Software Documentation
+ Clause 252.227-7014 (JUN 1995)
+
+ Copyright 2013 The MITRE Corporation. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!-- a basic solrconfig that tests can use when they want simple minimal
solrconfig/schema
+ DO NOT ADD THINGS TO THIS CONFIG! -->
+<config>
+ <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
+ <dataDir>${solr.data.dir:}</dataDir>
+ <directoryFactory name="DirectoryFactory"
class="${solr.directoryFactory:solr.MockDirectoryFactory}"/>
+
+ <codecFactory name="CuVSCodecFactory"
class="org.apache.solr.cuvs.CuVSCodecFactory">
+ <str name="cuvsWriterThreads">32</str>
+ <str name="intGraphDegree">128</str>
+ <str name="graphDegree">64</str>
+ <str name="hnswLayers">1</str>
+ <str name="maxConn">16</str>
+ <str name="beamWidth">100</str>
+ </codecFactory>
+
+ <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
+</config>
diff --git a/solr/modules/cuvs/src/test-files/solr/solr.xml
b/solr/modules/cuvs/src/test-files/solr/solr.xml
new file mode 100644
index 00000000000..7506c1c8951
--- /dev/null
+++ b/solr/modules/cuvs/src/test-files/solr/solr.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<solr>
+
+ <str name="shareSchema">${shareSchema:false}</str>
+ <str name="configSetBaseDir">${configSetBaseDir:configsets}</str>
+ <str name="coreRootDirectory">${coreRootDirectory:.}</str>
+
+ <shardHandlerFactory name="shardHandlerFactory"
class="HttpShardHandlerFactory">
+ <str name="urlScheme">${urlScheme:}</str>
+ <int name="socketTimeout">${socketTimeout:90000}</int>
+ <int name="connTimeout">${connTimeout:15000}</int>
+ </shardHandlerFactory>
+
+ <solrcloud>
+ <str name="host">127.0.0.1</str>
+ <int name="hostPort">${hostPort:8983}</int>
+ <int name="zkClientTimeout">${solr.zkclienttimeout:30000}</int>
+ <bool name="genericCoreNodeNames">${genericCoreNodeNames:true}</bool>
+ <int name="leaderVoteWait">${leaderVoteWait:10000}</int>
+ <int
name="distribUpdateConnTimeout">${distribUpdateConnTimeout:45000}</int>
+ <int name="distribUpdateSoTimeout">${distribUpdateSoTimeout:340000}</int>
+ </solrcloud>
+
+</solr>
diff --git
a/solr/modules/cuvs/src/test/org/apache/solr/cuvs/TestCuVSCodecSupportIT.java
b/solr/modules/cuvs/src/test/org/apache/solr/cuvs/TestCuVSCodecSupportIT.java
new file mode 100644
index 00000000000..5b1a238cb55
--- /dev/null
+++
b/solr/modules/cuvs/src/test/org/apache/solr/cuvs/TestCuVSCodecSupportIT.java
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.cuvs;
+
+import com.nvidia.cuvs.lucene.Lucene99AcceleratedHNSWVectorsFormat;
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import org.apache.commons.io.file.PathUtils;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.KnnFloatVectorQuery;
+import org.apache.lucene.search.ScoreDoc;
+import org.apache.lucene.search.TopDocs;
+import org.apache.lucene.tests.mockfile.FilterPath;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.common.SolrInputDocument;
+import org.apache.solr.core.SolrConfig;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.search.SolrIndexSearcher;
+import org.apache.solr.util.RefCounted;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Integration test to verify the indexing and searching using {@link
+ * org.apache.solr.cuvs.CuVSCodec}
+ *
+ * @since 10.0.0
+ */
+public class TestCuVSCodecSupportIT extends SolrTestCaseJ4 {
+
+ private static final Logger log =
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ private static Random random;
+ private static List<List<Float>> dataset1;
+ private static List<List<Float>> dataset2;
+ private static final int DATASET_SIZE = 1000;
+ private static final int DATASET_DIMENSION = 8;
+ private static final int TOPK = 5;
+ private static final String ID_FIELD = "id";
+ private static final String VECTOR_FIELD1 = "vector_field1";
+ private static final String VECTOR_FIELD2 = "vector_field2";
+ private static final String SOLRCONFIG_XML = "solrconfig.xml";
+ private static final String SCHEMA_XML = "schema.xml";
+ private static final String COLLECTION = "collection1";
+ private static final String CONF_DIR = COLLECTION + "/conf";
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ assumeTrue("Skipping cuvs tests",
Lucene99AcceleratedHNSWVectorsFormat.supported());
+ Path tmpSolrHome = createTempDir();
+ Path tmpConfDir = FilterPath.unwrap(tmpSolrHome.resolve(CONF_DIR));
+ Path testHomeConfDir = TEST_HOME().resolve(CONF_DIR);
+ Files.createDirectories(tmpConfDir);
+ PathUtils.copyFileToDirectory(testHomeConfDir.resolve(SOLRCONFIG_XML),
tmpConfDir);
+ PathUtils.copyFileToDirectory(testHomeConfDir.resolve(SCHEMA_XML),
tmpConfDir);
+
+ initCore(SOLRCONFIG_XML, SCHEMA_XML, tmpSolrHome);
+ random = new Random(222);
+ dataset1 = generateRandomVectors(random, DATASET_SIZE, DATASET_DIMENSION);
+ dataset2 = generateRandomVectors(random, DATASET_SIZE, DATASET_DIMENSION);
+ }
+
+ @Test
+ public void testIndexAndSearch() throws IOException {
+ SolrCore solrCore = h.getCore();
+ SolrConfig config = solrCore.getSolrConfig();
+ String codecFactory = config.get("codecFactory").attr("class");
+ assertEquals(
+ "Unexpected solrconfig codec factory",
+ "org.apache.solr.cuvs.CuVSCodecFactory",
+ codecFactory);
+ assertEquals("Unexpected core codec", "Lucene101",
solrCore.getCodec().getName());
+
+ // Index documents
+ for (int i = 0; i < DATASET_SIZE; i++) {
+ SolrInputDocument doc = new SolrInputDocument();
+ doc.addField(ID_FIELD, String.valueOf(i));
+ doc.addField(VECTOR_FIELD1, dataset1.get(i));
+ doc.addField(VECTOR_FIELD2, dataset2.get(i));
+ assertU(adoc(doc));
+ }
+ assertU(commit());
+
+ // Search documents
+ final RefCounted<SolrIndexSearcher> refCountedSearcher =
solrCore.getSearcher();
+ IndexSearcher searcher = refCountedSearcher.get();
+
+ KnnFloatVectorQuery q1 =
+ new KnnFloatVectorQuery(VECTOR_FIELD1, getQuery(random,
DATASET_DIMENSION), TOPK);
+ TopDocs results1 = searcher.search(q1, TOPK);
+ List<Integer> expected1 = Arrays.asList(390, 643, 127, 593, 627);
+ assertSearchResults(searcher, results1, expected1);
+
+ KnnFloatVectorQuery q2 =
+ new KnnFloatVectorQuery(VECTOR_FIELD2, getQuery(random,
DATASET_DIMENSION), TOPK);
+ TopDocs results2 = searcher.search(q2, TOPK);
+ List<Integer> expected2 = Arrays.asList(29, 88, 103, 915, 261);
+ assertSearchResults(searcher, results2, expected2);
+
+ refCountedSearcher.decref();
+ }
+
+ private static void assertSearchResults(
+ IndexSearcher searcher, TopDocs results, List<Integer> expected) throws
IOException {
+ if (log.isInfoEnabled()) {
+ log.info("Search results has ({} total hits)", results.totalHits);
+ }
+ int numResults = results.scoreDocs.length;
+ for (int i = 0; i < numResults; i++) {
+ ScoreDoc sd = results.scoreDocs[i];
+ Document doc = searcher.storedFields().document(sd.doc);
+ int r = i + 1;
+ if (log.isInfoEnabled()) {
+ log.info("Rank {}: doc {} (id={}), score: {}", r, sd.doc,
doc.get("id"), sd.score);
+ }
+ int idx = Integer.valueOf(doc.get("id"));
+ assertTrue("Expected doc id is missing:" + idx, expected.contains(idx));
+ }
+ assertTrue(numResults + " TopK results were returned instead of " + TOPK,
numResults == TOPK);
+ }
+
+ private static List<List<Float>> generateRandomVectors(Random random, int
size, int dimensions) {
+ List<List<Float>> dataset = new ArrayList<List<Float>>();
+ for (int i = 0; i < size; i++) {
+ List<Float> row = new ArrayList<Float>();
+ for (int j = 0; j < dimensions; j++) {
+ row.add(random.nextFloat() * 100);
+ }
+ dataset.add(row);
+ }
+ return dataset;
+ }
+
+ private static float[] getQuery(Random random, int dimension) {
+ List<Float> ql = generateRandomVectors(random, 1, dimension).get(0);
+ float[] query = new float[dimension];
+ for (int i = 0; i < dimension; i++) {
+ query[i] = ql.get(i);
+ }
+ return query;
+ }
+}
diff --git a/solr/server/etc/security.policy b/solr/server/etc/security.policy
index 2e65fc70e07..bd0be0fc42c 100644
--- a/solr/server/etc/security.policy
+++ b/solr/server/etc/security.policy
@@ -217,4 +217,7 @@ grant {
// expanded to a wildcard if set, allows all networking everywhere
permission java.net.SocketPermission "${solr.internal.network.permission}",
"accept,listen,connect,resolve";
+
+ // CUDA for GPU module (cuVS)
+ permission java.lang.RuntimePermission "loadLibrary.cudart";
};
diff --git
a/solr/solr-ref-guide/modules/query-guide/pages/dense-vector-search.adoc
b/solr/solr-ref-guide/modules/query-guide/pages/dense-vector-search.adoc
index c52fa7ffb08..942999f88c6 100644
--- a/solr/solr-ref-guide/modules/query-guide/pages/dense-vector-search.adoc
+++ b/solr/solr-ref-guide/modules/query-guide/pages/dense-vector-search.adoc
@@ -122,7 +122,7 @@ Here's how `DenseVectorField` can be configured with the
advanced hyperparameter
(advanced) Specifies the underlying knn algorithm to use
+
-Accepted values: `hnsw`.
+Accepted values: `hnsw`, `cagra_hnsw` (requires GPU acceleration setup).
Please note that the `knnAlgorithm` accepted values may change in future
releases.
@@ -657,6 +657,283 @@ The final ranked list of results will have the first pass
score(main query `q`)
Details about using the ReRank Query Parser can be found in the
xref:query-guide:query-re-ranking.adoc[Query Re-Ranking] section.
====
+== GPU Acceleration
+
+[NOTE]
+This is feature is currently experimental.
+
+Building HNSW graphs, esp. with high dimensions and cardinality, is usually
slow. If you have a NVIDIA GPU, then building HNSW based indexes can be sped up
manifold. This is powered by the
https://github.com/rapidsai/cuvs-lucene[cuVS-Lucene] library, a pluggable
vectors format for Apache Lucene. It uses the state of the art
https://arxiv.org/abs/2308.15136[CAGRA algorithm] for quickly building a fixed
degree connected graph, which is then serialized into a HNSW graph.
https://developer.n [...]
+
+
+To try this out, first copy the module jar files (found in the regular Solr
tarball, not the slim one) before starting Solr.
+
+[source,sh]
+----
+cp modules/cuvs/lib/*.jar server/solr-webapp/webapp/WEB-INF/lib/
+----
+
+Define the `fieldType` in the schema, with knnAlgorithm set to `cagra_hnsw`:
+
+[source,xml]
+----
+<fieldType name="knn_vector" class="solr.DenseVectorField" vectorDimension="8"
knnAlgorithm="cagra_hnsw" similarityFunction="cosine" />
+----
+
+Define the xref:configuration-guide:codec-factory.adoc[codecFactory] in
xref:configuration-guide:configuring-solrconfig-xml.adoc[solrconfig.xml]
+
+[source,xml]
+----
+<codecFactory name="CuVSCodecFactory"
class="org.apache.solr.cuvs.CuVSCodecFactory">
+ <str name="cuvsWriterThreads">8</str>
+ <str name="intGraphDegree">128</str>
+ <str name="graphDegree">64</str>
+ <str name="hnswLayers">1</str>
+ <str name="maxConn">16</str>
+ <str name="beamWidth">100</str>
+</codecFactory>
+----
+
+Where:
+
+* `cuvsWriterThreads` - number of threads to use
+
+* `intGraphDegree` - Intermediate graph degree for building the CAGRA index
+
+* `graphDegree` - Graph degree for building the CAGRA index
+
+* `hnswLayers` - Number of HNSW graph layers to construct while building the
HNSW index
+
+* `maxConn` - Max connections parameter passed to the fallback
Lucene99HnswVectorsWriter
+
+* `beamWidth` - Beam width parameter passed to the fallback
Lucene99HnswVectorsWriter
+
+=== Example
+
+Following is a complete example of setting up a collection with cuVS.
+
+. Install CUDA 13.0
++
+[tabs#cuda-install]
+======
+Ubuntu 22.04 LTS::
++
+====
+[source,sh]
+----
+# Install CUDA 13.0 from NVIDIA's repository
+wget
https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb
+sudo dpkg -i cuda-keyring_1.1-1_all.deb
+sudo apt-get update
+sudo apt-get install -y cuda-toolkit-13
+
+# Set up environment variables
+echo 'export PATH=/usr/local/cuda-13/bin:$PATH' >> ~/.bashrc
+echo 'export LD_LIBRARY_PATH=/usr/local/cuda-13/lib64:$LD_LIBRARY_PATH' >>
~/.bashrc
+source ~/.bashrc
+
+# Verify installation
+nvcc --version
+----
+====
+
+Ubuntu 24.04 LTS::
++
+====
+[source,sh]
+----
+# Install CUDA 13.0 from NVIDIA's repository
+wget
https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/cuda-keyring_1.1-1_all.deb
+sudo dpkg -i cuda-keyring_1.1-1_all.deb
+sudo apt-get update
+sudo apt-get install -y cuda-toolkit-13
+
+# Set up environment variables
+echo 'export PATH=/usr/local/cuda-13/bin:$PATH' >> ~/.bashrc
+echo 'export LD_LIBRARY_PATH=/usr/local/cuda-13/lib64:$LD_LIBRARY_PATH' >>
~/.bashrc
+source ~/.bashrc
+
+# Verify installation
+nvcc --version
+----
+====
+
+Fedora 39+::
++
+====
+[source,sh]
+----
+# Install CUDA 13.0 from NVIDIA's repository
+# For Fedora 39, 40, and newer versions:
+sudo dnf config-manager --add-repo
https://developer.download.nvidia.com/compute/cuda/repos/fedora39/x86_64/cuda-fedora39.repo
+sudo dnf clean all
+sudo dnf -y install cuda-toolkit-13
+
+# Set up environment variables
+echo 'export PATH=/usr/local/cuda-13/bin:$PATH' >> ~/.bashrc
+echo 'export LD_LIBRARY_PATH=/usr/local/cuda-13/lib64:$LD_LIBRARY_PATH' >>
~/.bashrc
+source ~/.bashrc
+
+# Verify installation
+nvcc --version
+----
+====
+======
+
+. Fetch libcuvs native libraries
++
+[source,sh]
+----
+# Create virtual environment and install libcuvs-cu13 from NVIDIA's RAPIDS
repositories
+python3 -m venv libcuvs-env
+source libcuvs-env/bin/activate
+
+# Install libcuvs-cu13 from NVIDIA's RAPIDS wheels (fetches latest 25.10.x
artifact)
+pip install "libcuvs-cu13<25.11.0" --pre
--extra-index-url=https://pypi.anaconda.org/rapidsai-wheels-nightly/simple/
+
+# Set LD_LIBRARY_PATH to include libcuvs libraries
+SITE_PACKAGES_PATH=$(pwd)/$(find libcuvs-env -name site-packages)
+export
VENV_LIB=$SITE_PACKAGES_PATH/libcuvs/lib64:$SITE_PACKAGES_PATH/librmm/lib64:$SITE_PACKAGES_PATH/rapids_logger/lib64
+export LD_LIBRARY_PATH=$VENV_LIB:$LD_LIBRARY_PATH:/usr/local/cuda-13/lib64
+
+# Verify libcuvs_c.so is available
+find $LD_LIBRARY_PATH -name "libcuvs_c.so" | head -1
+
+# Deactivate virtual environment (optional - libraries are now accessible via
LD_LIBRARY_PATH)
+deactivate
+----
+
+. Copy the `cuvs` module jar files (before starting Solr).
++
+[source,sh]
+----
+cp modules/cuvs/lib/*.jar server/solr-webapp/webapp/WEB-INF/lib/
+----
+
+. Create a configset
++
+[source,sh]
+----
+mkdir -p cuvs_configset/conf
+----
++
+[source,sh]
+----
+cat > cuvs_configset/conf/solrconfig.xml << 'EOF'
+<?xml version="1.0" ?>
+<config>
+ <luceneMatchVersion>10.0.0</luceneMatchVersion>
+ <dataDir>${solr.data.dir:}</dataDir>
+ <directoryFactory name="DirectoryFactory"
class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}"/>
+
+ <updateHandler class="solr.DirectUpdateHandler2">
+ <updateLog>
+ <str name="dir">${solr.ulog.dir:}</str>
+ </updateLog>
+ <autoCommit>
+ <maxTime>${solr.autoCommit.maxTime:15000}</maxTime>
+ <openSearcher>false</openSearcher>
+ </autoCommit>
+ <autoSoftCommit>
+ <maxTime>${solr.autoSoftCommit.maxTime:1000}</maxTime>
+ </autoSoftCommit>
+ </updateHandler>
+
+ <codecFactory name="CuVSCodecFactory"
class="org.apache.solr.cuvs.CuVSCodecFactory">
+ <str name="cuvsWriterThreads">32</str>
+ <str name="intGraphDegree">128</str>
+ <str name="graphDegree">64</str>
+ <str name="hnswLayers">1</str>
+ <str name="maxConn">16</str>
+ <str name="beamWidth">100</str>
+ </codecFactory>
+
+ <requestHandler name="/select" class="solr.SearchHandler">
+ <lst name="defaults">
+ <str name="echoParams">explicit</str>
+ <int name="rows">10</int>
+ </lst>
+ </requestHandler>
+
+ <requestHandler name="/update" class="solr.UpdateRequestHandler" />
+</config>
+EOF
+----
++
+[source,sh]
+----
+cat > cuvs_configset/conf/managed-schema << 'EOF'
+<?xml version="1.0" ?>
+<schema name="schema-densevector" version="1.7">
+ <fieldType name="string" class="solr.StrField" multiValued="true"/>
+ <fieldType name="knn_vector" class="solr.DenseVectorField"
+ vectorDimension="8"
+ knnAlgorithm="cagra_hnsw"
+ similarityFunction="cosine" />
+ <fieldType name="plong" class="solr.LongPointField"
useDocValuesAsStored="false"/>
+
+ <field name="id" type="string" indexed="true" stored="true"
multiValued="false" required="false"/>
+ <field name="article_vector" type="knn_vector" indexed="true"
stored="true"/>
+ <field name="_version_" type="plong" indexed="true" stored="true"
multiValued="false" />
+
+ <uniqueKey>id</uniqueKey>
+</schema>
+EOF
+----
+
+. Start Solr
++
+[source,sh]
+----
+./bin/solr start
+----
+
+. Upload the configset and create a collection
++
+[source,sh]
+----
+./bin/solr zk upconfig -n cuvs_vectors -d cuvs_configset/conf && ./bin/solr
create -c vectors -n cuvs_vectors
+----
+
+. Index documents
++
+[source,sh]
+----
+curl -s -X POST "http://localhost:8983/solr/vectors/update?commit=true" \
+ -H "Content-Type: application/json" \
+ -d '[
+ {"id": "doc1", "article_vector": [0.35648, 0.11664, 0.85660, 0.25043,
0.80778, 0.08031, 0.48444, 0.39083]},
+ {"id": "doc2", "article_vector": [0.86821, 0.24947, 0.38601, 0.22615,
0.31498, 0.74612, 0.69403, 0.19691]},
+ {"id": "doc3", "article_vector": [0.34098, 0.49236, 0.35950, 0.17840,
0.49470, 0.97242, 0.28249, 0.72526]},
+ {"id": "doc4", "article_vector": [0.44979, 0.49473, 0.47197, 0.02869,
0.05262, 0.60855, 0.67370, 0.78656]},
+ {"id": "doc5", "article_vector": [0.23235, 0.70062, 0.95036, 0.36251,
0.41233, 0.53170, 0.25459, 0.81606]}
+ ]'
+----
+
+. Query the index
++
+[source,sh]
+----
+curl -s
'http://localhost:8983/solr/vectors/select?q=%7B!knn%20f=article_vector%20topK=1%7D%5B0.84393,0.50073,0.57059,0.89899,-0.08722,0.26803,0.00807,0.09877%5D&fl=id,score&rows=3&omitHeader=true'
+----
++
+Should return the following
++
+[source,json]
+----
+{
+ "response":{
+ "numFound":1,
+ "start":0,
+ "maxScore":0.8377289,
+ "numFoundExact":true,
+ "docs":[{
+ "id":"doc2",
+ "score":0.8377289
+ }]
+ }
+}
+----
+
== Additional Resources
* Blog: https://sease.io/2022/01/apache-solr-neural-search.html