Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add QueryWithNegative #80

Merged
merged 5 commits into from
Jun 26, 2024

Conversation

erikdubbelboer
Copy link
Contributor

QueryWithNegative allows you to pass a string that will be excluded from the search results.

There are tree ways to implement this:

  1. Find the document matching the normal query. Then re-order the result by multiplying the similarity by the dot product with the negative vector and some constant.
  2. Find the document matching the normal query. Exclude documents where the dot product with the negative vector are above a constant.
  3. The simpler method I implemented which just subtracts the negative vector from the positive one and re-normalizes the result.

I have done some simple tests and the results look good.

I'm not sure if the extra function is a nice API. It could also be added as extra argument to Query. Or maybe Query should get a struct for it's argument as the number of arguments seems to keep increasing.

@philippgille
Copy link
Owner

philippgille commented May 21, 2024

That's an interesting feature!

  1. The simpler method I implemented which just subtracts the negative vector from the positive one and re-normalizes the result.

I have done some simple tests and the results look good.

Did you test with positive and negative queries that were similar (e.g. a use case where a result is likely to appear but you want to exclude), as well also where they were entirely different (e.g. for use cases where some result is already unlikely, but you want to be even more certain to exclude it)?

I'm worried that the resulting vector C=A-B might be too different from A in some cases. E.g.

image

What about implementing all three and letting the user choose between them?

I'm not sure if the extra function is a nice API. It could also be added as extra argument to Query. Or maybe Query should get a struct for it's argument as the number of arguments seems to keep increasing.

WDYT about keeping the Query for now (for backward compatibility and catering to simple / most common use cases), but introducing a QueryWithOptions that already takes a struct as parameter with the where, whereDocument and negativeQuery fields?

Related to above proposal with three implementations, one field could also be an enum for picking the way to exclude the negative query.


Maybe this PR could just introduce the QueryWithOptions and the enum with two values (unspecified, which validates to an error, and the substract exclusion), and follow-up PRs can introduce the other two ways?

@erikdubbelboer
Copy link
Contributor Author

I rewrote it to QueryWithOptions. Can you please have a look.

@erikdubbelboer erikdubbelboer force-pushed the QueryWithNegative branch 2 times, most recently from bb1407b to 7529c5d Compare May 26, 2024 07:40
Copy link
Owner

@philippgille philippgille left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the rewrite, plus adding the other two modes! 👍

Please consider my new comments more as questions for now, not yet as requests for change.

Regarding the reorder mode, if we don't find a good solution, one option can be to exclude that mode for now, and add it in a follow-up PR. That way users can already benefit from the simpler modes and it gives more time to discuss the reorder.

collection.go Outdated Show resolved Hide resolved
collection.go Outdated Show resolved Hide resolved
collection.go Outdated Show resolved Hide resolved
query_test.go Outdated Show resolved Hide resolved
collection.go Outdated Show resolved Hide resolved
@erikdubbelboer
Copy link
Contributor Author

I'm not using this feature in production yet. I'm still playing around with it, trying to improve it. Since embedding models can't encode something being negative, I'm currently using a fast model like Phi3 to split a search query users write into a positive and a negative part (see below). And then passing these parts to my index in chromem to find the results.

Break down the following search query in it's positive and negative parts. For example for
```
football not manager
```
you should return:
```
positive: football
negative: manager
```

Or another example, for:
```
village builder but not idle
```
you should return:
```
positive: village builder
negative: idle
```

Here is the query:
```
...
```

@philippgille
Copy link
Owner

Thank you for the changes/improvements! I should be able to review again before the end of the week.

Copy link
Owner

@philippgille philippgille left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving already. One comment is just a nitpick, and the other more a question, but I think I answered it already by running with different Ollama versions and getting different embeddings with each. You can address the comments if you have time, but otherwise no need and I'll merge next week.

collection.go Outdated Show resolved Hide resolved
fixtures_test.go Outdated
//
// fmt.Printf("%#v\n", testEmbeddings)
var testEmbeddings = map[string][]float32{
"search_document: Some Idle Game": {-0.0060760463, 0.034463942, -0.1387902, -0.01880036, 0.050515246, -0.0014757602, -0.023416985, -0.06163054, 0.025443453, 0.035569035, -0.03652287, -0.041155443, 0.015422994, 0.030235684, -0.0006920832, -0.055480313, -0.025413116, -0.030041033, 0.005120441, 0.016109098, 0.009329011, -0.0046394765, 0.013397162, -0.028488798, 0.037383143, 0.030361928, 0.0080388775, -0.046438914, -0.0071862284, 0.021990616, -0.060048018, -0.017467165, 0.07508827, -0.0013899342, 0.0016108179, -0.034226466, 0.03487904, 0.020598384, 0.040956654, 0.0027402623, -0.06460306, 0.047813166, 0.040316027, 0.035767395, 0.062046513, 0.016225044, 0.07777814, 0.07436007, 0.0010243986, -0.051667936, 0.023401909, -0.021025056, -0.01842488, -0.010212666, 0.007964244, 0.012940527, -0.005432107, 0.002917191, 0.013313262, -0.024190128, 0.01791604, 0.030846233, -0.0028429348, 0.042119455, 0.030468708, -0.045345176, -0.053462967, 0.007938011, 0.014024244, -0.03306285, 0.07962807, -0.016527858, -0.0013264868, 0.035366584, -0.022880074, -0.0045876186, -0.018306475, -0.013543297, 0.011919335, 0.0053336383, 0.011997243, -0.027264599, 0.06429813, 0.00266995, 0.08360438, -0.011504622, -0.052844565, -0.03591852, -0.030937092, 0.046289653, 0.029745601, 0.029248875, 0.04981176, 0.03016179, -0.06912066, 0.008791399, -0.029370002, -0.021201164, -0.040902793, -0.007160467, -0.03857601, -0.01702487, 0.051262982, -0.016211446, 0.07277702, 0.020603213, -0.05730489, -0.02332207, -0.022892129, 0.022575237, -0.0035119157, 0.054837994, -0.03218431, -0.021743948, 0.04216454, -0.0040691006, 0.083487205, 0.00038044903, 0.05258523, 0.055608504, -0.05096133, 0.04049317, -0.03324778, 0.035970695, 0.00019802092, -0.00022452897, -0.061869413, -0.015183144, 0.00016958747, -0.034726527, 0.029137151, -0.009906886, 0.03408785, -0.036178514, -0.02343292, 0.007823052, -0.093677655, -0.019243201, 0.06423939, -0.0021586656, 0.04809902, -0.08922962, -0.032001063, -0.012665633, 0.011560508, -0.043267842, 0.06001132, -0.062908895, -0.0038666173, -0.0033354622, 0.08371677, -0.012481466, 0.0008695344, -0.014768936, 0.039830826, -0.025028884, -0.05301726, 0.044927694, 0.005219821, -0.009900213, 0.0054140203, 0.023347214, -0.016090378, 0.044550452, -0.051075865, -0.025095524, -0.012297865, 0.029875154, 0.0222, -0.0058385707, -0.030563785, -0.0492457, 0.0042215837, 0.018291129, 0.06388193, 0.00901064, 0.097726315, -0.018828226, -0.010788638, -0.02387454, 0.0049764886, -0.014185669, 0.024190444, 0.00076448964, -0.024025504, -0.032507364, 0.081796415, -0.04403507, -0.029089598, 0.032030355, -0.019284742, 0.042974424, -0.006428326, -0.06446968, -0.0083833765, -0.032340713, 0.04722018, 0.046674285, 0.029749017, -0.05904713, -0.0018536821, -0.00025856224, -0.048942495, -0.017716412, -0.050341416, 0.040434062, -0.025483884, 0.021155149, -0.0136171905, 0.016699295, 0.06115873, 0.01275245, 0.010869778, 0.048479572, -0.0073152105, -0.02517437, -0.017701723, -0.01897822, -0.046055626, -0.018433034, 0.026886806, -0.012570846, -0.032101616, 0.009029427, 0.030772975, 0.015185716, -0.01784295, 0.05024066, -0.020696176, 0.03323633, -0.07057012, -0.09416582, 0.004350026, 0.0029397511, -0.025360627, -0.03816513, 0.0134742595, 0.09945575, 0.009843686, 0.019633522, 0.032418653, 0.0058328537, 0.029372053, -0.0029168923, -0.026235241, 0.019785464, -0.008126373, -0.04485804, 0.017756335, 0.01266649, -0.005916582, 0.009565844, 0.008608036, 0.053572405, -0.0022154502, -0.05914659, -0.015717434, 0.0050121965, 0.01086173, 0.012687361, 0.015670855, -0.045014888, 0.015066507, 0.00083025725, 0.011981217, -0.0324745, 0.026975399, -0.007345545, -0.030034268, -0.033238146, -0.072009556, -0.000638019, -0.041544903, 0.08075278, 0.0034031223, 0.02205926, 0.07446248, 0.01206271, 0.011793334, 0.021024115, 0.07939036, 0.0005655304, -0.04416273, 0.04733273, -0.0076252804, 0.01226603, 0.051349293, 0.00758653, -0.02025951, 0.0045099007, 0.005301482, -0.037059218, 0.009954591, 0.058889184, -0.01333225, 0.008794124, 0.01069274, -0.023669396, 0.0020664262, -0.045605805, -0.014060756, -0.014411602, 0.024560727, -0.00040147497, 0.062196497, -0.04922842, 0.03235299, -0.021694593, 0.019760333, 0.0023729233, -0.018878555, 0.02540936, -0.058375653, 0.06666951, -0.115034506, 0.07229192, -0.00072064274, 0.011708216, 0.020418538, -0.07669502, -0.031085705, -0.07195875, 0.03457435, -0.054948594, 0.021925226, 0.035557956, 0.05349583, -0.001034031, -0.0119233895, -0.057474744, -0.030577473, 0.032676727, -0.041095078, -0.014470331, -0.029771464, 0.023018358, 0.009091008, 0.019948045, -0.007921955, 0.016265664, 0.11836824, 0.0059667476, 0.009203025, -0.0046974653, -0.040411886, -0.020109894, 0.034951095, -0.030297315, 0.042659804, -0.019298302, 0.0034718113, -0.003556284, -0.022271687, 0.006395739, -0.015675915, -0.007846095, 0.00795862, -0.027382236, -0.013844011, 0.0067343186, 0.054027174, -0.013439075, -0.014695834, -0.04422655, 0.034129046, -0.026477411, 0.021682227, 0.030877832, -0.0074587027, -0.065585785, -0.0056468137, 0.018568536, 0.0063470807, 0.05095122, 0.038096607, 0.011253013, -0.07323222, 0.0072816135, -0.04996467, -0.005978087, 0.0443823, 0.024452059, 0.015773043, 0.032073732, 0.043041192, 0.010821024, -0.0031784582, 0.018992368, -0.004622888, 0.02014122, 0.00090508745, 0.025787236, -0.034013025, 0.015910035, -0.03268243, -0.026667148, 0.011168157, 0.030017823, 0.06854734, 0.028639382, 0.03080465, -0.026005648, 0.021279184, 0.0040799296, 0.016169557, 0.084184244, 0.01835841, -0.086466275, 0.0062229326, 0.015730636, -0.017927561, 0.023729656, -0.007282824, -0.008143011, -0.067766935, 0.035523567, 0.051593352, -0.019791922, -0.042587396, 0.06690624, 0.037767086, 0.008553358, -0.02938364, 0.038429726, -0.05053369, 0.033714093, 0.021192344, 0.07818021, -0.031022195, -0.07000928, -0.008958548, -0.024999667, 0.015705856, -0.027052531, -0.019134501, -0.04823093, 0.036368877, 0.02270509, 0.006880777, -0.013192124, 0.011860808, -0.014828852, 0.036245905, -0.02167447, 0.011465996, 0.13057837, 0.033250883, -0.0052989377, -0.013103826, -0.011665669, -0.029358167, 0.005983672, -0.04180638, 0.04029639, 0.045633983, -0.031386018, -0.03344101, 0.01934598, -0.009360906, 0.016800778, -0.009866494, 0.014215708, 0.019586826, -0.0069144587, -0.02837358, 0.0017182492, 0.052333336, -0.008981637, -0.009652344, 0.069439165, 0.004201992, 0.02904076, 0.018445836, -0.023353977, -0.019793965, -0.024139842, -0.034132652, 0.0011112315, 0.03572409, -0.009347155, -0.009739798, -0.015563562, -0.036546007, -0.021100484, 0.0010935924, -0.032232955, 0.05411164, 0.0026985048, 0.02943063, -0.029635444, 0.008110762, 0.024208656, 0.051097464, 0.025854284, -0.02744184, -0.06443368, -0.035319656, 0.046716347, 0.01020662, -0.038059115, 0.036957625, 0.021595465, -0.011965477, -0.016022926, 0.06356263, -0.034048714, -0.04667903, -0.07695168, -0.06236455, 0.018222928, -0.022491459, -0.027979556, -0.029401047, 0.033322394, 0.0012425089, 0.02387208, 0.012767657, -0.0152108, -0.0036661788, 0.010917645, 0.025263872, -0.034260664, -0.058003973, 0.011705901, -0.040191926, -0.009736485, 0.011073551, -0.02634881, 0.06709649, -0.018722985, 0.0048939455, -0.018719096, -0.056783892, -0.02663151, -0.06854834, -0.01834153, -0.050529163, -0.02894976, 0.036369096, 0.08269582, -0.011401266, 0.0071720066, 0.0068689873, -0.017017024, -0.013788332, -0.01757652, -0.046771515, 0.006021731, 0.0350991, -0.055127304, 0.0004067387, 0.0026264484, -0.00842346, -0.029608497, -0.043472905, -0.045593407, 0.030926447, -0.012382723, -0.039737374, -0.016628245, -0.028230408, 0.042542323, 0.024740454, 0.029905234, -0.021382011, 0.0087046465, 0.008666167, -0.01237462, 0.0058083804, 0.049879998, 0.027694289, -0.033726525, 0.018072732, 0.013075523, 0.04129341, -0.003759638, 0.025136042, -0.0048480816, -0.08633937, 0.026146557, 0.00095875195, -0.007239596, 0.030176798, 0.012911557, -0.05567729, 0.101863965, -0.012008359, -0.019885525, 0.06285349, -0.020306658, 0.021225194, 0.03904156, -0.018150982, 0.005765315, -0.014720191, 0.039356854, -0.05162945, -0.010809988, -0.019877022, -0.043858252, -0.016290769, -0.00052574894, 0.00071051397, -0.05228283, 0.00212076, 0.10330768, 0.03806923, -0.011989388, -0.0092820525, -0.07842139, -0.005238204, 0.0050059403, 0.004792647, -0.028316176, 0.008777532, -0.055501916, 0.0031685885, -0.044218272, -0.040338665, -0.035807323, 0.003954393, -0.059668504, 0.051771026, 0.023667619, 0.0073676254, -0.00062780967, -0.09302048, -0.028653411, 0.022346793, -0.0054721106, -0.035974275, 0.011861464, -0.044336487, -0.020843782, -0.034995276, 0.0073804525, -0.05347183, 0.027588347, 0.012416945, 0.038829893, 0.024596987, 0.0074599786, 0.014858577, 0.03851009, 0.014121627, -0.04871009, 0.027252283, 0.0553166, 0.05215012, 0.018370263, 0.0530953, 0.031772766, -0.017525164, -0.062617734, -0.008032683, 0.060756683, 0.037613112, -0.06970549, -0.03628826, 0.0060448144, 0.0106271915, 0.01570074, -0.032992955, 0.08146692, -0.0005743188, -0.003664223, 0.029400827, -0.007885519, -0.08933015, -0.019689526, 0.015134545, 0.0032099236, -0.02092406, -0.014055446, 0.010172088, 0.02639813, 0.028534463, 0.03089289, -0.017581366, -0.026170125, -0.028410664, -0.007110761, 0.052456588, 0.004216275, -0.0051908707, 0.02629775, 0.035634518, -0.024233747, -0.020206803, -0.08185167, -0.038406268, -0.019373732, 0.03597261, -0.063467175, -0.01582219, 0.05335854, -0.0067784563, 0.025629507, -0.005729798, 0.011919803, -0.049962502, 0.02882643, 0.040532112, 0.037180837, -0.0654546, -0.0078468155, 0.0056370874, -0.013275107, -0.012502071, -0.016623577, -0.00042084648, 0.0064675817, 0.05863257, 0.03738945, -0.021043384, 0.03962018, 0.011263337, -0.074983895, -0.026997007, 0.051713623, 0.019749667, 0.022187935, -0.02188655, -0.026837206, 0.0038193846, 0.019730948, 0.026408449, -0.073553264, 0.054254226, -0.021037942, -0.011475345, -0.008065046, -0.0041081496, 0.07153666, -0.0011454923, 0.0072494335, -0.02546474, -0.034410242, -0.008523845, -0.004515808, -0.0043068486, 0.06108401, 0.04297906, 0.04093538, 0.03570107, -0.032012034, 0.015930245, -0.043826263, 0.021157239, 0.029291723, -0.031764403, 0.032508258, -0.007936765, -0.0007478923, -0.05491598, -0.021232825, -0.011368038, 0.04037207, 0.028925741, 0.02602244, -0.022289654, 0.010383836, 0.0031105224, -0.0002327807, -0.04982281, -0.026878828, -0.026498057, -0.038631085},
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm getting different numbers for all prompts, but it seems to change with the Ollama version? I ran this, then updated Ollama and ran it again, and got different numbers both times (also different between the two runs). I didn't expect this, but maybe it's normal? Just to double check, can you run with the latest v0.1.44 please? (There's a v0.1.45 but it's pre-release).


On my side I'm running the code on an x86_64 Intel CPU, Fedora 39 (Kernel 6.8).

Ran with:

test code
package chromem

import (
	"context"
	"fmt"
	"os"
	"testing"
)

func TestFoo(t *testing.T) {
	e := NewEmbeddingFuncOllama("nomic-embed-text", os.Getenv("OLLAMA_HOST"))

	ee := func(s string) []float32 {
		v, err := e(context.Background(), s)
		if err != nil {
			panic(err)
		}
		return v
	}

	testEmbeddings := map[string][]float32{
		"search_document: Village Builder Game": ee("search_document: Village Builder Game"),
		"search_document: Town Craft Idle Game": ee("search_document: Town Craft Idle Game"),
		"search_document: Some Idle Game":       ee("search_document: Some Idle Game"),
		"search_query: town":                    ee("search_query: town"),
		"search_query: idle":                    ee("search_query: idle"),
	}

	fmt.Printf("%#v\n", testEmbeddings)
}

And then: go test -v -run TestFoo -count 1 .

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah embeddings were kinda broken in some versions of Ollama. See: ollama/ollama#3777 and ollama/ollama#3053. I used v0.1.31 to generated them originally. I have re-generated them with v0.1.45 now, which changes them slightly again 🤷‍♂️

@erikdubbelboer erikdubbelboer force-pushed the QueryWithNegative branch 2 times, most recently from 7d37ed9 to 526752e Compare June 23, 2024 15:21
QueryWithNegative allows you to pass a string that will be excluded from
the search results.

There are tree ways to implement this:
1. Find the document matching the normal query. Then re-order the result
   by multiplying the similarity by the dot product with the negative
   vector and some constant.
2. Find the document matching the normal query. Exclude documents where
   the dot product with the negative vector are above a constant.
3. The simpler method I implemented which just subtracts the negative
   vector from the positive one and re-normalizes the result.

I have done some simple tests and the results look good.

I'm not sure if the extra function is a nice API. It could also be added
as extra argument to Query. Or maybe Query should get a struct for it's
argument as the number of arguments seems to keep increasing.
Removed NEGATIVE_MODE_REORDER as it didn't make much sense.

NEGATIVE_MODE_FILTER now filters at query time instead of the result.
This means that when you want 10 results, you can get 10 results.
Instead of those 10 results then being filtered and resulting in less.

Removed default negative mode. You now always have to pick one when
providing negative text or embeddings.
Copy link
Owner

@philippgille philippgille left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again for this new feature! And sorry that I was slow with reviewing!

@philippgille philippgille merged commit 4b532fa into philippgille:main Jun 26, 2024
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants