Files
opencloud/vendor/github.com/blevesearch/go-faiss/search_params.go
dependabot[bot] 2b0d61acf5 build(deps): bump github.com/blevesearch/bleve/v2 from 2.5.7 to 2.6.0
Bumps [github.com/blevesearch/bleve/v2](https://github.com/blevesearch/bleve) from 2.5.7 to 2.6.0.
- [Release notes](https://github.com/blevesearch/bleve/releases)
- [Commits](https://github.com/blevesearch/bleve/compare/v2.5.7...v2.6.0)

---
updated-dependencies:
- dependency-name: github.com/blevesearch/bleve/v2
  dependency-version: 2.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-20 00:37:30 +00:00

204 lines
5.9 KiB
Go

package faiss
/*
#include <faiss/c_api/Index_c.h>
#include <faiss/c_api/IndexIVF_c.h>
#include <faiss/c_api/IndexIVF_c_ex.h>
#include <faiss/c_api/IndexBinaryIVF_c.h>
#include <faiss/c_api/impl/AuxIndexStructures_c.h>
*/
import "C"
import (
"encoding/json"
"fmt"
)
type SearchParams struct {
sp *C.FaissSearchParameters
}
// Delete frees the memory associated with s.
func (s *SearchParams) Delete() {
if s == nil || s.sp == nil {
return
}
C.faiss_SearchParameters_free(s.sp)
}
type searchParamsIVF struct {
NprobePct float32 `json:"ivf_nprobe_pct,omitempty"`
MaxCodesPct float32 `json:"ivf_max_codes_pct,omitempty"`
}
// IVF Parameters used to override the index-time defaults for a specific query.
// Serve as the 'new' defaults for this query, unless overridden by search-time
// params.
type defaultSearchParamsIVF struct {
Nprobe int `json:"ivf_nprobe,omitempty"`
Nlist int `json:"ivf_nlist,omitempty"`
}
func (s *searchParamsIVF) Validate() error {
if s.NprobePct < 0 || s.NprobePct > 100 {
return fmt.Errorf("invalid IVF search params, ivf_nprobe_pct:%v, "+
"should be in range [0, 100]", s.NprobePct)
}
if s.MaxCodesPct < 0 || s.MaxCodesPct > 100 {
return fmt.Errorf("invalid IVF search params, ivf_max_codes_pct:%v, "+
"should be in range [0, 100]", s.MaxCodesPct)
}
return nil
}
func getNProbeFromSearchParams(params *SearchParams) int32 {
return int32(C.faiss_SearchParametersIVF_nprobe(params.sp))
}
// Returns a valid SearchParams object, configured according to the provided
// parameters and selector. The returned SearchParams object is allocated,
// thus caller must clean up the object by invoking Delete() method.
func NewSearchParams(idx Index, params json.RawMessage, selector Selector,
defaultParams *defaultSearchParamsIVF) (*SearchParams, error) {
// Get the selector C pointer, if any.
// A nil selector indicates no ID filtering, and it is valid
// to send a nil pointer to Faiss.
var sel *C.FaissIDSelector
if selector != nil {
sel = selector.Get()
}
ivfIdx := C.faiss_IndexIVF_cast(idx.cPtr())
// if the index is not an IVF index, create a standard SearchParameters object
if ivfIdx == nil {
rv := &SearchParams{}
// Create standard SearchParameters for non-IVF index
if c := C.faiss_SearchParameters_new(&rv.sp, sel); c != 0 {
return nil, fmt.Errorf("failed to create faiss search params")
}
return rv, nil
}
nlist := int(C.faiss_IndexIVF_nlist(ivfIdx))
nprobe := int(C.faiss_IndexIVF_nprobe(ivfIdx))
nvecs := int(C.faiss_Index_ntotal(idx.cPtr()))
maxCodes, nprobe, err := resolveSearchParams(params, defaultParams, nlist, nprobe, nvecs)
if err != nil {
return nil, err
}
if idx.HasRaBitQ() {
return buildRaBitQSearchParams(maxCodes, nprobe, sel)
}
return buildIVFSearchParams(maxCodes, nprobe, sel)
}
func resolveSearchParams(params json.RawMessage, defaultParams *defaultSearchParamsIVF,
nlist, nprobe, nvecs int) (int, int, error) {
if defaultParams != nil {
if defaultParams.Nlist > 0 {
nlist = defaultParams.Nlist
}
if defaultParams.Nprobe > 0 {
nprobe = defaultParams.Nprobe
}
}
var ivfParams searchParamsIVF
if len(params) > 0 {
if err := json.Unmarshal(params, &ivfParams); err != nil {
return 0, 0, fmt.Errorf("failed to unmarshal IVF search params, "+
"err:%v", err)
}
if err := ivfParams.Validate(); err != nil {
return 0, 0, err
}
}
if ivfParams.NprobePct > 0 {
nprobe = max(int(float32(nlist)*(ivfParams.NprobePct/100)), 1)
}
var maxCodes int
if ivfParams.MaxCodesPct > 0 {
maxCodes = int(float32(nvecs) * (ivfParams.MaxCodesPct / 100))
} // else, maxCodes will be set to the default value of 0, which means no limit
return maxCodes, nprobe, nil
}
func buildIVFSearchParams(maxCodes, nprobe int, sel *C.FaissIDSelector) (*SearchParams, error) {
sp := &SearchParams{}
if c := C.faiss_SearchParametersIVF_new_with(
&sp.sp,
sel,
C.size_t(nprobe),
C.size_t(maxCodes),
); c != 0 {
return nil, fmt.Errorf("failed to create faiss IVF search params")
}
return sp, nil
}
func buildRaBitQSearchParams(maxCodes, nprobe int, sel *C.FaissIDSelector) (*SearchParams, error) {
sp := &SearchParams{}
if c := C.faiss_SearchParametersRaBitQ_new_with(
&sp.sp,
sel,
C.size_t(nprobe),
C.size_t(maxCodes),
); c != 0 {
return nil, fmt.Errorf("failed to create faiss IVF RaBitQ search params")
}
return sp, nil
}
// Returns a standard SearchParams object without any special settings with
// the provided selector. The returned SearchParams object is allocated,
// thus caller must clean up the object by invoking Delete() method.
func NewStandardSearchParams(selector Selector) (*SearchParams, error) {
var sel *C.FaissIDSelector
if selector != nil {
sel = selector.Get()
}
rv := &SearchParams{}
if c := C.faiss_SearchParameters_new(&rv.sp, sel); c != 0 {
return nil, fmt.Errorf("failed to create faiss search params")
}
return rv, nil
}
func NewBinarySearchParams(idx BinaryIndex, params json.RawMessage, selector Selector,
defaultParams *defaultSearchParamsIVF) (*SearchParams, error) {
// Get the selector C pointer, if any.
// A nil selector indicates no ID filtering, and it is valid
// to send a nil pointer to Faiss.
var sel *C.FaissIDSelector
if selector != nil {
sel = selector.Get()
}
ivfPtrBinary := C.faiss_IndexBinaryIVF_cast(idx.bPtr())
// if the index is not an IVF index, create a standard SearchParameters object
if ivfPtrBinary == nil {
rv := &SearchParams{}
// Create standard SearchParameters for non-IVF index
if c := C.faiss_SearchParameters_new(&rv.sp, sel); c != 0 {
return nil, fmt.Errorf("failed to create faiss search params")
}
return rv, nil
}
nlist := int(C.faiss_IndexBinaryIVF_nlist(ivfPtrBinary))
nprobe := int(C.faiss_IndexBinaryIVF_nprobe(ivfPtrBinary))
nvecs := int(C.faiss_IndexBinary_ntotal(idx.bPtr()))
maxCodes, nprobe, err := resolveSearchParams(params, defaultParams, nlist, nprobe, nvecs)
if err != nil {
return nil, err
}
return buildIVFSearchParams(maxCodes, nprobe, sel)
}