1
1
from pathlib import Path
2
+ from unittest .mock import AsyncMock , Mock
2
3
3
4
import pytest
4
5
from langchain_standard_tests .integration_tests .vectorstores import (
@@ -24,43 +25,65 @@ async def vectorstore(self) -> InMemoryVectorStore:
24
25
return InMemoryVectorStore (embedding = self .get_embeddings ())
25
26
26
27
27
- async def test_inmemory () -> None :
28
- """Test end to end construction and search."""
28
+ async def test_inmemory_similarity_search () -> None :
29
+ """Test end to end similarity search."""
29
30
store = await InMemoryVectorStore .afrom_texts (
30
- ["foo" , "bar" , "baz" ], DeterministicFakeEmbedding (size = 6 )
31
+ ["foo" , "bar" , "baz" ], DeterministicFakeEmbedding (size = 3 )
31
32
)
32
- output = await store .asimilarity_search ("foo" , k = 1 )
33
+
34
+ # Check sync version
35
+ output = store .similarity_search ("foo" , k = 1 )
33
36
assert output == [Document (page_content = "foo" , id = AnyStr ())]
34
37
38
+ # Check async version
35
39
output = await store .asimilarity_search ("bar" , k = 2 )
36
40
assert output == [
37
41
Document (page_content = "bar" , id = AnyStr ()),
38
42
Document (page_content = "baz" , id = AnyStr ()),
39
43
]
40
44
41
- output2 = await store .asimilarity_search_with_score ("bar" , k = 2 )
42
- assert output2 [0 ][1 ] > output2 [1 ][1 ]
45
+
46
+ async def test_inmemory_similarity_search_with_score () -> None :
47
+ """Test end to end similarity search with score"""
48
+ store = await InMemoryVectorStore .afrom_texts (
49
+ ["foo" , "bar" , "baz" ], DeterministicFakeEmbedding (size = 3 )
50
+ )
51
+
52
+ output = store .similarity_search_with_score ("foo" , k = 1 )
53
+ assert output [0 ][0 ].page_content == "foo"
54
+
55
+ output = await store .asimilarity_search_with_score ("bar" , k = 2 )
56
+ assert output [0 ][1 ] > output [1 ][1 ]
43
57
44
58
45
59
async def test_add_by_ids () -> None :
60
+ """Test add texts with ids."""
46
61
vectorstore = InMemoryVectorStore (embedding = DeterministicFakeEmbedding (size = 6 ))
47
62
48
63
# Check sync version
49
64
ids1 = vectorstore .add_texts (["foo" , "bar" , "baz" ], ids = ["1" , "2" , "3" ])
50
65
assert ids1 == ["1" , "2" , "3" ]
51
66
assert sorted (vectorstore .store .keys ()) == ["1" , "2" , "3" ]
52
67
68
+ # Check async version
53
69
ids2 = await vectorstore .aadd_texts (["foo" , "bar" , "baz" ], ids = ["4" , "5" , "6" ])
54
70
assert ids2 == ["4" , "5" , "6" ]
55
71
assert sorted (vectorstore .store .keys ()) == ["1" , "2" , "3" , "4" , "5" , "6" ]
56
72
57
73
58
74
async def test_inmemory_mmr () -> None :
75
+ """Test MMR search"""
59
76
texts = ["foo" , "foo" , "fou" , "foy" ]
60
77
docsearch = await InMemoryVectorStore .afrom_texts (
61
78
texts , DeterministicFakeEmbedding (size = 6 )
62
79
)
63
80
# make sure we can k > docstore size
81
+ output = docsearch .max_marginal_relevance_search ("foo" , k = 10 , lambda_mult = 0.1 )
82
+ assert len (output ) == len (texts )
83
+ assert output [0 ] == Document (page_content = "foo" , id = AnyStr ())
84
+ assert output [1 ] == Document (page_content = "foy" , id = AnyStr ())
85
+
86
+ # Check async version
64
87
output = await docsearch .amax_marginal_relevance_search (
65
88
"foo" , k = 10 , lambda_mult = 0.1
66
89
)
@@ -85,13 +108,91 @@ async def test_inmemory_dump_load(tmp_path: Path) -> None:
85
108
86
109
87
110
async def test_inmemory_filter () -> None :
88
- """Test end to end construction and search."""
111
+ """Test end to end construction and search with filter ."""
89
112
store = await InMemoryVectorStore .afrom_texts (
90
113
["foo" , "bar" ],
91
114
DeterministicFakeEmbedding (size = 6 ),
92
115
[{"id" : 1 }, {"id" : 2 }],
93
116
)
117
+
118
+ # Check sync version
119
+ output = store .similarity_search ("fee" , filter = lambda doc : doc .metadata ["id" ] == 1 )
120
+ assert output == [Document (page_content = "foo" , metadata = {"id" : 1 }, id = AnyStr ())]
121
+
122
+ # filter with not stored document id
94
123
output = await store .asimilarity_search (
95
- "baz" , filter = lambda doc : doc .metadata ["id" ] == 1
124
+ "baz" , filter = lambda doc : doc .metadata ["id" ] == 3
96
125
)
97
- assert output == [Document (page_content = "foo" , metadata = {"id" : 1 }, id = AnyStr ())]
126
+ assert output == []
127
+
128
+
129
+ async def test_inmemory_upsert () -> None :
130
+ """Test upsert documents."""
131
+ embedding = DeterministicFakeEmbedding (size = 2 )
132
+ store = InMemoryVectorStore (embedding = embedding )
133
+
134
+ # Check sync version
135
+ store .upsert ([Document (page_content = "foo" , id = "1" )])
136
+ assert sorted (store .store .keys ()) == ["1" ]
137
+
138
+ # Check async version
139
+ await store .aupsert ([Document (page_content = "bar" , id = "2" )])
140
+ assert sorted (store .store .keys ()) == ["1" , "2" ]
141
+
142
+ # update existing document
143
+ await store .aupsert (
144
+ [Document (page_content = "baz" , id = "2" , metadata = {"metadata" : "value" })]
145
+ )
146
+ item = store .store ["2" ]
147
+
148
+ baz_vector = embedding .embed_query ("baz" )
149
+ assert item == {
150
+ "id" : "2" ,
151
+ "text" : "baz" ,
152
+ "vector" : baz_vector ,
153
+ "metadata" : {"metadata" : "value" },
154
+ }
155
+
156
+
157
+ async def test_inmemory_get_by_ids () -> None :
158
+ """Test get by ids."""
159
+
160
+ store = InMemoryVectorStore (embedding = DeterministicFakeEmbedding (size = 3 ))
161
+
162
+ store .upsert (
163
+ [
164
+ Document (page_content = "foo" , id = "1" , metadata = {"metadata" : "value" }),
165
+ Document (page_content = "bar" , id = "2" ),
166
+ Document (page_content = "baz" , id = "3" ),
167
+ ],
168
+ )
169
+
170
+ # Check sync version
171
+ output = store .get_by_ids (["1" , "2" ])
172
+ assert output == [
173
+ Document (page_content = "foo" , id = "1" , metadata = {"metadata" : "value" }),
174
+ Document (page_content = "bar" , id = "2" ),
175
+ ]
176
+
177
+ # Check async version
178
+ output = await store .aget_by_ids (["1" , "3" , "5" ])
179
+ assert output == [
180
+ Document (page_content = "foo" , id = "1" , metadata = {"metadata" : "value" }),
181
+ Document (page_content = "baz" , id = "3" ),
182
+ ]
183
+
184
+
185
+ async def test_inmemory_call_embeddings_async () -> None :
186
+ embeddings_mock = Mock (
187
+ wraps = DeterministicFakeEmbedding (size = 3 ),
188
+ aembed_documents = AsyncMock (),
189
+ aembed_query = AsyncMock (),
190
+ )
191
+ store = InMemoryVectorStore (embedding = embeddings_mock )
192
+
193
+ await store .aadd_texts ("foo" )
194
+ await store .asimilarity_search ("foo" , k = 1 )
195
+
196
+ # Ensure the async embedding function is called
197
+ assert embeddings_mock .aembed_documents .await_count == 1
198
+ assert embeddings_mock .aembed_query .await_count == 1
0 commit comments