Repository navigation
Python: fix(python): Fix InMemoryCollection upsert with key storage_name alias - #14564
Jeevan Babu Gotru (jeevan1098) wants to merge 9 commits into
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
A confirmed indentation error prevents importing the connector and collecting its tests.
1 open finding
What changed in this PR
Addresses #14547 by supporting key storage-name aliases in Python’s in-memory vector store.
Changes:
- Looks up serialized keys by storage name, falling back to the Python field name.
- Adds regression tests for dictionary, dataclass, and Pydantic records.
| File | Description |
|---|---|
| python/tests/unit/connectors/memory/test_in_memory.py | Adds key-alias regression tests. |
| python/semantic_kernel/connectors/in_memory.py | Updates upsert key lookup to support storage aliases. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
PRABHU KIRAN VANDRANKI (VANDRANKI)
left a comment
There was a problem hiding this comment.
Community review. I am not a maintainer, so this does not clear the merge gate.
First, the branch as pushed does not import. In python/semantic_kernel/connectors/in_memory.py the diff changes the _inner_upsert definition line from 4 spaces to 8 spaces of indentation while leaving its body at 8, right after the @override decorator at 4 spaces (diff line + async def _inner_upsert(...)). On the PR head:
$ python -c "import semantic_kernel.connectors.in_memory"
File ".../semantic_kernel/connectors/in_memory.py", line 632
async def _inner_upsert(self, records: Sequence[Any], **kwargs: Any) -> Sequence[TKey]:
IndentationError: unexpected indent
pytest tests/unit/connectors/memory/test_in_memory.py stops at collection with that error, so every test in the file errors, including the new ones.
I then tried the idea itself. I read the full diff, de-indented line 632 by 4 spaces in a scratch copy of the PR head (python/ in a venv, Python 3.13, nothing else changed), and ran the file:
- Fixed PR head: 46 passed.
in_memory.pyfrom origin/main with the PR's tests:test_upsert_with_key_storage_name_dictandtest_upsert_with_key_storage_name_dataclassfail, the Pydantic test and the other 43 pass. So the storage-name problem is real for dict and dataclass records, and the Pydantic test is a guard that passes on main already.
So the logic is fine (use record[key_storage_name] when present and fall back to record[key_name]), and the fix to push is the one indentation change. I did not check whether ruff or the repo's pre-commit hooks flag anything else in the test file, and I did not run other connector tests or CI.
|
@microsoft-github-policy-service agree |
Eduard van Valkenburg (eavanvalkenburg)
left a comment
There was a problem hiding this comment.
The storage-name fallback introduces a Pydantic key collision; see the inline reproduction. CI also reports that Ruff modifies the new test imports, so please apply the configured hooks.
| # Serialized records index the key by its storage name (e.g. dict and | ||
| # dataclass records), while some record types (e.g. Pydantic models) | ||
| # serialize with the Python field name, so fall back to that. | ||
| key = record[key_storage_name] if key_storage_name in record else record[key_name] |
There was a problem hiding this comment.
Preferring the storage name can use a data-field value as the key for Pydantic records. With a key field id (storage_name="stored_id") and a data field stored_id (storage_name="payload"), Pydantic serialization keeps the logical names. I reproduced upsert(Record(id="actual-key", stored_id="payload-value", vector=[1.0, 0.0])) returning "payload-value"; get("actual-key") then returns None. The old Pydantic path used id correctly. Please choose the serialized key according to the record serializer's contract rather than a storage-first fallback, and add this overlapping-name regression.
…ng-name collision
|
Thanks Eduard van Valkenburg (@eavanvalkenburg) — fixed both points. Key choice: I also made the matching change on the read side in the same file: InMemory's Added AI-assisted contribution, verified locally as described above. |
|
Update after merging current main into this branch: while this PR was open, upstream #14548 (merged Oct 26) landed the serializer-contract fix for the upsert side — What remains in this PR is the read side of your reproduction, which still fails on current main: upsert returns Happy to close this instead if you would rather handle the read side separately — just say the word. AI-assisted contribution, verified locally as described above. |

Fixes #14547
Problem
InMemoryCollection.upsert()raisedVectorStoreOperationException: 'id'when a dict or dataclass record's key field had astorage_namedifferent from its Python field name. The record serializer produces the storage name, but_inner_upsert()indexed the serialized record using the Python name.Fix
_inner_upsertnow reads the key by the key field's storage name first, falling back to the Python field name for record types that serialize with it (e.g. Pydantic models viamodel_dump()).Tests
Added regression tests for dict, dataclass, and Pydantic records with a key
storage_namealias. Fulltest_in_memory.pysuite: 46 passed.