rag: cap chunk size at 6KB to fit nomic-embed-text 2048-tok context

The chunker emits any single paragraph as a stand-alone chunk regardless
of size. One HVM page had a 14,858-char paragraph (a big config table) —
nomic-embed-text 400'd the entire embed batch because the model's context
is 2048 tokens. Added a hard-split fallback that splits any oversized
chunk on line boundaries to MAX_CHARS=6000 (~1500 tokens, headroom).

Also defaulted PRODUCT_NAME to "hvm" in rag/index.py to match server.py.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-22 13:06:35 -04:00
parent 7a491ba9e4
commit dd691b0111
2 changed files with 36 additions and 12 deletions
+35 -11
View File
@@ -31,6 +31,27 @@ from typing import Iterator
CHARS_PER_TOKEN = 4
TARGET_TOKENS = 500
TARGET_CHARS = TARGET_TOKENS * CHARS_PER_TOKEN
# Hard cap: nomic-embed-text's context is 2048 tokens. Anything larger
# 400s the entire embed batch. 6000 chars ≈ 1500 tokens leaves headroom.
MAX_CHARS = 6000
def _hard_split(text: str) -> list[str]:
"""Split an oversized block on line boundaries into MAX_CHARS pieces."""
if len(text) <= MAX_CHARS:
return [text]
out: list[str] = []
buf: list[str] = []
buf_chars = 0
for line in text.splitlines(keepends=True):
if buf_chars + len(line) > MAX_CHARS and buf:
out.append("".join(buf).rstrip())
buf, buf_chars = [], 0
buf.append(line)
buf_chars += len(line)
if buf:
out.append("".join(buf).rstrip())
return out
def estimate_tokens(text: str) -> int:
@@ -104,23 +125,26 @@ def chunks_from_page(
# ----- Body chunks: pack paragraphs up to TARGET_CHARS -------
ordinal = 1
def emit(buf: list[str]) -> Iterator[dict]:
nonlocal ordinal
merged = "\n\n".join(buf)
for piece in _hard_split(merged):
yield {
"id": f"{metadata['bundle_id']}::{page_id}::{ordinal}",
"text": piece,
"metadata": {**metadata, "ordinal": ordinal},
}
ordinal += 1
buf: list[str] = []
buf_chars = 0
for p in paragraphs:
if buf_chars + len(p) > TARGET_CHARS and buf:
yield {
"id": f"{metadata['bundle_id']}::{page_id}::{ordinal}",
"text": "\n\n".join(buf),
"metadata": {**metadata, "ordinal": ordinal},
}
ordinal += 1
yield from emit(buf)
buf = []
buf_chars = 0
buf.append(p)
buf_chars += len(p)
if buf:
yield {
"id": f"{metadata['bundle_id']}::{page_id}::{ordinal}",
"text": "\n\n".join(buf),
"metadata": {**metadata, "ordinal": ordinal},
}
yield from emit(buf)