[PR] Strip C0 control characters from LLM JSON output - #612
Open
BetterAndBetterII wants to merge 1 commit into
Open
[PR] Strip C0 control characters from LLM JSON output#612BetterAndBetterII wants to merge 1 commit into
BetterAndBetterII wants to merge 1 commit into
Conversation
LLM translations can embed PDF C0 controls in otherwise well-formed JSON. _clean_json_output now drops those characters (keeping JSON whitespace) so json.loads succeeds and the fallback path does not leak source fragments. Co-authored-by: Yuzhong Zhang <BetterAndBetterII@users.noreply.github.com>
There was a problem hiding this comment.
1 issue found across 2 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="babeldoc/format/pdf/document_il/midend/il_translator_llm_only.py">
<violation number="1" location="babeldoc/format/pdf/document_il/midend/il_translator_llm_only.py:1000">
P2: The filter preserves literal `\n`, `\t`, `\r` everywhere, including inside JSON string values. Those bytes are invalid inside strings, so when a translated string contains one, `json.loads` still raises exactly the failure this PR targets. Use a context-aware clean (e.g. only strip control chars outside string literals, or escape them inside strings) so in-string whitespace is handled as well as structural whitespace.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| return llm_output.strip() | ||
| llm_output = llm_output.strip() | ||
| # JSON allows \n \t \r as whitespace; other C0 controls make json.loads fail. | ||
| return "".join( |
There was a problem hiding this comment.
P2: The filter preserves literal \n, \t, \r everywhere, including inside JSON string values. Those bytes are invalid inside strings, so when a translated string contains one, json.loads still raises exactly the failure this PR targets. Use a context-aware clean (e.g. only strip control chars outside string literals, or escape them inside strings) so in-string whitespace is handled as well as structural whitespace.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At babeldoc/format/pdf/document_il/midend/il_translator_llm_only.py, line 1000:
<comment>The filter preserves literal `\n`, `\t`, `\r` everywhere, including inside JSON string values. Those bytes are invalid inside strings, so when a translated string contains one, `json.loads` still raises exactly the failure this PR targets. Use a context-aware clean (e.g. only strip control chars outside string literals, or escape them inside strings) so in-string whitespace is handled as well as structural whitespace.</comment>
<file context>
@@ -995,4 +995,8 @@ def _clean_json_output(self, llm_output: str) -> str:
- return llm_output.strip()
+ llm_output = llm_output.strip()
+ # JSON allows \n \t \r as whitespace; other C0 controls make json.loads fail.
+ return "".join(
+ char for char in llm_output if ord(char) >= 32 or char in "\n\t\r"
+ )
</file context>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR Title
[PR] Strip C0 control characters from LLM JSON output
Related Issue(s)
Closes #577
Motivation and Context
PDF text can put C0 control characters into the LLM JSON.
_clean_json_outputonly stripped wrappers, sojson.loadsfailed and the fallback path left residual source fragments in the translation.Summary of Changes
Sanitize C0 controls in
_clean_json_outputwhile keeping JSON-legal whitespace (\n,\t,\r). Wrapper stripping is unchanged.PR Type
Breaking Changes
Contributor Checklist
Testing Instructions
python -m pytest tests/test_clean_json_output.py -v.Summary by cubic
Strips non-whitespace C0 control characters from LLM JSON output so
json.loadssucceeds and translations don’t fall back and leak source fragments. Previously,_clean_json_outputonly removed wrappers; JSON containing C0 controls failed to parse.Review notes
ILTranslatorLLMOnly._clean_json_output, after wrapper trimming andstrip(), drop chars withord(char) < 32except\n,\t,\r. Wrapper stripping is unchanged.tests/test_clean_json_output.pyto verify C0 controls are removed while JSON-legal whitespace and wrapper handling are preserved.Written for commit 2ff852f. Summary will update on new commits.