Skip to content

fix(ts): extract JSON from chatty LLM responses in fact retrieval#4533

Merged
whysosaket merged 3 commits intomem0ai:mainfrom
Krishnachaitanyakc:fix/ts-fact-retrieval-json-extraction
Mar 30, 2026
Merged

fix(ts): extract JSON from chatty LLM responses in fact retrieval#4533
whysosaket merged 3 commits intomem0ai:mainfrom
Krishnachaitanyakc:fix/ts-fact-retrieval-json-extraction

Conversation

@Krishnachaitanyakc
Copy link
Copy Markdown
Contributor

Linked Issue

Closes #4526

Description

Local LLMs (Ollama, LM Studio, Qwen, etc.) often wrap JSON output in conversational text without code fences:

Here are the facts I extracted:
{"facts": ["fact1", "fact2"]}
I hope this helps!

The existing removeCodeBlocks() only handles code-fence-wrapped responses. When there are no code fences, JSON.parse() fails on the raw text and all extracted facts are silently dropped (the try/catch sets facts = []). This means memory operations quietly produce no memories.

Root cause: removeCodeBlocks() passes through text unchanged when there are no code fences, so JSON.parse() receives the full chatty response and fails.

Fix: Add extractJson() to prompts/index.ts that:

  1. Strips code fences via removeCodeBlocks() (preserving existing behavior)
  2. Locates JSON by first {/last } (or [/]) boundaries to extract the outermost JSON object/array
  3. Returns the original text as-is if no boundaries are found (caller's try/catch handles the error)

Replace removeCodeBlocks() calls with extractJson() in both fact retrieval and memory action parsing paths in memory/index.ts.

This is the TypeScript SDK counterpart of the Python-side fix in PR #4525.

Files changed

File Change
mem0-ts/src/oss/src/prompts/index.ts Add extractJson() function
mem0-ts/src/oss/src/memory/index.ts Use extractJson() instead of removeCodeBlocks() for JSON parsing
mem0-ts/src/oss/tests/extract-json.test.ts 17 unit tests for extractJson()

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Refactor (no functional changes)
  • Documentation update

Breaking Changes

N/A — extractJson() is a strict superset of removeCodeBlocks() for JSON extraction. Clean JSON, code-fenced JSON, and JSON arrays all produce identical results. The existing try/catch graceful degradation is preserved.

Test Coverage

  • I added/updated unit tests
  • I added/updated integration tests
  • I tested manually (describe below)
  • No tests needed (explain why)

Tests added (mem0-ts/src/oss/tests/extract-json.test.ts — 17 tests)

Test What it verifies
returns clean JSON unchanged Pure JSON passthrough
extracts JSON from json code fence Code-fenced JSON extraction
extracts JSON from bare code fence Bare fence extraction
extracts JSON wrapped in explanation text Chatty text without fences
extracts JSON from chatty LLM response with leading text Leading explanation
extracts JSON from chatty LLM response with trailing text Trailing explanation
extracts JSON from text with both leading and trailing Both sides wrapped
extracts JSON from code-fenced response with surrounding text Code fence + chatty text
handles nested JSON objects Nested object extraction
handles multi-line JSON in chatty text Multi-line JSON
returns original text when no JSON boundaries found No-JSON graceful fallback
handles JSON array responses Array boundary detection
returns empty string for empty input Empty input edge case
handles truncated code block missing closing fence Truncated fence
handles whitespace-padded JSON Whitespace trimming
handles LM Studio-style verbose response LM Studio format
handles Ollama-style response with thinking prefix Ollama format

All 299 existing tests + 17 new tests pass.

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have added tests that prove my fix/feature works
  • New and existing tests pass locally
  • I have updated documentation if needed

When local LLMs (Ollama, LM Studio) return JSON wrapped in explanation
text without code fences, JSON.parse() fails and all facts are silently
dropped. Add extractJson() that strips code fences then locates JSON by
first `{`/last `}` boundaries, keeping the existing try/catch fallback.
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Mar 25, 2026

CLA assistant check
All committers have signed the CLA.

@whysosaket whysosaket merged commit 47969aa into mem0ai:main Mar 30, 2026
6 of 7 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.

Fact retrieval crashes on LLM responses with JSON wrapped in explanation text (no code fences)

5 participants