diff --git a/.github/workflows/check-dead-links.yml b/.github/workflows/check-dead-links.yml index faf4480bf..fb128837e 100644 --- a/.github/workflows/check-dead-links.yml +++ b/.github/workflows/check-dead-links.yml @@ -14,7 +14,7 @@ jobs: - name: Setup Hugo uses: peaceiris/actions-hugo@16361eb4acea8698b220b76c0d4e84e1fd22c61d # v2.6.0 with: - hugo-version: "latest" + hugo-version: "0.160.1" - name: Install npm uses: actions/setup-node@7c12f8017d5436eb855f1ed4399f037a36fbd9e8 # v2.5.2 with: diff --git a/.github/workflows/internal-dead-links.yml b/.github/workflows/internal-dead-links.yml index a5000ccbd..a50994e64 100644 --- a/.github/workflows/internal-dead-links.yml +++ b/.github/workflows/internal-dead-links.yml @@ -15,7 +15,7 @@ jobs: - name: Setup Hugo uses: peaceiris/actions-hugo@16361eb4acea8698b220b76c0d4e84e1fd22c61d # v2.6.0 with: - hugo-version: "0.123.0" + hugo-version: "0.160.1" - name: Install npm uses: actions/setup-node@7c12f8017d5436eb855f1ed4399f037a36fbd9e8 # v2.5.2 with: @@ -25,8 +25,13 @@ jobs: bash -x ./install-and-build.sh CURRENT_DIR=$(pwd) export PATH="${CURRENT_DIR}/dart-sass:${PATH}" - cd qdrant-landing && hugo --gc -b 'http://localhost:1314' && hugo serve --port 1314 & - sleep 5 # wait for server to start + cd qdrant-landing + hugo --gc -b 'http://localhost:1314' + hugo serve --port 1314 & + for i in {1..60}; do + curl -sf http://localhost:1314/ >/dev/null && break + sleep 1 + done - name: Internal Links Check id: lychee uses: lycheeverse/lychee-action@ec3ed119d4f44ad2673a7232460dc7dff59d2421 # v1.8.0 diff --git a/.gitignore b/.gitignore index 398b7f7b8..581688ede 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ qdrant-landing/.DS_Store .DS_Store .tools/ package-lock.json -.claude/ \ No newline at end of file +.claude/ +dart-sass/ \ No newline at end of file diff --git a/README.md b/README.md index c0365ed9b..1829da7fe 100644 --- a/README.md +++ b/README.md @@ -65,8 +65,7 @@ ## Run ```bash -cd qdrant-landing -hugo serve +./run.sh ``` Open http://localhost:1313/ in your browser. diff --git a/automation/snippets/docker/Dockerfile b/automation/snippets/docker/Dockerfile index 054800683..5d1894798 100644 --- a/automation/snippets/docker/Dockerfile +++ b/automation/snippets/docker/Dockerfile @@ -13,11 +13,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ openjdk-21-jdk-headless \ # for python client python3 \ - # for typescript client - nodejs \ - npm \ && rm -rf /var/lib/apt/lists/* +# for typescript client - Node 22 (Node 18 EOL April 2025, pnpm requires 20+) +RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \ + apt-get install -y --no-install-recommends nodejs && \ + rm -rf /var/lib/apt/lists/* + # for csharp client RUN add-apt-repository ppa:dotnet/backports && \ apt-get update && \ diff --git a/automation/snippets/sync-clients.py b/automation/snippets/sync-clients.py index a7e2dba07..f532ef566 100755 --- a/automation/snippets/sync-clients.py +++ b/automation/snippets/sync-clients.py @@ -88,7 +88,7 @@ def main() -> None: if args.java is not None: url = "https://github.com/qdrant/java-client" dir = BASE_DIR / "clients" / "java" - checkout_repo(url, dir, "master") + checkout_repo(url, dir, args.java) ok = True if args.typescript is not None: url = "https://github.com/qdrant/qdrant-js" @@ -195,6 +195,7 @@ def checkout_repo( if p.returncode == 0: rev = p.stdout.strip() + subprocess.run(["git", "-C", dest_dir, "reset", "--hard"], check=True) subprocess.run(["git", "-C", dest_dir, "checkout", "--detach", rev], check=True) diff --git a/automation/snippets/templates/go/go.mod b/automation/snippets/templates/go/go.mod index 5238b1554..634db0193 100644 --- a/automation/snippets/templates/go/go.mod +++ b/automation/snippets/templates/go/go.mod @@ -4,14 +4,14 @@ go 1.25.2 require ( github.com/google/uuid v1.6.0 - github.com/qdrant/go-client v1.17.1 + github.com/qdrant/go-client v1.18.1 ) require ( - golang.org/x/net v0.50.0 // indirect - golang.org/x/sys v0.41.0 // indirect - golang.org/x/text v0.34.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect - google.golang.org/grpc v1.78.0 // indirect + golang.org/x/net v0.53.0 // indirect + golang.org/x/sys v0.43.0 // indirect + golang.org/x/text v0.36.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260427160629-7cedc36a6bc4 // indirect + google.golang.org/grpc v1.80.0 // indirect google.golang.org/protobuf v1.36.11 // indirect ) diff --git a/automation/snippets/templates/go/go.sum b/automation/snippets/templates/go/go.sum index 200b52ecf..0387e7a98 100644 --- a/automation/snippets/templates/go/go.sum +++ b/automation/snippets/templates/go/go.sum @@ -10,31 +10,31 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/qdrant/go-client v1.17.1 h1:7QmPwDddrHL3hC4NfycwtQlraVKRLcRi++BX6TTm+3g= -github.com/qdrant/go-client v1.17.1/go.mod h1:n1h6GhkdAzcohoXt/5Z19I2yxbCkMA6Jejob3S6NZT8= +github.com/qdrant/go-client v1.18.1 h1:o/dDmSl6ONAlaAFtjdlzztcs3NH0tJY3l5C/z/Uu0bE= +github.com/qdrant/go-client v1.18.1/go.mod h1:Xkfp+r89uNOgSbvilVAhCZ3wKI4G+hB/r9Zr2m4zifI= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms= -go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g= -go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g= -go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc= -go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= -go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= -go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= -go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= -go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw= -go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA= -golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= -golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= -golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= -golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= -golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= -gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= -gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= -google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= -google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= +go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= +go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= +go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= +go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= +go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= +go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= +go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= +go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= +go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= +go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= +golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= +golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= +golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= +golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= +golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260427160629-7cedc36a6bc4 h1:tEkOQcXgF6dH1G+MVKZrfpYvozGrzb91k6ha7jireSM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260427160629-7cedc36a6bc4/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= +google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= diff --git a/automation/snippets/templates/python/pyproject.toml b/automation/snippets/templates/python/pyproject.toml index d283a6693..ca08bdb94 100644 --- a/automation/snippets/templates/python/pyproject.toml +++ b/automation/snippets/templates/python/pyproject.toml @@ -10,7 +10,7 @@ dependencies = [ ] [tool.uv.sources] -qdrant-client = { git = "https://github.com/qdrant/qdrant-client", tag = "dev" } +qdrant-client = { git = "https://github.com/qdrant/qdrant-client", tag = "v1.18.0" } [dependency-groups] dev = [ diff --git a/automation/snippets/templates/python/uv.lock b/automation/snippets/templates/python/uv.lock index 6c1ed96f6..eb2a61088 100644 --- a/automation/snippets/templates/python/uv.lock +++ b/automation/snippets/templates/python/uv.lock @@ -1420,8 +1420,8 @@ wheels = [ [[package]] name = "qdrant-client" -version = "1.17.1.dev0" -source = { git = "https://github.com/qdrant/qdrant-client?tag=dev#c7a5bef84b57ab3149b78d207b5de8aa3268d72e" } +version = "1.18.0" +source = { git = "https://github.com/qdrant/qdrant-client?tag=v1.18.0#326adefcc2158121dd0d04877e1a483b5aa2627b" } dependencies = [ { name = "grpcio" }, { name = "httpx", extra = ["http2"] }, @@ -1509,7 +1509,7 @@ dev = [ requires-dist = [ { name = "datasets", specifier = ">=4.4.1" }, { name = "fastembed" }, - { name = "qdrant-client", git = "https://github.com/qdrant/qdrant-client?tag=dev" }, + { name = "qdrant-client", git = "https://github.com/qdrant/qdrant-client?tag=v1.18.0" }, { name = "qdrant-edge-py", specifier = "==0.6.0" }, ] diff --git a/automation/snippets/templates/rust/Cargo.lock b/automation/snippets/templates/rust/Cargo.lock index 99a199c27..439a49887 100644 --- a/automation/snippets/templates/rust/Cargo.lock +++ b/automation/snippets/templates/rust/Cargo.lock @@ -2864,7 +2864,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.14.0", + "itertools 0.11.0", "proc-macro2", "quote", "syn", @@ -2881,8 +2881,8 @@ dependencies = [ [[package]] name = "qdrant-client" -version = "1.16.1-dev" -source = "git+https://github.com/qdrant/rust-client?branch=dev#d9cf226e4583b82d8cb8c065851380c6d0b49765" +version = "1.18.0" +source = "git+https://github.com/qdrant/rust-client?branch=master#357dec9e56da4e5afd41645e8c414873a7f8681d" dependencies = [ "anyhow", "derive_builder", @@ -3049,7 +3049,7 @@ dependencies = [ "once_cell", "socket2 0.6.3", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] @@ -3819,6 +3819,8 @@ name = "snippets-amalgamation" version = "0.1.0" dependencies = [ "anyhow", + "chrono", + "csv", "fs-err", "ordered-float 5.1.0", "qdrant-client", @@ -4973,7 +4975,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -4982,16 +4984,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", + "windows-targets", ] [[package]] @@ -5009,31 +5002,14 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link 0.2.1", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] @@ -5060,96 +5036,48 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - [[package]] name = "winnow" version = "0.7.15" diff --git a/automation/snippets/templates/rust/Cargo.toml b/automation/snippets/templates/rust/Cargo.toml index 24b1576cc..1a6fc4521 100644 --- a/automation/snippets/templates/rust/Cargo.toml +++ b/automation/snippets/templates/rust/Cargo.toml @@ -10,7 +10,7 @@ csv = "1.3" qdrant-edge = "0.6.0" fs-err = "3" ordered-float = "5" -qdrant-client = { git = "https://github.com/qdrant/rust-client", branch = "dev" } +qdrant-client = { git = "https://github.com/qdrant/rust-client", branch = "master" } serde_json = "1.0.145" tempfile = "3" tokio = { version = "1.48.0", features = ["rt-multi-thread", "macros"] } diff --git a/install-and-build.sh b/install-and-build.sh index 5c39e9341..bf37de316 100644 --- a/install-and-build.sh +++ b/install-and-build.sh @@ -5,9 +5,30 @@ DEPLOY_PRIME_URL=${DEPLOY_PRIME_URL:-"https://qdrant.com"} CURRENT_DIR=$(pwd) -curl -LJO https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \ - md5sum dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \ - tar -xf dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \ - rm dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \ +REQUIRED_HUGO_VERSION="0.160.1" +INSTALLED_HUGO_VERSION=$(hugo version | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' | head -1 | tr -d 'v') +if [ "${INSTALLED_HUGO_VERSION}" != "${REQUIRED_HUGO_VERSION}" ]; then + echo "Error: Hugo version ${REQUIRED_HUGO_VERSION} is required, but found ${INSTALLED_HUGO_VERSION}." + echo "See https://gohugo.io/installation/ for installation instructions." + exit 1 +fi + +OS=$(uname -s | tr '[:upper:]' '[:lower:]') +ARCH=$(uname -m) +case "${OS}" in + linux) SASS_OS="linux" ;; + darwin) SASS_OS="macos" ;; + *) echo "Error: Unsupported OS: ${OS}"; exit 1 ;; +esac +case "${ARCH}" in + x86_64) SASS_ARCH="x64" ;; + aarch64|arm64) SASS_ARCH="arm64" ;; + *) echo "Error: Unsupported architecture: ${ARCH}"; exit 1 ;; +esac +SASS_ARCHIVE="dart-sass-${DART_SASS_VERSION}-${SASS_OS}-${SASS_ARCH}.tar.gz" + +curl -LJO "https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/${SASS_ARCHIVE}" && \ + tar -xf "${SASS_ARCHIVE}" && \ + rm "${SASS_ARCHIVE}" && \ export PATH="${CURRENT_DIR}/dart-sass:${PATH}" && \ cd qdrant-landing && npm install && hugo --gc --minify --config config.toml,config-theme.toml --buildFuture -b ${DEPLOY_PRIME_URL} diff --git a/netlify.toml b/netlify.toml index ec5209c31..5025939a0 100644 --- a/netlify.toml +++ b/netlify.toml @@ -3,7 +3,7 @@ publish = "qdrant-landing/public" command = "bash -x ./install-and-build.sh" [build.environment] -HUGO_VERSION = "0.141.0" +HUGO_VERSION = "0.160.1" DART_SASS_VERSION = "1.70.0" NODE_VERSION = "22.22.2" HUGO_PARAMS_segmentWriteKey = "UOgPyE2GbtD4lletUP2uWfBGQQSfkzf1" @@ -33,6 +33,7 @@ HUGO_PARAMS_onetrustScriptId = "0196246a-3663-7350-9a45-b65f645d6314" [headers.values] X-Content-Type-Options = "nosniff" X-Frame-Options = "DENY" + Referrer-Policy = "no-referrer-when-downgrade" Link = '; rel="alternate"; type="text/markdown"' [[headers]] diff --git a/qdrant-landing/.nvmrc b/qdrant-landing/.nvmrc new file mode 100644 index 000000000..53d1c14db --- /dev/null +++ b/qdrant-landing/.nvmrc @@ -0,0 +1 @@ +v22 diff --git a/qdrant-landing/archetypes/delimiter.md b/qdrant-landing/archetypes/delimiter.md index 5dfb34755..f031f9314 100644 --- a/qdrant-landing/archetypes/delimiter.md +++ b/qdrant-landing/archetypes/delimiter.md @@ -4,7 +4,7 @@ title: "{{ replace .Name "-" " " | title }}" type: delimiter weight: 0 # Change this weight to change order of sections sitemapExclude: True -_build: +build: list: never publishResources: false render: never diff --git a/qdrant-landing/config.toml b/qdrant-landing/config.toml index 3a54551f4..45d74443f 100644 --- a/qdrant-landing/config.toml +++ b/qdrant-landing/config.toml @@ -109,10 +109,10 @@ disableKinds = ["taxonomy", "term"] # Not rendering the content of the cd following files in production [[cascade]] - [cascade._build] + [cascade.build] list = 'never' render = 'never' - [cascade._target] + [cascade.target] environment = '{production}' path = '{**.skip,**.skip/*}' diff --git a/qdrant-landing/content/blog/case-study-sapu.md b/qdrant-landing/content/blog/case-study-sapu.md new file mode 100644 index 000000000..c1ed1d32f --- /dev/null +++ b/qdrant-landing/content/blog/case-study-sapu.md @@ -0,0 +1,79 @@ +--- +draft: false +title: "How Sapu Indexed 28 Million PubMed Abstracts to Accelerate Cancer Research with Qdrant" +short_description: "Sapu indexed 28M PubMed abstracts into Qdrant to power AI-driven biomedical research for cancer drug development." +description: "Discover how Sapu, a nanomedicine biotech company, indexed 28 million PubMed abstracts into a single Qdrant collection, enabling researchers to query the entire biomedical literature corpus and accelerating hard-to-treat cancer therapy development." +preview_image: /blog/case-study-sapu/sapu-preview.png +social_preview_image: /blog/case-study-sapu/sapu-preview.png +date: 2026-05-12 +author: "Daniel Azoulai" +featured: false + +tags: +- Sapu +- vector search +- biomedical research +- PubMed +- hybrid search +- Qdrant Cloud Premium +- case study +partition: case-studies +--- + +![Summary](/blog/case-study-sapu/sapu-bento-box.png) + +Sapu is an early-stage biopharmaceutical company developing treatments for hard-to-treat cancers. From its San Diego facility, the team is pioneering a nanomedicine pipeline that takes existing FDA-approved drugs and re-engineers them at the nanoscale, making them smaller, more effective, and less toxic. Building on already-approved compounds gives Sapu a stronger and faster path to therapeutic success in an industry where most candidates never reach patients. + +Behind the lab work sits an AI tooling suite that does the reading, searching, and synthesis that would otherwise take researchers thousands of hours. Sapu's internal AI platform supports research paper authorship, references standard operating procedures, and lets the team query its document corpus with the precision biotech R\&D requires. As the company grew, so did the volume of documents, the variety of use cases, and the demands placed on the underlying retrieval infrastructure. + +## Why Early Vector Search Options Didn't Work + +Sapu started building its AI platform shortly after ChatGPT became available, beginning with a command-line prototype and graduating to a full user interface as the system matured. Documents were initially stored as text snippets, with no vector retrieval at all. As use cases expanded into research paper ingestion and SOP-aware chatbots, the team needed a vector search engine that worked. + +Scott Myers, who leads much of the AI development at Sapu, evaluated several options. "I just looked up vector search solutions and tried a couple of others. I couldn't get them to work at first. Qdrant happened to work really well right out of the box, and so we stuck with it." + +The team initially ran Qdrant self-hosted on Docker. That worked well enough to get the platform off the ground, but as Sapu scaled the variety and volume of its workloads, operating its own cluster became a liability. The setup wasn't optimized, stability issues started appearing, and the team didn't have Qdrant infrastructure expertise in-house to debug them. The cost of self-hosting was no longer just dollars: it was reliability and engineering attention pulled away from the actual research mission. + +## Why Sapu Moved to Qdrant Cloud Premium + +Sapu signed a [Qdrant Cloud](https://qdrant.tech/documentation/cloud-premium/) Premium partnership to get reliability without dedicating engineering bandwidth to managing infrastructure. The shift solved the stability problems immediately. + +>"So far it's paid dividends. We haven't run into the issues we had previously." — Scott Myers, Product Manager, Sapu + +Compliance was a second deciding factor. Sapu plans to license its AI platform to other biotech companies, so the underlying infrastructure has to carry credible certifications. SOC 2 compliance lets Sapu tell prospective licensees that the platform their data sits on meets enterprise security standards. + +Support quality also stood out. Myers described being surprised when a support engineer followed up on a ticket hours after the initial response with additional findings. "That does not happen with a larger company. Once they respond to a ticket, they move on. They don't keep looking at it." + +The continuous pace of new capabilities reinforced the decision. Recent releases like audit logging and Multi-Availability Zone deployment for Premium customers landed during Sapu's tenure on the platform, giving the team enterprise features without a migration or upgrade project. + +## Indexing 28 million PubMed Abstracts in a Single Collection + +The headline outcome is scale. Sapu's team indexed every abstract in the PubMed database, 28 million records, into a single Qdrant collection. Before this, researchers had to upload subsets of abstracts whenever they wanted to query. Now the entire corpus of biomedical literature is searchable in place. Researchers can query a small filtered slice using metadata, or run vector search across all 28 million abstracts at once. + +>"We indexed every single abstract from the PubMed database into a Qdrant vector database. That's 28 million abstracts. Now we can query across all of them, and that's something that just was not possible a few years ago." — Scott Myers, Product Manager, Sapu + +The downstream impact has been concrete. Sapu has published seven peer-reviewed research papers that used the AI tooling in the underlying research work. Editors reviewing the methods sections have asked specifically about the AI components. Internal adoption is broad: the CEO uses the AI tools daily, and the San Diego research staff relies on them for SOP lookup, document research, and paper drafting. + +The platform has also opened external opportunities. Sapu recently announced a partnership with Techforce, a robotics company, to extend the AI suite into robotic workflows for the lab. + +## Architecture: Hybrid Retrieval and Per-document Parallel Querying + +Sapu's pipeline runs OpenAI's text-embedding-3-large model at 3,072 dimensions, with LangChain orchestrating the ingestion path that writes to Qdrant Cloud. The team uses Qdrant for both vector search and pure metadata-filtered retrieval. Some queries use semantic similarity; others rely entirely on payload filtering over indexed metadata like tags, departments, and dates, with no vector component at all. + +Department-level access control combines a separate SQL database (which maps users to departments) with Qdrant payload filters that restrict each query to documents the user is authorized to see. Authentication is handled through NFT-based wallet login. + +The team also developed a novel querying pattern that goes beyond standard vector search. For some research workflows, retrieving the most relevant snippets across a corpus is the wrong default. Instead, Sapu's platform can split a corpus of, say, 1,000 documents into 1,000 independent queries, each scoped to a single document, and run them in parallel. This produces 1,000 independent responses rather than one synthesized answer. For literature review and abstract triage, that pattern surfaces context that single-shot retrieval misses. + +Documents themselves are stored in three forms today: snippets, full document content, and page images. Sapu is migrating the large content payloads to S3, with Qdrant retaining only a URL pointer, which will reduce collection size and improve query performance. + +## What's Next: Edge Deployments, Robotics, and Inference at the Cloud layer + +Sapu's near-term roadmap centers on extending the AI suite to robotics. The Techforce partnership will introduce physical robots into the lab, both for task automation and for compliance enforcement, ensuring procedures are followed and capturing voice and hands-free interactions when researchers can't operate a keyboard in a fully gowned environment. + +For closed lab systems with no internet access, the team is evaluating Qdrant Edge for on-device vector search. Air-gapped deployment is a hard requirement for facilities where data leakage is not an acceptable risk. + +Sapu is also exploring [Qdrant Cloud Inference](https://qdrant.tech/cloud-inference/) to simplify its embedding pipeline and explore lower-dimensional embedding models that could reduce storage and query costs without compromising relevance. + +## From Prototype to Production-Scale Biomedical Retrieval + +What started as a command-line prototype shortly after ChatGPT's release has become a production AI platform that touches every part of Sapu's research workflow, from drug development paper drafting to SOP-aware chatbots to a 28 million abstract literature index. Qdrant moved from a piece of evaluation software that "just worked" to the retrieval foundation under research that is now publishing in peer-reviewed journals and being licensed to external partners. For a biotech company building therapies for hard-to-treat cancers, the math is simple: the faster researchers can find what they need across the world's biomedical literature, the faster the next therapy reaches patients. \ No newline at end of file diff --git a/qdrant-landing/content/blog/qdrant-1.18.x.md b/qdrant-landing/content/blog/qdrant-1.18.x.md new file mode 100644 index 000000000..ab044a41d --- /dev/null +++ b/qdrant-landing/content/blog/qdrant-1.18.x.md @@ -0,0 +1,160 @@ +--- +title: "Qdrant 1.18 - TurboQuant" +draft: false +slug: qdrant-1.18.x +short_description: "Version 1.18 of Qdrant introduces TurboQuant, a novel quantization method." +description: "Version 1.18 of Qdrant introduces TurboQuant, a novel quantization method that, at twice the compression ratio of scalar quantization, delivers similar recall and speed." +preview_image: /blog/qdrant-1.18.x/social_preview.jpg +social_preview_image: /blog/qdrant-1.18.x/social_preview.jpg +date: 2026-05-11T00:00:00-08:00 +author: Abdon Pijpelink +featured: true +tags: + - vector search + - quantization + - observability + - memory monitoring +--- + +[**Qdrant 1.18.0 is out!**](https://github.com/qdrant/qdrant/releases/tag/v1.18.0) Let's look at the main features for this version: + +**TurboQuant:** A new quantization method that, at twice the compression ratio of scalar quantization, delivers similar recall and speed. + +**Memory Monitoring:** Inspect a collection's disk, RAM, and page cache usage broken down by component (vectors, payload, indexes, and more) via a new Web UI view and API endpoint. + +**Adding and Removing Named Vectors:** Add or remove named vectors to an existing collection's schema without having to recreate it. + +Additionally, version 1.18 adds two improvements to audit logging: a new API endpoint to query audit logs, and support for request tracing IDs. It also introduces per-collection API metrics and two new strict mode guardrails. + +## TurboQuant + +![Section 1](/blog/qdrant-1.18.x/section-1.png) + +Quantization is a technique that reduces the memory footprint of a vector collection by compressing floating-point values to a lower bit depth. Smaller vectors fit more readily in memory, which speeds up search and lowers infrastructure costs. + +Choosing a quantization method means accepting tradeoffs. Binary quantization is fast but requires a centered vector distribution, and accuracy degrades significantly for smaller vectors. Scalar quantization is reliable but compresses only by a factor of four. Product quantization compresses more aggressively, but at the cost of accuracy and speed. + +Version 1.18 introduces support for [TurboQuant](/documentation/manage-data/quantization/), a new quantization method developed by [Google Research](https://research.google/blog/turboquant-redefining-ai-efficiency-with-extreme-compression/). TurboQuant applies a fast Hadamard rotation to vectors before compression, which redistributes values evenly across coordinates. Because this rotation normalizes the data distribution, TurboQuant works well with any embedding model. + +Qdrant's implementation of TurboQuant extends the original algorithm to close the gap between the algorithm's theoretical assumptions and real-world embeddings. A length renormalization step corrects a recall-degrading bias caused by quantization error, an idea borrowed from [RaBitQ](https://arxiv.org/abs/2405.12497). A per-coordinate calibration pre-pass fits the data to precomputed codebooks, aiming to recover accuracy lost to distribution mismatch. Cosine, dot product, and L2 are all supported as first-class distance metrics. And finally, we implemented highly optimized SIMD acceleration for TurboQuant to achieve maximum performance. + +### How TurboQuant Compares + +#### TurboQuant vs Scalar Quantization + +The following table shows recall for 4-bit TurboQuant (TQ4) compared to uncompressed vectors (F32) and scalar quantization (SQ) across four benchmarked datasets. Benchmarks were run with HNSW configured with `m=16` and `ef_construct=128`. + +| Dataset | F32 | SQ | TQ4 | +|---|---|---|---| +| [arxiv-titles-instructorxl-embeddings](https://huggingface.co/datasets/Qdrant/arxiv-titles-instructorxl-embeddings) | 0.9419 | 0.9285 | 0.9193 | +| [gte-multilingual-ads-1M](https://huggingface.co/datasets/Qdrant/gte-multilingual-ads-1M) | 0.9298 | 0.9187 | 0.9169 | +| [dbpedia-entities-openai3-text-embedding-3-large-1536-100K](https://huggingface.co/datasets/Qdrant/dbpedia-entities-openai3-text-embedding-3-large-1536-100K) | 0.9348 | 0.9339 | 0.9271 | +| [wikipedia-2023-11-embed-multilingual-v3](https://huggingface.co/datasets/CohereLabs/wikipedia-2023-11-embed-multilingual-v3) | 0.9446 | 0.9014 | 0.9261 | + +Compared to scalar quantization, TurboQuant delivers similar recall **at double the compression ratio**. Results vary by dataset and embedding model: TurboQuant may slightly outperform or underperform scalar quantization. + +#### TurboQuant vs Binary Quantization + +The following table shows recall for 1-bit TurboQuant (TQ1) compared to uncompressed vectors (F32) and 1-bit binary quantization (BQ1) across four benchmarked datasets. Benchmarks were run with HNSW configured with `m=16` and `ef_construct=128`. + +| Dataset | F32 | BQ1 | TQ1 | +|---|---|---|---| +| [arxiv-titles-instructorxl-embeddings](https://huggingface.co/datasets/Qdrant/arxiv-titles-instructorxl-embeddings) | 0.9419 | 0.4683 | 0.6763 | +| [gte-multilingual-ads-1M](https://huggingface.co/datasets/Qdrant/gte-multilingual-ads-1M) | 0.9298 | 0.6760 | 0.7717 | +| [dbpedia-entities-openai3-text-embedding-3-large-1536-100K](https://huggingface.co/datasets/Qdrant/dbpedia-entities-openai3-text-embedding-3-large-1536-100K) | 0.9348 | 0.6921 | 0.7924 | +| [wikipedia-2023-11-embed-multilingual-v3](https://huggingface.co/datasets/CohereLabs/wikipedia-2023-11-embed-multilingual-v3) | 0.9446 | 0.5409 | 0.6300 | + +Compared to 1-bit binary quantization, 1-bit TurboQuant offers better recall at equivalent storage budgets, albeit at a lower speed. Similar trends are observed for 1.5-bit and 2-bit configurations. + +We will soon publish an article with detailed numbers, including throughput and indexing times. + +### Get Started with TurboQuant + +In our benchmarks, TurboQuant, at twice the compression ratio of scalar quantization, delivers similar recall and speed. Results vary by dataset and embedding model: it may outperform or slightly underperform scalar quantization. This makes TurboQuant a good default choice for many use cases. + +Compared to binary quantization, TurboQuant offers better recall at lower speed and equivalent storage budgets. + +Benchmark which quantization method performs best on your data and embedding model, and choose the one that fits your needs. To get started with TurboQuant, refer to the [documentation](/documentation/manage-data/quantization/). + +## Memory Monitoring + +![Section 2](/blog/qdrant-1.18.x/section-2.png) + +Understanding how much memory a Qdrant collection actually uses has traditionally required cross-referencing OS-level tools, Prometheus gauges, and rough estimates based on collection configuration. There was no straightforward way to see which component (vectors, payload, indexes) was consuming memory, making capacity planning and diagnosing memory pressure difficult. + +This release introduces [collection memory monitoring](/documentation/ops-monitoring/memory-usage/), offering a detailed breakdown of disk, RAM, and OS page cache usage per component, summed across the whole cluster. + +In Web UI, open the collection detail page and select the **Memory** tab to see the memory breakdown. + +
+ The Memory tab showing a breakdown of disk, RAM, cached, and expected cache values per collection component. +
+ The Memory tab shows disk, RAM, and cached usage for each component of the collection. +
+
+ +The same data is available [through Qdrant's API](/documentation/ops-monitoring/memory-usage/#api). + +## Adding and Removing Named Vectors + +![Section 4](/blog/qdrant-1.18.x/section-3.png) + +When a collection's vector schema needed to change, for example, when adding support for a new embedding model or retiring an old one, there was no way to update it in place. The only option was to recreate the collection from scratch and re-ingest all points. + +Version 1.18 makes it possible to [add and remove named vectors](/documentation/manage-data/collections/#update-vectors) to an existing collection's schema without having to recreate it. This makes embedding model migration considerably easier. You can now add a new vector field, populate it in the background, and remove the old one when you're ready. + +## Audit Logging Improvements + +![Section 3](/blog/qdrant-1.18.x/section-4.png) + +[Audit logging](/documentation/security/#audit-logging) was introduced in Qdrant 1.17 to track API operations. Version 1.18 adds two improvements: a new API endpoint to query audit logs, and support for attaching tracing IDs to requests. + +### Query Audit Logs + +Audit logs were previously only accessible as files on disk, which meant reviewing them required direct server access. There was no way to easily search, filter, or aggregate log entries, making security reviews and compliance audits labor-intensive. + +Version 1.18 introduces a [new query audit logs API endpoint](/documentation/security/#query-audit-logs). It returns log entries aggregated across all nodes in a cluster, with each entry covering the timestamp, API method, authentication type, access result, and client details. You can filter results by time range or by any field value. + +### Request Tracing IDs + +When an audit log entry records a denied request or an unexpected operation, it can be hard to link that entry back to the client-side request that triggered it, making incident response and debugging harder than it needs to be. + +This release adds support for [request tracing IDs](/documentation/security/#audit-logging). Attach a tracing ID to any request by passing it in the `x-request-id`, `x-tracing-id`, or `traceparent` header. Qdrant records the tracing ID in the corresponding audit log entry, enabling you to correlate client-side and server-side logs. + +## Per-Collection API Metrics + +![Section 5](/blog/qdrant-1.18.x/section-5.png) + +Qdrant's `/metrics` endpoint exposes REST and gRPC response metrics, but they were aggregated across all collections. When response times spiked or error rates climbed, there was no easy way to identify which collection was responsible. + +A [community contribution](https://github.com/qdrant/qdrant/pull/8214) to version 1.18 adds a [`?per_collection=true` parameter](/documentation/ops-monitoring/monitoring/#per-collection-api-metrics) to the `/metrics` endpoint. When set, the `rest_responses_*` and `grpc_responses_*` metrics include a `collection` label, giving you a per-collection breakdown of request counts, failure counts, and response durations. + +## New Strict Mode Guardrails + +![Section 6](/blog/qdrant-1.18.x/section-6.png) + +[Strict mode](/documentation/ops-configuration/administration/#strict-mode) lets administrators set guardrails to prevent inefficient API requests from overloading your system. Version 1.18 adds two new guardrails to strict mode: + +**`max_resident_memory_percent`**: Rejects memory-consuming write operations when the process's resident memory exceeds the specified percentage of total system memory. This protects against out-of-memory situations under sustained data ingestion. + +**`search_max_batchsize`**: Caps the number of queries allowed in a single batch search request, preventing oversized batches from degrading other workloads running on the same node. + +## Full Change Log + +![Section 7](/blog/qdrant-1.18.x/section-7.png) + +For a full list of all changes in version 1.18, refer to the [change log](https://github.com/qdrant/qdrant/releases/tag/v1.18.0). + +## Upgrading to Version 1.18 + +![Section 8](/blog/qdrant-1.18.x/section-8.png) + +On Qdrant Cloud, navigate to the Cluster Details screen and select Version 1.18 from the dropdown menu. The upgrade process may take a few moments. + +We recommend upgrading versions one by one. On Qdrant Cloud, this is done automatically when you select the target version. If you're self-hosting, upgrade to the latest patch version of each intermediate minor version first, for example 1.16.x→1.17.x→1.18.0. + +## Engage + +![Section 9](/blog/qdrant-1.18.x/section-9.png) + +We would love to hear your thoughts on this release. If you have any questions or feedback, join our [Discord](https://discord.gg/qdrant) or create an issue on [GitHub](https://github.com/qdrant/qdrant/issues). diff --git a/qdrant-landing/content/blog/vector-space-day-2026-sf.md b/qdrant-landing/content/blog/vector-space-day-2026-sf.md index e45606956..1f83d2f6f 100644 --- a/qdrant-landing/content/blog/vector-space-day-2026-sf.md +++ b/qdrant-landing/content/blog/vector-space-day-2026-sf.md @@ -4,8 +4,8 @@ draft: false slug: vector-space-day-sf-2026 short_description: "Join 300+ AI builders in San Francisco to talk about search, AI retrieval, agents, memory, edge & robotics AI, and more." description: "From building scalable RAG pipelines to enabling real-time AI memory and next-gen context engineering, we’re covering the full spectrum of modern vector-native search." -preview_image: /blog/vector-space-day-2026-sf/sf-hero-20-april.jpg -social_preview_image: /blog/vector-space-day-2026-sf/sf-hero-20-april.jpg +preview_image: /blog/vector-space-day-2026-sf/VSD-SF-Blog-Hero_may7.jpg +social_preview_image: /blog/vector-space-day-2026-sf/VSD-SF-Blog-Hero_may7.jpg date: 2026-04-21 author: Qdrant featured: false @@ -43,11 +43,13 @@ The day won’t end when the last session wraps. Your ticket includes access to ### Call for Speakers -We’ve locked in a strong lineup including Llamaindex, mem0, Neo4j, and more, but we’re saving a few select slots for standout talks from the community. If you’re building something novel in vector search, AI memory, context engineering, or retrieval infra, we want to hear from you. +We’ve locked in a strong lineup including Llamaindex, mem0, Neo4j, and more, but we’ve saving a few select slots for standout talks from the community. If you’re building something novel in vector search, AI memory, context engineering, or retrieval infra, we want to hear from you. + +[Proposal submissions are closed. Missed the May 6 deadline? Go ahead and send it in anyway.](https://docs.google.com/forms/d/e/1FAIpQLSfefAtmGP59-0IhNxCCMbNRCDlU-JRkJnSja3GfOrBnTZw-CA/viewform?usp=dialog) + +Proposals submitted after the deadline, without prior communication with the event organizers, will be reviewed if space becomes available. -[Submit your proposal.](https://docs.google.com/forms/d/e/1FAIpQLSfefAtmGP59-0IhNxCCMbNRCDlU-JRkJnSja3GfOrBnTZw-CA/viewform?usp=dialog) -Due May 6th. ### Get Your Ticket diff --git a/qdrant-landing/content/community/community-features.md b/qdrant-landing/content/community/community-features.md index 58600b888..1a33b757b 100644 --- a/qdrant-landing/content/community/community-features.md +++ b/qdrant-landing/content/community/community-features.md @@ -34,9 +34,6 @@ features: alt: Rocket title: Events description: Meet us at upcoming hackathons, meetups, webinars and conferences. - link: - text: Learn More - url: https://try.qdrant.tech/events - id: 4 icon: src: /icons/outline/guide-blue.svg diff --git a/qdrant-landing/content/customers/clients/_index.md b/qdrant-landing/content/customers/clients/_index.md index f4d7ad5ed..7d776e963 100644 --- a/qdrant-landing/content/customers/clients/_index.md +++ b/qdrant-landing/content/customers/clients/_index.md @@ -110,6 +110,18 @@ clients: logo: src: /img/customers-case-studies-logo/dailymotion.svg alt: Dailymotion logo + - id: data-graphs + name: Data Graphs + industry: Developer tools + product: Hybrid + company_size: 51-200 + location: Europe + use_cases: ["Customer support", "Graph RAG", "Generative AI"] + title: "How Data Graphs Built a True Hybrid Graph RAG Platform - Qdrant" + blog_path: /blog/case-study-datagraphs/ + logo: + src: /img/customers-case-studies-logo/data-graphs.svg + alt: Data Graphs - id: deutsche-telekom name: Deutsche Telekom industry: Telecommunications diff --git a/qdrant-landing/content/documentation/dl-cloud-getting-started.md b/qdrant-landing/content/documentation/dl-cloud-getting-started.md index 5c87a7f06..44841289e 100644 --- a/qdrant-landing/content/documentation/dl-cloud-getting-started.md +++ b/qdrant-landing/content/documentation/dl-cloud-getting-started.md @@ -7,7 +7,7 @@ type: delimiter weight: 1 # Change this weight to change order of sections hideInSidebar: true sitemapExclude: True -_build: +build: publishResources: false render: never partition: deploy diff --git a/qdrant-landing/content/documentation/dl-cloud-interfaces.md b/qdrant-landing/content/documentation/dl-cloud-interfaces.md index 019345ac1..5b2a97cfd 100644 --- a/qdrant-landing/content/documentation/dl-cloud-interfaces.md +++ b/qdrant-landing/content/documentation/dl-cloud-interfaces.md @@ -7,7 +7,7 @@ type: delimiter weight: 25 # Change this weight to change order of sections hideInSidebar: true sitemapExclude: True -_build: +build: publishResources: false render: never partition: deploy diff --git a/qdrant-landing/content/documentation/dl-cloud-support.md b/qdrant-landing/content/documentation/dl-cloud-support.md index fc1a2dc5e..cb6f3f047 100644 --- a/qdrant-landing/content/documentation/dl-cloud-support.md +++ b/qdrant-landing/content/documentation/dl-cloud-support.md @@ -6,7 +6,7 @@ description: "Support resources for Qdrant Cloud users — community Discord, do type: delimiter weight: 300 sitemapExclude: True -_build: +build: publishResources: false render: never partition: deploy diff --git a/qdrant-landing/content/documentation/dl-getting-started.md b/qdrant-landing/content/documentation/dl-getting-started.md index 11e58ebb0..dfdab06b3 100644 --- a/qdrant-landing/content/documentation/dl-getting-started.md +++ b/qdrant-landing/content/documentation/dl-getting-started.md @@ -6,7 +6,7 @@ description: "Get started with Qdrant — install the vector database, connect w type: delimiter weight: 100 # Change this weight to change order of sections sitemapExclude: True -_build: +build: publishResources: false render: never partition: develop diff --git a/qdrant-landing/content/documentation/dl-integration-examples.md b/qdrant-landing/content/documentation/dl-integration-examples.md index 672844c4d..59eed672e 100644 --- a/qdrant-landing/content/documentation/dl-integration-examples.md +++ b/qdrant-landing/content/documentation/dl-integration-examples.md @@ -7,7 +7,7 @@ type: delimiter weight: 1100 # Change this weight to change order of sections partition: ecosystem sitemapExclude: True -_build: +build: publishResources: false render: never --- \ No newline at end of file diff --git a/qdrant-landing/content/documentation/dl-integrations.md b/qdrant-landing/content/documentation/dl-integrations.md index 56834eac3..72f5ebc4d 100644 --- a/qdrant-landing/content/documentation/dl-integrations.md +++ b/qdrant-landing/content/documentation/dl-integrations.md @@ -6,7 +6,7 @@ description: "Browse Qdrant integrations across LLM frameworks, embedding provid type: delimiter weight: 500 # Change this weight to change order of sections sitemapExclude: True -_build: +build: publishResources: false render: never partition: ecosystem diff --git a/qdrant-landing/content/documentation/dl-managed-services.md b/qdrant-landing/content/documentation/dl-managed-services.md index 02f277e8d..3388fd9db 100644 --- a/qdrant-landing/content/documentation/dl-managed-services.md +++ b/qdrant-landing/content/documentation/dl-managed-services.md @@ -6,7 +6,7 @@ description: "Qdrant managed cloud services — fully managed clusters, Hybrid C type: delimiter weight: 200 # Change this weight to change order of sections sitemapExclude: True -_build: +build: publishResources: false render: never partition: deploy diff --git a/qdrant-landing/content/documentation/dl-migrate.md b/qdrant-landing/content/documentation/dl-migrate.md index 534a88961..35be42fef 100644 --- a/qdrant-landing/content/documentation/dl-migrate.md +++ b/qdrant-landing/content/documentation/dl-migrate.md @@ -6,7 +6,7 @@ description: "Migrate to Qdrant from existing vector databases like Pinecone, We type: delimiter weight: 100 # Change this weight to change order of sections sitemapExclude: True -_build: +build: publishResources: false render: never partition: ecosystem diff --git a/qdrant-landing/content/documentation/dl-support.md b/qdrant-landing/content/documentation/dl-support.md index dd5508a53..045187a7a 100644 --- a/qdrant-landing/content/documentation/dl-support.md +++ b/qdrant-landing/content/documentation/dl-support.md @@ -6,7 +6,7 @@ description: "Support options for Qdrant — community channels on Discord and G type: delimiter weight: 500 # Change this weight to change order of sections sitemapExclude: True -_build: +build: publishResources: false render: never partition: develop diff --git a/qdrant-landing/content/documentation/dl-tools.md b/qdrant-landing/content/documentation/dl-tools.md index 90841b673..800cd77a5 100644 --- a/qdrant-landing/content/documentation/dl-tools.md +++ b/qdrant-landing/content/documentation/dl-tools.md @@ -6,7 +6,7 @@ description: "Tools for working with Qdrant — the qcloud CLI, MCP server, web type: delimiter weight: 300 # Change this weight to change order of sections sitemapExclude: True -_build: +build: publishResources: false render: never partition: develop diff --git a/qdrant-landing/content/documentation/dl-tutorials.md b/qdrant-landing/content/documentation/dl-tutorials.md index 106425fb0..3ede49f91 100644 --- a/qdrant-landing/content/documentation/dl-tutorials.md +++ b/qdrant-landing/content/documentation/dl-tutorials.md @@ -6,7 +6,7 @@ description: "Hands-on Qdrant tutorials for semantic and hybrid search, retrieva type: delimiter weight: 400 # Change this weight to change order of sections sitemapExclude: True -_build: +build: publishResources: false render: never partition: develop diff --git a/qdrant-landing/content/documentation/dl-user-manual.md b/qdrant-landing/content/documentation/dl-user-manual.md index 5cb7a38be..462288d03 100644 --- a/qdrant-landing/content/documentation/dl-user-manual.md +++ b/qdrant-landing/content/documentation/dl-user-manual.md @@ -6,7 +6,7 @@ description: "Qdrant user manual covering collections, indexing, quantization, s type: delimiter weight: 200 # Change this weight to change order of sections sitemapExclude: True -_build: +build: publishResources: false render: never partition: develop diff --git a/qdrant-landing/content/documentation/embeddings/gemini.md b/qdrant-landing/content/documentation/embeddings/gemini.md index 59c6ecc7e..17a235181 100644 --- a/qdrant-landing/content/documentation/embeddings/gemini.md +++ b/qdrant-landing/content/documentation/embeddings/gemini.md @@ -41,11 +41,14 @@ texts = [ "Gemini is a family of natively multimodal, large language models (LLMs).", ] -result = gemini_client.models.embed_content( - model="gemini-embedding-2", - contents=texts, - config=types.EmbedContentConfig(task_type="RETRIEVAL_DOCUMENT"), -) +embeddings = [ + gemini_client.models.embed_content( + model="gemini-embedding-2", + contents=text, + config=types.EmbedContentConfig(task_type="RETRIEVAL_DOCUMENT"), + ).embeddings[0] + for text in texts +] ``` ```typescript @@ -60,13 +63,20 @@ const texts = [ "Gemini is a family of natively multimodal, large language models (LLMs).", ]; -const result = await geminiClient.models.embedContent({ - model: "gemini-embedding-2", - contents: texts, - config: { taskType: "RETRIEVAL_DOCUMENT" }, -}); +const embeddings = await Promise.all( + texts.map(async (text) => { + const result = await geminiClient.models.embedContent({ + model: "gemini-embedding-2", + contents: text, + config: { taskType: "RETRIEVAL_DOCUMENT" }, + }); + return result.embeddings[0]; + }) +); ``` +> Note: `gemini-embedding-2` returns one aggregated embedding when given multiple inputs. Embed each text separately and parallelize on the caller side. + ## Creating Qdrant Points and Indexing documents with Qdrant ### Creating Qdrant Points @@ -78,14 +88,14 @@ points = [ vector=embedding.values, payload={"text": text}, ) - for idx, (embedding, text) in enumerate(zip(result.embeddings, texts)) + for idx, (embedding, text) in enumerate(zip(embeddings, texts)) ] ``` ```typescript const points = texts.map((text, idx) => ({ id: idx, - vector: result.embeddings[idx].values, + vector: embeddings[idx].values, payload: { text }, })); ``` diff --git a/qdrant-landing/content/documentation/faq/qdrant-fundamentals.md b/qdrant-landing/content/documentation/faq/qdrant-fundamentals.md index 3ce892983..50921a820 100644 --- a/qdrant-landing/content/documentation/faq/qdrant-fundamentals.md +++ b/qdrant-landing/content/documentation/faq/qdrant-fundamentals.md @@ -57,6 +57,43 @@ There are two possible reasons for this: - You used the `Cosine` distance metric in the [collection settings](/documentation/manage-data/collections/#collections). In this case, Qdrant pre-normalizes your vectors for faster distance computation. If you strictly need the original vectors to be preserved, consider using the `Dot` distance metric instead. - You used the `uint8` [datatype](/documentation/manage-data/vectors/#datatypes) to store vectors. `uint8` requires a special format for input values, which might not be compatible with the typical output of embedding models. +### How many vectors can I store in a point? Can a point have no vector at all? + +A point can hold any number of dense, sparse, and multi vectors, though each has to be configured in the collection's schema. There's no hard limit imposed by Qdrant, though practical limits apply: each additional vector increases memory usage, so the realistic ceiling is determined by available RAM and storage. You can attach a single vector, or multiple vectors with different names (for example, a dense vector for semantic search alongside a sparse vector for keyword matching). This lets you run [hybrid queries](/documentation/search/hybrid-queries/) over several representations of the same data within one collection. Each vector must be defined in the collection's schema. + +A point can also have zero vectors. If you don't provide any vectors at upsert time, Qdrant stores the point with its ID and payload only. This is useful when you want to use Qdrant as a document store with filtering, or when you plan to add vectors to a point later. A vector-less point won't appear in nearest-neighbor search results, but it's fully accessible via [scroll](/documentation/manage-data/points/#scroll-points) and payload filtering. + +### Can Qdrant generate vector embeddings? + +Yes, if you're using Qdrant Cloud, you can generate embeddings with [**Qdrant Cloud Inference**](/documentation/inference/). It lets you embed, store, and index your data in a single API call, so you don't need a separate inference service or embedding pipeline. + +Cloud Inference supports dense models for semantic search, sparse models for keyword recall, and multimodal models for image and text search. Since embeddings are generated inside your cluster's network, you avoid external API overhead — which means lower latency, no egress costs, and fewer moving parts. + +Several models are available at no cost, available on all cluster tiers, including the free tier. You can review available models and current usage in the **Inference** tab of the Cluster Detail page in the [Qdrant Cloud Console](https://cloud.qdrant.io/). + +If you're running Qdrant open-source or self-hosted, Cloud Inference isn't available. You can use [FastEmbed](/documentation/fastembed/), Qdrant's lightweight, local inference library, or bring your own embedding model or service. See the [Embeddings documentation](/documentation/embeddings/) for supported models and providers. + +### Should each chunk of my document be a separate point in Qdrant? + +Yes, in most Retrieval-Augmented Generation (RAG) setups, each chunk is stored as a separate point. The chunk text (or a reference to it) goes in the payload, and the embedding of that chunk is the vector. Points can share a `document_id` payload field so you can trace results back to the source document. + +How you chunk matters significantly and is domain-dependent. As a starting point: paragraph-level chunking works well for books and prose; sentence-level chunking tends to work better for technical articles and Q\&A content. Plan to experiment — chunking strategy is one of the highest-leverage variables in retrieval quality. + +See also: [Text Chunking Strategies](course/essentials/day-1/chunking-strategies/) + +### How does point deletion work internally? Does Qdrant rebuild the index on every delete? + +Qdrant implements deletions as soft deletes using a bitmask, so the index is not rebuilt after each deletion. The bitmask is a lightweight data structure, enabling Qdrant to quickly determine whether a point should be excluded from an operation without accessing the deleted point's data. The Vacuum Optimizer handles physical cleanup in the background. + +After a delete operation, the point is immediately inaccessible via the API. The soft-delete mechanism is an internal implementation detail. + +### Does upserting a point with no changes still trigger a delete and re-insert? + +Yes. Qdrant performs no similarity check before an upsert. If you upsert a point that already exists with identical data, the system still marks the old version as deleted and inserts a new copy. + +### What does the `version` field on a point represent? + +The version field in the Query API response represents the internal shard-level operation number of the last modification to that point. It is incremented by internal processes, so it is not a reliable proxy for application-level write counts and cannot be compared across replicas. Use a user-managed payload counter if you need application-level write tracking. ## Search @@ -75,6 +112,16 @@ If you're still seeing `"vector": null` in your results, it might be that the ve You are likely looking for the [scroll](/documentation/manage-data/points/#scroll-points) method. It allows you to retrieve the records based on filters or even iterate over all the records in the collection. +### My filtered vector search is slow. What should I check first? + +Add a [payload index](/documentation/manage-data/indexing/#payload-index) on all the fields you're filtering by. Payload indexing often produces larger speedups for filtered queries than other optimizations such as changes to Hierarchical Navigable Small World (HNSW) parameters. + +For best results, create payload indexes **before** uploading data. When uploading data later, rebuild the HNSW index by making a minimal change to `m` or `ef_construct` (for example, from 100 to 101). Queries continue to be served by the old index until the new index is complete, so there is no downtime. Don't immediately change the value of `ef_construct` back to its original value, but keep it set to the new value. + +To prevent clients from filtering on payload fields that don't have a payload index, enable strict mode and [set unindexed\_filtering\_retrieve to false](/documentation/ops-configuration/administration/#disable-retrieving-via-non-indexed-payload). + +See also: [Indexing](/documentation/manage-data/indexing/), [Low-Latency Search](/documentation/search/low-latency-search/) + ### Does Qdrant support a full-text search or a hybrid search? Qdrant is a vector search engine in the first place, and we only implement full-text support as long as it doesn't compromise the vector search use case. @@ -98,6 +145,60 @@ What Qdrant doesn't plan to support: Of course, you can always combine Qdrant with any specialized tool you need, including full-text search engines. Read more about [our approach](/articles/hybrid-search/) to hybrid search. +### When should I use Reciprocal Rank Fusion (RRF) vs. Distribution-Based Score Fusion (DBSF) for hybrid search? + +Both methods combine scores from multiple retrieval legs (for example, dense and sparse), but they work differently: + +* **RRF (Reciprocal Rank Fusion)** combines ranked lists based on position, not score magnitude. It works well when scores from different retrieval methods are on incompatible scales (common with dense vs. sparse). Start here by default. [Tune weights and k](/documentation/search/hybrid-queries/#setting-rrf-constant-k) as needed. +* **DBSF (Distribution-Based Score Fusion)** normalizes scores based on their statistical distribution per prefetch before combining them. It can produce better results when score distributions are well-behaved and you want absolute score values to influence the final ranking. + +For custom fusion, use the [Formula Query](/documentation/search/search-relevance/#score-boosting). For example, you can use decay functions to normalize both scores to a 0-1 range and then fuse them. This approach requires you to determine the approximate score distribution for each corpus, since you can't set decay function parameters dynamically. The Formula Query doesn't support custom rank-based fusion because it doesn't have access to prefetch ranks; only to the raw scores. + +To evaluate which works better for your use case, create a small golden query set and compare [retrieval quality metrics](/documentation/improve-search/retrieval-relevance/) (for example, NDCG@10) under each method. + +See also: [Hybrid Queries](/documentation/search/hybrid-queries/) + +### My hybrid search results aren't relevant. Where do I start debugging? + +Work through these in order: + +1. **Check sparse preprocessing.** Poor sparse results are often a tokenization issue. For non-English text, configure language-specific stemming and stop-word lists in the [text search settings](/documentation/search/text-search/#language-specific-settings). +2. **Isolate the legs.** Run your dense-only and sparse-only queries separately. If one leg is producing bad results in isolation, fix it before tuning fusion. +3. **Tune fusion weights.** If both legs look reasonable individually but fusion degrades quality, try adjusting the per-prefetch weights in your RRF configuration. There is no universal default. Evaluate against a small labeled query set. +4. **Add a reranking stage.** If precision matters more than latency, [reranking](/documentation/search/hybrid-queries/#multi-stage-queries) as a final stage can recover from imperfect retrieval. + +### What are the three approaches to filtering in Qdrant, and when should I use each? + +There are three strategies: + +1. **Payload index only** — purely logical separation via filtering. Works for any cardinality. +2. **Payload index with `is_tenant=true`** — logical separation plus physical co-location on shared shards with per-tenant sub-indexes. Still works for any cardinality; only one field per collection can use this setting. +3. **Custom sharding (`shard_key_selector`)** — hard physical boundaries with distinct shards. Eliminates noisy-neighbor problems. Recommended only for low cardinality (< ~1,000 unique values) and only when you *always* filter on that field. + +### If I run the same query with `limit=20` and `limit=100`, are the first 20 results guaranteed to match? + +Results are generally expected to be consistent for the overlapping portion. However, HNSW is an approximate algorithm. A larger limit increases the search scope and may find points that are a better match than those returned for a smaller limit. If `limit=100` manages to find points that are a better match, it will reorder the first 20 points. + +### What does the `time` field in the Query API response represent? Does it include network latency? + +The time value is in seconds and represents the total duration the Qdrant server spent processing the request. It does not include network round-trip time between the client and the server. + +### If `limit` is higher than `hnsw_ef`, does Qdrant automatically adjust `hnsw_ef`? + +Yes. Qdrant internally sets `ef = max(ef, limit)` so that the candidate list is always at least as large as the requested result count. + +### What is the default value of `hnsw_ef` during search? + +By default, `hnsw_ef` equals `ef_construct` (default: 100). `ef_construct` is a collection-level configuration that controls the number of neighbors considered during graph construction. `hnsw_ef` is the per-query parameter controlling the size of the dynamic candidate list during search. + +### What are the default `rescore` values for different quantization methods? + +Only binary quantization uses rescoring by default. All other quantization methods do not rescore by default. The default behavior can be overridden with the query-time `rescore` parameter. + +### What does `ignore=true` do in quantization search params? + +When `ignore` is `true`, Qdrant still traverses the HNSW graph that was built from quantized vectors, but uses exact (full-precision) distances to score candidates during traversal rather than quantized distances. This can improve recall at some cost, since different neighbors may be selected compared to a fully quantized search. + ## Collections ### How many collections can I create? @@ -107,16 +208,61 @@ It is _highly_ recommended not to create many small collections, as it will lead We consider creating a collection for each user/dialog/document as an antipattern. -Please read more about collections, isolation, and multiple users in our [Multitenancy](/documentation/manage-data/collections/#multitenancy) tutorial. +Read more about collections, isolation, and multiple users in our [Multitenancy](/documentation/manage-data/multitenancy/) documentation. + +### Should I use named vectors or separate collections for different embedding models? + +Use **named vectors** when the data you're embedding shares the same payload structure and you want to query across vector spaces in a single request (for example, combining a dense text vector with a CLIP image vector for the same product). Use **separate collections** when the payload schemas differ significantly, when you need independent scaling, when you only set and query one of the configured vectors on a point, to test new embeddings, or when one set of vectors is queried in isolation far more often. + +As a general guideline: named vectors share a point (and its payload). If different embeddings represent fundamentally different entities, they belong in different collections. + +See also: [Named Vectors](/documentation/manage-data/vectors/#named-vectors) + +### Can I switch to a different embedding model without recreating my collection? + +The recommended pattern is an alias-based swap: + +1. Create a new collection and ingest your data re-embedded with the new model. +2. Once indexed, atomically update the [collection alias](/documentation/manage-data/collections/#collection-aliases) to point to the new collection. +3. Delete the old collection when you're confident the migration is stable. + +This gives you zero-downtime migrations and a rollback path. + +See also: [Migrate to a New Embedding Model](/documentation/tutorials-operations/embedding-model-migration/) + +### Why is my collection in "grey" status? + +A collection in grey status means the optimizer has stalled. This can happen if a Qdrant instance is restarted while optimizations are ongoing. During this state, the amount of unindexed data can grow. Because Qdrant falls back to full-scan search on unindexed segments, this degrades query latency. If [`indexed_only` or `prevent_unoptimized` are enabled](/documentation/search/low-latency-search/#query-indexed-data-only), Qdrant doesn't return unindexed data, and search results may be incomplete. + +Common recovery steps: + +1. Use the **Trigger Optimizers** button in the Qdrant Web UI. It is shown next to the grey collection status on the collection info page. +2. Send any [update collection operation](/documentation/manage-data/collections/#grey-collection-status) to trigger and start the optimizations again. + +See also: [Grey collection status](/documentation/manage-data/collections/#grey-collection-status) ### How do I upload a large number of vectors into a Qdrant collection? Read about our recommendations in the [bulk upload](/documentation/tutorials-develop/bulk-upload/) tutorial. +### What's the recommended batch size for uploading vectors? + +There is no universal recommended batch size. The optimum depends on your vector dimensionality, payload size, cluster configuration, and available memory. You should benchmark different batch sizes against your own setup to find what works best. + +A good starting point is 16 to 32 MB per request. This translates to approximately 100 points per batch when dealing with large payloads, or up to 1000 points per batch for pure vectors. However, if operations within a batch are inherently expensive, such as updates impacting many points or updates by filter, it is more efficient to send individual requests. + +A useful pattern for large-scale bulk loads is **staged indexing**: disable HNSW graph construction during upload [by setting the HNSQ `m` parameter to `0`](/documentation/tutorials-develop/bulk-upload/#defer-hnsw-graph-construction-m-0), upload in batches using the upsert API, then restore the threshold to trigger background indexing once the load is complete. This avoids optimizer thrashing and significantly improves throughput during the initial load. + +See also: [Bulk Operations](/documentation/tutorials-develop/bulk-upload/) + ### Can I only store quantized vectors and discard full precision vectors? No, Qdrant requires full precision vectors for operations like reindexing, rescoring, etc. +### Can I delete the original full-precision vectors after enabling quantization? + +No. Qdrant requires the original full-precision vectors to recompute quantized representations whenever the Vacuum Optimizer rebuilds a segment. Qdrant derives quantization statistics (offset and alpha) from the full-precision vectors in each segment, so removing them would make reindexing impossible. + ## Compatibility ### Is Qdrant compatible with CPUs or GPUs for vector computation? @@ -143,6 +289,10 @@ Create payload indexes before uploading to avoid index rebuilding. However, ther You should always index first if you know your filters upfront. If you need to index another payload later, you can still do it, but be aware of the performance hit. +### If I need to add a payload index after the HNSW index has already been built, how do I trigger a full reindex? + +Changing `m` or `ef_construct` automatically triggers a full background HNSW rebuild. For cases where only a payload index is being added, make a minimal change to `ef_construct` (for example, from 100 to 101). Queries continue to be served by the old index until the new index is complete, so there is no downtime. Don't immediately change the value of `ef_construct` back to its original value, but keep it set to the new value. + ## Should I create one Qdrant collection per user? No. Creating one collection per user is more resource intensive. diff --git a/qdrant-landing/content/documentation/headless/content/tutorials/search-engineering.md b/qdrant-landing/content/documentation/headless/content/tutorials/search-engineering.md index 586053f63..ee8d15d3a 100644 --- a/qdrant-landing/content/documentation/headless/content/tutorials/search-engineering.md +++ b/qdrant-landing/content/documentation/headless/content/tutorials/search-engineering.md @@ -5,7 +5,7 @@ | [Relevance Feedback](/documentation/tutorials-search-engineering/using-relevance-feedback/) | Relevance Feedback Retrieval in Qdrant | Python | 30m | Intermediate | | [Collaborative Filtering](/documentation/tutorials-search-engineering/collaborative-filtering/) | Collaborative filtering using sparse embeddings. | Python | 45m | Intermediate | | [Multivector Document Retrieval](/documentation/tutorials-search-engineering/pdf-retrieval-at-scale/) | PDF RAG using ColPali and embedding pooling. | Python | 30m | Intermediate | -| [Retrieval Quality Evaluation](/documentation/tutorials-search-engineering/retrieval-quality/) | Measure quality and tune HNSW parameters. | Python | 30m | Intermediate | +| [Measuring ANN Recall](/documentation/tutorials-search-engineering/ann-recall/) | Measure ANN recall with the Web UI and tune HNSW parameters. | Web UI | 15m | Beginner | | [Hybrid Search with Reranking](/documentation/tutorials-search-engineering/reranking-hybrid-search/) | Implement late interaction and sparse reranking. | Python | 40m | Intermediate | | [Semantic Search for Code](/documentation/tutorials-search-engineering/code-search/) | Navigate codebases using vector similarity. | Python | 45m | Intermediate | | [Multivectors and Late Interaction](/documentation/tutorials-search-engineering/using-multivector-representations/) | Effective use of multivector representations. | Python | 30m | Intermediate | diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-logging/query-with-filters/_description.md b/qdrant-landing/content/documentation/headless/snippets/audit-logging/query-with-filters/_description.md new file mode 100644 index 000000000..127e054b6 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-logging/query-with-filters/_description.md @@ -0,0 +1 @@ +Query the audit log with time range and exact-match filters. diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-logging/query-with-filters/bash.sh b/qdrant-landing/content/documentation/headless/snippets/audit-logging/query-with-filters/bash.sh new file mode 100644 index 000000000..fcf52a77c --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-logging/query-with-filters/bash.sh @@ -0,0 +1,12 @@ +curl -X POST 'https://YOUR-CLUSTER-URL:6333/audit/logs' \ + -H 'api-key: QDRANT_API_KEY' \ + -H 'Content-Type: application/json' \ + -d '{ + "limit": 50, + "time_from": "2026-03-26T00:00:00Z", + "time_to": "2026-03-27T00:00:00Z", + "filters": { + "result": "denied", + "collection": "my_collection" + } + }' diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-logging/query-with-filters/generated/bash.md b/qdrant-landing/content/documentation/headless/snippets/audit-logging/query-with-filters/generated/bash.md new file mode 100644 index 000000000..5b77c6efe --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-logging/query-with-filters/generated/bash.md @@ -0,0 +1,14 @@ +```bash +curl -X POST 'https://YOUR-CLUSTER-URL:6333/audit/logs' \ + -H 'api-key: QDRANT_API_KEY' \ + -H 'Content-Type: application/json' \ + -d '{ + "limit": 50, + "time_from": "2026-03-26T00:00:00Z", + "time_to": "2026-03-27T00:00:00Z", + "filters": { + "result": "denied", + "collection": "my_collection" + } + }' +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-logging/query/_description.md b/qdrant-landing/content/documentation/headless/snippets/audit-logging/query/_description.md new file mode 100644 index 000000000..155c88b0d --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-logging/query/_description.md @@ -0,0 +1 @@ +Query the audit log via the REST API. diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-logging/query/bash.sh b/qdrant-landing/content/documentation/headless/snippets/audit-logging/query/bash.sh new file mode 100644 index 000000000..ab77e18b1 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-logging/query/bash.sh @@ -0,0 +1,4 @@ +curl -X POST 'https://YOUR-CLUSTER-URL:6333/audit/logs' \ + -H 'api-key: QDRANT_API_KEY' \ + -H 'Content-Type: application/json' \ + -d '{}' diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-logging/query/generated/bash.md b/qdrant-landing/content/documentation/headless/snippets/audit-logging/query/generated/bash.md new file mode 100644 index 000000000..baca7d60b --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-logging/query/generated/bash.md @@ -0,0 +1,6 @@ +```bash +curl -X POST 'https://YOUR-CLUSTER-URL:6333/audit/logs' \ + -H 'api-key: QDRANT_API_KEY' \ + -H 'Content-Type: application/json' \ + -d '{}' +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/_description.md b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/_description.md new file mode 100644 index 000000000..531945aaf --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/_description.md @@ -0,0 +1 @@ +Attach a tracing ID to a request so it appears in the audit log entry for that request. diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/bash.sh b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/bash.sh new file mode 100644 index 000000000..1a9caf356 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/bash.sh @@ -0,0 +1,3 @@ +curl -X GET http://localhost:6333/collections \ + --header 'api-key: your_api_key_here' \ + --header 'x-request-id: my-trace-id' diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/csharp.cs b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/csharp.cs new file mode 100644 index 000000000..ae1433361 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/csharp.cs @@ -0,0 +1,14 @@ +using Qdrant.Client; + +public class Snippet +{ + public static async Task Run() + { + // @hide-start + var client = new QdrantClient("localhost", 6334); + // @hide-end + + using (RequestHeaders.Use("x-request-id", "my-trace-id")) + await client.ListCollectionsAsync(); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/bash.md b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/bash.md new file mode 100644 index 000000000..2c90b824b --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/bash.md @@ -0,0 +1,5 @@ +```bash +curl -X GET http://localhost:6333/collections \ + --header 'api-key: your_api_key_here' \ + --header 'x-request-id: my-trace-id' +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/csharp.md b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/csharp.md new file mode 100644 index 000000000..ec8b59f41 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/csharp.md @@ -0,0 +1,6 @@ +```csharp +using Qdrant.Client; + +using (RequestHeaders.Use("x-request-id", "my-trace-id")) + await client.ListCollectionsAsync(); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/go.md b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/go.md new file mode 100644 index 000000000..7ff1fb045 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/go.md @@ -0,0 +1,10 @@ +```go +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +ctx := qdrant.WithHeader(context.Background(), "x-request-id", "my-trace-id") +client.ListCollections(ctx) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/java.md b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/java.md new file mode 100644 index 000000000..55f7b23b6 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/java.md @@ -0,0 +1,9 @@ +```java +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.RequestHeaders; +import io.grpc.Context; + +Context ctx = RequestHeaders.withHeader(Context.current(), "x-request-id", "my-trace-id"); +ctx.run(() -> client.listCollectionsAsync()); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/python.md b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/python.md new file mode 100644 index 000000000..4a6bdfc5f --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/python.md @@ -0,0 +1,7 @@ +```python +from qdrant_client import QdrantClient +from qdrant_client.context_headers import headers + +with headers({"x-request-id": "my-trace-id"}): + client.get_collections() +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/rust.md b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/rust.md new file mode 100644 index 000000000..069f2ed3c --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/rust.md @@ -0,0 +1,8 @@ +```rust +use qdrant_client::Qdrant; + +client + .with_header("x-request-id", "my-trace-id") + .list_collections() + .await?; +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/typescript.md b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/typescript.md new file mode 100644 index 000000000..aba388635 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/generated/typescript.md @@ -0,0 +1,7 @@ +```typescript +import { QdrantClient, withHeaders } from "@qdrant/js-client-rest"; + +const result = await withHeaders({ "x-request-id": "my-trace-id" }, () => + client.getCollections() +); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/go.go b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/go.go new file mode 100644 index 000000000..3242566f2 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/go.go @@ -0,0 +1,17 @@ +package snippet + +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +func Main() { + // @hide-start + client, err := qdrant.NewClient(&qdrant.Config{Host: "localhost", Port: 6334}) + if err != nil { panic(err) } + // @hide-end + + ctx := qdrant.WithHeader(context.Background(), "x-request-id", "my-trace-id") + client.ListCollections(ctx) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/java.java b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/java.java new file mode 100644 index 000000000..09e00c9b8 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/java.java @@ -0,0 +1,18 @@ +package com.example.snippets_amalgamation; + +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.RequestHeaders; +import io.grpc.Context; + +public class Snippet { + public static void run() throws Exception { + // @hide-start + QdrantClient client = new QdrantClient( + QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + // @hide-end + + Context ctx = RequestHeaders.withHeader(Context.current(), "x-request-id", "my-trace-id"); + ctx.run(() -> client.listCollectionsAsync()); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/python.py b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/python.py new file mode 100644 index 000000000..842ef1e4f --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/python.py @@ -0,0 +1,7 @@ +from qdrant_client import QdrantClient +from qdrant_client.context_headers import headers + +client = QdrantClient(url="http://localhost:6333") # @hide + +with headers({"x-request-id": "my-trace-id"}): + client.get_collections() diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/rust.rs b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/rust.rs new file mode 100644 index 000000000..7e678de4f --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/rust.rs @@ -0,0 +1,12 @@ +use qdrant_client::Qdrant; + +pub async fn main() -> anyhow::Result<()> { + let client = Qdrant::from_url("http://localhost:6334").build()?; // @hide + + client + .with_header("x-request-id", "my-trace-id") + .list_collections() + .await?; + + Ok(()) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/typescript.ts b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/typescript.ts new file mode 100644 index 000000000..695fbeb85 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/audit-tracing-id/simple/typescript.ts @@ -0,0 +1,7 @@ +import { QdrantClient, withHeaders } from "@qdrant/js-client-rest"; + +const client = new QdrantClient({ host: "localhost", port: 6333 }); // @hide + +const result = await withHeaders({ "x-request-id": "my-trace-id" }, () => + client.getCollections() +); diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/_description.md b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/_description.md new file mode 100644 index 000000000..c9d91baa4 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/_description.md @@ -0,0 +1 @@ +This code creates a collection with TurboQuant using 2-bit encoding. Specify `bits` to select the compression level. Available values are `bits4` (default, 8× compression), `bits2` (16× compression), `bits1_5` (24× compression), and `bits1` (32× compression). \ No newline at end of file diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/csharp.cs b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/csharp.cs new file mode 100644 index 000000000..1c2bd721d --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/csharp.cs @@ -0,0 +1,21 @@ +using Qdrant.Client; +using Qdrant.Client.Grpc; + +public class Snippet +{ + public static async Task Run() + { + // @hide-start + var client = new QdrantClient("localhost", 6334); + // @hide-end + + await client.CreateCollectionAsync( + collectionName: "{collection_name}", + vectorsConfig: new VectorParams { Size = 1536, Distance = Distance.Cosine }, + quantizationConfig: new QuantizationConfig + { + Turboquant = new TurboQuantization { AlwaysRam = true, Bits = TurboQuantBitSize.Bits2 } + } + ); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/generated/csharp.md b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/generated/csharp.md new file mode 100644 index 000000000..b5c722679 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/generated/csharp.md @@ -0,0 +1,13 @@ +```csharp +using Qdrant.Client; +using Qdrant.Client.Grpc; + +await client.CreateCollectionAsync( + collectionName: "{collection_name}", + vectorsConfig: new VectorParams { Size = 1536, Distance = Distance.Cosine }, + quantizationConfig: new QuantizationConfig + { + Turboquant = new TurboQuantization { AlwaysRam = true, Bits = TurboQuantBitSize.Bits2 } + } +); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/generated/go.md b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/generated/go.md new file mode 100644 index 000000000..cee9e5ae0 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/generated/go.md @@ -0,0 +1,21 @@ +```go +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +client.CreateCollection(context.Background(), &qdrant.CreateCollection{ + CollectionName: "{collection_name}", + VectorsConfig: qdrant.NewVectorsConfig(&qdrant.VectorParams{ + Size: 1536, + Distance: qdrant.Distance_Cosine, + }), + QuantizationConfig: qdrant.NewQuantizationTurbo( + &qdrant.TurboQuantization{ + AlwaysRam: qdrant.PtrOf(true), + Bits: qdrant.TurboQuantBitSize_Bits2.Enum(), + }, + ), +}) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/generated/java.md b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/generated/java.md new file mode 100644 index 000000000..d2ca03692 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/generated/java.md @@ -0,0 +1,34 @@ +```java +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.CreateCollection; +import io.qdrant.client.grpc.Collections.Distance; +import io.qdrant.client.grpc.Collections.QuantizationConfig; +import io.qdrant.client.grpc.Collections.TurboQuantBitSize; +import io.qdrant.client.grpc.Collections.TurboQuantization; +import io.qdrant.client.grpc.Collections.VectorParams; +import io.qdrant.client.grpc.Collections.VectorsConfig; + +client + .createCollectionAsync( + CreateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setVectorsConfig( + VectorsConfig.newBuilder() + .setParams( + VectorParams.newBuilder() + .setSize(1536) + .setDistance(Distance.Cosine) + .build()) + .build()) + .setQuantizationConfig( + QuantizationConfig.newBuilder() + .setTurboquant( + TurboQuantization.newBuilder() + .setAlwaysRam(true) + .setBits(TurboQuantBitSize.Bits2) + .build()) + .build()) + .build()) + .get(); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/generated/python.md b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/generated/python.md new file mode 100644 index 000000000..6494d1965 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/generated/python.md @@ -0,0 +1,14 @@ +```python +from qdrant_client import QdrantClient, models + +client.create_collection( + collection_name="{collection_name}", + vectors_config=models.VectorParams(size=1536, distance=models.Distance.COSINE), + quantization_config=models.TurboQuantization( + turbo=models.TurboQuantQuantizationConfig( + always_ram=True, + bits=models.TurboQuantBitSize.BITS2, + ), + ), +) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/generated/rust.md b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/generated/rust.md new file mode 100644 index 000000000..b90dce37e --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/generated/rust.md @@ -0,0 +1,19 @@ +```rust +use qdrant_client::qdrant::{ + CreateCollectionBuilder, Distance, TurboQuantBitSize, TurboQuantizationBuilder, + VectorParamsBuilder, +}; +use qdrant_client::Qdrant; + +client + .create_collection( + CreateCollectionBuilder::new("{collection_name}") + .vectors_config(VectorParamsBuilder::new(1536, Distance::Cosine)) + .quantization_config( + TurboQuantizationBuilder::new() + .always_ram(true) + .bits(TurboQuantBitSize::Bits2), + ), + ) + .await?; +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/generated/typescript.md b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/generated/typescript.md new file mode 100644 index 000000000..22567c93b --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/generated/typescript.md @@ -0,0 +1,16 @@ +```typescript +import { QdrantClient } from "@qdrant/js-client-rest"; + +client.createCollection("{collection_name}", { + vectors: { + size: 1536, + distance: "Cosine", + }, + quantization_config: { + turbo: { + always_ram: true, + bits: "bits2", + }, + }, +}); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/go.go b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/go.go new file mode 100644 index 000000000..fee109e24 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/go.go @@ -0,0 +1,32 @@ +package snippet + +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +func Main() { + // @hide-start + client, err := qdrant.NewClient(&qdrant.Config{ + Host: "localhost", + Port: 6334, + }) + + if err != nil { panic(err) } + // @hide-end + + client.CreateCollection(context.Background(), &qdrant.CreateCollection{ + CollectionName: "{collection_name}", + VectorsConfig: qdrant.NewVectorsConfig(&qdrant.VectorParams{ + Size: 1536, + Distance: qdrant.Distance_Cosine, + }), + QuantizationConfig: qdrant.NewQuantizationTurbo( + &qdrant.TurboQuantization{ + AlwaysRam: qdrant.PtrOf(true), + Bits: qdrant.TurboQuantBitSize_Bits2.Enum(), + }, + ), + }) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/http.md b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/http.md new file mode 100644 index 000000000..bc9865a4c --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/http.md @@ -0,0 +1,15 @@ +```http +PUT /collections/{collection_name} +{ + "vectors": { + "size": 1536, + "distance": "Cosine" + }, + "quantization_config": { + "turbo": { + "bits": "bits2", + "always_ram": true + } + } +} +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/java.java b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/java.java new file mode 100644 index 000000000..84b2ec2c0 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/java.java @@ -0,0 +1,43 @@ +package com.example.snippets_amalgamation; + +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.CreateCollection; +import io.qdrant.client.grpc.Collections.Distance; +import io.qdrant.client.grpc.Collections.QuantizationConfig; +import io.qdrant.client.grpc.Collections.TurboQuantBitSize; +import io.qdrant.client.grpc.Collections.TurboQuantization; +import io.qdrant.client.grpc.Collections.VectorParams; +import io.qdrant.client.grpc.Collections.VectorsConfig; + +public class Snippet { + public static void run() throws Exception { + // @hide-start + QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + // @hide-end + + client + .createCollectionAsync( + CreateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setVectorsConfig( + VectorsConfig.newBuilder() + .setParams( + VectorParams.newBuilder() + .setSize(1536) + .setDistance(Distance.Cosine) + .build()) + .build()) + .setQuantizationConfig( + QuantizationConfig.newBuilder() + .setTurboquant( + TurboQuantization.newBuilder() + .setAlwaysRam(true) + .setBits(TurboQuantBitSize.Bits2) + .build()) + .build()) + .build()) + .get(); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/python.py b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/python.py new file mode 100644 index 000000000..8e9f60034 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/python.py @@ -0,0 +1,16 @@ +from qdrant_client import QdrantClient, models + +# @hide-start +client = QdrantClient(url="http://localhost:6333") +# @hide-end + +client.create_collection( + collection_name="{collection_name}", + vectors_config=models.VectorParams(size=1536, distance=models.Distance.COSINE), + quantization_config=models.TurboQuantization( + turbo=models.TurboQuantQuantizationConfig( + always_ram=True, + bits=models.TurboQuantBitSize.BITS2, + ), + ), +) diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/rust.rs b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/rust.rs new file mode 100644 index 000000000..e7eedaa2a --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/rust.rs @@ -0,0 +1,25 @@ +use qdrant_client::qdrant::{ + CreateCollectionBuilder, Distance, TurboQuantBitSize, TurboQuantizationBuilder, + VectorParamsBuilder, +}; +use qdrant_client::Qdrant; + +pub async fn main() -> anyhow::Result<()> { + // @hide-start + let client = Qdrant::from_url("http://localhost:6334").build()?; + // @hide-end + + client + .create_collection( + CreateCollectionBuilder::new("{collection_name}") + .vectors_config(VectorParamsBuilder::new(1536, Distance::Cosine)) + .quantization_config( + TurboQuantizationBuilder::new() + .always_ram(true) + .bits(TurboQuantBitSize::Bits2), + ), + ) + .await?; + + Ok(()) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/typescript.ts b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/typescript.ts new file mode 100644 index 000000000..45d95d330 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant-bits/typescript.ts @@ -0,0 +1,18 @@ +import { QdrantClient } from "@qdrant/js-client-rest"; + +// @hide-start +const client = new QdrantClient({ host: "localhost", port: 6333 }); +// @hide-end + +client.createCollection("{collection_name}", { + vectors: { + size: 1536, + distance: "Cosine", + }, + quantization_config: { + turbo: { + always_ram: true, + bits: "bits2", + }, + }, +}); diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/_description.md b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/_description.md new file mode 100644 index 000000000..1cd889046 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/_description.md @@ -0,0 +1 @@ +This code creates a collection with TurboQuant enabled using the default 4-bit encoding. To enable TurboQuant on an existing collection, use a PATCH request or the `update_collection` method and omit the vector configuration. \ No newline at end of file diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/csharp.cs b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/csharp.cs new file mode 100644 index 000000000..0628de2cc --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/csharp.cs @@ -0,0 +1,21 @@ +using Qdrant.Client; +using Qdrant.Client.Grpc; + +public class Snippet +{ + public static async Task Run() + { + // @hide-start + var client = new QdrantClient("localhost", 6334); + // @hide-end + + await client.CreateCollectionAsync( + collectionName: "{collection_name}", + vectorsConfig: new VectorParams { Size = 1536, Distance = Distance.Cosine }, + quantizationConfig: new QuantizationConfig + { + Turboquant = new TurboQuantization { AlwaysRam = true } + } + ); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/generated/csharp.md b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/generated/csharp.md new file mode 100644 index 000000000..277a7e8eb --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/generated/csharp.md @@ -0,0 +1,13 @@ +```csharp +using Qdrant.Client; +using Qdrant.Client.Grpc; + +await client.CreateCollectionAsync( + collectionName: "{collection_name}", + vectorsConfig: new VectorParams { Size = 1536, Distance = Distance.Cosine }, + quantizationConfig: new QuantizationConfig + { + Turboquant = new TurboQuantization { AlwaysRam = true } + } +); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/generated/go.md b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/generated/go.md new file mode 100644 index 000000000..c74b12f14 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/generated/go.md @@ -0,0 +1,20 @@ +```go +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +client.CreateCollection(context.Background(), &qdrant.CreateCollection{ + CollectionName: "{collection_name}", + VectorsConfig: qdrant.NewVectorsConfig(&qdrant.VectorParams{ + Size: 1536, + Distance: qdrant.Distance_Cosine, + }), + QuantizationConfig: qdrant.NewQuantizationTurbo( + &qdrant.TurboQuantization{ + AlwaysRam: qdrant.PtrOf(true), + }, + ), +}) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/generated/java.md b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/generated/java.md new file mode 100644 index 000000000..17e74a489 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/generated/java.md @@ -0,0 +1,29 @@ +```java +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.CreateCollection; +import io.qdrant.client.grpc.Collections.Distance; +import io.qdrant.client.grpc.Collections.QuantizationConfig; +import io.qdrant.client.grpc.Collections.TurboQuantization; +import io.qdrant.client.grpc.Collections.VectorParams; +import io.qdrant.client.grpc.Collections.VectorsConfig; + +client + .createCollectionAsync( + CreateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setVectorsConfig( + VectorsConfig.newBuilder() + .setParams( + VectorParams.newBuilder() + .setSize(1536) + .setDistance(Distance.Cosine) + .build()) + .build()) + .setQuantizationConfig( + QuantizationConfig.newBuilder() + .setTurboquant(TurboQuantization.newBuilder().setAlwaysRam(true).build()) + .build()) + .build()) + .get(); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/generated/python.md b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/generated/python.md new file mode 100644 index 000000000..cd2d20c99 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/generated/python.md @@ -0,0 +1,13 @@ +```python +from qdrant_client import QdrantClient, models + +client.create_collection( + collection_name="{collection_name}", + vectors_config=models.VectorParams(size=1536, distance=models.Distance.COSINE), + quantization_config=models.TurboQuantization( + turbo=models.TurboQuantQuantizationConfig( + always_ram=True, + ), + ), +) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/generated/rust.md b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/generated/rust.md new file mode 100644 index 000000000..50f91df38 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/generated/rust.md @@ -0,0 +1,14 @@ +```rust +use qdrant_client::qdrant::{ + CreateCollectionBuilder, Distance, TurboQuantizationBuilder, VectorParamsBuilder, +}; +use qdrant_client::Qdrant; + +client + .create_collection( + CreateCollectionBuilder::new("{collection_name}") + .vectors_config(VectorParamsBuilder::new(1536, Distance::Cosine)) + .quantization_config(TurboQuantizationBuilder::new().always_ram(true)), + ) + .await?; +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/generated/typescript.md b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/generated/typescript.md new file mode 100644 index 000000000..f0a665e9a --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/generated/typescript.md @@ -0,0 +1,15 @@ +```typescript +import { QdrantClient } from "@qdrant/js-client-rest"; + +client.createCollection("{collection_name}", { + vectors: { + size: 1536, + distance: "Cosine", + }, + quantization_config: { + turbo: { + always_ram: true, + }, + }, +}); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/go.go b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/go.go new file mode 100644 index 000000000..3becebeca --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/go.go @@ -0,0 +1,31 @@ +package snippet + +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +func Main() { + // @hide-start + client, err := qdrant.NewClient(&qdrant.Config{ + Host: "localhost", + Port: 6334, + }) + + if err != nil { panic(err) } + // @hide-end + + client.CreateCollection(context.Background(), &qdrant.CreateCollection{ + CollectionName: "{collection_name}", + VectorsConfig: qdrant.NewVectorsConfig(&qdrant.VectorParams{ + Size: 1536, + Distance: qdrant.Distance_Cosine, + }), + QuantizationConfig: qdrant.NewQuantizationTurbo( + &qdrant.TurboQuantization{ + AlwaysRam: qdrant.PtrOf(true), + }, + ), + }) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/http.md b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/http.md new file mode 100644 index 000000000..5ad693e8d --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/http.md @@ -0,0 +1,14 @@ +```http +PUT /collections/{collection_name} +{ + "vectors": { + "size": 1536, + "distance": "Cosine" + }, + "quantization_config": { + "turbo": { + "always_ram": true + } + } +} +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/java.java b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/java.java new file mode 100644 index 000000000..da0769db0 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/java.java @@ -0,0 +1,38 @@ +package com.example.snippets_amalgamation; + +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.CreateCollection; +import io.qdrant.client.grpc.Collections.Distance; +import io.qdrant.client.grpc.Collections.QuantizationConfig; +import io.qdrant.client.grpc.Collections.TurboQuantization; +import io.qdrant.client.grpc.Collections.VectorParams; +import io.qdrant.client.grpc.Collections.VectorsConfig; + +public class Snippet { + public static void run() throws Exception { + // @hide-start + QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + // @hide-end + + client + .createCollectionAsync( + CreateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setVectorsConfig( + VectorsConfig.newBuilder() + .setParams( + VectorParams.newBuilder() + .setSize(1536) + .setDistance(Distance.Cosine) + .build()) + .build()) + .setQuantizationConfig( + QuantizationConfig.newBuilder() + .setTurboquant(TurboQuantization.newBuilder().setAlwaysRam(true).build()) + .build()) + .build()) + .get(); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/python.py b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/python.py new file mode 100644 index 000000000..28c004333 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/python.py @@ -0,0 +1,15 @@ +from qdrant_client import QdrantClient, models + +# @hide-start +client = QdrantClient(url="http://localhost:6333") +# @hide-end + +client.create_collection( + collection_name="{collection_name}", + vectors_config=models.VectorParams(size=1536, distance=models.Distance.COSINE), + quantization_config=models.TurboQuantization( + turbo=models.TurboQuantQuantizationConfig( + always_ram=True, + ), + ), +) diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/rust.rs b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/rust.rs new file mode 100644 index 000000000..9e0cc5aef --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/rust.rs @@ -0,0 +1,20 @@ +use qdrant_client::qdrant::{ + CreateCollectionBuilder, Distance, TurboQuantizationBuilder, VectorParamsBuilder, +}; +use qdrant_client::Qdrant; + +pub async fn main() -> anyhow::Result<()> { + // @hide-start + let client = Qdrant::from_url("http://localhost:6334").build()?; + // @hide-end + + client + .create_collection( + CreateCollectionBuilder::new("{collection_name}") + .vectors_config(VectorParamsBuilder::new(1536, Distance::Cosine)) + .quantization_config(TurboQuantizationBuilder::new().always_ram(true)), + ) + .await?; + + Ok(()) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/typescript.ts b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/typescript.ts new file mode 100644 index 000000000..8665b60e9 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-collection/with-turbo-quant/typescript.ts @@ -0,0 +1,17 @@ +import { QdrantClient } from "@qdrant/js-client-rest"; + +// @hide-start +const client = new QdrantClient({ host: "localhost", port: 6333 }); +// @hide-end + +client.createCollection("{collection_name}", { + vectors: { + size: 1536, + distance: "Cosine", + }, + quantization_config: { + turbo: { + always_ram: true, + }, + }, +}); diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/_description.md b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/_description.md new file mode 100644 index 000000000..e014fbf87 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/_description.md @@ -0,0 +1 @@ +Create a new dense named vector on an existing collection. Only the immutable vector-space properties are required: size and distance. Storage type, index, and quantization can be configured separately afterward. \ No newline at end of file diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/csharp.cs b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/csharp.cs new file mode 100644 index 000000000..093815b2a --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/csharp.cs @@ -0,0 +1,19 @@ +using Qdrant.Client; +using Qdrant.Client.Grpc; + +public class Snippet +{ + public static async Task Run() + { + // @hide-start + var client = new QdrantClient("localhost", 6334); + // @hide-end + + await client.CreateVectorNameAsync(new() + { + CollectionName = "{collection_name}", + VectorName = "{vector_name}", + DenseConfig = new() { Size = 256, Distance = Distance.Cosine } + }); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/generated/csharp.md b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/generated/csharp.md new file mode 100644 index 000000000..90d156dae --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/generated/csharp.md @@ -0,0 +1,11 @@ +```csharp +using Qdrant.Client; +using Qdrant.Client.Grpc; + +await client.CreateVectorNameAsync(new() +{ + CollectionName = "{collection_name}", + VectorName = "{vector_name}", + DenseConfig = new() { Size = 256, Distance = Distance.Cosine } +}); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/generated/go.md b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/generated/go.md new file mode 100644 index 000000000..913a60404 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/generated/go.md @@ -0,0 +1,18 @@ +```go +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +client.CreateVectorName(context.Background(), &qdrant.CreateVectorNameRequest{ + CollectionName: "{collection_name}", + VectorName: "{vector_name}", + VectorConfig: &qdrant.CreateVectorNameRequest_DenseConfig{ + DenseConfig: &qdrant.DenseVectorCreationConfig{ + Size: 256, + Distance: qdrant.Distance_Cosine, + }, + }, +}) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/generated/java.md b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/generated/java.md new file mode 100644 index 000000000..a4e28390e --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/generated/java.md @@ -0,0 +1,20 @@ +```java +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.Distance; +import io.qdrant.client.grpc.Points.CreateVectorNameRequest; +import io.qdrant.client.grpc.Points.DenseVectorCreationConfig; + +client + .createVectorNameAsync( + CreateVectorNameRequest.newBuilder() + .setCollectionName("{collection_name}") + .setVectorName("{vector_name}") + .setDenseConfig( + DenseVectorCreationConfig.newBuilder() + .setSize(256) + .setDistance(Distance.Cosine) + .build()) + .build()) + .get(); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/generated/python.md b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/generated/python.md new file mode 100644 index 000000000..641678407 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/generated/python.md @@ -0,0 +1,12 @@ +```python +client.create_vector_name( + collection_name="{collection_name}", + vector_name="{vector_name}", + vector_name_config=models.DenseVectorNameConfig( + dense=models.DenseVectorConfig( + size=256, + distance=models.Distance.COSINE, + ), + ), +) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/generated/rust.md b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/generated/rust.md new file mode 100644 index 000000000..ac272bb8d --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/generated/rust.md @@ -0,0 +1,16 @@ +```rust +use qdrant_client::qdrant::{ + CreateVectorNameRequestBuilder, DenseVectorCreationConfigBuilder, Distance, +}; +use qdrant_client::Qdrant; + +client + .create_vector_name( + CreateVectorNameRequestBuilder::new( + "{collection_name}", + "{vector_name}", + DenseVectorCreationConfigBuilder::new(256, Distance::Cosine), + ), + ) + .await?; +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/generated/typescript.md b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/generated/typescript.md new file mode 100644 index 000000000..f415725e3 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/generated/typescript.md @@ -0,0 +1,8 @@ +```typescript +client.createVectorName("{collection_name}", "{vector_name}", { + dense: { + size: 256, + distance: "Cosine", + }, +}); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/go.go b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/go.go new file mode 100644 index 000000000..8a8a4ceea --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/go.go @@ -0,0 +1,29 @@ +package snippet + +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +func Main() { + // @hide-start + client, err := qdrant.NewClient(&qdrant.Config{ + Host: "localhost", + Port: 6334, + }) + + if err != nil { panic(err) } + // @hide-end + + client.CreateVectorName(context.Background(), &qdrant.CreateVectorNameRequest{ + CollectionName: "{collection_name}", + VectorName: "{vector_name}", + VectorConfig: &qdrant.CreateVectorNameRequest_DenseConfig{ + DenseConfig: &qdrant.DenseVectorCreationConfig{ + Size: 256, + Distance: qdrant.Distance_Cosine, + }, + }, + }) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/http.md b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/http.md new file mode 100644 index 000000000..5fb6125b3 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/http.md @@ -0,0 +1,9 @@ +```http +PUT /collections/{collection_name}/vectors/{vector_name} +{ + "dense": { + "size": 256, + "distance": "Cosine" + } +} +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/java.java b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/java.java new file mode 100644 index 000000000..6a0745f92 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/java.java @@ -0,0 +1,29 @@ +package com.example.snippets_amalgamation; + +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.Distance; +import io.qdrant.client.grpc.Points.CreateVectorNameRequest; +import io.qdrant.client.grpc.Points.DenseVectorCreationConfig; + +public class Snippet { + public static void run() throws Exception { + // @hide-start + QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + // @hide-end + + client + .createVectorNameAsync( + CreateVectorNameRequest.newBuilder() + .setCollectionName("{collection_name}") + .setVectorName("{vector_name}") + .setDenseConfig( + DenseVectorCreationConfig.newBuilder() + .setSize(256) + .setDistance(Distance.Cosine) + .build()) + .build()) + .get(); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/python.py b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/python.py new file mode 100644 index 000000000..236020bcc --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/python.py @@ -0,0 +1,14 @@ +from qdrant_client import QdrantClient, models # @hide + +client = QdrantClient(url="http://localhost:6333") # @hide + +client.create_vector_name( + collection_name="{collection_name}", + vector_name="{vector_name}", + vector_name_config=models.DenseVectorNameConfig( + dense=models.DenseVectorConfig( + size=256, + distance=models.Distance.COSINE, + ), + ), +) diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/rust.rs b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/rust.rs new file mode 100644 index 000000000..348b60b50 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/rust.rs @@ -0,0 +1,22 @@ +use qdrant_client::qdrant::{ + CreateVectorNameRequestBuilder, DenseVectorCreationConfigBuilder, Distance, +}; +use qdrant_client::Qdrant; + +pub async fn main() -> anyhow::Result<()> { + // @hide-start + let client = Qdrant::from_url("http://localhost:6334").build()?; + // @hide-end + + client + .create_vector_name( + CreateVectorNameRequestBuilder::new( + "{collection_name}", + "{vector_name}", + DenseVectorCreationConfigBuilder::new(256, Distance::Cosine), + ), + ) + .await?; + + Ok(()) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/typescript.ts b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/typescript.ts new file mode 100644 index 000000000..3f19a3401 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/dense/typescript.ts @@ -0,0 +1,10 @@ +import { QdrantClient } from "@qdrant/js-client-rest"; // @hide + +const client = new QdrantClient({ host: "localhost", port: 6333 }); // @hide + +client.createVectorName("{collection_name}", "{vector_name}", { + dense: { + size: 256, + distance: "Cosine", + }, +}); diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/_description.md b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/_description.md new file mode 100644 index 000000000..abc753cf1 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/_description.md @@ -0,0 +1 @@ +Create a new sparse named vector on an existing collection. Only the immutable vector-space properties are required. Storage type, index, and quantization can be configured separately afterward. \ No newline at end of file diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/csharp.cs b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/csharp.cs new file mode 100644 index 000000000..930e8ba38 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/csharp.cs @@ -0,0 +1,19 @@ +using Qdrant.Client; +using Qdrant.Client.Grpc; + +public class Snippet +{ + public static async Task Run() + { + // @hide-start + var client = new QdrantClient("localhost", 6334); + // @hide-end + + await client.CreateVectorNameAsync(new() + { + CollectionName = "{collection_name}", + VectorName = "{vector_name}", + SparseConfig = new() { Modifier = Modifier.Idf } + }); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/generated/csharp.md b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/generated/csharp.md new file mode 100644 index 000000000..8610d48dc --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/generated/csharp.md @@ -0,0 +1,11 @@ +```csharp +using Qdrant.Client; +using Qdrant.Client.Grpc; + +await client.CreateVectorNameAsync(new() +{ + CollectionName = "{collection_name}", + VectorName = "{vector_name}", + SparseConfig = new() { Modifier = Modifier.Idf } +}); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/generated/go.md b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/generated/go.md new file mode 100644 index 000000000..1bc5e0454 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/generated/go.md @@ -0,0 +1,17 @@ +```go +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +client.CreateVectorName(context.Background(), &qdrant.CreateVectorNameRequest{ + CollectionName: "{collection_name}", + VectorName: "{vector_name}", + VectorConfig: &qdrant.CreateVectorNameRequest_SparseConfig{ + SparseConfig: &qdrant.SparseVectorCreationConfig{ + Modifier: qdrant.Modifier_Idf.Enum(), + }, + }, +}) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/generated/java.md b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/generated/java.md new file mode 100644 index 000000000..15a6bafa5 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/generated/java.md @@ -0,0 +1,19 @@ +```java +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.Modifier; +import io.qdrant.client.grpc.Points.CreateVectorNameRequest; +import io.qdrant.client.grpc.Points.SparseVectorCreationConfig; + +client + .createVectorNameAsync( + CreateVectorNameRequest.newBuilder() + .setCollectionName("{collection_name}") + .setVectorName("{vector_name}") + .setSparseConfig( + SparseVectorCreationConfig.newBuilder() + .setModifier(Modifier.Idf) + .build()) + .build()) + .get(); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/generated/python.md b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/generated/python.md new file mode 100644 index 000000000..d6da661ac --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/generated/python.md @@ -0,0 +1,11 @@ +```python +client.create_vector_name( + collection_name="{collection_name}", + vector_name="{vector_name}", + vector_name_config=models.SparseVectorNameConfig( + sparse=models.SparseVectorConfig( + modifier=models.Modifier.IDF, + ), + ), +) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/generated/rust.md b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/generated/rust.md new file mode 100644 index 000000000..18ca3e07e --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/generated/rust.md @@ -0,0 +1,16 @@ +```rust +use qdrant_client::qdrant::{ + CreateVectorNameRequestBuilder, Modifier, SparseVectorCreationConfigBuilder, +}; +use qdrant_client::Qdrant; + +client + .create_vector_name( + CreateVectorNameRequestBuilder::new( + "{collection_name}", + "{vector_name}", + SparseVectorCreationConfigBuilder::new().modifier(Modifier::Idf), + ), + ) + .await?; +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/generated/typescript.md b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/generated/typescript.md new file mode 100644 index 000000000..37005b6a7 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/generated/typescript.md @@ -0,0 +1,7 @@ +```typescript +client.createVectorName("{collection_name}", "{vector_name}", { + sparse: { + modifier: "idf", + }, +}); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/go.go b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/go.go new file mode 100644 index 000000000..65a14832d --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/go.go @@ -0,0 +1,28 @@ +package snippet + +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +func Main() { + // @hide-start + client, err := qdrant.NewClient(&qdrant.Config{ + Host: "localhost", + Port: 6334, + }) + + if err != nil { panic(err) } + // @hide-end + + client.CreateVectorName(context.Background(), &qdrant.CreateVectorNameRequest{ + CollectionName: "{collection_name}", + VectorName: "{vector_name}", + VectorConfig: &qdrant.CreateVectorNameRequest_SparseConfig{ + SparseConfig: &qdrant.SparseVectorCreationConfig{ + Modifier: qdrant.Modifier_Idf.Enum(), + }, + }, + }) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/http.md b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/http.md new file mode 100644 index 000000000..e1132f2c8 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/http.md @@ -0,0 +1,8 @@ +```http +PUT /collections/{collection_name}/vectors/{vector_name} +{ + "sparse": { + "modifier": "Idf" + } +} +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/java.java b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/java.java new file mode 100644 index 000000000..f97c951e8 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/java.java @@ -0,0 +1,28 @@ +package com.example.snippets_amalgamation; + +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.Modifier; +import io.qdrant.client.grpc.Points.CreateVectorNameRequest; +import io.qdrant.client.grpc.Points.SparseVectorCreationConfig; + +public class Snippet { + public static void run() throws Exception { + // @hide-start + QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + // @hide-end + + client + .createVectorNameAsync( + CreateVectorNameRequest.newBuilder() + .setCollectionName("{collection_name}") + .setVectorName("{vector_name}") + .setSparseConfig( + SparseVectorCreationConfig.newBuilder() + .setModifier(Modifier.Idf) + .build()) + .build()) + .get(); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/python.py b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/python.py new file mode 100644 index 000000000..0b2a97835 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/python.py @@ -0,0 +1,13 @@ +from qdrant_client import QdrantClient, models # @hide + +client = QdrantClient(url="http://localhost:6333") # @hide + +client.create_vector_name( + collection_name="{collection_name}", + vector_name="{vector_name}", + vector_name_config=models.SparseVectorNameConfig( + sparse=models.SparseVectorConfig( + modifier=models.Modifier.IDF, + ), + ), +) diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/rust.rs b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/rust.rs new file mode 100644 index 000000000..48943bde2 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/rust.rs @@ -0,0 +1,22 @@ +use qdrant_client::qdrant::{ + CreateVectorNameRequestBuilder, Modifier, SparseVectorCreationConfigBuilder, +}; +use qdrant_client::Qdrant; + +pub async fn main() -> anyhow::Result<()> { + // @hide-start + let client = Qdrant::from_url("http://localhost:6334").build()?; + // @hide-end + + client + .create_vector_name( + CreateVectorNameRequestBuilder::new( + "{collection_name}", + "{vector_name}", + SparseVectorCreationConfigBuilder::new().modifier(Modifier::Idf), + ), + ) + .await?; + + Ok(()) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/typescript.ts b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/typescript.ts new file mode 100644 index 000000000..a96ba0231 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/create-named-vector/sparse/typescript.ts @@ -0,0 +1,9 @@ +import { QdrantClient } from "@qdrant/js-client-rest"; // @hide + +const client = new QdrantClient({ host: "localhost", port: 6333 }); // @hide + +client.createVectorName("{collection_name}", "{vector_name}", { + sparse: { + modifier: "idf", + }, +}); diff --git a/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/_description.md b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/_description.md new file mode 100644 index 000000000..3416797a7 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/_description.md @@ -0,0 +1 @@ +Delete a named vector from an existing collection. This removes the vector schema and all associated data from every segment. Existing points lose this vector field; they are not otherwise affected. \ No newline at end of file diff --git a/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/csharp.cs b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/csharp.cs new file mode 100644 index 000000000..8e620e2b0 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/csharp.cs @@ -0,0 +1,18 @@ +using Qdrant.Client; +using Qdrant.Client.Grpc; + +public class Snippet +{ + public static async Task Run() + { + // @hide-start + var client = new QdrantClient("localhost", 6334); + // @hide-end + + await client.DeleteVectorNameAsync(new() + { + CollectionName = "{collection_name}", + VectorName = "{vector_name}" + }); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/generated/csharp.md b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/generated/csharp.md new file mode 100644 index 000000000..f97fe587f --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/generated/csharp.md @@ -0,0 +1,10 @@ +```csharp +using Qdrant.Client; +using Qdrant.Client.Grpc; + +await client.DeleteVectorNameAsync(new() +{ + CollectionName = "{collection_name}", + VectorName = "{vector_name}" +}); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/generated/go.md b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/generated/go.md new file mode 100644 index 000000000..7b51d7f97 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/generated/go.md @@ -0,0 +1,12 @@ +```go +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +client.DeleteVectorName(context.Background(), &qdrant.DeleteVectorNameRequest{ + CollectionName: "{collection_name}", + VectorName: "{vector_name}", +}) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/generated/java.md b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/generated/java.md new file mode 100644 index 000000000..b35bf236d --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/generated/java.md @@ -0,0 +1,13 @@ +```java +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Points.DeleteVectorNameRequest; + +client + .deleteVectorNameAsync( + DeleteVectorNameRequest.newBuilder() + .setCollectionName("{collection_name}") + .setVectorName("{vector_name}") + .build()) + .get(); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/generated/python.md b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/generated/python.md new file mode 100644 index 000000000..057341568 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/generated/python.md @@ -0,0 +1,6 @@ +```python +client.delete_vector_name( + collection_name="{collection_name}", + vector_name="{vector_name}", +) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/generated/rust.md b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/generated/rust.md new file mode 100644 index 000000000..e98fa1704 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/generated/rust.md @@ -0,0 +1,11 @@ +```rust +use qdrant_client::qdrant::DeleteVectorNameRequestBuilder; +use qdrant_client::Qdrant; + +client + .delete_vector_name(DeleteVectorNameRequestBuilder::new( + "{collection_name}", + "{vector_name}", + )) + .await?; +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/generated/typescript.md b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/generated/typescript.md new file mode 100644 index 000000000..7c0f22a06 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/generated/typescript.md @@ -0,0 +1,3 @@ +```typescript +client.deleteVectorName("{collection_name}", "{vector_name}"); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/go.go b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/go.go new file mode 100644 index 000000000..94be0eff9 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/go.go @@ -0,0 +1,23 @@ +package snippet + +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +func Main() { + // @hide-start + client, err := qdrant.NewClient(&qdrant.Config{ + Host: "localhost", + Port: 6334, + }) + + if err != nil { panic(err) } + // @hide-end + + client.DeleteVectorName(context.Background(), &qdrant.DeleteVectorNameRequest{ + CollectionName: "{collection_name}", + VectorName: "{vector_name}", + }) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/http.md b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/http.md new file mode 100644 index 000000000..d4de7d653 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/http.md @@ -0,0 +1,3 @@ +```http +DELETE /collections/{collection_name}/vectors/{vector_name} +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/java.java b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/java.java new file mode 100644 index 000000000..9561924de --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/java.java @@ -0,0 +1,22 @@ +package com.example.snippets_amalgamation; + +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Points.DeleteVectorNameRequest; + +public class Snippet { + public static void run() throws Exception { + // @hide-start + QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + // @hide-end + + client + .deleteVectorNameAsync( + DeleteVectorNameRequest.newBuilder() + .setCollectionName("{collection_name}") + .setVectorName("{vector_name}") + .build()) + .get(); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/python.py b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/python.py new file mode 100644 index 000000000..27fd94e4f --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/python.py @@ -0,0 +1,8 @@ +from qdrant_client import QdrantClient # @hide + +client = QdrantClient(url="http://localhost:6333") # @hide + +client.delete_vector_name( + collection_name="{collection_name}", + vector_name="{vector_name}", +) diff --git a/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/rust.rs b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/rust.rs new file mode 100644 index 000000000..ce7d5f83a --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/rust.rs @@ -0,0 +1,17 @@ +use qdrant_client::qdrant::DeleteVectorNameRequestBuilder; +use qdrant_client::Qdrant; + +pub async fn main() -> anyhow::Result<()> { + // @hide-start + let client = Qdrant::from_url("http://localhost:6334").build()?; + // @hide-end + + client + .delete_vector_name(DeleteVectorNameRequestBuilder::new( + "{collection_name}", + "{vector_name}", + )) + .await?; + + Ok(()) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/typescript.ts b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/typescript.ts new file mode 100644 index 000000000..4d4084fcf --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/delete-named-vector/typescript.ts @@ -0,0 +1,5 @@ +import { QdrantClient } from "@qdrant/js-client-rest"; // @hide + +const client = new QdrantClient({ host: "localhost", port: 6333 }); // @hide + +client.deleteVectorName("{collection_name}", "{vector_name}"); diff --git a/qdrant-landing/content/documentation/headless/snippets/filter-condition/match-except/csharp.cs b/qdrant-landing/content/documentation/headless/snippets/filter-condition/match-except/csharp.cs index cc62bbeb7..29df61f1a 100644 --- a/qdrant-landing/content/documentation/headless/snippets/filter-condition/match-except/csharp.cs +++ b/qdrant-landing/content/documentation/headless/snippets/filter-condition/match-except/csharp.cs @@ -4,6 +4,6 @@ public class Snippet { public static async Task Run() { - Match("color", ["black", "yellow"]); + MatchExcept("color", ["black", "yellow"]); } } diff --git a/qdrant-landing/content/documentation/headless/snippets/filter-condition/match-except/generated/csharp.md b/qdrant-landing/content/documentation/headless/snippets/filter-condition/match-except/generated/csharp.md index a362cb37a..5a037eee2 100644 --- a/qdrant-landing/content/documentation/headless/snippets/filter-condition/match-except/generated/csharp.md +++ b/qdrant-landing/content/documentation/headless/snippets/filter-condition/match-except/generated/csharp.md @@ -1,5 +1,5 @@ ```csharp using static Qdrant.Client.Grpc.Conditions; -Match("color", ["black", "yellow"]); +MatchExcept("color", ["black", "yellow"]); ``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/_description.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/_description.md new file mode 100644 index 000000000..0482a8c35 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/_description.md @@ -0,0 +1 @@ +This code snippet sets `max_resident_memory_percent` on the strict mode configuration to reject memory-consuming write operations when resident memory exceeds the given percentage of total system memory. \ No newline at end of file diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/bash.sh b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/bash.sh new file mode 100644 index 000000000..05f8bfe71 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/bash.sh @@ -0,0 +1,8 @@ +curl -X PUT http://localhost:6333/collections/{collection_name} \ + -H 'Content-Type: application/json' \ + --data-raw '{ + "strict_mode_config": { + "enabled": true, + "max_resident_memory_percent": 90 + } + }' diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/csharp.cs b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/csharp.cs new file mode 100644 index 000000000..88d3439ba --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/csharp.cs @@ -0,0 +1,15 @@ +using Qdrant.Client; +using Qdrant.Client.Grpc; + +public class Snippet +{ + public static async Task Run() + { + var client = new QdrantClient("localhost", 6334); + + await client.CreateCollectionAsync( + collectionName: "{collection_name}", + strictModeConfig: new StrictModeConfig { Enabled = true, MaxResidentMemoryPercent = 90 } + ); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/bash.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/bash.md new file mode 100644 index 000000000..7d5473310 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/bash.md @@ -0,0 +1,10 @@ +```bash +curl -X PUT http://localhost:6333/collections/{collection_name} \ + -H 'Content-Type: application/json' \ + --data-raw '{ + "strict_mode_config": { + "enabled": true, + "max_resident_memory_percent": 90 + } + }' +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/csharp.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/csharp.md new file mode 100644 index 000000000..68ddc35ef --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/csharp.md @@ -0,0 +1,11 @@ +```csharp +using Qdrant.Client; +using Qdrant.Client.Grpc; + +var client = new QdrantClient("localhost", 6334); + +await client.CreateCollectionAsync( + collectionName: "{collection_name}", + strictModeConfig: new StrictModeConfig { Enabled = true, MaxResidentMemoryPercent = 90 } +); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/go.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/go.md new file mode 100644 index 000000000..37371f03b --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/go.md @@ -0,0 +1,20 @@ +```go +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +client, err := qdrant.NewClient(&qdrant.Config{ + Host: "localhost", + Port: 6334, +}) + +client.CreateCollection(context.Background(), &qdrant.CreateCollection{ + CollectionName: "{collection_name}", + StrictModeConfig: &qdrant.StrictModeConfig{ + Enabled: qdrant.PtrOf(true), + MaxResidentMemoryPercent: qdrant.PtrOf(uint32(90)), + }, +}) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/java.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/java.md new file mode 100644 index 000000000..a69c99c6a --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/java.md @@ -0,0 +1,18 @@ +```java +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.CreateCollection; +import io.qdrant.client.grpc.Collections.StrictModeConfig; + +QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + +client + .createCollectionAsync( + CreateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setStrictModeConfig( + StrictModeConfig.newBuilder().setEnabled(true).setMaxResidentMemoryPercent(90).build()) + .build()) + .get(); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/python.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/python.md new file mode 100644 index 000000000..4a443dbf2 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/python.md @@ -0,0 +1,10 @@ +```python +from qdrant_client import QdrantClient, models + +client = QdrantClient(url="http://localhost:6333") + +client.create_collection( + collection_name="{collection_name}", + strict_mode_config=models.StrictModeConfig(enabled=True, max_resident_memory_percent=90), +) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/rust.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/rust.md new file mode 100644 index 000000000..fbbf29679 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/rust.md @@ -0,0 +1,13 @@ +```rust +use qdrant_client::Qdrant; +use qdrant_client::qdrant::{CreateCollectionBuilder, StrictModeConfigBuilder}; + +let client = Qdrant::from_url("http://localhost:6334").build()?; + +client + .create_collection( + CreateCollectionBuilder::new("{collection_name}") + .strict_mode_config(StrictModeConfigBuilder::default().enabled(true).max_resident_memory_percent(90u32)), + ) + .await?; +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/typescript.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/typescript.md new file mode 100644 index 000000000..991c3cef5 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/generated/typescript.md @@ -0,0 +1,12 @@ +```typescript +import { QdrantClient } from "@qdrant/js-client-rest"; + +const client = new QdrantClient({ host: "localhost", port: 6333 }); + +client.createCollection("{collection_name}", { + strict_mode_config: { + enabled: true, + max_resident_memory_percent: 90, + }, +}); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/go.go b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/go.go new file mode 100644 index 000000000..d2f8372b8 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/go.go @@ -0,0 +1,24 @@ +package snippet + +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +func Main() { + client, err := qdrant.NewClient(&qdrant.Config{ + Host: "localhost", + Port: 6334, + }) + + if err != nil { panic(err) } // @hide + + client.CreateCollection(context.Background(), &qdrant.CreateCollection{ + CollectionName: "{collection_name}", + StrictModeConfig: &qdrant.StrictModeConfig{ + Enabled: qdrant.PtrOf(true), + MaxResidentMemoryPercent: qdrant.PtrOf(uint32(90)), + }, + }) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/http.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/http.md new file mode 100644 index 000000000..5c8671a5e --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/http.md @@ -0,0 +1,9 @@ +```http +PUT /collections/{collection_name} +{ + "strict_mode_config": { + "enabled": true, + "max_resident_memory_percent": 90 + } +} +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/java.java b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/java.java new file mode 100644 index 000000000..938301117 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/java.java @@ -0,0 +1,22 @@ +package com.example.snippets_amalgamation; + +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.CreateCollection; +import io.qdrant.client.grpc.Collections.StrictModeConfig; + +public class Snippet { + public static void run() throws Exception { + QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + + client + .createCollectionAsync( + CreateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setStrictModeConfig( + StrictModeConfig.newBuilder().setEnabled(true).setMaxResidentMemoryPercent(90).build()) + .build()) + .get(); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/python.py b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/python.py new file mode 100644 index 000000000..4c054b501 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/python.py @@ -0,0 +1,8 @@ +from qdrant_client import QdrantClient, models + +client = QdrantClient(url="http://localhost:6333") + +client.create_collection( + collection_name="{collection_name}", + strict_mode_config=models.StrictModeConfig(enabled=True, max_resident_memory_percent=90), +) diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/rust.rs b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/rust.rs new file mode 100644 index 000000000..98eb706b8 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/rust.rs @@ -0,0 +1,15 @@ +use qdrant_client::Qdrant; +use qdrant_client::qdrant::{CreateCollectionBuilder, StrictModeConfigBuilder}; + +pub async fn main() -> anyhow::Result<()> { + let client = Qdrant::from_url("http://localhost:6334").build()?; + + client + .create_collection( + CreateCollectionBuilder::new("{collection_name}") + .strict_mode_config(StrictModeConfigBuilder::default().enabled(true).max_resident_memory_percent(90u32)), + ) + .await?; + + Ok(()) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/typescript.ts b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/typescript.ts new file mode 100644 index 000000000..a388fc934 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/max-resident-memory-percent/typescript.ts @@ -0,0 +1,10 @@ +import { QdrantClient } from "@qdrant/js-client-rest"; + +const client = new QdrantClient({ host: "localhost", port: 6333 }); + +client.createCollection("{collection_name}", { + strict_mode_config: { + enabled: true, + max_resident_memory_percent: 90, + }, +}); diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/_description.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/_description.md new file mode 100644 index 000000000..285b50080 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/_description.md @@ -0,0 +1 @@ +This code snippet sets `multivector_config` on the strict mode configuration to cap the maximum number of vectors per multivector for a named vector. \ No newline at end of file diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/bash.sh b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/bash.sh new file mode 100644 index 000000000..2d8c0fc96 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/bash.sh @@ -0,0 +1,12 @@ +curl -X PUT http://localhost:6333/collections/{collection_name} \ + -H 'Content-Type: application/json' \ + --data-raw '{ + "strict_mode_config": { + "enabled": true, + "multivector_config": { + "{vector_name}": { + "max_vectors": 10 + } + } + } + }' diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/csharp.cs b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/csharp.cs new file mode 100644 index 000000000..576212499 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/csharp.cs @@ -0,0 +1,22 @@ +using Qdrant.Client; +using Qdrant.Client.Grpc; + +public class Snippet +{ + public static async Task Run() + { + var client = new QdrantClient("localhost", 6334); + + await client.CreateCollectionAsync( + collectionName: "{collection_name}", + strictModeConfig: new StrictModeConfig + { + Enabled = true, + MultivectorConfig = new StrictModeMultivectorConfig + { + MultivectorConfig = { ["{vector_name}"] = new StrictModeMultivector { MaxVectors = 10 } } + } + } + ); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/bash.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/bash.md new file mode 100644 index 000000000..7566d08ad --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/bash.md @@ -0,0 +1,14 @@ +```bash +curl -X PUT http://localhost:6333/collections/{collection_name} \ + -H 'Content-Type: application/json' \ + --data-raw '{ + "strict_mode_config": { + "enabled": true, + "multivector_config": { + "{vector_name}": { + "max_vectors": 10 + } + } + } + }' +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/csharp.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/csharp.md new file mode 100644 index 000000000..bf5928c6a --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/csharp.md @@ -0,0 +1,18 @@ +```csharp +using Qdrant.Client; +using Qdrant.Client.Grpc; + +var client = new QdrantClient("localhost", 6334); + +await client.CreateCollectionAsync( + collectionName: "{collection_name}", + strictModeConfig: new StrictModeConfig + { + Enabled = true, + MultivectorConfig = new StrictModeMultivectorConfig + { + MultivectorConfig = { ["{vector_name}"] = new StrictModeMultivector { MaxVectors = 10 } } + } + } +); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/go.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/go.md new file mode 100644 index 000000000..ba5b4948f --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/go.md @@ -0,0 +1,24 @@ +```go +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +client, err := qdrant.NewClient(&qdrant.Config{ + Host: "localhost", + Port: 6334, +}) + +client.CreateCollection(context.Background(), &qdrant.CreateCollection{ + CollectionName: "{collection_name}", + StrictModeConfig: &qdrant.StrictModeConfig{ + Enabled: qdrant.PtrOf(true), + MultivectorConfig: &qdrant.StrictModeMultivectorConfig{ + MultivectorConfig: map[string]*qdrant.StrictModeMultivector{ + "{vector_name}": {MaxVectors: qdrant.PtrOf(uint64(10))}, + }, + }, + }, +}) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/java.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/java.md new file mode 100644 index 000000000..7421cd7fa --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/java.md @@ -0,0 +1,26 @@ +```java +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.CreateCollection; +import io.qdrant.client.grpc.Collections.StrictModeConfig; +import io.qdrant.client.grpc.Collections.StrictModeMultivector; +import io.qdrant.client.grpc.Collections.StrictModeMultivectorConfig; + +QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + +client + .createCollectionAsync( + CreateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setStrictModeConfig( + StrictModeConfig.newBuilder() + .setEnabled(true) + .setMultivectorConfig( + StrictModeMultivectorConfig.newBuilder() + .putMultivectorConfig("{vector_name}", StrictModeMultivector.newBuilder().setMaxVectors(10).build()) + .build()) + .build()) + .build()) + .get(); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/python.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/python.md new file mode 100644 index 000000000..c15c782b9 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/python.md @@ -0,0 +1,13 @@ +```python +from qdrant_client import QdrantClient, models + +client = QdrantClient(url="http://localhost:6333") + +client.create_collection( + collection_name="{collection_name}", + strict_mode_config=models.StrictModeConfig( + enabled=True, + multivector_config={"{vector_name}": models.StrictModeMultivector(max_vectors=10)}, + ), +) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/rust.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/rust.md new file mode 100644 index 000000000..2c4fd2bf1 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/rust.md @@ -0,0 +1,28 @@ +```rust +use std::collections::HashMap; + +use qdrant_client::Qdrant; +use qdrant_client::qdrant::{ + CreateCollectionBuilder, StrictModeConfigBuilder, StrictModeMultivector, + StrictModeMultivectorConfig, +}; + +let client = Qdrant::from_url("http://localhost:6334").build()?; + +client + .create_collection( + CreateCollectionBuilder::new("{collection_name}").strict_mode_config( + StrictModeConfigBuilder::default() + .enabled(true) + .multivector_config(StrictModeMultivectorConfig { + multivector_config: HashMap::from([( + "{vector_name}".to_string(), + StrictModeMultivector { + max_vectors: Some(10), + }, + )]), + }), + ), + ) + .await?; +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/typescript.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/typescript.md new file mode 100644 index 000000000..fd5be60e8 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/generated/typescript.md @@ -0,0 +1,16 @@ +```typescript +import { QdrantClient } from "@qdrant/js-client-rest"; + +const client = new QdrantClient({ host: "localhost", port: 6333 }); + +client.createCollection("{collection_name}", { + strict_mode_config: { + enabled: true, + multivector_config: { + "{vector_name}": { + max_vectors: 10, + }, + }, + }, +}); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/go.go b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/go.go new file mode 100644 index 000000000..0f2f7f2ab --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/go.go @@ -0,0 +1,28 @@ +package snippet + +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +func Main() { + client, err := qdrant.NewClient(&qdrant.Config{ + Host: "localhost", + Port: 6334, + }) + + if err != nil { panic(err) } // @hide + + client.CreateCollection(context.Background(), &qdrant.CreateCollection{ + CollectionName: "{collection_name}", + StrictModeConfig: &qdrant.StrictModeConfig{ + Enabled: qdrant.PtrOf(true), + MultivectorConfig: &qdrant.StrictModeMultivectorConfig{ + MultivectorConfig: map[string]*qdrant.StrictModeMultivector{ + "{vector_name}": {MaxVectors: qdrant.PtrOf(uint64(10))}, + }, + }, + }, + }) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/http.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/http.md new file mode 100644 index 000000000..0d34ee525 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/http.md @@ -0,0 +1,13 @@ +```http +PUT /collections/{collection_name} +{ + "strict_mode_config": { + "enabled": true, + "multivector_config": { + "{vector_name}": { + "max_vectors": 10 + } + } + } +} +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/java.java b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/java.java new file mode 100644 index 000000000..7d815f4d1 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/java.java @@ -0,0 +1,30 @@ +package com.example.snippets_amalgamation; + +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.CreateCollection; +import io.qdrant.client.grpc.Collections.StrictModeConfig; +import io.qdrant.client.grpc.Collections.StrictModeMultivector; +import io.qdrant.client.grpc.Collections.StrictModeMultivectorConfig; + +public class Snippet { + public static void run() throws Exception { + QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + + client + .createCollectionAsync( + CreateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setStrictModeConfig( + StrictModeConfig.newBuilder() + .setEnabled(true) + .setMultivectorConfig( + StrictModeMultivectorConfig.newBuilder() + .putMultivectorConfig("{vector_name}", StrictModeMultivector.newBuilder().setMaxVectors(10).build()) + .build()) + .build()) + .build()) + .get(); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/python.py b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/python.py new file mode 100644 index 000000000..2fb762706 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/python.py @@ -0,0 +1,11 @@ +from qdrant_client import QdrantClient, models + +client = QdrantClient(url="http://localhost:6333") + +client.create_collection( + collection_name="{collection_name}", + strict_mode_config=models.StrictModeConfig( + enabled=True, + multivector_config={"{vector_name}": models.StrictModeMultivector(max_vectors=10)}, + ), +) diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/rust.rs b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/rust.rs new file mode 100644 index 000000000..9072ea241 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/rust.rs @@ -0,0 +1,30 @@ +use std::collections::HashMap; + +use qdrant_client::Qdrant; +use qdrant_client::qdrant::{ + CreateCollectionBuilder, StrictModeConfigBuilder, StrictModeMultivector, + StrictModeMultivectorConfig, +}; + +pub async fn main() -> anyhow::Result<()> { + let client = Qdrant::from_url("http://localhost:6334").build()?; + + client + .create_collection( + CreateCollectionBuilder::new("{collection_name}").strict_mode_config( + StrictModeConfigBuilder::default() + .enabled(true) + .multivector_config(StrictModeMultivectorConfig { + multivector_config: HashMap::from([( + "{vector_name}".to_string(), + StrictModeMultivector { + max_vectors: Some(10), + }, + )]), + }), + ), + ) + .await?; + + Ok(()) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/typescript.ts b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/typescript.ts new file mode 100644 index 000000000..ff046d4f3 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/multivector-config/typescript.ts @@ -0,0 +1,14 @@ +import { QdrantClient } from "@qdrant/js-client-rest"; + +const client = new QdrantClient({ host: "localhost", port: 6333 }); + +client.createCollection("{collection_name}", { + strict_mode_config: { + enabled: true, + multivector_config: { + "{vector_name}": { + max_vectors: 10, + }, + }, + }, +}); diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/_description.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/_description.md new file mode 100644 index 000000000..14694edb0 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/_description.md @@ -0,0 +1 @@ +This code snippet sets `search_allow_exact` to false on the strict mode configuration to prevent exact (brute-force) search, which can be very slow on large collections. \ No newline at end of file diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/bash.sh b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/bash.sh new file mode 100644 index 000000000..285183088 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/bash.sh @@ -0,0 +1,8 @@ +curl -X PUT http://localhost:6333/collections/{collection_name} \ + -H 'Content-Type: application/json' \ + --data-raw '{ + "strict_mode_config": { + "enabled": true, + "search_allow_exact": false + } + }' diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/csharp.cs b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/csharp.cs new file mode 100644 index 000000000..49c4473f5 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/csharp.cs @@ -0,0 +1,15 @@ +using Qdrant.Client; +using Qdrant.Client.Grpc; + +public class Snippet +{ + public static async Task Run() + { + var client = new QdrantClient("localhost", 6334); + + await client.CreateCollectionAsync( + collectionName: "{collection_name}", + strictModeConfig: new StrictModeConfig { Enabled = true, SearchAllowExact = false } + ); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/bash.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/bash.md new file mode 100644 index 000000000..12b9af684 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/bash.md @@ -0,0 +1,10 @@ +```bash +curl -X PUT http://localhost:6333/collections/{collection_name} \ + -H 'Content-Type: application/json' \ + --data-raw '{ + "strict_mode_config": { + "enabled": true, + "search_allow_exact": false + } + }' +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/csharp.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/csharp.md new file mode 100644 index 000000000..b3b9cb591 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/csharp.md @@ -0,0 +1,11 @@ +```csharp +using Qdrant.Client; +using Qdrant.Client.Grpc; + +var client = new QdrantClient("localhost", 6334); + +await client.CreateCollectionAsync( + collectionName: "{collection_name}", + strictModeConfig: new StrictModeConfig { Enabled = true, SearchAllowExact = false } +); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/go.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/go.md new file mode 100644 index 000000000..e1d444368 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/go.md @@ -0,0 +1,20 @@ +```go +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +client, err := qdrant.NewClient(&qdrant.Config{ + Host: "localhost", + Port: 6334, +}) + +client.CreateCollection(context.Background(), &qdrant.CreateCollection{ + CollectionName: "{collection_name}", + StrictModeConfig: &qdrant.StrictModeConfig{ + Enabled: qdrant.PtrOf(true), + SearchAllowExact: qdrant.PtrOf(false), + }, +}) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/java.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/java.md new file mode 100644 index 000000000..0adaaee4d --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/java.md @@ -0,0 +1,18 @@ +```java +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.CreateCollection; +import io.qdrant.client.grpc.Collections.StrictModeConfig; + +QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + +client + .createCollectionAsync( + CreateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setStrictModeConfig( + StrictModeConfig.newBuilder().setEnabled(true).setSearchAllowExact(false).build()) + .build()) + .get(); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/python.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/python.md new file mode 100644 index 000000000..0a5611e01 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/python.md @@ -0,0 +1,10 @@ +```python +from qdrant_client import QdrantClient, models + +client = QdrantClient(url="http://localhost:6333") + +client.create_collection( + collection_name="{collection_name}", + strict_mode_config=models.StrictModeConfig(enabled=True, search_allow_exact=False), +) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/rust.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/rust.md new file mode 100644 index 000000000..3f8c10a56 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/rust.md @@ -0,0 +1,13 @@ +```rust +use qdrant_client::Qdrant; +use qdrant_client::qdrant::{CreateCollectionBuilder, StrictModeConfigBuilder}; + +let client = Qdrant::from_url("http://localhost:6334").build()?; + +client + .create_collection( + CreateCollectionBuilder::new("{collection_name}") + .strict_mode_config(StrictModeConfigBuilder::default().enabled(true).search_allow_exact(false)), + ) + .await?; +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/typescript.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/typescript.md new file mode 100644 index 000000000..0681de84b --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/generated/typescript.md @@ -0,0 +1,12 @@ +```typescript +import { QdrantClient } from "@qdrant/js-client-rest"; + +const client = new QdrantClient({ host: "localhost", port: 6333 }); + +client.createCollection("{collection_name}", { + strict_mode_config: { + enabled: true, + search_allow_exact: false, + }, +}); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/go.go b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/go.go new file mode 100644 index 000000000..5ce36e44e --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/go.go @@ -0,0 +1,24 @@ +package snippet + +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +func Main() { + client, err := qdrant.NewClient(&qdrant.Config{ + Host: "localhost", + Port: 6334, + }) + + if err != nil { panic(err) } // @hide + + client.CreateCollection(context.Background(), &qdrant.CreateCollection{ + CollectionName: "{collection_name}", + StrictModeConfig: &qdrant.StrictModeConfig{ + Enabled: qdrant.PtrOf(true), + SearchAllowExact: qdrant.PtrOf(false), + }, + }) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/http.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/http.md new file mode 100644 index 000000000..a0ec883c4 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/http.md @@ -0,0 +1,9 @@ +```http +PUT /collections/{collection_name} +{ + "strict_mode_config": { + "enabled": true, + "search_allow_exact": false + } +} +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/java.java b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/java.java new file mode 100644 index 000000000..963b88381 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/java.java @@ -0,0 +1,22 @@ +package com.example.snippets_amalgamation; + +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.CreateCollection; +import io.qdrant.client.grpc.Collections.StrictModeConfig; + +public class Snippet { + public static void run() throws Exception { + QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + + client + .createCollectionAsync( + CreateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setStrictModeConfig( + StrictModeConfig.newBuilder().setEnabled(true).setSearchAllowExact(false).build()) + .build()) + .get(); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/python.py b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/python.py new file mode 100644 index 000000000..d9db7759a --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/python.py @@ -0,0 +1,8 @@ +from qdrant_client import QdrantClient, models + +client = QdrantClient(url="http://localhost:6333") + +client.create_collection( + collection_name="{collection_name}", + strict_mode_config=models.StrictModeConfig(enabled=True, search_allow_exact=False), +) diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/rust.rs b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/rust.rs new file mode 100644 index 000000000..d25a49cba --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/rust.rs @@ -0,0 +1,15 @@ +use qdrant_client::Qdrant; +use qdrant_client::qdrant::{CreateCollectionBuilder, StrictModeConfigBuilder}; + +pub async fn main() -> anyhow::Result<()> { + let client = Qdrant::from_url("http://localhost:6334").build()?; + + client + .create_collection( + CreateCollectionBuilder::new("{collection_name}") + .strict_mode_config(StrictModeConfigBuilder::default().enabled(true).search_allow_exact(false)), + ) + .await?; + + Ok(()) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/typescript.ts b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/typescript.ts new file mode 100644 index 000000000..d3681560c --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-allow-exact/typescript.ts @@ -0,0 +1,10 @@ +import { QdrantClient } from "@qdrant/js-client-rest"; + +const client = new QdrantClient({ host: "localhost", port: 6333 }); + +client.createCollection("{collection_name}", { + strict_mode_config: { + enabled: true, + search_allow_exact: false, + }, +}); diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/_description.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/_description.md new file mode 100644 index 000000000..70bfab502 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/_description.md @@ -0,0 +1 @@ +This code snippet sets `search_max_batchsize` on the strict mode configuration to cap the maximum number of searches in a single batch request. \ No newline at end of file diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/bash.sh b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/bash.sh new file mode 100644 index 000000000..9dfb3d642 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/bash.sh @@ -0,0 +1,8 @@ +curl -X PUT http://localhost:6333/collections/{collection_name} \ + -H 'Content-Type: application/json' \ + --data-raw '{ + "strict_mode_config": { + "enabled": true, + "search_max_batchsize": 1000 + } + }' diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/csharp.cs b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/csharp.cs new file mode 100644 index 000000000..84b32e7ec --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/csharp.cs @@ -0,0 +1,15 @@ +using Qdrant.Client; +using Qdrant.Client.Grpc; + +public class Snippet +{ + public static async Task Run() + { + var client = new QdrantClient("localhost", 6334); + + await client.CreateCollectionAsync( + collectionName: "{collection_name}", + strictModeConfig: new StrictModeConfig { Enabled = true, SearchMaxBatchsize = 1000 } + ); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/bash.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/bash.md new file mode 100644 index 000000000..526744536 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/bash.md @@ -0,0 +1,10 @@ +```bash +curl -X PUT http://localhost:6333/collections/{collection_name} \ + -H 'Content-Type: application/json' \ + --data-raw '{ + "strict_mode_config": { + "enabled": true, + "search_max_batchsize": 1000 + } + }' +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/csharp.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/csharp.md new file mode 100644 index 000000000..ba3293319 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/csharp.md @@ -0,0 +1,11 @@ +```csharp +using Qdrant.Client; +using Qdrant.Client.Grpc; + +var client = new QdrantClient("localhost", 6334); + +await client.CreateCollectionAsync( + collectionName: "{collection_name}", + strictModeConfig: new StrictModeConfig { Enabled = true, SearchMaxBatchsize = 1000 } +); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/go.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/go.md new file mode 100644 index 000000000..7e16c4dd8 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/go.md @@ -0,0 +1,20 @@ +```go +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +client, err := qdrant.NewClient(&qdrant.Config{ + Host: "localhost", + Port: 6334, +}) + +client.CreateCollection(context.Background(), &qdrant.CreateCollection{ + CollectionName: "{collection_name}", + StrictModeConfig: &qdrant.StrictModeConfig{ + Enabled: qdrant.PtrOf(true), + SearchMaxBatchsize: qdrant.PtrOf(uint64(1000)), + }, +}) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/java.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/java.md new file mode 100644 index 000000000..b4717726a --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/java.md @@ -0,0 +1,18 @@ +```java +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.CreateCollection; +import io.qdrant.client.grpc.Collections.StrictModeConfig; + +QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + +client + .createCollectionAsync( + CreateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setStrictModeConfig( + StrictModeConfig.newBuilder().setEnabled(true).setSearchMaxBatchsize(1000).build()) + .build()) + .get(); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/python.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/python.md new file mode 100644 index 000000000..48147a1f5 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/python.md @@ -0,0 +1,10 @@ +```python +from qdrant_client import QdrantClient, models + +client = QdrantClient(url="http://localhost:6333") + +client.create_collection( + collection_name="{collection_name}", + strict_mode_config=models.StrictModeConfig(enabled=True, search_max_batchsize=1000), +) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/rust.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/rust.md new file mode 100644 index 000000000..321843978 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/rust.md @@ -0,0 +1,13 @@ +```rust +use qdrant_client::Qdrant; +use qdrant_client::qdrant::{CreateCollectionBuilder, StrictModeConfigBuilder}; + +let client = Qdrant::from_url("http://localhost:6334").build()?; + +client + .create_collection( + CreateCollectionBuilder::new("{collection_name}") + .strict_mode_config(StrictModeConfigBuilder::default().enabled(true).search_max_batchsize(1000u64)), + ) + .await?; +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/typescript.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/typescript.md new file mode 100644 index 000000000..7e9d3677b --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/generated/typescript.md @@ -0,0 +1,12 @@ +```typescript +import { QdrantClient } from "@qdrant/js-client-rest"; + +const client = new QdrantClient({ host: "localhost", port: 6333 }); + +client.createCollection("{collection_name}", { + strict_mode_config: { + enabled: true, + search_max_batchsize: 1000, + }, +}); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/go.go b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/go.go new file mode 100644 index 000000000..fea3ea24d --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/go.go @@ -0,0 +1,24 @@ +package snippet + +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +func Main() { + client, err := qdrant.NewClient(&qdrant.Config{ + Host: "localhost", + Port: 6334, + }) + + if err != nil { panic(err) } // @hide + + client.CreateCollection(context.Background(), &qdrant.CreateCollection{ + CollectionName: "{collection_name}", + StrictModeConfig: &qdrant.StrictModeConfig{ + Enabled: qdrant.PtrOf(true), + SearchMaxBatchsize: qdrant.PtrOf(uint64(1000)), + }, + }) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/http.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/http.md new file mode 100644 index 000000000..52b5024d5 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/http.md @@ -0,0 +1,9 @@ +```http +PUT /collections/{collection_name} +{ + "strict_mode_config": { + "enabled": true, + "search_max_batchsize": 1000 + } +} +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/java.java b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/java.java new file mode 100644 index 000000000..af4e9b22b --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/java.java @@ -0,0 +1,22 @@ +package com.example.snippets_amalgamation; + +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.CreateCollection; +import io.qdrant.client.grpc.Collections.StrictModeConfig; + +public class Snippet { + public static void run() throws Exception { + QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + + client + .createCollectionAsync( + CreateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setStrictModeConfig( + StrictModeConfig.newBuilder().setEnabled(true).setSearchMaxBatchsize(1000).build()) + .build()) + .get(); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/python.py b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/python.py new file mode 100644 index 000000000..b1486fe60 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/python.py @@ -0,0 +1,8 @@ +from qdrant_client import QdrantClient, models + +client = QdrantClient(url="http://localhost:6333") + +client.create_collection( + collection_name="{collection_name}", + strict_mode_config=models.StrictModeConfig(enabled=True, search_max_batchsize=1000), +) diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/rust.rs b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/rust.rs new file mode 100644 index 000000000..463cec854 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/rust.rs @@ -0,0 +1,15 @@ +use qdrant_client::Qdrant; +use qdrant_client::qdrant::{CreateCollectionBuilder, StrictModeConfigBuilder}; + +pub async fn main() -> anyhow::Result<()> { + let client = Qdrant::from_url("http://localhost:6334").build()?; + + client + .create_collection( + CreateCollectionBuilder::new("{collection_name}") + .strict_mode_config(StrictModeConfigBuilder::default().enabled(true).search_max_batchsize(1000u64)), + ) + .await?; + + Ok(()) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/typescript.ts b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/typescript.ts new file mode 100644 index 000000000..09830524e --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-batchsize/typescript.ts @@ -0,0 +1,10 @@ +import { QdrantClient } from "@qdrant/js-client-rest"; + +const client = new QdrantClient({ host: "localhost", port: 6333 }); + +client.createCollection("{collection_name}", { + strict_mode_config: { + enabled: true, + search_max_batchsize: 1000, + }, +}); diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/_description.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/_description.md new file mode 100644 index 000000000..0974cb3d5 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/_description.md @@ -0,0 +1 @@ +This code snippet sets `search_max_hnsw_ef` on the strict mode configuration to cap the maximum HNSW ef value allowed in search parameters. \ No newline at end of file diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/bash.sh b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/bash.sh new file mode 100644 index 000000000..31f57e97c --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/bash.sh @@ -0,0 +1,8 @@ +curl -X PUT http://localhost:6333/collections/{collection_name} \ + -H 'Content-Type: application/json' \ + --data-raw '{ + "strict_mode_config": { + "enabled": true, + "search_max_hnsw_ef": 128 + } + }' diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/csharp.cs b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/csharp.cs new file mode 100644 index 000000000..9c1b7a440 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/csharp.cs @@ -0,0 +1,15 @@ +using Qdrant.Client; +using Qdrant.Client.Grpc; + +public class Snippet +{ + public static async Task Run() + { + var client = new QdrantClient("localhost", 6334); + + await client.CreateCollectionAsync( + collectionName: "{collection_name}", + strictModeConfig: new StrictModeConfig { Enabled = true, SearchMaxHnswEf = 128 } + ); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/bash.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/bash.md new file mode 100644 index 000000000..f56261c06 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/bash.md @@ -0,0 +1,10 @@ +```bash +curl -X PUT http://localhost:6333/collections/{collection_name} \ + -H 'Content-Type: application/json' \ + --data-raw '{ + "strict_mode_config": { + "enabled": true, + "search_max_hnsw_ef": 128 + } + }' +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/csharp.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/csharp.md new file mode 100644 index 000000000..fa93aa67f --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/csharp.md @@ -0,0 +1,11 @@ +```csharp +using Qdrant.Client; +using Qdrant.Client.Grpc; + +var client = new QdrantClient("localhost", 6334); + +await client.CreateCollectionAsync( + collectionName: "{collection_name}", + strictModeConfig: new StrictModeConfig { Enabled = true, SearchMaxHnswEf = 128 } +); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/go.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/go.md new file mode 100644 index 000000000..75f199070 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/go.md @@ -0,0 +1,20 @@ +```go +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +client, err := qdrant.NewClient(&qdrant.Config{ + Host: "localhost", + Port: 6334, +}) + +client.CreateCollection(context.Background(), &qdrant.CreateCollection{ + CollectionName: "{collection_name}", + StrictModeConfig: &qdrant.StrictModeConfig{ + Enabled: qdrant.PtrOf(true), + SearchMaxHnswEf: qdrant.PtrOf(uint32(128)), + }, +}) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/java.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/java.md new file mode 100644 index 000000000..5c70f028f --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/java.md @@ -0,0 +1,18 @@ +```java +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.CreateCollection; +import io.qdrant.client.grpc.Collections.StrictModeConfig; + +QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + +client + .createCollectionAsync( + CreateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setStrictModeConfig( + StrictModeConfig.newBuilder().setEnabled(true).setSearchMaxHnswEf(128).build()) + .build()) + .get(); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/python.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/python.md new file mode 100644 index 000000000..143b876a7 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/python.md @@ -0,0 +1,10 @@ +```python +from qdrant_client import QdrantClient, models + +client = QdrantClient(url="http://localhost:6333") + +client.create_collection( + collection_name="{collection_name}", + strict_mode_config=models.StrictModeConfig(enabled=True, search_max_hnsw_ef=128), +) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/rust.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/rust.md new file mode 100644 index 000000000..7184104a8 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/rust.md @@ -0,0 +1,13 @@ +```rust +use qdrant_client::Qdrant; +use qdrant_client::qdrant::{CreateCollectionBuilder, StrictModeConfigBuilder}; + +let client = Qdrant::from_url("http://localhost:6334").build()?; + +client + .create_collection( + CreateCollectionBuilder::new("{collection_name}") + .strict_mode_config(StrictModeConfigBuilder::default().enabled(true).search_max_hnsw_ef(128u32)), + ) + .await?; +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/typescript.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/typescript.md new file mode 100644 index 000000000..bf664fc17 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/generated/typescript.md @@ -0,0 +1,12 @@ +```typescript +import { QdrantClient } from "@qdrant/js-client-rest"; + +const client = new QdrantClient({ host: "localhost", port: 6333 }); + +client.createCollection("{collection_name}", { + strict_mode_config: { + enabled: true, + search_max_hnsw_ef: 128, + }, +}); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/go.go b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/go.go new file mode 100644 index 000000000..f737ff33d --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/go.go @@ -0,0 +1,24 @@ +package snippet + +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +func Main() { + client, err := qdrant.NewClient(&qdrant.Config{ + Host: "localhost", + Port: 6334, + }) + + if err != nil { panic(err) } // @hide + + client.CreateCollection(context.Background(), &qdrant.CreateCollection{ + CollectionName: "{collection_name}", + StrictModeConfig: &qdrant.StrictModeConfig{ + Enabled: qdrant.PtrOf(true), + SearchMaxHnswEf: qdrant.PtrOf(uint32(128)), + }, + }) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/http.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/http.md new file mode 100644 index 000000000..c4a9d79d4 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/http.md @@ -0,0 +1,9 @@ +```http +PUT /collections/{collection_name} +{ + "strict_mode_config": { + "enabled": true, + "search_max_hnsw_ef": 128 + } +} +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/java.java b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/java.java new file mode 100644 index 000000000..18da088c0 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/java.java @@ -0,0 +1,22 @@ +package com.example.snippets_amalgamation; + +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.CreateCollection; +import io.qdrant.client.grpc.Collections.StrictModeConfig; + +public class Snippet { + public static void run() throws Exception { + QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + + client + .createCollectionAsync( + CreateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setStrictModeConfig( + StrictModeConfig.newBuilder().setEnabled(true).setSearchMaxHnswEf(128).build()) + .build()) + .get(); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/python.py b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/python.py new file mode 100644 index 000000000..2efc2eccf --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/python.py @@ -0,0 +1,8 @@ +from qdrant_client import QdrantClient, models + +client = QdrantClient(url="http://localhost:6333") + +client.create_collection( + collection_name="{collection_name}", + strict_mode_config=models.StrictModeConfig(enabled=True, search_max_hnsw_ef=128), +) diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/rust.rs b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/rust.rs new file mode 100644 index 000000000..5cfa8cf3b --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/rust.rs @@ -0,0 +1,15 @@ +use qdrant_client::Qdrant; +use qdrant_client::qdrant::{CreateCollectionBuilder, StrictModeConfigBuilder}; + +pub async fn main() -> anyhow::Result<()> { + let client = Qdrant::from_url("http://localhost:6334").build()?; + + client + .create_collection( + CreateCollectionBuilder::new("{collection_name}") + .strict_mode_config(StrictModeConfigBuilder::default().enabled(true).search_max_hnsw_ef(128u32)), + ) + .await?; + + Ok(()) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/typescript.ts b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/typescript.ts new file mode 100644 index 000000000..e99dae976 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-hnsw-ef/typescript.ts @@ -0,0 +1,10 @@ +import { QdrantClient } from "@qdrant/js-client-rest"; + +const client = new QdrantClient({ host: "localhost", port: 6333 }); + +client.createCollection("{collection_name}", { + strict_mode_config: { + enabled: true, + search_max_hnsw_ef: 128, + }, +}); diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/_description.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/_description.md new file mode 100644 index 000000000..b743a34a3 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/_description.md @@ -0,0 +1 @@ +This code snippet sets `search_max_oversampling` on the strict mode configuration to cap the maximum oversampling factor allowed in search parameters. \ No newline at end of file diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/bash.sh b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/bash.sh new file mode 100644 index 000000000..0119feb9a --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/bash.sh @@ -0,0 +1,8 @@ +curl -X PUT http://localhost:6333/collections/{collection_name} \ + -H 'Content-Type: application/json' \ + --data-raw '{ + "strict_mode_config": { + "enabled": true, + "search_max_oversampling": 2.0 + } + }' diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/csharp.cs b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/csharp.cs new file mode 100644 index 000000000..b7d3dba18 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/csharp.cs @@ -0,0 +1,15 @@ +using Qdrant.Client; +using Qdrant.Client.Grpc; + +public class Snippet +{ + public static async Task Run() + { + var client = new QdrantClient("localhost", 6334); + + await client.CreateCollectionAsync( + collectionName: "{collection_name}", + strictModeConfig: new StrictModeConfig { Enabled = true, SearchMaxOversampling = 2.0f } + ); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/bash.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/bash.md new file mode 100644 index 000000000..09a6ea913 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/bash.md @@ -0,0 +1,10 @@ +```bash +curl -X PUT http://localhost:6333/collections/{collection_name} \ + -H 'Content-Type: application/json' \ + --data-raw '{ + "strict_mode_config": { + "enabled": true, + "search_max_oversampling": 2.0 + } + }' +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/csharp.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/csharp.md new file mode 100644 index 000000000..8dd136724 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/csharp.md @@ -0,0 +1,11 @@ +```csharp +using Qdrant.Client; +using Qdrant.Client.Grpc; + +var client = new QdrantClient("localhost", 6334); + +await client.CreateCollectionAsync( + collectionName: "{collection_name}", + strictModeConfig: new StrictModeConfig { Enabled = true, SearchMaxOversampling = 2.0f } +); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/go.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/go.md new file mode 100644 index 000000000..f62ad862b --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/go.md @@ -0,0 +1,20 @@ +```go +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +client, err := qdrant.NewClient(&qdrant.Config{ + Host: "localhost", + Port: 6334, +}) + +client.CreateCollection(context.Background(), &qdrant.CreateCollection{ + CollectionName: "{collection_name}", + StrictModeConfig: &qdrant.StrictModeConfig{ + Enabled: qdrant.PtrOf(true), + SearchMaxOversampling: qdrant.PtrOf(float32(2.0)), + }, +}) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/java.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/java.md new file mode 100644 index 000000000..39f200e2b --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/java.md @@ -0,0 +1,18 @@ +```java +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.CreateCollection; +import io.qdrant.client.grpc.Collections.StrictModeConfig; + +QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + +client + .createCollectionAsync( + CreateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setStrictModeConfig( + StrictModeConfig.newBuilder().setEnabled(true).setSearchMaxOversampling(2.0f).build()) + .build()) + .get(); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/python.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/python.md new file mode 100644 index 000000000..88503d8ab --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/python.md @@ -0,0 +1,10 @@ +```python +from qdrant_client import QdrantClient, models + +client = QdrantClient(url="http://localhost:6333") + +client.create_collection( + collection_name="{collection_name}", + strict_mode_config=models.StrictModeConfig(enabled=True, search_max_oversampling=2.0), +) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/rust.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/rust.md new file mode 100644 index 000000000..a0c21eeb2 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/rust.md @@ -0,0 +1,13 @@ +```rust +use qdrant_client::Qdrant; +use qdrant_client::qdrant::{CreateCollectionBuilder, StrictModeConfigBuilder}; + +let client = Qdrant::from_url("http://localhost:6334").build()?; + +client + .create_collection( + CreateCollectionBuilder::new("{collection_name}") + .strict_mode_config(StrictModeConfigBuilder::default().enabled(true).search_max_oversampling(2.0f32)), + ) + .await?; +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/typescript.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/typescript.md new file mode 100644 index 000000000..be9df7862 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/generated/typescript.md @@ -0,0 +1,12 @@ +```typescript +import { QdrantClient } from "@qdrant/js-client-rest"; + +const client = new QdrantClient({ host: "localhost", port: 6333 }); + +client.createCollection("{collection_name}", { + strict_mode_config: { + enabled: true, + search_max_oversampling: 2.0, + }, +}); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/go.go b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/go.go new file mode 100644 index 000000000..84f846130 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/go.go @@ -0,0 +1,24 @@ +package snippet + +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +func Main() { + client, err := qdrant.NewClient(&qdrant.Config{ + Host: "localhost", + Port: 6334, + }) + + if err != nil { panic(err) } // @hide + + client.CreateCollection(context.Background(), &qdrant.CreateCollection{ + CollectionName: "{collection_name}", + StrictModeConfig: &qdrant.StrictModeConfig{ + Enabled: qdrant.PtrOf(true), + SearchMaxOversampling: qdrant.PtrOf(float32(2.0)), + }, + }) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/http.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/http.md new file mode 100644 index 000000000..a7e4c62a5 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/http.md @@ -0,0 +1,9 @@ +```http +PUT /collections/{collection_name} +{ + "strict_mode_config": { + "enabled": true, + "search_max_oversampling": 2.0 + } +} +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/java.java b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/java.java new file mode 100644 index 000000000..938d9d3d7 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/java.java @@ -0,0 +1,22 @@ +package com.example.snippets_amalgamation; + +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.CreateCollection; +import io.qdrant.client.grpc.Collections.StrictModeConfig; + +public class Snippet { + public static void run() throws Exception { + QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + + client + .createCollectionAsync( + CreateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setStrictModeConfig( + StrictModeConfig.newBuilder().setEnabled(true).setSearchMaxOversampling(2.0f).build()) + .build()) + .get(); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/python.py b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/python.py new file mode 100644 index 000000000..30069dd38 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/python.py @@ -0,0 +1,8 @@ +from qdrant_client import QdrantClient, models + +client = QdrantClient(url="http://localhost:6333") + +client.create_collection( + collection_name="{collection_name}", + strict_mode_config=models.StrictModeConfig(enabled=True, search_max_oversampling=2.0), +) diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/rust.rs b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/rust.rs new file mode 100644 index 000000000..bbe3a3996 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/rust.rs @@ -0,0 +1,15 @@ +use qdrant_client::Qdrant; +use qdrant_client::qdrant::{CreateCollectionBuilder, StrictModeConfigBuilder}; + +pub async fn main() -> anyhow::Result<()> { + let client = Qdrant::from_url("http://localhost:6334").build()?; + + client + .create_collection( + CreateCollectionBuilder::new("{collection_name}") + .strict_mode_config(StrictModeConfigBuilder::default().enabled(true).search_max_oversampling(2.0f32)), + ) + .await?; + + Ok(()) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/typescript.ts b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/typescript.ts new file mode 100644 index 000000000..2ce60d536 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/search-max-oversampling/typescript.ts @@ -0,0 +1,10 @@ +import { QdrantClient } from "@qdrant/js-client-rest"; + +const client = new QdrantClient({ host: "localhost", port: 6333 }); + +client.createCollection("{collection_name}", { + strict_mode_config: { + enabled: true, + search_max_oversampling: 2.0, + }, +}); diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/_description.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/_description.md new file mode 100644 index 000000000..daca3b601 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/_description.md @@ -0,0 +1 @@ +This code snippet sets `sparse_config` on the strict mode configuration to cap the maximum length of sparse vectors for a named vector. \ No newline at end of file diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/bash.sh b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/bash.sh new file mode 100644 index 000000000..99a3244ff --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/bash.sh @@ -0,0 +1,12 @@ +curl -X PUT http://localhost:6333/collections/{collection_name} \ + -H 'Content-Type: application/json' \ + --data-raw '{ + "strict_mode_config": { + "enabled": true, + "sparse_config": { + "{vector_name}": { + "max_length": 1000 + } + } + } + }' diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/csharp.cs b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/csharp.cs new file mode 100644 index 000000000..c5addfeb1 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/csharp.cs @@ -0,0 +1,22 @@ +using Qdrant.Client; +using Qdrant.Client.Grpc; + +public class Snippet +{ + public static async Task Run() + { + var client = new QdrantClient("localhost", 6334); + + await client.CreateCollectionAsync( + collectionName: "{collection_name}", + strictModeConfig: new StrictModeConfig + { + Enabled = true, + SparseConfig = new StrictModeSparseConfig + { + SparseConfig = { ["{vector_name}"] = new StrictModeSparse { MaxLength = 1000 } } + } + } + ); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/bash.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/bash.md new file mode 100644 index 000000000..fa292790c --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/bash.md @@ -0,0 +1,14 @@ +```bash +curl -X PUT http://localhost:6333/collections/{collection_name} \ + -H 'Content-Type: application/json' \ + --data-raw '{ + "strict_mode_config": { + "enabled": true, + "sparse_config": { + "{vector_name}": { + "max_length": 1000 + } + } + } + }' +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/csharp.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/csharp.md new file mode 100644 index 000000000..e3f7b0208 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/csharp.md @@ -0,0 +1,18 @@ +```csharp +using Qdrant.Client; +using Qdrant.Client.Grpc; + +var client = new QdrantClient("localhost", 6334); + +await client.CreateCollectionAsync( + collectionName: "{collection_name}", + strictModeConfig: new StrictModeConfig + { + Enabled = true, + SparseConfig = new StrictModeSparseConfig + { + SparseConfig = { ["{vector_name}"] = new StrictModeSparse { MaxLength = 1000 } } + } + } +); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/go.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/go.md new file mode 100644 index 000000000..9f69e4412 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/go.md @@ -0,0 +1,24 @@ +```go +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +client, err := qdrant.NewClient(&qdrant.Config{ + Host: "localhost", + Port: 6334, +}) + +client.CreateCollection(context.Background(), &qdrant.CreateCollection{ + CollectionName: "{collection_name}", + StrictModeConfig: &qdrant.StrictModeConfig{ + Enabled: qdrant.PtrOf(true), + SparseConfig: &qdrant.StrictModeSparseConfig{ + SparseConfig: map[string]*qdrant.StrictModeSparse{ + "{vector_name}": {MaxLength: qdrant.PtrOf(uint64(1000))}, + }, + }, + }, +}) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/java.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/java.md new file mode 100644 index 000000000..8303aa562 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/java.md @@ -0,0 +1,26 @@ +```java +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.CreateCollection; +import io.qdrant.client.grpc.Collections.StrictModeConfig; +import io.qdrant.client.grpc.Collections.StrictModeSparse; +import io.qdrant.client.grpc.Collections.StrictModeSparseConfig; + +QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + +client + .createCollectionAsync( + CreateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setStrictModeConfig( + StrictModeConfig.newBuilder() + .setEnabled(true) + .setSparseConfig( + StrictModeSparseConfig.newBuilder() + .putSparseConfig("{vector_name}", StrictModeSparse.newBuilder().setMaxLength(1000).build()) + .build()) + .build()) + .build()) + .get(); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/python.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/python.md new file mode 100644 index 000000000..984bf92b0 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/python.md @@ -0,0 +1,13 @@ +```python +from qdrant_client import QdrantClient, models + +client = QdrantClient(url="http://localhost:6333") + +client.create_collection( + collection_name="{collection_name}", + strict_mode_config=models.StrictModeConfig( + enabled=True, + sparse_config={"{vector_name}": models.StrictModeSparse(max_length=1000)}, + ), +) +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/rust.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/rust.md new file mode 100644 index 000000000..4de07f343 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/rust.md @@ -0,0 +1,27 @@ +```rust +use std::collections::HashMap; + +use qdrant_client::Qdrant; +use qdrant_client::qdrant::{ + CreateCollectionBuilder, StrictModeConfigBuilder, StrictModeSparse, StrictModeSparseConfig, +}; + +let client = Qdrant::from_url("http://localhost:6334").build()?; + +client + .create_collection( + CreateCollectionBuilder::new("{collection_name}").strict_mode_config( + StrictModeConfigBuilder::default() + .enabled(true) + .sparse_config(StrictModeSparseConfig { + sparse_config: HashMap::from([( + "{vector_name}".to_string(), + StrictModeSparse { + max_length: Some(1000), + }, + )]), + }), + ), + ) + .await?; +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/typescript.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/typescript.md new file mode 100644 index 000000000..4f8f98dd4 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/generated/typescript.md @@ -0,0 +1,16 @@ +```typescript +import { QdrantClient } from "@qdrant/js-client-rest"; + +const client = new QdrantClient({ host: "localhost", port: 6333 }); + +client.createCollection("{collection_name}", { + strict_mode_config: { + enabled: true, + sparse_config: { + "{vector_name}": { + max_length: 1000, + }, + }, + }, +}); +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/go.go b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/go.go new file mode 100644 index 000000000..861a8b0d2 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/go.go @@ -0,0 +1,28 @@ +package snippet + +import ( + "context" + + "github.com/qdrant/go-client/qdrant" +) + +func Main() { + client, err := qdrant.NewClient(&qdrant.Config{ + Host: "localhost", + Port: 6334, + }) + + if err != nil { panic(err) } // @hide + + client.CreateCollection(context.Background(), &qdrant.CreateCollection{ + CollectionName: "{collection_name}", + StrictModeConfig: &qdrant.StrictModeConfig{ + Enabled: qdrant.PtrOf(true), + SparseConfig: &qdrant.StrictModeSparseConfig{ + SparseConfig: map[string]*qdrant.StrictModeSparse{ + "{vector_name}": {MaxLength: qdrant.PtrOf(uint64(1000))}, + }, + }, + }, + }) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/http.md b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/http.md new file mode 100644 index 000000000..5443d4e56 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/http.md @@ -0,0 +1,13 @@ +```http +PUT /collections/{collection_name} +{ + "strict_mode_config": { + "enabled": true, + "sparse_config": { + "{vector_name}": { + "max_length": 1000 + } + } + } +} +``` diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/java.java b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/java.java new file mode 100644 index 000000000..1ed3cd64c --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/java.java @@ -0,0 +1,30 @@ +package com.example.snippets_amalgamation; + +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.CreateCollection; +import io.qdrant.client.grpc.Collections.StrictModeConfig; +import io.qdrant.client.grpc.Collections.StrictModeSparse; +import io.qdrant.client.grpc.Collections.StrictModeSparseConfig; + +public class Snippet { + public static void run() throws Exception { + QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + + client + .createCollectionAsync( + CreateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setStrictModeConfig( + StrictModeConfig.newBuilder() + .setEnabled(true) + .setSparseConfig( + StrictModeSparseConfig.newBuilder() + .putSparseConfig("{vector_name}", StrictModeSparse.newBuilder().setMaxLength(1000).build()) + .build()) + .build()) + .build()) + .get(); + } +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/python.py b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/python.py new file mode 100644 index 000000000..757ed4642 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/python.py @@ -0,0 +1,11 @@ +from qdrant_client import QdrantClient, models + +client = QdrantClient(url="http://localhost:6333") + +client.create_collection( + collection_name="{collection_name}", + strict_mode_config=models.StrictModeConfig( + enabled=True, + sparse_config={"{vector_name}": models.StrictModeSparse(max_length=1000)}, + ), +) diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/rust.rs b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/rust.rs new file mode 100644 index 000000000..2eacc97f8 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/rust.rs @@ -0,0 +1,29 @@ +use std::collections::HashMap; + +use qdrant_client::Qdrant; +use qdrant_client::qdrant::{ + CreateCollectionBuilder, StrictModeConfigBuilder, StrictModeSparse, StrictModeSparseConfig, +}; + +pub async fn main() -> anyhow::Result<()> { + let client = Qdrant::from_url("http://localhost:6334").build()?; + + client + .create_collection( + CreateCollectionBuilder::new("{collection_name}").strict_mode_config( + StrictModeConfigBuilder::default() + .enabled(true) + .sparse_config(StrictModeSparseConfig { + sparse_config: HashMap::from([( + "{vector_name}".to_string(), + StrictModeSparse { + max_length: Some(1000), + }, + )]), + }), + ), + ) + .await?; + + Ok(()) +} diff --git a/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/typescript.ts b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/typescript.ts new file mode 100644 index 000000000..f7e9d3bf5 --- /dev/null +++ b/qdrant-landing/content/documentation/headless/snippets/strict-mode/sparse-config/typescript.ts @@ -0,0 +1,14 @@ +import { QdrantClient } from "@qdrant/js-client-rest"; + +const client = new QdrantClient({ host: "localhost", port: 6333 }); + +client.createCollection("{collection_name}", { + strict_mode_config: { + enabled: true, + sparse_config: { + "{vector_name}": { + max_length: 1000, + }, + }, + }, +}); diff --git a/qdrant-landing/content/documentation/hybrid-cloud/hybrid-cloud-cluster-creation.md b/qdrant-landing/content/documentation/hybrid-cloud/hybrid-cloud-cluster-creation.md index c67222a8a..23f4113c4 100644 --- a/qdrant-landing/content/documentation/hybrid-cloud/hybrid-cloud-cluster-creation.md +++ b/qdrant-landing/content/documentation/hybrid-cloud/hybrid-cloud-cluster-creation.md @@ -98,7 +98,7 @@ The service type and necessary annotations can be configured in the "Kubernetes ![Hybrid Cloud API Key configuration](/documentation/cloud/hybrid_cloud_service.png) -Especially if you create a LoadBalancer Service, you may need to provide annotations for the loadbalancer configration. Please refer to the documention of your cloud provider for more details. +Especially if you create a LoadBalancer Service, you may need to provide annotations for the loadbalancer configuration. Please refer to the documentation of your cloud provider for more details. Examples: diff --git a/qdrant-landing/content/documentation/hybrid-cloud/hybrid-cloud-setup.md b/qdrant-landing/content/documentation/hybrid-cloud/hybrid-cloud-setup.md index d6c7c9a85..421196d87 100644 --- a/qdrant-landing/content/documentation/hybrid-cloud/hybrid-cloud-setup.md +++ b/qdrant-landing/content/documentation/hybrid-cloud/hybrid-cloud-setup.md @@ -67,7 +67,7 @@ By default, Qdrant Cloud will provision two volumes per Qdrant Pod: One for the - Helm chart repository URL for the Qdrant services. The default is . - An optional secret with credentials to access your own container registry. - Log level for the operator and agent. -- Node selectors and tolerations for the operater, agent, cluster-manager and monitoring stack. +- Node selectors and tolerations for the operator, agent, cluster-manager and monitoring stack. - Control Plane Labels that will be added to all Kubernetes resources of the Hybrid Cloud control-plane components. ![Create Hybrid Cloud Environment - Advanced Configuration](/documentation/cloud/hybrid_cloud_advanced_configuration.png) diff --git a/qdrant-landing/content/documentation/hybrid-cloud/operator-configuration.md b/qdrant-landing/content/documentation/hybrid-cloud/operator-configuration.md index 5697faed6..d4398c965 100644 --- a/qdrant-landing/content/documentation/hybrid-cloud/operator-configuration.md +++ b/qdrant-landing/content/documentation/hybrid-cloud/operator-configuration.md @@ -139,7 +139,7 @@ settings: # The endpoint address the cluster manager could be reached # If set, this should be a full URL like: http://cluster-manager.qdrant-cloud-ns.svc.cluster.local:7333 endpointAddress: http://qdrant-cluster-manager:80 - # InvocationInterval is the interval between calls (started after the previous call is retured) + # InvocationInterval is the interval between calls (started after the previous call is returned) # Default is 10 seconds invocationInterval: 10s # Timeout is the duration a single call to the cluster manager is allowed to take. diff --git a/qdrant-landing/content/documentation/hybrid-cloud/platform-deployment-options.md b/qdrant-landing/content/documentation/hybrid-cloud/platform-deployment-options.md index b19f92bbe..ae477cff5 100644 --- a/qdrant-landing/content/documentation/hybrid-cloud/platform-deployment-options.md +++ b/qdrant-landing/content/documentation/hybrid-cloud/platform-deployment-options.md @@ -35,7 +35,7 @@ At the time of writing, Linode [does not support CSI Volume Snapshots](https://g First, consult AWS' managed Kubernetes instructions below. Then, **to set up Qdrant Hybrid Cloud on AWS**, follow our [step-by-step documentation](/documentation/hybrid-cloud/hybrid-cloud-setup/). -For a good balance between peformance and cost, we recommend: +For a good balance between performance and cost, we recommend: * Depending on your cluster resource configuration either general purpose (m6*, m7*, or m8*), memory optimized (r6*, r7*, or r8*) or cpu optimized (c6*, c7*, or c8*) instance types. Qdrant Hybrid Cloud also supports AWS Graviton ARM64 instances. * At least gp3 EBS volumes for storage @@ -138,7 +138,7 @@ First, consult Gcore's managed Kubernetes instructions below. Then, **to set up First, consult GCP's managed Kubernetes instructions below. Then, **to set up Qdrant Hybrid Cloud on GCP**, follow our [step-by-step documentation](/documentation/hybrid-cloud/hybrid-cloud-setup/). -For a good balance between peformance and cost, we recommend: +For a good balance between performance and cost, we recommend: * Depending on your cluster resource configuration either general purpose (standard), memory optimized (highmem) or cpu optimized (highcpu) instance types of at least 2nd generation. Qdrant Hybrid Cloud also supports ARM64 instances. * At least pd-balanced disks for storage @@ -169,7 +169,7 @@ With [Azure Kubernetes Service (AKS)](https://azure.microsoft.com/en-in/products First, consult Azure's managed Kubernetes instructions below. Then, **to set up Qdrant Hybrid Cloud on Azure**, follow our [step-by-step documentation](/documentation/hybrid-cloud/hybrid-cloud-setup/). -For a good balance between peformance and cost, we recommend: +For a good balance between performance and cost, we recommend: * Depending on your cluster resource configuration either general purpose (D-family), memory optimized (E-family) or cpu optimized (F-family) instance types. Qdrant Hybrid Cloud also supports Azure Cobalt ARM64 instances. * At least Premium SSD v2 disks for storage diff --git a/qdrant-landing/content/documentation/improve-search/_index.md b/qdrant-landing/content/documentation/improve-search/_index.md new file mode 100644 index 000000000..76bd911dd --- /dev/null +++ b/qdrant-landing/content/documentation/improve-search/_index.md @@ -0,0 +1,14 @@ +--- +title: Improve Search +weight: 1450 +partition: ecosystem +--- + +# Improve Search + +*Embedding choice, chunking strategies, and retrieval evaluation using Python ecosystem tools.* + +| Tutorial | Objective | Stack | Time | Level | +| :--- | :--- | :--- | :--- | :--- | +| [Measuring Retrieval Relevance](/documentation/improve-search/retrieval-relevance/) | Build a labeled golden set and score retrieval relevance with ranx. | Python | 40m | Intermediate | +| [Evaluating Pipeline Output Quality](/documentation/improve-search/pipeline-output-quality/) | Score a RAG pipeline with Ragas and isolate retrieval vs generation failures. | Python | 45m | Intermediate | diff --git a/qdrant-landing/content/documentation/improve-search/pipeline-output-quality.md b/qdrant-landing/content/documentation/improve-search/pipeline-output-quality.md new file mode 100644 index 000000000..3e4f42280 --- /dev/null +++ b/qdrant-landing/content/documentation/improve-search/pipeline-output-quality.md @@ -0,0 +1,206 @@ +--- +title: Evaluating Pipeline Output Quality +weight: 7 +aliases: + - /documentation/tutorials/retrieval-quality-pipeline-output/ +partition: ecosystem +--- + +# Evaluating Pipeline Output Quality + +| Time: 45 min | Level: Intermediate | | | +|--------------|---------------------|--|----| + +This tutorial focuses on **pipeline output quality**: whether the full retrieval pipeline produces the right output once retrieved results reach a consumer, most often an LLM generator in a RAG system. +To measure pipeline output quality, you run your golden set through the full pipeline, capture each `(question, retrieved_context, answer)` triple, and score the triples against judgment metrics like faithfulness, answer relevancy, and context precision. + +Two related tutorials cover the other retrieval-evaluation concerns: [Measuring ANN Recall](/documentation/tutorials-search-engineering/ann-recall/) (does the approximate index match exact kNN?) and [Measuring Retrieval Relevance](/documentation/improve-search/retrieval-relevance/) (do the top-k results match query intent?). + +**Prerequisites.** A Qdrant collection populated with your documents as points (vectors + a `text` payload field for the chunk content), a labeled golden set (see [Measuring Retrieval Relevance](/documentation/improve-search/retrieval-relevance/)), LLM access for generation and judging, and Python with `ragas` installed. + +## Wiring the RAG Pipeline + +Several frameworks score RAG outputs with an LLM judge, including Ragas, DeepEval, and others. We use Ragas here because it's the lightest setup for the three metrics this tutorial covers. If your team has standardized on a different framework or prefers to call the judge LLM directly, the same workflow applies. + +Ragas is a Python library that uses an LLM as a judge to score RAG outputs (rating each answer against criteria like faithfulness and relevancy). It expects samples shaped as `(question, retrieved_context, answer)` triples, so you build a fresh evaluation set from your labeled data. Three steps: prepare the evaluation data, define a grounding prompt, and run the retrieve-generate-record loop. + +**1. Prepare the evaluation data.** Each entry needs a `query_id`, a `query_text` (used for both prompting the generator and embedding for retrieval), and `labels`. For `context_precision` only, also include a `ground_truth` reference answer. + +Synthetic queries don't ship with ground-truth answers. If you're only scoring `faithfulness` and `answer_relevancy`, skip this step since both are reference-free. Otherwise, generate references by running each query through an LLM scoped to its source document. Have the model return `NO_ANSWER` when the source can't answer, and drop those rows before scoring, or `context_precision` ends up judging retrieval against a reference the source doc doesn't support. + +```python +# Example of an evaluation-ready entry. +{ + "query_id": "q1", + "query_text": "how does X work", + "labels": {"doc_42": 1}, + "ground_truth": "...", # optional; required for context_precision only +} +``` + +Different golden-set sources (human annotation, log sampling, or LLM synthesis) produce different raw shapes. Normalize to this structure before running the loop. + +**2. Define the grounding prompt.** The prompt is the seam between retrieval and generation. Keep it in a versioned string so you can swap models without touching the evaluation code: + +```python +PROMPT_TEMPLATE = """You are answering questions using retrieved source material. + +Answer the question below using only the provided context. +If the context does not contain the answer, say so explicitly. +Do not rely on outside knowledge. + +Context: +{retrieved_context} + +Question: +{query_text} +""" +``` + +The prompt above is a starting point; tune it for your domain: answer style, refusal behavior, whether outside knowledge is allowed, and output format. + +**3. Run retrieval and generation.** For each entry, retrieve the top-k chunks, pass them through the generator, and record a `SingleTurnSample` (Ragas's data class for one evaluation record: question, retrieved context, generated answer, and optional reference). + + +```python +import os + +import anthropic +from qdrant_client import QdrantClient +from ragas import SingleTurnSample + +from your_embedding_model import embed # must match the model your Qdrant collection uses + +client = QdrantClient("http://localhost:6333") # or QdrantClient(url="https://.cloud.qdrant.io", api_key="...") for Qdrant Cloud + +# The example uses Anthropic, but any LLM provider works. +anthropic_client = anthropic.Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY")) + + +def generate_answer(query_text: str, contexts: list) -> str: + """Fill the prompt template with context + question, then call the LLM.""" + prompt = PROMPT_TEMPLATE.format( + retrieved_context="\n\n".join(contexts), + query_text=query_text, + ) + response = anthropic_client.messages.create( + model=os.environ.get("ANTHROPIC_MODEL", "claude-sonnet-4-6"), + max_tokens=512, + messages=[{"role": "user", "content": prompt}], + ) + return response.content[0].text + + +def build_eval_set(golden_set: list, collection: str, k: int = 10) -> list: + """For each labeled query: retrieve from Qdrant, generate an answer, package as a Ragas sample.""" + samples = [] + for entry in golden_set: + # Retrieve top-k chunks from Qdrant. + results = client.query_points( + collection_name=collection, + query=embed(entry["query_text"]), + limit=k, + ).points + contexts = [p.payload["text"] for p in results] # adjust the payload key to match your schema + + # Generate an answer grounded in those chunks. + answer = generate_answer(entry["query_text"], contexts) + + # Package into a Ragas sample: question, context, answer, optional reference. + samples.append(SingleTurnSample( + user_input=entry["query_text"], + retrieved_contexts=contexts, + response=answer, + reference=entry.get("ground_truth", ""), + )) + return samples +``` + +If an entry's `ground_truth` is empty, Ragas silently skips that sample for metrics that need a reference (like `context_precision`). Populate it only when you'll actually score those metrics. + +## Scoring with Ragas + +Three Ragas metrics cover the common failure modes for pipeline output quality: + +- **`faithfulness`** checks whether the answer only makes claims supported by the retrieved context. It drops when the generator hallucinates or uses its training knowledge instead of the retrieved context. +- **`answer_relevancy`** checks whether the answer addresses the question. It drops when the generator pads, dodges, or drifts off-topic. +- **`context_precision`** checks whether the retrieved chunks are relevant to the ground-truth answer and ranked highly. It drops when retrieval surfaces noise that crowds out the useful chunks. `context_precision` compares against the `reference` field, so it only scores queries that carry a ground-truth answer. + +Pass the eval samples into `evaluate()` with those three metrics: + +```python +from anthropic import Anthropic +from openai import OpenAI +from ragas import EvaluationDataset, evaluate +from ragas.embeddings.base import embedding_factory +from ragas.llms import llm_factory +from ragas.metrics.collections import AnswerRelevancy, ContextPrecision, Faithfulness + +# Judge LLM, Use a different LLM family as the generator to avoid self-evaluation bias +judge_client = OpenAI() # reads OPENAI_API_KEY from the environment +judge_llm = llm_factory("gpt-5.4", client=judge_client) + +# This is the judge's question-similarity check; it does not need to match the retrieval embedder. +judge_embeddings = embedding_factory("openai", model="text-embedding-3-large", client=judge_client) + +metrics = [ + Faithfulness(llm=judge_llm), + AnswerRelevancy(llm=judge_llm, embeddings=judge_embeddings), + ContextPrecision(llm=judge_llm), +] + +dataset = EvaluationDataset(samples=samples) +scores = evaluate(dataset, metrics=metrics) +``` + +`evaluate()` returns an `EvaluationResult` object. Its aggregate scores print like this: + +```python +{"faithfulness": 0.88, "answer_relevancy": 0.81, "context_precision": 0.74} +``` + +Higher is better on all three. Aggregates hide the distribution that tells you what's breaking, so drop into the per-query view to find the worst-scoring samples: + +```python +per_query = scores.to_pandas() # row-per-query scores +worst = per_query.nsmallest(10, "faithfulness") +``` + +### Running in CI + +If you ship retrieval changes regularly, this evaluation earns its place in CI. Running it on every change against a fixed golden set catches generator regressions from prompt edits, model swaps, or chunking changes before they reach production. The usual pattern: set a target threshold per metric and fail the job when any score drops below. + +### Alternatives + +**Without a golden set.** `faithfulness` and `answer_relevancy` are reference-free; swap `context_precision` for `LLMContextPrecisionWithoutReference`. You can then score synthetic queries offline or sampled production traffic live, at the cost of no fixed baseline for regression gating. + +## Isolating Retrieval vs Generation + +If you're also running [retrieval evaluation](/documentation/improve-search/retrieval-relevance/) against the same golden set, pairing the two scores on every run gives a diagnostic 2x2 for attributing score changes. When a metric drops after a change (new embedding model, new prompt, or new chunking strategy), the pair tells you which half of the pipeline to investigate. + +Pair `recall@10` from the retrieval evaluation with `faithfulness` from the pipeline-output evaluation. In the table, High and Low are relative to the target thresholds you set per metric. + +| Recall@10 | Faithfulness | Diagnosis | +|---|---|---| +| High | High | Ready to ship. | +| High | Low | Generator or prompt problem. Retrieval is surfacing the right context; something downstream (prompt, model, or temperature) is misusing it. | +| Low | Low | Fix retrieval first. The generator can't be faithful to context it never saw. | +| Low | High | Rare. Usually means either the golden-set labels are incomplete (retrieval found useful docs the label set doesn't cover) or the generator punted with a non-committal answer that has no claims to fail on. Read a sample of per-query outputs before acting. | + +This split is the reason to keep retrieval and pipeline-output evaluation separate. Collapsing them into one end-to-end score tells you the pipeline moved, but not which half moved, so the next iteration becomes guesswork. + +## Non-RAG Use Cases + +Ragas's metrics assume the consumer is an LLM generator. If retrieval feeds something else (a ranker, a recommendation surface, an agent, a search UI), swap the metrics to match: CTR or dwell time for a UI, graded rubrics for a ranker, task-completion rate for an agent. The method stays the same: freeze the consumer, run the golden set through the full pipeline, score the end-to-end output. Only the metric changes. + +## Pitfalls to Watch For + +**Judge bias.** LLM judges reward verbose, confident, or well-formatted answers even when the underlying claim is weaker. Calibrate by running a sample of outputs through human raters and comparing; if judge and human scores disagree often, adjust the rubric or swap the judge model. + +**Self-judging contamination.** Using the same model to generate and to judge inflates scores because the judge recognizes and rewards its own output style. Pick a different model family for the judge than for the generator, and record both versions in every run so score shifts can't be blamed on a silent upgrade. + +**Cost scaling.** LLM-as-judge cost grows with queries times metrics times judge calls per metric, and Ragas makes multiple judge calls per sample. A 500-query golden set with three metrics runs into the thousands of judge-model calls per run. Sample 50 to 100 queries with a cheap judge (`claude-haiku-4-5` or `gpt-4o-mini`) during iteration; reserve the full sweep with the strong judge for release candidates. + +## Wrapping Up + +You now have a Ragas-based scoring loop for the full RAG pipeline, a 2x2 to attribute regressions to retrieval or generation, and a CI pattern to gate releases on `faithfulness`, `answer_relevancy`, and `context_precision`. diff --git a/qdrant-landing/content/documentation/improve-search/retrieval-relevance.md b/qdrant-landing/content/documentation/improve-search/retrieval-relevance.md new file mode 100644 index 000000000..4f54468ac --- /dev/null +++ b/qdrant-landing/content/documentation/improve-search/retrieval-relevance.md @@ -0,0 +1,179 @@ +--- +title: Measuring Retrieval Relevance +weight: 6 +aliases: + - /documentation/tutorials/retrieval-quality-golden-set/ +partition: ecosystem +--- + +# Measuring Retrieval Relevance + +| Time: 40 min | Level: Intermediate | | | +|--------------|---------------------|--|----| + +This tutorial focuses on **retrieval relevance**: how well retrieved results match real user intent. +To measure retrieval relevance, you need a labeled dataset of queries paired with their expected relevant documents (commonly called a *golden query set* or *ground truth*). This tutorial covers both building that dataset and running it through Qdrant to compute relevance metrics. + +Two related tutorials cover the other retrieval-evaluation concerns: [Measuring ANN Recall](/documentation/tutorials-search-engineering/ann-recall/) (does the approximate index match exact kNN?) and [Evaluating Pipeline Output Quality](/documentation/improve-search/pipeline-output-quality/) (does the end-to-end pipeline produce the right output?). + +**Prerequisites.** A Qdrant collection populated with your documents as points (vectors + optional payload), an embedding model available to encode queries at evaluation time, and Python with `ranx` installed. + +## Generating Queries + +There are three practical approaches to building a golden set. Each one trades quality against cost and scale. + +### 1. Human Annotation + +Domain experts assign relevance scores on a binary (relevant / not relevant) or graded (0/1/2 or 1–5) scale. Human-labeled data produces the highest-fidelity signal and is the primary source for graded labels. Expert time is the bottleneck, which typically limits this approach to a small set of high-value queries. + +### 2. Real User Queries from Logs + +Sample query-document pairs from your production logs, using clicks or explicit feedback (thumbs up/down, ratings) as the relevance signal. Real user queries capture intent and vocabulary that synthetic generation can't match, but you need enough traffic and a signal that maps to relevance. + +Balance the sample so frequent queries don't crowd out rare ones: group by query type, topic, or intent class. Start with a few hundred labeled pairs to detect large metric differences; per-slice analysis or small ranking deltas need substantially more. + +### 3. LLM-Based Synthetic Generation + +An LLM can generate plausible queries for documents sampled from your corpus. This scales cheaply to thousands of pairs, but synthetic queries are typically easier to retrieve than real user queries, which inflates offline scores. For very large corpora, log-based sampling is often more practical. + +The document you feed the LLM (the **source document**) becomes the relevance label for every query it generates: + +```text +You are helping build an evaluation dataset for a search system. + +Generate 3 realistic search queries for the document below. +Each query should be what a real user would type to find it. +Phrase queries naturally, not as paraphrases of the document. + +Return exactly 3 lines, one query per line. No numbering, no bullets, no preamble. Example: +how does X work +best way to configure Y +what is Z used for + +Document: +{document_text} +``` + +**Tune the prompt to your corpus:** + +- **Query style.** Questions for FAQ/RAG, keyword phrases for e-commerce, intent phrases for code search, or technical terms for specialist domains. +- **Count per document.** `3` is a default; tune to document length and golden-set size. +- **Persona.** A generic "user" works broadly; specialist corpora (medical, legal, technical) benefit from targeted personas. +- **Language.** Default English; state multilingual explicitly. + +## Using the Golden Set + +ranx is a Python library for ranking-metric evaluation. It covers the standard ranking metrics (`recall@k`, `MRR`, `NDCG@k`, `Precision@k`, MAP, and others) through one consistent interface, so you don't hand-roll each metric or juggle different libraries as needs grow. + +The evaluation runs in three steps: load the labeled queries into the shape ranx expects, run each through Qdrant, then compute metrics. + +**1. Load and assemble.** For each labeled query, build an entry with `query_id`, `query_text`, and `labels`: + +```python +{ + "query_id": "q1", + "query_text": "how does X work", + "labels": {"doc_42": 1}, # source doc for synthetic queries, relevant docs otherwise +} +``` + +Build the full `golden_set` by normalizing whatever your generation pipeline produced, then looping through it: + +```python +# Normalize whatever your generation pipeline produced into this shape: +# - Synthetic: one item per generated query, labels = {source_doc_id: 1} +# - Logs: one item per query-click pair, labels = {clicked_doc_id: 1} +# - Human: one item per annotated query, labels = {doc_id: score, ...} +labeled_data = [ + {"query_text": "how does X work", "labels": {"doc_42": 1}}, + {"query_text": "what is Y used for", "labels": {"doc_55": 1, "doc_88": 1}}, + # ...one entry per labeled query +] + +golden_set = [] +for i, item in enumerate(labeled_data): + golden_set.append({ + "query_id": f"q{i}", + "query_text": item["query_text"], + "labels": item["labels"], + }) +``` + +**2. Build `Qrels` and `Run`.** ranx compares two inputs, both shaped as `{query_id: {doc_id: score}}`: + +- **`Qrels`** (query relevance judgments). The labeled ground truth. Use `1` for binary labels or the raw `0/1/2` for graded labels. +- **`Run`** (retrieval output). What Qdrant returned for each query, with similarity scores. + +```python +from qdrant_client import QdrantClient +from ranx import Qrels, Run, evaluate + +from your_embedding_model import embed # must match the model your Qdrant collection uses + +client = QdrantClient("http://localhost:6333") # or QdrantClient(url="https://.cloud.qdrant.io", api_key="...") for Qdrant Cloud + +def retrieval_run(golden_set: list, collection: str, k: int = 10) -> Run: + run = {} + for entry in golden_set: + results = client.query_points( + collection_name=collection, + query=embed(entry["query_text"]), + limit=k, + ).points + # p.id type must match the doc_id type in labels (ranx matches by equality). + run[entry["query_id"]] = {p.id: p.score for p in results} + return Run(run) + +qrels = Qrels({entry["query_id"]: entry["labels"] for entry in golden_set}) +run = retrieval_run(golden_set, collection="my_collection", k=10) +``` + +**3. Compute metrics.** `evaluate(qrels, run, [...])` compares the two and returns a dict of metric names to floats. + +```python +metrics = evaluate(qrels, run, ["recall@10", "mrr", "ndcg@10"]) +``` + +`evaluate()` returns: + +```python +{"recall@10": 0.82, "mrr": 0.71, "ndcg@10": 0.76} +``` + +Higher is better on all three. + +### Choosing the Right Metric + +Which metric matters most depends on what your pipeline does with results: + +| Scenario | Recommended Metric | Why | +|---|---|---| +| RAG pipeline (LLM reads top-k chunks) | `Recall@k` | The LLM can recover if a relevant doc is at position 3 vs 1; missing it entirely hurts more | +| Single-answer retrieval (FAQ or Q&A) | `MRR` or `Hits@1` | The first result is what the user acts on; lower ranks matter little | +| Re-ranking or recommendation feeds | `NDCG@k` | Order within the result list matters; a highly relevant doc at rank 5 is worse than at rank 1 | + +[NDCG (Normalized Discounted Cumulative Gain)](https://en.wikipedia.org/wiki/Discounted_cumulative_gain) needs graded labels (for example, 0/1/2 scores per query-document pair). For binary labels, stick with `recall@k` and [`MRR` (Mean Reciprocal Rank)](https://en.wikipedia.org/wiki/Mean_reciprocal_rank). For the full metric list (Precision@k, MAP, ERR, and others), see the ranx docs. + +On choosing `k`: set it to match actual usage. If the application shows 5 results to the user, measure `@5`. If a RAG pipeline passes 10 chunks to the LLM, measure `@10`. Reporting `@100` for a UI that surfaces 5 results makes the metric look artificially good. + +### Re-running in CI + +Re-run whenever the retrieval stack changes: new embedding model (which also requires re-embedding queries and re-indexing), new index config, or new reranker. In CI, compute `recall@10` against a fixed golden set and fail the job when the score drops below your target threshold. + +## Pitfalls to Watch For + +In golden sets, **data leakage** means any setup that makes offline metrics look better than production reality. Unlike classic train/test leakage, the issue is often evaluation design. Keep source documents in the index (they are the expected relevant answers). Focus on these risks: + +**Synthetic-query unrealism.** LLMs often mirror source wording, creating easier queries than real user input. This inflates offline scores. Mitigate it by instructing the LLM to generate queries as a user who hasn't seen the source document, then compare synthetic and real-query distributions (length and specificity). + +**Embedding-model contamination.** If your embedding model was trained on pairs overlapping with the golden set, results will look better than true generalization. For hosted models, review published training data when possible. For in-house fine-tuning, keep strict train/eval separation. + +**Near-duplicate documents.** Your retrieval may return a near-duplicate of a labeled document that isn't in the label set. That makes **metrics look worse** because labels are incomplete, not because retrieval is failing. A score dip here is a signal to audit your labels before tuning retrieval. Deduplicate before labeling (for example, cosine similarity > 0.95), or label duplicate clusters together. + +**Temporal drift.** If the corpus changes after labeling, labels go stale: referenced docs may be removed or superseded by newer versions. Pin a corpus snapshot for each run and regenerate the golden set after material corpus changes. + +**Setup reproducibility.** Version the full evaluation setup: corpus snapshot, how labels were produced, and any preprocessing thresholds. Otherwise you can't tell whether a later score drop is model/index regression or dataset drift. + +## Next Steps + +Once retrieval relevance is on target, the next layer is pipeline output quality: whether the full pipeline produces the right output when retrieval feeds into a consumer (LLM generator, ranker, or UI). See [Evaluating Pipeline Output Quality](/documentation/improve-search/pipeline-output-quality/). diff --git a/qdrant-landing/content/documentation/manage-data/collections.md b/qdrant-landing/content/documentation/manage-data/collections.md index b7d7e2a0d..ca2360309 100644 --- a/qdrant-landing/content/documentation/manage-data/collections.md +++ b/qdrant-landing/content/documentation/manage-data/collections.md @@ -28,13 +28,13 @@ Qdrant supports these most popular types of metrics: In addition to metrics and vector size, each collection uses its own set of parameters that controls collection optimization, index construction, and vacuum. These settings can be changed at any time by a corresponding request. -## Setting up multitenancy +## Setting Up Multitenancy **How many collections should you create?** In most cases, you should only use a single collection with payload-based partitioning. This approach is called [multitenancy](https://en.wikipedia.org/wiki/Multitenancy). It is efficient for most of users, but it requires additional configuration. [Learn how to set it up](/documentation/manage-data/collections/#multitenancy) **When should you create multiple collections?** When you have a limited number of users and you need isolation. This approach is flexible, but it may be more costly, since creating numerous collections may result in resource overhead. Also, you need to ensure that they do not affect each other in any way, including performance-wise. -## Create a collection +## Create a Collection {{< code-snippet path="/documentation/headless/snippets/create-collection/simple/" >}} @@ -62,13 +62,13 @@ will enable the use of which is suitable for ingesting a large amount of data. -### Collection with multiple vectors +### Collection with Multiple Vectors *Available as of v0.10.0* It is possible to have multiple vectors per record. This feature allows for multiple vector storages per collection. -To distinguish vectors in one record, they should have a unique name defined when creating the collection. +To distinguish vectors in one record, they should have a unique [name](/documentation/manage-data/vectors/#named-vectors). Each named vector in this mode has its distance and size: @@ -93,7 +93,7 @@ the use of which is suitable for ingesting a large amount of data. -### Vector datatypes +### Vector Datatypes *Available as of v1.9.0* @@ -109,7 +109,7 @@ Vectors with `uint8` datatype are stored in a more compact format, which can sav If you choose to use the `uint8` datatype, elements of the vector will be stored as unsigned 8-bit integers, which can take values **from 0 to 255**. -### Collection with sparse vectors +### Collection with Sparse Vectors *Available as of v1.7.0* @@ -130,7 +130,7 @@ The distance function for sparse vectors is always `Dot` and does not need to be However, there are optional parameters to tune the underlying [sparse vector index](/documentation/manage-data/indexing/#sparse-vector-index). -### Create collection from another collection +### Create Collection from Another Collection To create a collection from another collection, use the [Migration Tool](https://github.com/qdrant/migration/). You can use it to either copy a collection within the same Qdrant instance or to copy a collection to another instance. @@ -146,17 +146,21 @@ docker run --net=host --rm -it registry.cloud.qdrant.io/library/qdrant-migration --migration.batch-size 64 ``` -## Check collection existence +## Check Collection Existence *Available as of v1.8.0* {{< code-snippet path="/documentation/headless/snippets/check-collection-exists/simple/" >}} -## Delete collection +## Delete Collection {{< code-snippet path="/documentation/headless/snippets/delete-collection/simple/" >}} -## Update collection parameters +## Update Collection + +After creating a collection, you can change its configuration, its vectors, and the configuration of its vectors. + +### Update Collection Parameters Dynamic parameter updates may be helpful, for example, for more efficient initial loading of vectors. For example, you can disable indexing during the upload process, and enable it immediately after the upload is finished. @@ -181,7 +185,35 @@ Calls to this endpoint may be blocking as it waits for existing optimizers to finish. We recommended against using this in a production database as it may introduce huge overhead due to the rebuilding of the index. -#### Update vector parameters +### Update Vector Schema + +*Available as of v1.18.0* + +Named vectors can be added to or removed from an existing collection without having to recreate the collection. + + + +To add a new dense named vector to an existing collection: + +{{< code-snippet path="/documentation/headless/snippets/create-named-vector/dense/" >}} + +To add a new sparse named vector to an existing collection: + +{{< code-snippet path="/documentation/headless/snippets/create-named-vector/sparse/" >}} + +The request body only accepts properties that define the vector space (size and distance for dense vectors). Quantization, storage type, and index configuration can be set afterward using the [update collection parameters](/documentation/manage-data/collections/#update-collection-parameters) or [update vector parameters](/documentation/manage-data/collections/#update-vector-parameters) APIs. + +Existing points will not have values for the newly added vector until they are upserted again. The new vector can be queried immediately, but will return no results until it is populated. + +To delete a named vector from an existing collection: + +{{< code-snippet path="/documentation/headless/snippets/delete-named-vector/" >}} + +Deleting a named vector removes its schema and all associated data. Existing points are otherwise unaffected. + +### Update Vector Parameters *Available as of v1.4.0* @@ -212,7 +244,7 @@ both for the whole collection, and for `my_vector` specifically: {{< code-snippet path="/documentation/headless/snippets/update-collection/hnsw-and-quantization/" >}} -## Collection info +## Collection Info Qdrant allows determining the configuration parameters of an existing collection to better understand how the points are distributed and indexed. @@ -282,7 +314,7 @@ The following color statuses are possible: - ⚫ `grey`: collection is pending optimization ([help](#grey-collection-status)) - 🔴 `red`: an error occurred which the engine could not recover from -### Grey collection status +### Grey Collection Status _Available as of v1.9.0_ @@ -300,7 +332,7 @@ For example: Alternatively you may use the `Trigger Optimizers` button in the [Qdrant Web UI](/documentation/web-ui/). It is shown next to the grey collection status on the collection info page. -### Approximate point and vector counts +### Approximate Point and Vector Counts You may be interested in the count attributes: @@ -328,7 +360,7 @@ points or vectors you can query. If you want to know exact counts, refer to the _Note: these numbers may be removed in a future version of Qdrant._ -### Indexing vectors in HNSW +### Indexing Vectors in HNSW In some cases, you might be surprised the value of `indexed_vectors_count` is lower than you expected. This is an intended behaviour and depends on the [optimizer configuration](/documentation/ops-optimization/optimizer/). A new index segment is built if the size of non-indexed vectors is higher than the @@ -337,7 +369,7 @@ created and `indexed_vectors_count` might be equal to `0`. It is possible to reduce the `indexing_threshold` for an existing collection by [updating collection parameters](#update-collection-parameters). -### Collection metadata +### Collection Metadata *Available as of v1.16.0* @@ -373,7 +405,7 @@ When specified, metadata is returned as part of collection info: ``` -## Collection aliases +## Collection Aliases In a production environment, it is sometimes necessary to switch different versions of vectors seamlessly. For example, when upgrading to a new version of the neural network. @@ -385,30 +417,30 @@ All queries to the collection can also be done identically, using an alias inste Thus, it is possible to build a second collection in the background and then switch alias from the old to the new collection. Since all changes of aliases happen atomically, no concurrent requests will be affected during the switch. -### Create alias +### Create Alias {{< code-snippet path="/documentation/headless/snippets/collection-aliases/create/" >}} -### Remove alias +### Remove Alias {{< code-snippet path="/documentation/headless/snippets/collection-aliases/delete/" >}} -### Switch collection +### Switch Collection Multiple alias actions are performed atomically. For example, you can switch underlying collection with the following command: {{< code-snippet path="/documentation/headless/snippets/collection-aliases/switch/" >}} -### List collection aliases +### List Collection Aliases {{< code-snippet path="/documentation/headless/snippets/collection-aliases/list/" >}} -### List all aliases +### List All Aliases {{< code-snippet path="/documentation/headless/snippets/collection-aliases/list-all/" >}} -### List all collections +### List All Collections {{< code-snippet path="/documentation/headless/snippets/list-all-collections/simple/" >}} diff --git a/qdrant-landing/content/documentation/manage-data/quantization.md b/qdrant-landing/content/documentation/manage-data/quantization.md index 1d2cb9b72..a672a4973 100644 --- a/qdrant-landing/content/documentation/manage-data/quantization.md +++ b/qdrant-landing/content/documentation/manage-data/quantization.md @@ -16,7 +16,7 @@ By transforming original vectors into a new representations, quantization compre Different quantization methods have different mechanics and tradeoffs. We will cover them in this section. Quantization is primarily used to reduce the memory footprint and accelerate the search process in high-dimensional vector spaces. -In the context of the Qdrant, quantization allows you to optimize the search engine for specific use cases, striking a balance between accuracy, storage efficiency, and search speed. +In the context of Qdrant, quantization allows you to optimize the search engine for specific use cases, striking a balance between accuracy, storage efficiency, and search speed. There are tradeoffs associated with quantization. On the one hand, quantization allows for significant reductions in storage requirements and faster search times. @@ -24,6 +24,63 @@ This can be particularly beneficial in large-scale applications where minimizing On the other hand, quantization introduces an approximation error, which can lead to a slight decrease in search quality. The level of this tradeoff depends on the quantization method and its parameters, as well as the characteristics of the data. +Qdrant supports four quantization methods: + +- **[TurboQuant](#turboquant-quantization)** supports up to 32x compression, with strong recall across most embedding models. +- **[Scalar Quantization](#scalar-quantization)** compresses each vector component from a 32-bit float to an 8-bit integer, achieving 4x compression with minimal accuracy loss. +- **[Binary Quantization](#binary-quantization)** reduces each vector component to one to two bits for up to 32x compression. Best suited for high-dimensional, centered vector distributions. +- **[Product Quantization](#product-quantization)** enables up to 64x compression when minimizing memory is the top priority. + +To help you choose the right quantization method for your use case, refer to the [next section](#how-to-choose-the-right-quantization-method). + +## How to Choose the Right Quantization Method + +Depending on your requirements for recall, compression, and distance metrics, consult this table for guidance: + +| Compression | Method | +|-------------|-------------| +| 4 | Use **Scalar Quantization**. It is a well-established quantization method with a good balance between recall and compression.

However, unless you need to use the Manhattan (L1) distance metric, consider using 4-bit **TurboQuant** instead of scalar quantization, as it offers comparable recall at double the compression. | +| 8 | Use 4-bit **TurboQuant**. It offers a good balance between recall and compression.

When using the Manhattan (L1) distance metric, consider using another quantization method. | +| 16 | **2-bit TurboQuant** and **2-bit binary quantization** offer similar results at this compression level. Binary quantization is faster, but TurboQuant provides better recall. | +| 24 | **1.5-bit TurboQuant** and **1.5-bit binary quantization** offer similar results at this compression level. Binary quantization is faster, but TurboQuant provides better recall. | +| 32 | **1-bit TurboQuant** and **1-bit binary quantization** offer similar results at this compression level. Binary quantization is faster, but TurboQuant provides better recall. | +| Up to 64 | Use **Product Quantization** if the memory footprint is the top priority and accuracy and speed are not critical. | + +## TurboQuant Quantization + +*Available as of v1.18.0* + + + +TurboQuant is [a quantization method developed by Google](https://research.google/blog/turboquant-redefining-ai-efficiency-with-extreme-compression/). It operates by applying a fast random rotation to vectors before compression, which evenly redistributes data across coordinates. This allows applying a single pre-computed, globally optimized quantization mapping across the dataset, enabling TurboQuant to work effectively with any vector distribution and overcoming a key limitation found in binary quantization. + +Qdrant's implementation of TurboQuant extends the original algorithm to close the gap between the algorithm's theoretical assumptions and real-world embeddings. + +TurboQuant uses asymmetric quantization automatically: only stored vectors are compressed, while queries are scored in full precision. This improves accuracy and requires no additional configuration. + +### Encoding Options + +TurboQuant supports four bit depths: + +| Encoding | Bit Depth | Compression | +|----------|-----------|-------------| +| `bits4` (default) | 4 bits | 8× | +| `bits2` | 2 bits | 16× | +| `bits1_5` | 1.5 bits | 24× | +| `bits1` | 1 bit | 32× | + +In our benchmarks, 4-bit TurboQuant, at twice the compression ratio of scalar quantization, delivers similar recall and speed. Results vary by dataset and embedding model: it may outperform or slightly underperform scalar quantization. This makes 4-bit TurboQuant a good default choice for many use cases. + +Compared to binary quantization, TurboQuant offers better recall at lower speed and equivalent storage budgets. + +The default encoding is `bits4`, which offers the best accuracy. + +### Distance Metric Support + +TurboQuant fully supports Cosine, Dot, and Euclidean (L2) distance with SIMD-accelerated scoring. + +Manhattan (L1) distance is supported but requires full vector reconstruction per comparison, making it significantly slower than the other metrics. Use Cosine, Dot, or Euclidean distance for best performance with TurboQuant. + ## Scalar Quantization *Available as of v1.1.0* @@ -50,11 +107,7 @@ Please refer to the [Quantization Tips](#quantization-tips) section for more inf *Available as of v1.5.0* Binary quantization is an extreme case of scalar quantization. -This feature lets you represent each vector component as a single bit, effectively reducing the memory footprint by a **factor of 32**. - -This is the fastest quantization method, since it lets you perform a vector comparison with a few CPU instructions. - -Binary quantization can achieve up to a **40x** speedup compared to the original vectors. +This feature lets you represent each vector component as a single bit, effectively reducing the memory footprint by a factor of 32. This is the fastest quantization method, since it lets you perform a vector comparison with a few CPU instructions. Binary quantization can achieve up to a 40x speedup compared to the original vectors. However, binary quantization is only efficient for high-dimensional vectors and require a centered distribution of vector components. @@ -65,9 +118,9 @@ At the moment, binary quantization shows good accuracy results with the followin Models with a lower dimensionality or a different distribution of vector components may require additional experiments to find the optimal quantization parameters. -We recommend using binary quantization only with rescoring enabled, as it can significantly improve the search quality -with just a minor performance impact. -Additionally, oversampling can be used to tune the tradeoff between search speed and search quality in the query time. +We recommend using binary quantization only with rescoring enabled, as this can significantly improve search quality. However, keep in mind that if the original vectors are stored on disk, rescoring can significantly decrease search speed. + +Additionally, oversampling can be used to tune the tradeoff between search speed and search quality at query time. ### Binary Quantization as Hamming Distance @@ -150,29 +203,7 @@ Also, product quantization has a loss of accuracy, so it is recommended to use i Please refer to the [Quantization Tips](#quantization-tips) section for more information on how to optimize the quantization parameters for your use case. -## How to choose the right quantization method - -Here is a brief table of the pros and cons of each quantization method: - -| Quantization method | Accuracy | Speed | Compression | -|---------------------|----------|--------------|-------------| -| Scalar | 0.99 | up to x2 | 4 | -| Product | 0.7 | 0.5 | up to 64 | -| Binary (1 bit) | 0.95* | up to x40 | 32 | -| Binary (1.5 bit) | 0.95** | up to x30 | 24 | -| Binary (2 bit) | 0.95*** | up to x20 | 16 | - -- `*` - for compatible models with high-dimensional vectors (approx. 1536+ dimensions) -- `**` - for compatible models with medium-dimensional vectors (approx. 1024-1536 dimensions) -- `***` - for compatible models with low-dimensional vectors (approx. 768-1024 dimensions) - -- **Binary Quantization** is the fastest method and the most memory-efficient, but it requires a centered distribution of vector components. It is recommended to use with tested models only. - - If you are planning to use binary quantization with low or medium-dimensional vectors (approx. 512-1024 dimensions), it is recommended to use 1.5-bit or 2-bit quantization as well as asymmetric quantization feature. - -- **Scalar Quantization** is the most universal method, as it provides a good balance between accuracy, speed, and compression. It is recommended as default quantization if binary quantization is not applicable. -- **Product Quantization** may provide a better compression ratio, but it has a significant loss of accuracy and is slower than scalar quantization. It is recommended if the memory footprint is the top priority and the search speed is not critical. - -## Setting up Quantization in Qdrant +## Setting Up Quantization in Qdrant You can configure quantization for a collection by specifying the quantization parameters in the `quantization_config` section of the collection configuration. @@ -183,7 +214,25 @@ Quantized vectors are stored alongside the original vectors in the collection, s The `quantization_config` can also be set on a per vector basis by specifying it in a named vector. -### Setting up Scalar Quantization +### Setting Up TurboQuant + +To enable TurboQuant, specify it in the `quantization_config` section of the collection configuration. + +When enabling TurboQuant on an existing collection, use a PATCH request or the corresponding `update_collection` method and omit the vector configuration, as it's already defined. + +{{< code-snippet path="/documentation/headless/snippets/create-collection/with-turbo-quant/" >}} + +`bits` - the encoding bit depth. Defaults to `bits4`. Available values: `bits4`, `bits2`, `bits1_5`, and `bits1`. Lower bit depths offer higher compression at the cost of accuracy. + +`always_ram` - whether to keep quantized vectors always cached in RAM or not. By default, quantized vectors are loaded in the same way as the original vectors. Set `always_ram` to `true` to store quantized vectors in RAM. + +#### Select a Bit Depth + +To use a specific compression level, set the `bits` parameter: + +{{< code-snippet path="/documentation/headless/snippets/create-collection/with-turbo-quant-bits/" >}} + +### Setting Up Scalar Quantization To enable scalar quantization, you need to specify the quantization parameters in the `quantization_config` section of the collection configuration. @@ -208,7 +257,7 @@ However, in some setups you might want to keep quantized vectors in RAM to speed In this case, you can set `always_ram` to `true` to store quantized vectors in RAM. -### Setting up Binary Quantization +### Setting Up Binary Quantization To enable binary quantization, you need to specify the quantization parameters in the `quantization_config` section of the collection configuration. @@ -221,14 +270,14 @@ However, in some setups you might want to keep quantized vectors in RAM to speed In this case, you can set `always_ram` to `true` to store quantized vectors in RAM. -#### Set up bit depth +#### Set Up Bit Depth To enable 2bit or 1.5bit quantization, you need to specify `encoding` parameter in the `quantization_config` section of the collection configuration. Available values are `two_bits` and `one_and_half_bits`. {{< code-snippet path="/documentation/headless/snippets/create-collection/with-binary-quantization-and-encoding/" >}} -#### Set up asymmetric quantization +#### Set Up Asymmetric Quantization To enable asymmetric quantization, you need to specify `query_encoding` parameter in the `quantization_config` section of the collection configuration. Available values are: - `default` and `binary` - use regular binary quantization for the query. @@ -237,7 +286,7 @@ To enable asymmetric quantization, you need to specify `query_encoding` paramete {{< code-snippet path="/documentation/headless/snippets/create-collection/with-binary-quantization-and-query-encoding/" >}} -### Setting up Product Quantization +### Setting Up Product Quantization To enable product quantization, you need to specify the quantization parameters in the `quantization_config` section of the collection configuration. @@ -272,10 +321,7 @@ However, there are a few options that you can use to control the search process: `ignore` - Toggle whether to ignore quantized vectors during the search process. By default, Qdrant will use quantized vectors if they are available. -`rescore` - Having the original vectors available, Qdrant can re-evaluate top-k search results using the original vectors. -This can improve the search quality, but may slightly decrease the search speed, compared to the search without rescore. -It is recommended to disable rescore only if the original vectors are stored on a slow storage (e.g. HDD or network storage). -By default, rescore is enabled. +`rescore` - Qdrant can re-evaluate top-k search results using the original vectors. While this can improve search quality, it may decrease search speed, especially if the original vectors are stored on disk. In such cases, it is recommended to disable rescoring. By default, rescoring is only enabled for binary quantization. Other quantization methods do not rescore by default. **Available as of v1.3.0** @@ -283,9 +329,9 @@ By default, rescore is enabled. For example, if oversampling is 2.4 and limit is 100, then 240 vectors will be pre-selected using quantized index, and then top-100 will be returned after re-scoring. Oversampling is useful if you want to tune the tradeoff between search speed and search quality in the query time. -## Quantization tips +## Quantization Tips -#### Accuracy tuning +### Accuracy Tuning In this section, we will discuss how to tune the search precision. The fastest way to understand the impact of quantization on the search quality is to compare the search results with and without quantization. @@ -299,9 +345,9 @@ By setting it to a value lower than 1.0, you can exclude extreme values (outlier For example, if you set the quantile to 0.99, 1% of the extreme values will be excluded. By adjusting the quantile, you find an optimal value that will provide the best search quality for your collection. -- **Enable rescore**: Having the original vectors available, Qdrant can re-evaluate top-k search results using the original vectors. On large collections, this can improve the search quality, with just minor performance impact. +- **Enable rescoring**: Qdrant can re-evaluate top-k search results using the original vectors. While this can improve search quality, it may decrease search speed, especially if the original vectors are stored on disk. In such cases, it is recommended to disable rescoring. By default, rescoring is only enabled for binary quantization. Other quantization methods do not rescore by default. -#### Memory and speed tuning +### Memory and Speed Tuning In this section, we will discuss how to tune the memory and speed of the search process with quantization. @@ -311,21 +357,18 @@ There are 3 possible modes to place storage of vectors within the qdrant collect - **Original on Disk, quantized in RAM** - this is a hybrid mode, allows to obtain a good balance between speed and memory usage. Recommended scenario if you are aiming to shrink the memory footprint while keeping the search speed. -This mode is enabled by setting `always_ram` to `true` in the quantization config while using memmap storage: - + This mode is enabled by setting `always_ram` to `true` in the quantization config while using memmap storage:\ {{< code-snippet path="/documentation/headless/snippets/create-collection/scalar-quantization-in-ram/" >}} -In this scenario, the number of disk reads may play a significant role in the search speed. -In a system with high disk latency, the re-scoring step may become a bottleneck. - -Consider disabling `rescore` to improve the search speed: + In this scenario, the number of disk reads may play a significant role in the search speed. + In a system with high disk latency, the re-scoring step may become a bottleneck. + Consider disabling `rescore` to improve the search speed:\ {{< code-snippet path="/documentation/headless/snippets/query-points/with-disabled-rescoring/" >}} - **All on Disk** - all vectors, original and quantized, are stored on disk. This mode allows to achieve the smallest memory footprint, but at the cost of the search speed. -It is recommended to use this mode if you have a large collection and fast storage (e.g. SSD or NVMe). - -This mode is enabled by setting `always_ram` to `false` in the quantization config while using mmap storage: + It is recommended to use this mode if you have a large collection and fast storage (e.g. SSD or NVMe). + This mode is enabled by setting `always_ram` to `false` in the quantization config while using mmap storage:\ {{< code-snippet path="/documentation/headless/snippets/create-collection/quantization-on-disk/" >}} diff --git a/qdrant-landing/content/documentation/manage-data/vectors.md b/qdrant-landing/content/documentation/manage-data/vectors.md index e0b1eec77..a687cac10 100644 --- a/qdrant-landing/content/documentation/manage-data/vectors.md +++ b/qdrant-landing/content/documentation/manage-data/vectors.md @@ -133,7 +133,7 @@ $$ Where $N$ is the number of vectors in the first matrix, $M$ is the number of vectors in the second matrix, and $\text{Sim}$ is a similarity function, for example, cosine similarity. -To use multivectors, create a collection with the following configuration: +To use multivectors, create a dense vector with a multivector comparator: {{< code-snippet path="/documentation/headless/snippets/create-collection/with-multivector/" >}} @@ -150,7 +150,7 @@ To search with multivector (available in `query` API): In Qdrant, you can store multiple vectors of different sizes and [types](#vector-types) in the same data [point](/documentation/manage-data/points/). This is useful when you need to define your data with multiple embeddings to represent different features or modalities (e.g., image, text or video). -To store different vectors for each point, you need to create separate named vector spaces in the [collection](/documentation/manage-data/collections/). You can define these vector spaces during collection creation and manage them independently. +To store different vectors for each point, you need to create separate named vector spaces in the [collection](/documentation/manage-data/collections/). You can define these vector spaces during collection creation or [add them later](#adding-and-removing-named-vectors) and manage them independently.