From 54cdaa61fd2e1d03be37ee3464a910d846c55a55 Mon Sep 17 00:00:00 2001 From: zhangsixiao Date: Fri, 3 Jul 2026 01:23:10 +0800 Subject: [PATCH] fix(langchain): escape empty json braces in prompts --- langfuse/model.py | 4 +-- tests/unit/test_prompt_compilation.py | 37 +++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/langfuse/model.py b/langfuse/model.py index 69d721597..883a07345 100644 --- a/langfuse/model.py +++ b/langfuse/model.py @@ -171,7 +171,7 @@ def _escape_json_for_langchain(text: str) -> str: A curly brace is considered “JSON-related” when, after skipping any immediate whitespace, the next non-whitespace character is a single - or double quote. + quote, double quote, or the matching closing brace of an empty object. Braces that are already doubled (e.g. {{variable}} placeholders) are left untouched. @@ -206,7 +206,7 @@ def _escape_json_for_langchain(text: str) -> str: while j < n and text[j].isspace(): j += 1 - is_json = j < n and text[j] in {"'", '"'} + is_json = j < n and text[j] in {"'", '"', "}"} out.append("{{" if is_json else "{") stack.append(is_json) # remember how this “{” was treated i += 1 diff --git a/tests/unit/test_prompt_compilation.py b/tests/unit/test_prompt_compilation.py index 1b96a14dd..cc348e9b9 100644 --- a/tests/unit/test_prompt_compilation.py +++ b/tests/unit/test_prompt_compilation.py @@ -449,6 +449,43 @@ def test_edge_case_empty_json_objects(self): assert formatted_prompt == expected + def test_langchain_prompt_escapes_bare_empty_json_objects(self): + """Test that bare empty JSON objects remain literals in LangChain prompts.""" + prompt_string = """Variable: {{test_var}} +Empty object: {} +Spaced empty object: { } +Multiline empty object: { +} +LangChain variable: {langchain_var}""" + + prompt = TextPromptClient( + Prompt_Text( + type="text", + name="bare_empty_json_test", + version=1, + config={}, + tags=[], + labels=[], + prompt=prompt_string, + ) + ) + + langchain_prompt_string = prompt.get_langchain_prompt() + langchain_prompt = PromptTemplate.from_template(langchain_prompt_string) + formatted_prompt = langchain_prompt.format( + test_var="value", + langchain_var="chain", + ) + + expected = """Variable: value +Empty object: {} +Spaced empty object: { } +Multiline empty object: { +} +LangChain variable: chain""" + + assert formatted_prompt == expected + def test_edge_case_nested_quotes_in_json(self): """Test edge case with nested quotes and escaped characters in JSON.""" prompt_string = """Message: {{message}}