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:
+35
-11
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user