Commit 672b89d
authored
* fix(embedding): split oversized canonical lines so chunk windows never exceed the provider context (#206)
chunkCanonicalText windowed compartment chunk-embedding input only at
canonical line (U:/A: span) boundaries. A single line larger than the
per-window token budget was emitted whole, so a compartment span containing
a large message (e.g. a file dump rendered into one A: span) produced one
window far over the provider's hard context window — jina via litellm
returned 400 exceed_context_size for a 51774-token window against an 8192
ceiling, and the compartment could never be embedded.
Split a single oversized line down to the per-window budget before emitting
its windows, using @langchain/textsplitters RecursiveCharacterTextSplitter
with a lengthFunction backed by the existing estimateTokens tokenizer, so
slicing is token-accurate and deterministic (cache-safe, no provider call).
Each sub-slice becomes its own window carrying the owning line's ordinal
range; a char-budget fallback guarantees termination on token-dense text
with no separators. windowIndex stays 1-based contiguous so stored chunk
identity (compartmentId + windowIndex + hash) is preserved.
chunkCanonicalText is now async (the splitter API is async); the two
production callers and the test seams await it.
Adds tests: a single oversized line splits into multiple in-budget windows
with stable ordinals/indices, and split sub-windows interleave with normal
line windows without index gaps.
* fix(embedding): address PR #207 review — vendor splitter, bound provider calls, log fallback
Review feedback (greptile/cubic/socket) on #207:
- Drop the @langchain/textsplitters dependency (tripped an org Socket
"obfuscated code" alert on its minified dist) and vendor a minimal
synchronous port of RecursiveCharacterTextSplitter as
recursive-text-splitter.ts (algorithm + separator hierarchy ported from
v1.0.1, MIT). This also reverts chunkCanonicalText back to sync, removing
the async ripple through callers and tests.
- Bound provider call size when a SINGLE compartment produces more windows
than MAX_WINDOWS_PER_EMBED_CALL: embedTextsWindowBounded sub-batches the
texts across provider calls and concatenates vectors, so the slice
builder's "always include at least one compartment whole" rule can no
longer hand the provider one enormous payload (cubic P2). Per-compartment
persistence/retry accounting is unchanged.
- Log when the recursive splitter throws before falling back to the
char-budget split, instead of swallowing the error silently (greptile/cubic P2).
- Clarify the charBudgetSplit budget guarantee: every slice is within budget
except the degenerate single-character case under a tiny budget, which is
unreachable with real provider budgets (cubic P3).
Tests: vendored splitter unit tests (separator fallthrough, char split,
custom length fn, round-trip); a #207 batching test asserting no provider
call exceeds the window cap when one compartment yields many windows.
55 tests pass across the affected files; tsc + biome clean.
* fix(embedding): re-check char-budget split output so no over-budget slice escapes (PR #207)
greptile flagged that splitOversizedLine's final guard pushed charBudgetSplit
sub-slices to the result unchecked, so a degenerate single-character slice that
alone exceeds the budget could escape the 'no window over budget' guarantee.
Route every charBudgetSplit sub-slice through a checked push that re-splits any
still-over-budget slice with length > 1 and only emits a lone irreducible
character as the terminal case.
* test(embedding): drop stale async on test callbacks after chunkCanonicalText went sync
chunkCanonicalText reverted to synchronous when the splitter was vendored, but
several test callbacks kept their now-pointless async marker (no remaining
await). Strip async from the 7 affected test blocks. Production embedTextsWindowBounded
stays async — it awaits real provider calls.
* fix(embedding): coerce empty input to a space at the provider chokepoint
Some OpenAI-compatible providers (jina via litellm) reject an empty-string
embedding input with HTTP 400 "Input content cannot be empty", which fails the
WHOLE batch (response is all-null) — so one empty input blocks embedding every
other text sent with it, and the affected compartment/memory loops as
"could not be embedded" forever.
Coerce empty/whitespace-only inputs to a single space (verified to embed) in
OpenAICompatibleEmbeddingProvider.embedBatch, before the POST. This is the
single chokepoint covering every caller (chunk, memory, query), independent of
any provider-side hook. Real text and token-id-shaped inputs are untouched;
result mapping is unchanged (coercion preserves array length 1:1).
1 parent 2ccf3de commit 672b89d
9 files changed
Lines changed: 538 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 51 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
138 | 138 | | |
139 | 139 | | |
140 | 140 | | |
141 | | - | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
142 | 148 | | |
143 | 149 | | |
144 | 150 | | |
| |||
167 | 173 | | |
168 | 174 | | |
169 | 175 | | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
170 | 220 | | |
171 | 221 | | |
172 | 222 | | |
| |||
Lines changed: 124 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
2 | 3 | | |
3 | 4 | | |
| 5 | + | |
4 | 6 | | |
| 7 | + | |
5 | 8 | | |
6 | 9 | | |
7 | 10 | | |
| |||
501 | 504 | | |
502 | 505 | | |
503 | 506 | | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
504 | 529 | | |
505 | 530 | | |
506 | 531 | | |
| |||
513 | 538 | | |
514 | 539 | | |
515 | 540 | | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
516 | 545 | | |
517 | 546 | | |
518 | 547 | | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
519 | 643 | | |
520 | 644 | | |
521 | 645 | | |
| |||
Lines changed: 13 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
153 | 153 | | |
154 | 154 | | |
155 | 155 | | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
156 | 169 | | |
157 | 170 | | |
158 | 171 | | |
| |||
Lines changed: 11 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
198 | 198 | | |
199 | 199 | | |
200 | 200 | | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
201 | 211 | | |
202 | 212 | | |
203 | 213 | | |
| |||
245 | 255 | | |
246 | 256 | | |
247 | 257 | | |
248 | | - | |
| 258 | + | |
249 | 259 | | |
250 | 260 | | |
251 | 261 | | |
| |||
Lines changed: 77 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
167 | 167 | | |
168 | 168 | | |
169 | 169 | | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
170 | 200 | | |
171 | 201 | | |
172 | 202 | | |
| |||
641 | 671 | | |
642 | 672 | | |
643 | 673 | | |
644 | | - | |
| 674 | + | |
645 | 675 | | |
646 | 676 | | |
647 | 677 | | |
| |||
716 | 746 | | |
717 | 747 | | |
718 | 748 | | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
| 789 | + | |
| 790 | + | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
719 | 794 | | |
720 | 795 | | |
721 | 796 | | |
| |||
763 | 838 | | |
764 | 839 | | |
765 | 840 | | |
766 | | - | |
| 841 | + | |
767 | 842 | | |
768 | 843 | | |
769 | 844 | | |
| |||
0 commit comments