What happens
VolatileMemoryStore.get_batch and get_nearest_matches take a flag (with_embeddings) that is documented as "Whether to include the embeddings in the results". With the flag False (the default) the embeddings are still returned. The code makes a deepcopy and clears the embedding on the copy, but the loop variable is rebound and the copy is thrown away, so the original records are returned unchanged.
get (the single-record version) does this correctly, which shows the intended behavior.
Where
python/semantic_kernel/memory/volatile_memory_store.py on current main.
get_batch:
if not with_embeddings:
# create copy of results without embeddings
for result in results:
result = deepcopy(result)
result._embedding = None
return results
get_nearest_matches:
if not with_embeddings:
# create copy of results without embeddings
for result in top_results:
result = deepcopy(result)
result[0]._embedding = None
return top_results
In the second case deepcopy(result) copies the (record, score) tuple, and the copy is dropped. Note that a naive fix of removing the deepcopy would clear the embedding on the stored record itself, so the fix has to return copies.
Reproduce
import asyncio, numpy as np
from semantic_kernel.memory.volatile_memory_store import VolatileMemoryStore
from semantic_kernel.memory.memory_record import MemoryRecord
async def main():
s = VolatileMemoryStore()
await s.create_collection("c")
await s.upsert("c", MemoryRecord.local_record("id1", "text", "desc", None, np.array([1.0, 0.0])))
ms = await s.get_nearest_matches("c", np.array([1.0, 0.0]), limit=1)
print("get_nearest_matches:", ms[0][0]._embedding)
b = await s.get_batch("c", ["id1"])
print("get_batch:", b[0]._embedding)
g = await s.get("c", "id1")
print("get:", g._embedding)
asyncio.run(main())
Output on semantic-kernel main (also 1.44.1):
get_nearest_matches: [1. 0.]
get_batch: [1. 0.]
get: None
Expected
All three return None for the embedding when the embeddings flag is False, and the stored records keep their embeddings. I am happy to send a fix with tests.
What happens
VolatileMemoryStore.get_batchandget_nearest_matchestake a flag (with_embeddings) that is documented as "Whether to include the embeddings in the results". With the flagFalse(the default) the embeddings are still returned. The code makes adeepcopyand clears the embedding on the copy, but the loop variable is rebound and the copy is thrown away, so the original records are returned unchanged.get(the single-record version) does this correctly, which shows the intended behavior.Where
python/semantic_kernel/memory/volatile_memory_store.pyon current main.get_batch:get_nearest_matches:In the second case
deepcopy(result)copies the(record, score)tuple, and the copy is dropped. Note that a naive fix of removing thedeepcopywould clear the embedding on the stored record itself, so the fix has to return copies.Reproduce
Output on semantic-kernel main (also 1.44.1):
Expected
All three return
Nonefor the embedding when the embeddings flag isFalse, and the stored records keep their embeddings. I am happy to send a fix with tests.