Keep numpy scalars out of memory metadata and API JSON

Memory consolidation stores FAISS relevance scores (numpy scalars) in document metadata. The values get pickled into the docstore and crash json.dumps with 'Object of type float32 is not JSON serializable' in helpers/api.py for handlers that return full metadata. Coerce scores to native floats at the source and serialize responses with default=float.

Jehu committed Aug 21, 2026 at 08:34 UTC c26ed8064e872ba23d8fbf79057d4caeec064b3d
3 files changed +4 -4
helpers/api.py
+1 -1
@@ -83,7 +83,7 @@ class ApiHandler:
83 if isinstance(output, Response):
84 return output
85 else:
86 - response_json = json.dumps(output)
86 + response_json = json.dumps(output, default=float)
87 return Response(
88 response=response_json, status=200, mimetype="application/json"
89 )
plugins/_memory/helpers/memory.py
+1 -1
@@ -594,7 +594,7 @@ class Memory:
594 res = max(
595 0, min(1, res)
596 ) # float precision can cause values like 1.0000000596046448
597 - return res
597 + return float(res) # native float, not numpy scalar (JSON serializable)
598
599 @staticmethod
600 def format_docs_plain(docs: list[Document]) -> list[str]:
plugins/_memory/helpers/memory_consolidation.py
+2 -2
@@ -344,7 +344,7 @@ class MemoryConsolidator:
344 filter=f"area == '{area}'"
345 )
346 for doc, score in semantic_results:
347 - doc.metadata['_consolidation_similarity'] = score
347 + doc.metadata['_consolidation_similarity'] = float(score) if score is not None else 0.0
348 all_similar.append(doc)
349
350 # Step 3: Keyword-based searches with real scores
@@ -358,7 +358,7 @@ class MemoryConsolidator:
358 filter=f"area == '{area}'"
359 )
360 for doc, score in keyword_results:
361 - doc.metadata['_consolidation_similarity'] = score
361 + doc.metadata['_consolidation_similarity'] = float(score) if score is not None else 0.0
362 all_similar.append(doc)
363
364 # Step 4: Deduplicate by document ID, keep highest score per memory ID