Skip to content

embeddings: MAX_INPUT_TOKENS cap on the tokens taken from each input text (manticoresearch#4816) - #201

Open
tudorvasinca wants to merge 1 commit into
manticoresoftware:masterfrom
tudorvasinca:issue-4816-max-input-tokens
Open

embeddings: MAX_INPUT_TOKENS cap on the tokens taken from each input text (manticoresearch#4816)#201
tudorvasinca wants to merge 1 commit into
manticoresoftware:masterfrom
tudorvasinca:issue-4816-max-input-tokens

Conversation

@tudorvasinca

Copy link
Copy Markdown

Embeddings-library half of the fix for manticoresoftware/manticoresearch#4816 (the daemon half — DDL option, ALTER, SHOW CREATE TABLE, docs, CLT test — is a separate PR on manticoresearch that pins this commit in the mcl submodule).

Problem

Auto-embedding time grows superlinearly with input length, and the only limit is the model's own context window (max_position_embeddings, 32,768 tokens for Qwen/Qwen3-Embedding-0.6B). Measured on 29.0.2 (details in the issue): 500 B → 4.6 s, 2,000 B → 35.6 s, 5,000 B → 196 s per document on CPU. A single long document holds an embedding statement for minutes; clients time out, the statement keeps running, retries stack more statements and the daemon is eventually OOM-killed.

Change

A per-model cap on the number of tokens taken from each input text, max_input_tokens (0 / None = the model's own limit; the cap can only lower it):

  • ModelOptions.max_input_tokens: Option<usize>; LocalModel::new applies min(model limit, cap) to every architecture's max_input_len (BERT / T5 / Causal / Quantized / ONNX), so all predict paths truncate on it — no change to the truncation code itself.
  • FFI: load_model gains a trailing i32 max_input_tokens; EmbedLib.version 4 → 5 (header regenerated accordingly).
  • knn::ModelSettings_t::m_iMaxInputTokens, part of the model cache key, passed through in knn/embeddings.cpp; SUPPORTED_EMBEDDINGS_LIB_VER 4 → 5.
  • Unit test test_max_input_tokens_cap: cap lowers the limit, never raises it, zero = no cap, and a text plus a long tail embeds identically to the text alone under the cap (and differs without it).

Remote providers (OpenAI / Voyage / Jina) are not capped by this change — happy to add pre-truncation there in a follow-up if wanted.

Verification

  • cargo check --tests, cargo fmt --check, cargo test --release --features download-ort test_max_input_tokens_cap (rust 1.98).
  • End-to-end with the daemon PR on sentence-transformers/all-MiniLM-L6-v2: with a cap of 6 tokens, "a red apple on the table" and the same text followed by 300 extra words produce byte-identical vectors, a different head differs; uncapped the tail changes the vector. A ~5 KB document: 38 ms capped (64 tokens) vs 409 ms uncapped per REPLACE.

@CLAassistant

CLAassistant commented Aug 25, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@donhardman donhardman left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for PR. It's all good to me. I also rebased your branch to latest Qwen optimization we had in master

@donhardman
donhardman force-pushed the issue-4816-max-input-tokens branch from efec895 to 2e37406 Compare September 1, 2026 09:38
@tudorvasinca
tudorvasinca force-pushed the issue-4816-max-input-tokens branch from 2e37406 to 72fcbd3 Compare September 3, 2026 18:03
@tudorvasinca

Copy link
Copy Markdown
Author

Rebased onto current master (the branch had drifted into conflict): the FFI version moved to 9 (8 was taken by the chunked-embeddings work meanwhile), and two test call sites added upstream since (LocalModel::new in local.rs, load_model in ffi_test.rs) now pass the new max_input_tokens argument. cargo check --tests, the release build and the test suite (cap test + FFI tests) are green; the daemon side of manticoresoftware/manticoresearch#4857 is rebased on top and smoke-tested against this head (CREATE/INSERT/knn with a local model, SHOW CREATE, ALTER of the cap, validation). Sorry for resetting the approval with the force-push - it was the only way to resolve the conflicts.

…text (manticoresearch#4816)

Auto-embedding time grows superlinearly with input length and the only limit
was the model's own context window (32,768 tokens for Qwen3-Embedding-0.6B),
so a single long document could hold an embedding statement for minutes and,
under client retries, stack statements until the daemon ran out of memory
(manticoresoftware/manticoresearch#4816).

- ModelOptions.max_input_tokens (None = model limit); LocalModel::new applies
  min(model limit, cap) to every architecture's max_input_len, so all predict
  paths truncate on it. The cap can only lower the limit; 0 means no cap.
- FFI: load_model gains a trailing i32 max_input_tokens; EmbedLib version 4 -> 5.
- knn::ModelSettings_t::m_iMaxInputTokens, part of the model cache key, passed
  to load_model; SUPPORTED_EMBEDDINGS_LIB_VER 4 -> 5.
- Unit test test_max_input_tokens_cap (lowers, never raises, truncates).
@tudorvasinca
tudorvasinca force-pushed the issue-4816-max-input-tokens branch from 72fcbd3 to 9fef334 Compare September 4, 2026 06:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants