AI News HubLIVE
サイト内リライト6 分で読了

翻訳待ち:Weaviate 1.39 Release

AI サービスが一時的に利用できないため、復旧後に翻訳を補完します。ソース概要:Weaviate 1.39 promotes the Boost API and MMR diversity selection to GA, previews 4-bit Rotational Quantization, and ships an experimental Search REST API.

ソースWeaviate Blog

AI サービスが一時的に利用できないため、復旧後に翻訳を補完します。

Weaviate v1.39 is now available open-source and on Weaviate Cloud. Two search features reach general availability in this release: the Boost API for query-time rescoring, and Maximal Marginal Relevance (MMR) diversity selection, which works on hybrid search as well as vector search. Two more are new: 4-bit Rotational Quantization as a preview, and an experimental Search REST API. This post also covers gRPC-Web, which shipped quietly in the 1.38 line, and the HNSW snapshot rework, which cuts commit-log disk usage and speeds up startup. Here are the release highlights! Boost API - General Availability MMR Diversity Selection - General Availability 4-bit Rotational Quantization (Preview) Search REST API (Experimental) gRPC-Web HNSW Snapshots, Automatic - General Availability Performance Improvements and Fixes Community Contributions Summary Boost API - General Availability​ The Boost API, introduced as a preview in v1.38, is now generally available. Boost is a query-time rescorer. After the primary search fetches its candidates, Weaviate scores each one against your boost conditions and re-sorts the list. Unlike a filter, it never removes anything: an object that matches nothing is demoted, not dropped. That is the difference between "only show me in-stock products" and "prefer in-stock products, but still show me the perfect match that is out of stock". How it works​ A boost holds between one and twenty conditions, and there are four kinds: filter promotes results that satisfy a filter property_value ranks by a numeric property's value time_decay favors objects near a point in time numeric_decay favors objects near a target number Two weights control the result. The outer weight (default 0.5) mixes the boost score into the original relevance score: (1 - weight) * primary + weight * boost. Each condition then carries its own weight (default 1.0). Make that one negative if you want the condition to demote instead of promote. A third setting, depth (default 100, capped by QUERY_MAXIMUM_RESULTS), is how many candidates the primary search fetches before the re-sort. An operator can move that default for the whole cluster with QUERY_BOOST_DEFAULT_DEPTH. Here is what that does to a real result page. The same query runs twice over a small product catalog: once plain, once with a boost that prefers products that are in stock and recently released: from datetime import timedelta from weaviate.classes.query import Boost, Filter prefer_in_stock_and_recent = Boost.blend( [ Boost.filter(Filter.by_property("in_stock").equal(True), weight=2.0), Boost.time_decay("released", scale=timedelta(days=30)), ], weight=0.3, # 30% boost, 70% original relevance depth=200, # re-score the top 200 candidates ) for label, boost in (("plain hybrid", None), ("with boost", prefer_in_stock_and_recent)): response = collection.query.hybrid(query="wireless headphones", limit=4, boost=boost) print(label) for obj in response.objects: print(" ", obj.properties["title"], "| in stock:", obj.properties["in_stock"]) plain hybrid Kestrel Wireless Headphones | in stock: True Meridian Wireless Headphones | in stock: False Aurora Wireless Headphones | in stock: False Nimbus Wireless Headphones | in stock: True with boost Kestrel Wireless Headphones | in stock: True Nimbus Wireless Headphones | in stock: True Wireless Earbuds Pro | in stock: True Meridian Wireless Headphones | in stock: False Nimbus is in stock and twelve days old, so it climbs from fourth to second. The earbuds take third for the same reason, even though the text match is weaker. The two out-of-stock listings lose ground: Meridian slides to fourth, and Aurora drops off the page. Neither one was removed from the result set. Kestrel, the best keyword and vector match, still holds first place. A weight of 0.3 leaves 70% of the score with the search itself. Raise it toward 1.0 and stock and freshness take over the ordering. Lower it toward 0.0 and you get the plain result back. Boost is available on hybrid, bm25, near_text, near_vector, near_object, near_media, and near_image, in both the .query.* and .generate.* namespaces. It is not available on fetch_objects, which has no relevance score to blend with. Boost runs before a reranker If you combine boost= with rerank=, the reranker runs afterwards and re-sorts the boosted page, so it has the last word. Use one or the other unless you want that layering. Related resources How-to: Search - Boost results How-to: Search - Blending and weights MMR Diversity Selection - General Availability​ MMR diversity selection, a preview since v1.37, is now generally available. It works on hybrid search alongside every near_* search. Hybrid support is not new in v1.39: it landed in v1.38.6, so if you are on a recent 1.38 patch you already have it. What v1.39 changes is the maturity label. MMR picks results one at a time. At each step it weighs two things: how well a candidate matches the query, and how different it is from the results already picked. You end up with a first page that covers the topic instead of showing the same passage nine times. That helps most in hybrid search. The keyword half and the vector half of a hybrid query tend to agree on the same cluster of near-identical chunks, so their merged top 10 is often the most repetitive list in your system. How it works​ MMR runs near the end of the query pipeline, after the two halves are merged and before the page is cut. A reranker, if you use one, runs after MMR: Two values configure it, and both are easy to get backwards. balance trades relevance against diversity. It takes a value from 0.0 to 1.0, and anything outside that range is rejected with MMR balance must be between 0 and 1. At 1.0 you get pure relevance, which is the same order you would get without MMR. At 0.0 you get pure diversity. So lower means more diverse. The default is 0.0, not 0.5. Leave balance out and you get the most aggressive setting there is, so always pass it explicitly. limit on the MMR selection is your page size, the number of results you get back. MMR picks those results out of a candidate pool, and the pool is the query's own limit. The MMR limit must be at least 1 and no larger than the query limit. Here is the same query at three settings. The collection holds documentation chunks, and four of them say roughly the same thing about carbon pricing: from weaviate.classes.query import Diversity for balance in (1.0, 0.3, 0.0): response = collection.query.hybrid( query="carbon pricing", limit=8, # candidate pool diversity_selection=Diversity.mmr(limit=4, balance=balance), # 4 returned ) print(f"balance={balance}") for obj in response.objects: print(" ", obj.properties["title"]) balance=1.0 Carbon tax versus cap and trade Carbon pricing basics Carbon pricing FAQ What is a carbon price? balance=0.3 Carbon tax versus cap and trade Carbon pricing FAQ Carbon pricing basics Adaptation funding for coastal cities balance=0.0 Carbon tax versus cap and trade Methane rules for oil and gas Adaptation funding for coastal cities Renewable subsidies and grid buildout At 1.0 the page is four ways of saying the same thing, which is the page you get without MMR. At 0.3 one of the duplicates gives up its slot to a chunk on adaptation funding. At 0.0 relevance stops counting after the first pick, and a carbon-pricing query comes back with methane rules and grid buildout. That last one is what you get if you leave balance out. You need Python client 4.23.0 or newer. That is the release where diversity_selection arrives on collection.query.hybrid and collection.generate.hybrid. MMR is not available on bm25, which has no vectors to measure distance between, and it does not work on multi-vector collections. Related resources How-to: Search - Diversity selection (MMR) How-to: Hybrid search - Diversity selection (MMR) Blog: Hybrid search explained 4-bit Rotational Quantization (Preview)​ Rotational quantization (RQ) shrinks vectors in two steps. First it rotates the vector so the values spread evenly across the dimensions. Then it stores each dimension as a small integer code instead of a 32-bit float. Weaviate already ships 8-bit and 1-bit RQ. v1.39 adds a 4-bit width as a preview. Four bits is half a byte, so two dimensions pack into one byte. At 1536 dimensions that is a 16-byte header plus 768 bytes of codes: 784 bytes per vector, against 6144 bytes for raw float32. That is 7.84x smaller, not a round "8x", because the header stays. The general form is 16 + ceil(outputDim / 2) bytes, where outputDim = 64 * ceil(inputDim / 64). The rotation rounds your dimension count up to the next multiple of 64. At 1536 that round-up is free, because 1536 is 24 x 64. At 1000 dimensions it is not: you pay for 1024. How it works​ There is no preview flag to unlock. It is a plain schema value, rq.bits = 4, on a vector index: from weaviate.classes.config import Configure client.collections.create( "Doc", vector_config=Configure.Vectors.text2vec_weaviate( name="default", source_properties=["title", "body"], vector_index_config=Configure.VectorIndex.hnsw( quantizer=Configure.VectorIndex.Quantizer.rq( bits=4, rescore_limit=20, ), ), ), ) bits is fixed the moment RQ is first enabled on a vector, and you cannot change it later. There is no migration from 8-bit codes to 4-bit codes, so pick the width when you create the collection. If you would rather not set it per collection, an operator can make it the cluster-wide default for new vector indexes with DEFAULT_QUANTIZATION=rq-4. A new HNSW index then comes up with bits: 4 and a rescoreLimit of 20. Flat indexes are left alone. 4-bit is HNSW-only The flat index still rejects it with RQ bits must be either 1 or 8, and that applies to the flat side of a dynamic index too. Use bits: 4 on an HNSW index. Like the other RQ widths, 4-bit works with the cosine, dot, and l2-squared distance metrics. Preview The 4-bit width is a preview feature. Its behavior and defaults may change in future releases. Related resources Concepts: Vector quantization - Rotational quantization Concepts: Vector quantization - Rescoring Config references: Vector index parameters Search REST API (Experimental)​ Weaviate has two search APIs today. gRPC is fast, but it wants a generated client and HTTP/2. GraphQL means building a query string by hand and digging metadata out of _additional. Neither is pleasant from a shell script, a Lambda, an edge worker, an API gateway, or a language with no Weaviate client. v1.39 adds an experimental Search REST API. You post JSON over plain HTTP/1.1 and get JSON back, and the endpoints are described by the OpenAPI spec like the rest of the REST API. That also suits LLM tool calling, where a model needs a documented HTTP endpoint rather than a client library. v1.39.0 shipped one endpoint, POST /v1/search/{collection}/near-text. The v1.39.1 patch added three more search endpoints and a matching aggregate endpoint, so on 1.39.1 or newer you get all five: POST /v1/search/{collection}/near-text POST /v1/search/{collection}/bm25 POST /v1/search/{collection}/hybrid POST /v1/search/{collection}/near-object POST /v1/aggregate/{collection} The examples below use near-text. How it works​ The endpoints are off by default. Turn them on per node with EXPERIMENTAL_REST_SEARCH_ENABLED: services: weaviate: image: cr.weaviate.io/semitechnologies/weaviate:1.39.1 environment: EXPERIMENTAL_REST_SEARCH_ENABLED: 'true' Accepted truthy values are on, enabled, 1, and true. One switch covers every endpoint in the set. When the feature is off, the routes are still there. They answer 422 with a message naming the variable to set, instead of a confusing 404. The request body is all camelCase. For near-text, query is a required array of strings, and each string is a piece of text to search for. Send one string for an ordinary search. Send several and Weaviate averages them into a single search [truncated for AI cost control]