image search test
This commit is contained in:
@@ -501,3 +501,55 @@ func TestConfirmReportsDistanceToTheChosenStore(t *testing.T) {
|
||||
t.Fatalf("no position at all is -1; got %v", resp.Store)
|
||||
}
|
||||
}
|
||||
|
||||
var parleG = repositories.CatalogueHit{Brand: "parle", ID: 1, ProductName: "Parle-G Original Glucose Biscuits 250g", Title: "Parle-G", VariantKey: "parle_g", ImageID: "parle_parle_g_250g", Distance: 0.20}
|
||||
var monaco = repositories.CatalogueHit{Brand: "parle", ID: 2, ProductName: "Parle Monaco Classic Regular 200g", Title: "Monaco", VariantKey: "monaco", ImageID: "parle_monaco_200g", Distance: 0.20}
|
||||
|
||||
// Lens reads "Parle-G" off the packet and the customer types "Parle G". Both
|
||||
// spellings, and the run-together one, have to reach the biscuit — not the
|
||||
// salted cracker that merely shares a brand. In production "Parle G" returned
|
||||
// "Parle Monaco Classic Regular 200g" at a confident 0.9.
|
||||
func TestLookupMatchesAHyphenatedNameHoweverItIsWritten(t *testing.T) {
|
||||
for _, label := range []string{"Parle G", "Parle-G", "ParleG", "parle g"} {
|
||||
repo := newLookupFixture()
|
||||
repo.vector = []repositories.CatalogueHit{monaco, parleG} // model puts the cracker first
|
||||
repo.text = []repositories.CatalogueHit{monaco, parleG}
|
||||
svc := NewScanService(repo, fakeEmbedder{vec: []float32{0.1}})
|
||||
|
||||
resp, err := svc.Lookup(context.Background(), models.ScanLookupRequest{Customerid: 5, Label: label})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.Match == nil {
|
||||
t.Fatalf("%q: a stocked product went unrecognised", label)
|
||||
}
|
||||
if resp.Match.Catalogueid != parleG.ID {
|
||||
t.Fatalf("%q: matched %q (%.3f), want Parle-G", label, resp.Match.ProductName, resp.Match.Score)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Equal blended scores used to be settled by product name, which let ASCII
|
||||
// decide relevance: a space sorts before a hyphen, so "Parle Monaco …" beat
|
||||
// "Parle-G …". The model's own similarity settles it instead.
|
||||
func TestSortHitsBreaksTiesOnSimilarityNotPunctuation(t *testing.T) {
|
||||
near := parleG
|
||||
near.Distance = 0.10 // the model is surer about this one
|
||||
far := monaco
|
||||
far.Distance = 0.40
|
||||
|
||||
hits := []scoredHit{{CatalogueHit: far, score: 0.9}, {CatalogueHit: near, score: 0.9}}
|
||||
sortHits(hits)
|
||||
if hits[0].ID != near.ID {
|
||||
t.Fatalf("the nearer vector should win a tie, got %q", hits[0].ProductName)
|
||||
}
|
||||
|
||||
// A row the model never scored (-1, text-only) ranks behind one it did.
|
||||
textOnly := parleG
|
||||
textOnly.Distance = -1
|
||||
hits = []scoredHit{{CatalogueHit: textOnly, score: 0.9}, {CatalogueHit: far, score: 0.9}}
|
||||
sortHits(hits)
|
||||
if hits[0].ID != far.ID {
|
||||
t.Fatalf("a scored row outranks an unscored one, got %q", hits[0].ProductName)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user