#2954·typesense

[Feature Request] Make NL-search LLM facet-value collection and prompt-sample caps configurable (replace hardcoded 20/10)

Author: rowansailCreated Jun 15, 2026Updated Sep 14, 2026
Labelsfeature-request

Describe your feature request

Allow Typesense's natural-language-search pipeline to expose configurable caps for how many facet values are collected and how many are shown in the schema prompt sent to the LLM. In v30.2 these two limits are hardcoded inside generate_schema_prompt():

  • Collection cap (max facet values fetched): src/natural_language_search_model_manager.cpp — generate_schema_prompt(), call to coll->search(..., 20, ...) (around line 232)
  • Prompt display cap (values shown in the schema table): src/natural_language_search_model_manager.cpp — generate_schema_prompt(), loop that limits to 10 values: for (size_t i = 0; i < values.size() && i < 10; ++i) (around lines 270–274)

These are literals in the v30.2 source and currently cannot be changed at runtime without recompiling.

Request: add runtime-configurable controls for both caps (server-wide config and per-request override), plus an optional per-model/per-collection override so deployments that cannot recompile can raise the limits safely.

Proposed knobs (examples):

  • Server config (typesense.ini / CLI / env): nlp.max_facet_values (default: 20), nlp.schema_prompt_sample_values (default: 10), nlp.max_nl_filter_values (global safety upper bound, e.g. 1000)
  • Per-request query parameters: llm_max_facet_values (controls collection step), llm_schema_sample_values (controls how many are listed in prompt)
  • Per-model fields on /nl_search_models registration: max_facet_values and schema_sample_values so a model can opt-in to different behavior (these would be merged with server defaults)

Backward compatibility and safety:

  • Keep current defaults (20 and 10) unless overridden.
  • Enforce a global upper bound (server-configurable) to avoid accidental huge prompts/token blowups (e.g., default upper bound 1000).
  • Apply per-request overrides only when explicitly present; require admin-enabled flag to allow large per-request values in production builds.

Please describe your use-case for the feature request

We use Typesense NL search (nl_query=true on multi_search) with a Gemini model registered under /nl_search_models. Our categories field has ~1,200 unique values. In v30.2 the pipeline fetches up to 20 values and then only shows the first 10 in the schema prompt. This truncation prevents the LLM from seeing long-tail categories (e.g. user query "zadelhoes" should map to category fietszadelhoes) and results in missed mappings.

We will not compile a custom build. We need a purely runtime way to raise these caps so the LLM receives the broader set of values without changing Typesense binaries.

Describe alternatives you've considered

  • Recompiling Typesense with increased constants (works but not allowed in our environment).
  • Stuffing all values into the model's system_prompt (works and we validated it), but it's a per-model manual workaround that increases token usage on every request and isn't per-request/collection-scoped.
  • Pre-processing on the client side (e.g., client-side synonym mapping or multi-query patterns) — adds complexity and latency.

Additional context

  • File and code references (v30.2):
    • src/natural_language_search_model_manager.cpp — generate_schema_prompt(): coll->search(...) call contains the 20 literal used for collecting facet values (call parameters around line ~232 in v30.2 source).
    • src/natural_language_search_model_manager.cpp — generate_schema_prompt(): the enum-values loop uses i < 10 and appends ", ..." if more exist (loop around lines ~270–275 in v30.2 source).
  • The prompt generation is used before the model's token budget is applied (i.e., these caps happen prior to considering max_bytes), so simply increasing max_bytes does not solve the problem.

Thanks — opening this feature request on behalf of teams who need runtime control of NL-search facet sampling and prompt enumeration to handle long-tail facet values without recompiling.