github.com/weaviate/weaviate@v1.24.6/usecases/traverser/fakes_for_test.go (about)

     1  //                           _       _
     2  // __      _____  __ ___   ___  __ _| |_ ___
     3  // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
     4  //  \ V  V /  __/ (_| |\ V /| | (_| | ||  __/
     5  //   \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
     6  //
     7  //  Copyright © 2016 - 2024 Weaviate B.V. All rights reserved.
     8  //
     9  //  CONTACT: hello@weaviate.io
    10  //
    11  
    12  package traverser
    13  
    14  import (
    15  	"context"
    16  	"fmt"
    17  	"net/http"
    18  
    19  	"github.com/go-openapi/strfmt"
    20  	"github.com/pkg/errors"
    21  	"github.com/stretchr/testify/mock"
    22  	"github.com/tailor-inc/graphql"
    23  	"github.com/tailor-inc/graphql/language/ast"
    24  	"github.com/weaviate/weaviate/adapters/handlers/graphql/descriptions"
    25  	"github.com/weaviate/weaviate/entities/additional"
    26  	"github.com/weaviate/weaviate/entities/aggregation"
    27  	"github.com/weaviate/weaviate/entities/dto"
    28  	"github.com/weaviate/weaviate/entities/filters"
    29  	"github.com/weaviate/weaviate/entities/models"
    30  	"github.com/weaviate/weaviate/entities/modulecapabilities"
    31  	"github.com/weaviate/weaviate/entities/moduletools"
    32  	"github.com/weaviate/weaviate/entities/schema"
    33  	"github.com/weaviate/weaviate/entities/search"
    34  	"github.com/weaviate/weaviate/entities/searchparams"
    35  	"github.com/weaviate/weaviate/entities/storobj"
    36  	"github.com/weaviate/weaviate/entities/vectorindex/hnsw"
    37  	"github.com/weaviate/weaviate/usecases/sharding"
    38  )
    39  
    40  type fakeLocks struct{}
    41  
    42  func (f *fakeLocks) LockConnector() (func() error, error) {
    43  	return func() error { return nil }, nil
    44  }
    45  
    46  func (f *fakeLocks) LockSchema() (func() error, error) {
    47  	return func() error { return nil }, nil
    48  }
    49  
    50  type ClassIndexCheck interface {
    51  	PropertyIndexed(property string) bool
    52  	VectorizeClassName() bool
    53  	VectorizePropertyName(propertyName string) bool
    54  }
    55  
    56  type fakeTxt2VecVectorizer struct{}
    57  
    58  func (f *fakeTxt2VecVectorizer) Object(ctx context.Context, object *models.Object, icheck ClassIndexCheck) error {
    59  	panic("not implemented")
    60  }
    61  
    62  func (f *fakeTxt2VecVectorizer) Corpi(ctx context.Context, corpi []string) ([]float32, error) {
    63  	return []float32{1, 2, 3}, nil
    64  }
    65  
    66  func (f *fakeTxt2VecVectorizer) MoveTo(source []float32, target []float32, weight float32) ([]float32, error) {
    67  	res := make([]float32, len(source))
    68  	for i, v := range source {
    69  		res[i] = v + 1
    70  	}
    71  	return res, nil
    72  }
    73  
    74  func (f *fakeTxt2VecVectorizer) MoveAwayFrom(source []float32, target []float32, weight float32) ([]float32, error) {
    75  	res := make([]float32, len(source))
    76  	for i, v := range source {
    77  		res[i] = v - 0.5
    78  	}
    79  	return res, nil
    80  }
    81  
    82  type fakeVectorSearcher struct {
    83  	mock.Mock
    84  	calledWithVector []float32
    85  	calledWithLimit  int
    86  	calledWithOffset int
    87  	results          []search.Result
    88  }
    89  
    90  func (f *fakeVectorSearcher) CrossClassVectorSearch(ctx context.Context,
    91  	vector []float32, targetVector string, offset, limit int, filters *filters.LocalFilter,
    92  ) ([]search.Result, error) {
    93  	f.calledWithVector = vector
    94  	f.calledWithLimit = limit
    95  	f.calledWithOffset = offset
    96  	return f.results, nil
    97  }
    98  
    99  func (f *fakeVectorSearcher) Aggregate(ctx context.Context,
   100  	params aggregation.Params,
   101  ) (*aggregation.Result, error) {
   102  	args := f.Called(params)
   103  	return args.Get(0).(*aggregation.Result), args.Error(1)
   104  }
   105  
   106  func (f *fakeVectorSearcher) VectorSearch(ctx context.Context,
   107  	params dto.GetParams,
   108  ) ([]search.Result, error) {
   109  	args := f.Called(params)
   110  	return args.Get(0).([]search.Result), args.Error(1)
   111  }
   112  
   113  func (f *fakeVectorSearcher) Search(ctx context.Context,
   114  	params dto.GetParams,
   115  ) ([]search.Result, error) {
   116  	args := f.Called(params)
   117  	return args.Get(0).([]search.Result), args.Error(1)
   118  }
   119  
   120  func (f *fakeVectorSearcher) Object(ctx context.Context,
   121  	className string, id strfmt.UUID, props search.SelectProperties,
   122  	additional additional.Properties, repl *additional.ReplicationProperties,
   123  	tenant string,
   124  ) (*search.Result, error) {
   125  	args := f.Called(className, id)
   126  	return args.Get(0).(*search.Result), args.Error(1)
   127  }
   128  
   129  func (f *fakeVectorSearcher) ObjectsByID(ctx context.Context, id strfmt.UUID,
   130  	props search.SelectProperties, additional additional.Properties, tenant string,
   131  ) (search.Results, error) {
   132  	args := f.Called(id)
   133  	return args.Get(0).(search.Results), args.Error(1)
   134  }
   135  
   136  func (f *fakeVectorSearcher) SparseObjectSearch(ctx context.Context,
   137  	params dto.GetParams,
   138  ) ([]*storobj.Object, []float32, error) {
   139  	return nil, nil, nil
   140  }
   141  
   142  func (f *fakeVectorSearcher) DenseObjectSearch(context.Context, string,
   143  	[]float32, string, int, int, *filters.LocalFilter, additional.Properties, string,
   144  ) ([]*storobj.Object, []float32, error) {
   145  	return nil, nil, nil
   146  }
   147  
   148  func (f *fakeVectorSearcher) ResolveReferences(ctx context.Context, objs search.Results,
   149  	props search.SelectProperties, groupBy *searchparams.GroupBy,
   150  	additional additional.Properties, tenant string,
   151  ) (search.Results, error) {
   152  	return nil, nil
   153  }
   154  
   155  type fakeAuthorizer struct{}
   156  
   157  func (f *fakeAuthorizer) Authorize(principal *models.Principal, verb, resource string) error {
   158  	return nil
   159  }
   160  
   161  type fakeVectorRepo struct {
   162  	mock.Mock
   163  }
   164  
   165  func (f *fakeVectorRepo) ObjectsByID(ctx context.Context,
   166  	id strfmt.UUID, props search.SelectProperties,
   167  	additional additional.Properties, tenant string,
   168  ) (search.Results, error) {
   169  	return nil, nil
   170  }
   171  
   172  func (f *fakeVectorRepo) Object(ctx context.Context, className string, id strfmt.UUID,
   173  	props search.SelectProperties, additional additional.Properties,
   174  	repl *additional.ReplicationProperties, tenant string,
   175  ) (*search.Result, error) {
   176  	return nil, nil
   177  }
   178  
   179  func (f *fakeVectorRepo) Aggregate(ctx context.Context,
   180  	params aggregation.Params,
   181  ) (*aggregation.Result, error) {
   182  	args := f.Called(params)
   183  	return args.Get(0).(*aggregation.Result), args.Error(1)
   184  }
   185  
   186  func (f *fakeVectorRepo) GetObject(ctx context.Context, uuid strfmt.UUID,
   187  	res *models.Object,
   188  ) error {
   189  	args := f.Called(uuid)
   190  	*res = args.Get(0).(models.Object)
   191  	return args.Error(1)
   192  }
   193  
   194  type fakeExplorer struct{}
   195  
   196  func (f *fakeExplorer) GetClass(ctx context.Context, p dto.GetParams) ([]interface{}, error) {
   197  	return nil, nil
   198  }
   199  
   200  func (f *fakeExplorer) CrossClassVectorSearch(ctx context.Context, p ExploreParams) ([]search.Result, error) {
   201  	return nil, nil
   202  }
   203  
   204  type fakeSchemaGetter struct {
   205  	schema schema.Schema
   206  }
   207  
   208  func newFakeSchemaGetter(className string) *fakeSchemaGetter {
   209  	return &fakeSchemaGetter{
   210  		schema: schema.Schema{Objects: &models.Schema{
   211  			Classes: []*models.Class{
   212  				{
   213  					Class: className,
   214  				},
   215  			},
   216  		}},
   217  	}
   218  }
   219  
   220  func (f *fakeSchemaGetter) SetVectorIndexConfig(cfg hnsw.UserConfig) {
   221  	for _, cls := range f.schema.Objects.Classes {
   222  		cls.VectorIndexConfig = cfg
   223  	}
   224  }
   225  
   226  func (f *fakeSchemaGetter) GetSchemaSkipAuth() schema.Schema {
   227  	return f.schema
   228  }
   229  
   230  func (f *fakeSchemaGetter) CopyShardingState(class string) *sharding.State {
   231  	panic("not implemented")
   232  }
   233  
   234  func (f *fakeSchemaGetter) ShardOwner(class, shard string) (string, error) {
   235  	return shard, nil
   236  }
   237  
   238  func (f *fakeSchemaGetter) ShardReplicas(class, shard string) ([]string, error) {
   239  	return []string{shard}, nil
   240  }
   241  
   242  func (f *fakeSchemaGetter) TenantShard(class, tenant string) (string, string) {
   243  	return tenant, models.TenantActivityStatusHOT
   244  }
   245  func (f *fakeSchemaGetter) ShardFromUUID(class string, uuid []byte) string { return string(uuid) }
   246  
   247  func (f *fakeSchemaGetter) Nodes() []string {
   248  	panic("not implemented")
   249  }
   250  
   251  func (f *fakeSchemaGetter) NodeName() string {
   252  	panic("not implemented")
   253  }
   254  
   255  func (f *fakeSchemaGetter) ClusterHealthScore() int {
   256  	panic("not implemented")
   257  }
   258  
   259  func (f *fakeSchemaGetter) ResolveParentNodes(string, string,
   260  ) (map[string]string, error) {
   261  	panic("not implemented")
   262  }
   263  
   264  type fakeInterpretation struct{}
   265  
   266  func (f *fakeInterpretation) AdditionalPropertyFn(ctx context.Context,
   267  	in []search.Result, params interface{}, limit *int,
   268  	argumentModuleParams map[string]interface{}, cfg moduletools.ClassConfig,
   269  ) ([]search.Result, error) {
   270  	return in, nil
   271  }
   272  
   273  func (f *fakeInterpretation) ExtractAdditionalFn(param []*ast.Argument) interface{} {
   274  	return true
   275  }
   276  
   277  func (f *fakeInterpretation) AdditionalPropertyDefaultValue() interface{} {
   278  	return true
   279  }
   280  
   281  type fakeExtender struct {
   282  	returnArgs []search.Result
   283  }
   284  
   285  func (f *fakeExtender) AdditionalPropertyFn(ctx context.Context,
   286  	in []search.Result, params interface{}, limit *int,
   287  	argumentModuleParams map[string]interface{}, cfg moduletools.ClassConfig,
   288  ) ([]search.Result, error) {
   289  	return f.returnArgs, nil
   290  }
   291  
   292  func (f *fakeExtender) ExtractAdditionalFn(param []*ast.Argument) interface{} {
   293  	return nil
   294  }
   295  
   296  func (f *fakeExtender) AdditionalPropertyDefaultValue() interface{} {
   297  	return true
   298  }
   299  
   300  type fakeProjectorParams struct {
   301  	Enabled          bool
   302  	Algorithm        string
   303  	Dimensions       int
   304  	Perplexity       int
   305  	Iterations       int
   306  	LearningRate     int
   307  	IncludeNeighbors bool
   308  }
   309  
   310  type fakeProjector struct {
   311  	returnArgs []search.Result
   312  }
   313  
   314  func (f *fakeProjector) AdditionalPropertyFn(ctx context.Context,
   315  	in []search.Result, params interface{}, limit *int,
   316  	argumentModuleParams map[string]interface{}, cfg moduletools.ClassConfig,
   317  ) ([]search.Result, error) {
   318  	return f.returnArgs, nil
   319  }
   320  
   321  func (f *fakeProjector) ExtractAdditionalFn(param []*ast.Argument) interface{} {
   322  	return nil
   323  }
   324  
   325  func (f *fakeProjector) AdditionalPropertyDefaultValue() interface{} {
   326  	return &fakeProjectorParams{}
   327  }
   328  
   329  type pathBuilderParams struct{}
   330  
   331  type fakePathBuilder struct {
   332  	returnArgs []search.Result
   333  }
   334  
   335  func (f *fakePathBuilder) AdditionalPropertyFn(ctx context.Context,
   336  	in []search.Result, params interface{}, limit *int,
   337  	argumentModuleParams map[string]interface{}, cfg moduletools.ClassConfig,
   338  ) ([]search.Result, error) {
   339  	return f.returnArgs, nil
   340  }
   341  
   342  func (f *fakePathBuilder) ExtractAdditionalFn(param []*ast.Argument) interface{} {
   343  	return nil
   344  }
   345  
   346  func (f *fakePathBuilder) AdditionalPropertyDefaultValue() interface{} {
   347  	return &pathBuilderParams{}
   348  }
   349  
   350  type fakeText2vecContextionaryModule struct {
   351  	customExtender       *fakeExtender
   352  	customProjector      *fakeProjector
   353  	customPathBuilder    *fakePathBuilder
   354  	customInterpretation *fakeInterpretation
   355  }
   356  
   357  func newFakeText2vecContextionaryModuleWithCustomExtender(
   358  	customExtender *fakeExtender,
   359  	customProjector *fakeProjector,
   360  	customPathBuilder *fakePathBuilder,
   361  ) *fakeText2vecContextionaryModule {
   362  	return &fakeText2vecContextionaryModule{customExtender, customProjector, customPathBuilder, &fakeInterpretation{}}
   363  }
   364  
   365  func (m *fakeText2vecContextionaryModule) Name() string {
   366  	return "text2vec-contextionary"
   367  }
   368  
   369  func (m *fakeText2vecContextionaryModule) Init(params moduletools.ModuleInitParams) error {
   370  	return nil
   371  }
   372  
   373  func (m *fakeText2vecContextionaryModule) RootHandler() http.Handler {
   374  	return nil
   375  }
   376  
   377  func (m *fakeText2vecContextionaryModule) Arguments() map[string]modulecapabilities.GraphQLArgument {
   378  	return newNearCustomTextModule(m.getExtender(), m.getProjector(), m.getPathBuilder(), m.getInterpretation()).Arguments()
   379  }
   380  
   381  func (m *fakeText2vecContextionaryModule) VectorSearches() map[string]modulecapabilities.VectorForParams {
   382  	searcher := &fakeSearcher{&fakeTxt2VecVectorizer{}}
   383  	return searcher.VectorSearches()
   384  }
   385  
   386  func (m *fakeText2vecContextionaryModule) AdditionalProperties() map[string]modulecapabilities.AdditionalProperty {
   387  	return newNearCustomTextModule(m.getExtender(), m.getProjector(), m.getPathBuilder(), m.getInterpretation()).AdditionalProperties()
   388  }
   389  
   390  func (m *fakeText2vecContextionaryModule) getExtender() *fakeExtender {
   391  	if m.customExtender != nil {
   392  		return m.customExtender
   393  	}
   394  	return &fakeExtender{}
   395  }
   396  
   397  func (m *fakeText2vecContextionaryModule) getProjector() *fakeProjector {
   398  	if m.customProjector != nil {
   399  		return m.customProjector
   400  	}
   401  	return &fakeProjector{}
   402  }
   403  
   404  func (m *fakeText2vecContextionaryModule) getPathBuilder() *fakePathBuilder {
   405  	if m.customPathBuilder != nil {
   406  		return m.customPathBuilder
   407  	}
   408  	return &fakePathBuilder{}
   409  }
   410  
   411  func (m *fakeText2vecContextionaryModule) getInterpretation() *fakeInterpretation {
   412  	if m.customInterpretation != nil {
   413  		return m.customInterpretation
   414  	}
   415  	return &fakeInterpretation{}
   416  }
   417  
   418  type nearCustomTextParams struct {
   419  	Values        []string
   420  	MoveTo        nearExploreMove
   421  	MoveAwayFrom  nearExploreMove
   422  	Certainty     float64
   423  	Distance      float64
   424  	WithDistance  bool
   425  	TargetVectors []string
   426  }
   427  
   428  func (p nearCustomTextParams) GetCertainty() float64 {
   429  	return p.Certainty
   430  }
   431  
   432  func (p nearCustomTextParams) GetDistance() float64 {
   433  	return p.Distance
   434  }
   435  
   436  func (p nearCustomTextParams) SimilarityMetricProvided() bool {
   437  	return p.Certainty != 0 || p.WithDistance
   438  }
   439  
   440  func (p nearCustomTextParams) GetTargetVectors() []string {
   441  	return p.TargetVectors
   442  }
   443  
   444  type nearExploreMove struct {
   445  	Values  []string
   446  	Force   float32
   447  	Objects []nearObjectMove
   448  }
   449  
   450  type nearObjectMove struct {
   451  	ID     string
   452  	Beacon string
   453  }
   454  
   455  type nearCustomTextModule struct {
   456  	fakeExtender       *fakeExtender
   457  	fakeProjector      *fakeProjector
   458  	fakePathBuilder    *fakePathBuilder
   459  	fakeInterpretation *fakeInterpretation
   460  }
   461  
   462  func newNearCustomTextModule(
   463  	fakeExtender *fakeExtender,
   464  	fakeProjector *fakeProjector,
   465  	fakePathBuilder *fakePathBuilder,
   466  	fakeInterpretation *fakeInterpretation,
   467  ) *nearCustomTextModule {
   468  	return &nearCustomTextModule{fakeExtender, fakeProjector, fakePathBuilder, fakeInterpretation}
   469  }
   470  
   471  func (m *nearCustomTextModule) Name() string {
   472  	return "mock-custom-near-text-module"
   473  }
   474  
   475  func (m *nearCustomTextModule) Init(params moduletools.ModuleInitParams) error {
   476  	return nil
   477  }
   478  
   479  func (m *nearCustomTextModule) RootHandler() http.Handler {
   480  	return nil
   481  }
   482  
   483  func (m *nearCustomTextModule) getNearCustomTextArgument(classname string) *graphql.ArgumentConfig {
   484  	prefix := classname
   485  	return &graphql.ArgumentConfig{
   486  		Type: graphql.NewInputObject(
   487  			graphql.InputObjectConfig{
   488  				Name: fmt.Sprintf("%sNearCustomTextInpObj", prefix),
   489  				Fields: graphql.InputObjectConfigFieldMap{
   490  					"concepts": &graphql.InputObjectFieldConfig{
   491  						Type: graphql.NewNonNull(graphql.NewList(graphql.String)),
   492  					},
   493  					"moveTo": &graphql.InputObjectFieldConfig{
   494  						Description: descriptions.VectorMovement,
   495  						Type: graphql.NewInputObject(
   496  							graphql.InputObjectConfig{
   497  								Name: fmt.Sprintf("%sMoveTo", prefix),
   498  								Fields: graphql.InputObjectConfigFieldMap{
   499  									"concepts": &graphql.InputObjectFieldConfig{
   500  										Description: descriptions.Keywords,
   501  										Type:        graphql.NewList(graphql.String),
   502  									},
   503  									"objects": &graphql.InputObjectFieldConfig{
   504  										Description: "objects",
   505  										Type: graphql.NewList(graphql.NewInputObject(
   506  											graphql.InputObjectConfig{
   507  												Name: fmt.Sprintf("%sMovementObjectsToInpObj", prefix),
   508  												Fields: graphql.InputObjectConfigFieldMap{
   509  													"id": &graphql.InputObjectFieldConfig{
   510  														Type:        graphql.String,
   511  														Description: "id of an object",
   512  													},
   513  													"beacon": &graphql.InputObjectFieldConfig{
   514  														Type:        graphql.String,
   515  														Description: descriptions.Beacon,
   516  													},
   517  												},
   518  												Description: "Movement Object",
   519  											},
   520  										)),
   521  									},
   522  									"force": &graphql.InputObjectFieldConfig{
   523  										Description: descriptions.Force,
   524  										Type:        graphql.NewNonNull(graphql.Float),
   525  									},
   526  								},
   527  							}),
   528  					},
   529  					"moveAwayFrom": &graphql.InputObjectFieldConfig{
   530  						Description: descriptions.VectorMovement,
   531  						Type: graphql.NewInputObject(
   532  							graphql.InputObjectConfig{
   533  								Name: fmt.Sprintf("%sMoveAway", prefix),
   534  								Fields: graphql.InputObjectConfigFieldMap{
   535  									"concepts": &graphql.InputObjectFieldConfig{
   536  										Description: descriptions.Keywords,
   537  										Type:        graphql.NewList(graphql.String),
   538  									},
   539  									"objects": &graphql.InputObjectFieldConfig{
   540  										Description: "objects",
   541  										Type: graphql.NewList(graphql.NewInputObject(
   542  											graphql.InputObjectConfig{
   543  												Name: fmt.Sprintf("%sMovementObjectsAwayInpObj", prefix),
   544  												Fields: graphql.InputObjectConfigFieldMap{
   545  													"id": &graphql.InputObjectFieldConfig{
   546  														Type:        graphql.String,
   547  														Description: "id of an object",
   548  													},
   549  													"beacon": &graphql.InputObjectFieldConfig{
   550  														Type:        graphql.String,
   551  														Description: descriptions.Beacon,
   552  													},
   553  												},
   554  												Description: "Movement Object",
   555  											},
   556  										)),
   557  									},
   558  									"force": &graphql.InputObjectFieldConfig{
   559  										Description: descriptions.Force,
   560  										Type:        graphql.NewNonNull(graphql.Float),
   561  									},
   562  								},
   563  							}),
   564  					},
   565  					"certainty": &graphql.InputObjectFieldConfig{
   566  						Description: descriptions.Certainty,
   567  						Type:        graphql.Float,
   568  					},
   569  					"distance": &graphql.InputObjectFieldConfig{
   570  						Description: descriptions.Distance,
   571  						Type:        graphql.Float,
   572  					},
   573  				},
   574  				Description: descriptions.GetWhereInpObj,
   575  			},
   576  		),
   577  	}
   578  }
   579  
   580  func (m *nearCustomTextModule) extractNearCustomTextArgument(source map[string]interface{}) *nearCustomTextParams {
   581  	var args nearCustomTextParams
   582  
   583  	concepts := source["concepts"].([]interface{})
   584  	args.Values = make([]string, len(concepts))
   585  	for i, value := range concepts {
   586  		args.Values[i] = value.(string)
   587  	}
   588  
   589  	certainty, ok := source["certainty"]
   590  	if ok {
   591  		args.Certainty = certainty.(float64)
   592  	}
   593  
   594  	distance, ok := source["distance"]
   595  	if ok {
   596  		args.Distance = distance.(float64)
   597  		args.WithDistance = true
   598  	}
   599  
   600  	// moveTo is an optional arg, so it could be nil
   601  	moveTo, ok := source["moveTo"]
   602  	if ok {
   603  		moveToMap := moveTo.(map[string]interface{})
   604  		args.MoveTo = m.parseMoveParam(moveToMap)
   605  	}
   606  
   607  	moveAwayFrom, ok := source["moveAwayFrom"]
   608  	if ok {
   609  		moveAwayFromMap := moveAwayFrom.(map[string]interface{})
   610  		args.MoveAwayFrom = m.parseMoveParam(moveAwayFromMap)
   611  	}
   612  
   613  	return &args
   614  }
   615  
   616  func (m *nearCustomTextModule) parseMoveParam(source map[string]interface{}) nearExploreMove {
   617  	res := nearExploreMove{}
   618  	res.Force = float32(source["force"].(float64))
   619  
   620  	concepts, ok := source["concepts"].([]interface{})
   621  	if ok {
   622  		res.Values = make([]string, len(concepts))
   623  		for i, value := range concepts {
   624  			res.Values[i] = value.(string)
   625  		}
   626  	}
   627  
   628  	objects, ok := source["objects"].([]interface{})
   629  	if ok {
   630  		res.Objects = make([]nearObjectMove, len(objects))
   631  		for i, value := range objects {
   632  			v, ok := value.(map[string]interface{})
   633  			if ok {
   634  				if v["id"] != nil {
   635  					res.Objects[i].ID = v["id"].(string)
   636  				}
   637  				if v["beacon"] != nil {
   638  					res.Objects[i].Beacon = v["beacon"].(string)
   639  				}
   640  			}
   641  		}
   642  	}
   643  
   644  	return res
   645  }
   646  
   647  func (m *nearCustomTextModule) Arguments() map[string]modulecapabilities.GraphQLArgument {
   648  	arguments := map[string]modulecapabilities.GraphQLArgument{}
   649  	// define nearCustomText argument
   650  	arguments["nearCustomText"] = modulecapabilities.GraphQLArgument{
   651  		GetArgumentsFunction: func(classname string) *graphql.ArgumentConfig {
   652  			return m.getNearCustomTextArgument(classname)
   653  		},
   654  		ExploreArgumentsFunction: func() *graphql.ArgumentConfig {
   655  			return m.getNearCustomTextArgument("")
   656  		},
   657  		ExtractFunction: func(source map[string]interface{}) interface{} {
   658  			return m.extractNearCustomTextArgument(source)
   659  		},
   660  		ValidateFunction: func(param interface{}) error {
   661  			nearText, ok := param.(*nearCustomTextParams)
   662  			if !ok {
   663  				return errors.New("'nearCustomText' invalid parameter")
   664  			}
   665  
   666  			if nearText.MoveTo.Force > 0 &&
   667  				nearText.MoveTo.Values == nil && nearText.MoveTo.Objects == nil {
   668  				return errors.Errorf("'nearCustomText.moveTo' parameter " +
   669  					"needs to have defined either 'concepts' or 'objects' fields")
   670  			}
   671  
   672  			if nearText.MoveAwayFrom.Force > 0 &&
   673  				nearText.MoveAwayFrom.Values == nil && nearText.MoveAwayFrom.Objects == nil {
   674  				return errors.Errorf("'nearCustomText.moveAwayFrom' parameter " +
   675  					"needs to have defined either 'concepts' or 'objects' fields")
   676  			}
   677  
   678  			if nearText.Certainty != 0 && nearText.WithDistance {
   679  				return errors.Errorf(
   680  					"nearText cannot provide both distance and certainty")
   681  			}
   682  
   683  			return nil
   684  		},
   685  	}
   686  	return arguments
   687  }
   688  
   689  // additional properties
   690  func (m *nearCustomTextModule) AdditionalProperties() map[string]modulecapabilities.AdditionalProperty {
   691  	additionalProperties := map[string]modulecapabilities.AdditionalProperty{}
   692  	additionalProperties["featureProjection"] = m.getFeatureProjection()
   693  	additionalProperties["nearestNeighbors"] = m.getNearestNeighbors()
   694  	additionalProperties["semanticPath"] = m.getSemanticPath()
   695  	additionalProperties["interpretation"] = m.getInterpretation()
   696  	return additionalProperties
   697  }
   698  
   699  func (m *nearCustomTextModule) getFeatureProjection() modulecapabilities.AdditionalProperty {
   700  	return modulecapabilities.AdditionalProperty{
   701  		DefaultValue: m.fakeProjector.AdditionalPropertyDefaultValue(),
   702  		GraphQLNames: []string{"featureProjection"},
   703  		GraphQLFieldFunction: func(classname string) *graphql.Field {
   704  			return &graphql.Field{
   705  				Args: graphql.FieldConfigArgument{
   706  					"algorithm": &graphql.ArgumentConfig{
   707  						Type:         graphql.String,
   708  						DefaultValue: nil,
   709  					},
   710  					"dimensions": &graphql.ArgumentConfig{
   711  						Type:         graphql.Int,
   712  						DefaultValue: nil,
   713  					},
   714  					"learningRate": &graphql.ArgumentConfig{
   715  						Type:         graphql.Int,
   716  						DefaultValue: nil,
   717  					},
   718  					"iterations": &graphql.ArgumentConfig{
   719  						Type:         graphql.Int,
   720  						DefaultValue: nil,
   721  					},
   722  					"perplexity": &graphql.ArgumentConfig{
   723  						Type:         graphql.Int,
   724  						DefaultValue: nil,
   725  					},
   726  				},
   727  				Type: graphql.NewObject(graphql.ObjectConfig{
   728  					Name: fmt.Sprintf("%sAdditionalFeatureProjection", classname),
   729  					Fields: graphql.Fields{
   730  						"vector": &graphql.Field{Type: graphql.NewList(graphql.Float)},
   731  					},
   732  				}),
   733  			}
   734  		},
   735  		GraphQLExtractFunction: m.fakeProjector.ExtractAdditionalFn,
   736  		SearchFunctions: modulecapabilities.AdditionalSearch{
   737  			ObjectList:  m.fakeProjector.AdditionalPropertyFn,
   738  			ExploreGet:  m.fakeProjector.AdditionalPropertyFn,
   739  			ExploreList: m.fakeProjector.AdditionalPropertyFn,
   740  		},
   741  	}
   742  }
   743  
   744  func (m *nearCustomTextModule) getNearestNeighbors() modulecapabilities.AdditionalProperty {
   745  	return modulecapabilities.AdditionalProperty{
   746  		DefaultValue: m.fakeExtender.AdditionalPropertyDefaultValue(),
   747  		GraphQLNames: []string{"nearestNeighbors"},
   748  		GraphQLFieldFunction: func(classname string) *graphql.Field {
   749  			return &graphql.Field{
   750  				Type: graphql.NewObject(graphql.ObjectConfig{
   751  					Name: fmt.Sprintf("%sAdditionalNearestNeighbors", classname),
   752  					Fields: graphql.Fields{
   753  						"neighbors": &graphql.Field{Type: graphql.NewList(graphql.NewObject(graphql.ObjectConfig{
   754  							Name: fmt.Sprintf("%sAdditionalNearestNeighborsNeighbors", classname),
   755  							Fields: graphql.Fields{
   756  								"concept":  &graphql.Field{Type: graphql.String},
   757  								"distance": &graphql.Field{Type: graphql.Float},
   758  							},
   759  						}))},
   760  					},
   761  				}),
   762  			}
   763  		},
   764  		GraphQLExtractFunction: m.fakeExtender.ExtractAdditionalFn,
   765  		SearchFunctions: modulecapabilities.AdditionalSearch{
   766  			ObjectGet:   m.fakeExtender.AdditionalPropertyFn,
   767  			ObjectList:  m.fakeExtender.AdditionalPropertyFn,
   768  			ExploreGet:  m.fakeExtender.AdditionalPropertyFn,
   769  			ExploreList: m.fakeExtender.AdditionalPropertyFn,
   770  		},
   771  	}
   772  }
   773  
   774  func (m *nearCustomTextModule) getSemanticPath() modulecapabilities.AdditionalProperty {
   775  	return modulecapabilities.AdditionalProperty{
   776  		DefaultValue: m.fakePathBuilder.AdditionalPropertyDefaultValue(),
   777  		GraphQLNames: []string{"semanticPath"},
   778  		GraphQLFieldFunction: func(classname string) *graphql.Field {
   779  			return &graphql.Field{
   780  				Type: graphql.NewObject(graphql.ObjectConfig{
   781  					Name: fmt.Sprintf("%sAdditionalSemanticPath", classname),
   782  					Fields: graphql.Fields{
   783  						"path": &graphql.Field{Type: graphql.NewList(graphql.NewObject(graphql.ObjectConfig{
   784  							Name: fmt.Sprintf("%sAdditionalSemanticPathElement", classname),
   785  							Fields: graphql.Fields{
   786  								"concept":            &graphql.Field{Type: graphql.String},
   787  								"distanceToQuery":    &graphql.Field{Type: graphql.Float},
   788  								"distanceToResult":   &graphql.Field{Type: graphql.Float},
   789  								"distanceToNext":     &graphql.Field{Type: graphql.Float},
   790  								"distanceToPrevious": &graphql.Field{Type: graphql.Float},
   791  							},
   792  						}))},
   793  					},
   794  				}),
   795  			}
   796  		},
   797  		GraphQLExtractFunction: m.fakePathBuilder.ExtractAdditionalFn,
   798  		SearchFunctions: modulecapabilities.AdditionalSearch{
   799  			ExploreGet: m.fakePathBuilder.AdditionalPropertyFn,
   800  		},
   801  	}
   802  }
   803  
   804  func (m *nearCustomTextModule) getInterpretation() modulecapabilities.AdditionalProperty {
   805  	return modulecapabilities.AdditionalProperty{
   806  		DefaultValue: m.fakeInterpretation.AdditionalPropertyDefaultValue(),
   807  		GraphQLNames: []string{"interpretation"},
   808  		GraphQLFieldFunction: func(classname string) *graphql.Field {
   809  			return &graphql.Field{
   810  				Type: graphql.NewObject(graphql.ObjectConfig{
   811  					Name: fmt.Sprintf("%sAdditionalInterpretation", classname),
   812  					Fields: graphql.Fields{
   813  						"source": &graphql.Field{Type: graphql.NewList(graphql.NewObject(graphql.ObjectConfig{
   814  							Name: fmt.Sprintf("%sAdditionalInterpretationSource", classname),
   815  							Fields: graphql.Fields{
   816  								"concept":    &graphql.Field{Type: graphql.String},
   817  								"weight":     &graphql.Field{Type: graphql.Float},
   818  								"occurrence": &graphql.Field{Type: graphql.Int},
   819  							},
   820  						}))},
   821  					},
   822  				}),
   823  			}
   824  		},
   825  		GraphQLExtractFunction: m.fakeInterpretation.ExtractAdditionalFn,
   826  		SearchFunctions: modulecapabilities.AdditionalSearch{
   827  			ObjectGet:   m.fakeInterpretation.AdditionalPropertyFn,
   828  			ObjectList:  m.fakeInterpretation.AdditionalPropertyFn,
   829  			ExploreGet:  m.fakeInterpretation.AdditionalPropertyFn,
   830  			ExploreList: m.fakeInterpretation.AdditionalPropertyFn,
   831  		},
   832  	}
   833  }
   834  
   835  func (m *nearCustomTextModule) VectorSearches() map[string]modulecapabilities.VectorForParams {
   836  	vectorSearches := map[string]modulecapabilities.VectorForParams{}
   837  	return vectorSearches
   838  }
   839  
   840  type fakeSearcher struct {
   841  	vectorizer *fakeTxt2VecVectorizer
   842  }
   843  
   844  func (s *fakeSearcher) VectorSearches() map[string]modulecapabilities.VectorForParams {
   845  	vectorSearches := map[string]modulecapabilities.VectorForParams{}
   846  	vectorSearches["nearCustomText"] = s.vectorForNearTextParam
   847  	return vectorSearches
   848  }
   849  
   850  func (s *fakeSearcher) vectorForNearTextParam(ctx context.Context, params interface{},
   851  	className string, findVectorFn modulecapabilities.FindVectorFn, cfg moduletools.ClassConfig,
   852  ) ([]float32, error) {
   853  	vector, err := s.vectorizer.Corpi(ctx, nil)
   854  	if err != nil {
   855  		return nil, err
   856  	}
   857  
   858  	p, ok := params.(*nearCustomTextParams)
   859  	if ok && p.MoveTo.Force > 0 {
   860  		afterMoveTo, err := s.vectorizer.MoveTo(vector, nil, 0)
   861  		if err != nil {
   862  			return nil, err
   863  		}
   864  		vector = afterMoveTo
   865  	}
   866  	if ok && p.MoveAwayFrom.Force > 0 {
   867  		afterMoveAway, err := s.vectorizer.MoveAwayFrom(vector, nil, 0)
   868  		if err != nil {
   869  			return nil, err
   870  		}
   871  		vector = afterMoveAway
   872  	}
   873  	return vector, nil
   874  }
   875  
   876  type fakeMetrics struct {
   877  	mock.Mock
   878  }
   879  
   880  func (m *fakeMetrics) AddUsageDimensions(class, query, op string, dims int) {
   881  	m.Called(class, query, op, dims)
   882  }