fix(llm): strip NUL/control chars from chunk text before pgvector insert
All checks were successful
CI / lint (push) Successful in 29s
CI / notebooks-smoke (push) Successful in 1m29s
Deploy / notebooks (push) Has been skipped
Deploy / zotero (push) Has been skipped
Deploy / docs (push) Has been skipped
Deploy / api (push) Has been skipped
Deploy / llm (push) Has been skipped
Deploy / mc (push) Has been skipped
Infra CI / notebooks (push) Successful in 55s
Infra CI / zotero (push) Successful in 17s
Infra CI / docs (push) Successful in 17s
Infra CI / api (push) Successful in 1m6s
Infra CI / llm (push) Successful in 47s
Infra CI / mc (push) Successful in 13s
Deploy / report (push) Successful in 13s
CI / test (push) Successful in 14m3s
Harden / build-scan-report (push) Successful in 26m9s
Renovate / renovate (push) Successful in 14s
Notebooks Integration / notebooks-integration (push) Successful in 7m21s
Zotero Sync / zotero-sync (push) Successful in 1m8s
Package Supply Chain / pkg-supply-chain (push) Successful in 1m2s
All checks were successful
CI / lint (push) Successful in 29s
CI / notebooks-smoke (push) Successful in 1m29s
Deploy / notebooks (push) Has been skipped
Deploy / zotero (push) Has been skipped
Deploy / docs (push) Has been skipped
Deploy / api (push) Has been skipped
Deploy / llm (push) Has been skipped
Deploy / mc (push) Has been skipped
Infra CI / notebooks (push) Successful in 55s
Infra CI / zotero (push) Successful in 17s
Infra CI / docs (push) Successful in 17s
Infra CI / api (push) Successful in 1m6s
Infra CI / llm (push) Successful in 47s
Infra CI / mc (push) Successful in 13s
Deploy / report (push) Successful in 13s
CI / test (push) Successful in 14m3s
Harden / build-scan-report (push) Successful in 26m9s
Renovate / renovate (push) Successful in 14s
Notebooks Integration / notebooks-integration (push) Successful in 7m21s
Zotero Sync / zotero-sync (push) Successful in 1m8s
Package Supply Chain / pkg-supply-chain (push) Successful in 1m2s
Extracted PDF comment text carries NUL (0x00) and form-feed bytes that Postgres text columns reject (DataError: cannot contain NUL bytes) — the 2017 pilot was clean by luck, the 2018+ dockets crash the indexer. Strip C0 control chars (except tab/newline/return) in chunk_doc.
This commit is contained in:
@@ -35,6 +35,10 @@ def content_hash(text: str) -> str:
|
||||
|
||||
_FRONTMATTER = re.compile(r"\A---\n.*?\n---\n", re.DOTALL)
|
||||
_HEADING = re.compile(r"^#{1,6} ", re.MULTILINE)
|
||||
# C0 control chars except tab/newline/carriage-return. Extracted PDF text
|
||||
# carries NUL (0x00) and form-feeds that Postgres text columns reject
|
||||
# ("cannot contain NUL bytes") and that add no semantic value to embeddings.
|
||||
_CONTROL = re.compile(r"[\x00-\x08\x0b\x0c\x0e-\x1f]")
|
||||
|
||||
|
||||
def _sections(text: str) -> list[str]:
|
||||
@@ -90,7 +94,7 @@ def chunk_doc(
|
||||
"""
|
||||
if overlap_chars >= target_chars:
|
||||
raise ValueError("overlap_chars must be smaller than target_chars")
|
||||
body = _FRONTMATTER.sub("", doc.text).strip()
|
||||
body = _CONTROL.sub("", _FRONTMATTER.sub("", doc.text)).strip()
|
||||
if not body:
|
||||
return []
|
||||
prefix = f"{doc.key}:{content_hash(doc.text)[:12]}"
|
||||
|
||||
@@ -61,3 +61,19 @@ class TestChunkDoc:
|
||||
def test_overlap_gte_target_raises(self):
|
||||
with pytest.raises(ValueError, match="overlap_chars must be smaller"):
|
||||
chunk_doc(_doc("some text"), target_chars=100, overlap_chars=100)
|
||||
|
||||
|
||||
class TestControlCharStripping:
|
||||
def test_strips_nul_and_control_chars(self):
|
||||
doc = _doc("Clean text\x00 with\x0c a NUL\x07 and formfeed.")
|
||||
chunks = chunk_doc(doc)
|
||||
joined = "".join(c.text for c in chunks)
|
||||
assert "\x00" not in joined
|
||||
assert "\x0c" not in joined
|
||||
assert "\x07" not in joined
|
||||
assert "Clean text with a NUL and formfeed." in joined
|
||||
|
||||
def test_keeps_tab_newline_return(self):
|
||||
doc = _doc("line1\n\nline2\twith tab")
|
||||
joined = "".join(c.text for c in chunk_doc(doc))
|
||||
assert "\t" in joined and "line2" in joined
|
||||
|
||||
Reference in New Issue
Block a user