Skip to main content

Natural-language search providers and API

The search-nlp integration turns query text into a validated search intent. For the map interaction and consent controls, see Natural-language search. Operators configure the provider chain and credentials in the integration's admin page.

Provider architecture​

Parsing runs through one ordered provider array, tried from left to right. The first provider that returns a valid structured intent wins. A failed or timed-out provider advances to the next definition. A valid low-confidence intent can still stop the provider chain; the client separately decides whether to offer it as a natural-language search. If the array contains no keyword definition, the deterministic keyword parser is appended automatically as the final safety net.

The default is entirely local:

[
{ "id": "local", "type": "ollama", "model": "gemma3:4b-it-qat" },
{ "id": "keyword", "type": "keyword" }
]
Provider typeWhat it connects toCredentialCloud
keywordBuilt-in deterministic parserNoneNo
ollamaOllama's OpenAI-compatible APINoneNo; public endpoints are rejected
anthropicAnthropic ClaudeanthropicApiKeyYes
openaiOpenAI Responses or Chat CompletionsopenaiApiKeyYes
googleGoogle GeminigoogleApiKeyYes
openrouterOpenRouter and its model/provider catalogueopenrouterApiKeyYes
openai-compatibleAny compatible local or hosted endpointcompatibleApiKey or noneDeclared by local

All model-backed providers use the AI SDK through direct provider instances. OpenMapX does not route them through the Vercel AI Gateway, so no Vercel account, gateway key, or gateway model identifier is involved.

Common provider fields​

Every definition has an operator-chosen id; it is not restricted to a fixed provider enum. This allows multiple models or endpoints of the same type in one chain.

FieldRequiredMeaning
idYesUnique lowercase identifier, 1 to 64 characters: letters, digits, ., _, and -
typeYesOne of the provider types listed above
labelNoOperator-facing/result label; otherwise derived from type and model
modelAll except keywordExact model identifier understood by that provider
timeoutMsModel-backed types onlyPer-attempt timeout, 250 to 120,000 ms; defaults to 10 seconds for Ollama and 3 seconds for the other adapters

Provider order is significant. Provider IDs must be unique even when their types differ. The full normalized definition participates in the intent-cache key, while the short-lived circuit breaker is isolated by provider ID. Definitions of the same built-in type share that type's vault credential; each definition can still select a different model, label, timeout, and position.

Provider-specific fields​

keyword has no additional fields.

TypeAdditional fields
ollamaOptional baseURL, which must use a private/local hostname or IP. OpenMapX appends /v1 and defaults to the enabled local-ai service, then http://localhost:11434.
openaiapi may be responses (default) or chat.
openrouterproviderOrder (default []), allowFallbacks (default true), dataCollection (deny by default), and zeroDataRetention (true by default).
openai-compatiblebaseURL, credential (compatibleApiKey by default, or none), supportsStructuredOutputs (default true), local (default false), and processor metadata for cloud endpoints.

The built-in Anthropic, Google, and OpenAI adapters need only their model and optional common fields.

Gemini​

Store googleApiKey on the Credentials tab, then put a Google definition in the array. This example tries Gemini, then local Ollama, then keyword parsing:

[
{ "id": "gemini", "type": "google", "model": "gemini-2.5-flash" },
{ "id": "local", "type": "ollama", "model": "gemma3:4b-it-qat" },
{ "id": "keyword", "type": "keyword" }
]

OpenAI and Anthropic​

[
{ "id": "openai-fast", "type": "openai", "model": "gpt-5-mini" },
{ "id": "claude", "type": "anthropic", "model": "claude-haiku-4-5" },
{ "id": "keyword", "type": "keyword" }
]

Set api: "chat" on an OpenAI definition only when the selected model or deployment requires Chat Completions. Anthropic definitions mark the stable system prompt for provider-side ephemeral prompt caching.

OpenRouter​

OpenRouter provides broad model coverage without adding a new OpenMapX adapter for every inference vendor. OpenMapX always asks OpenRouter to choose only routes that support the required parameters. Its defaults deny data collection and require zero-data-retention routes.

[
{
"id": "router",
"type": "openrouter",
"model": "google/gemini-2.5-flash",
"providerOrder": ["Google"],
"allowFallbacks": false,
"dataCollection": "deny",
"zeroDataRetention": true
},
{ "id": "keyword", "type": "keyword" }
]

providerOrder uses OpenRouter's provider identifiers. Keeping it empty lets OpenRouter select among compatible routes. Relaxing dataCollection or zeroDataRetention is an explicit operator decision; it may increase route availability but changes the privacy posture.

OpenAI-compatible endpoints​

Use this adapter for services such as vLLM, LM Studio, Groq, or another API that implements OpenAI-compatible chat completions. Give it a dedicated compatibleApiKey; standard OpenAI, Anthropic, Google, and OpenRouter secrets cannot be selected here, preventing accidental credential disclosure to a custom URL.

A local vLLM service can be configured without a credential:

[
{
"id": "vllm",
"type": "openai-compatible",
"model": "local-instruct-model",
"baseURL": "http://vllm:8000/v1",
"credential": "none",
"local": true,
"supportsStructuredOutputs": true
},
{ "id": "keyword", "type": "keyword" }
]

A cloud-compatible endpoint must use HTTPS and include processor disclosure metadata. OpenMapX uses that metadata to build the live privacy table:

[
{
"id": "groq",
"type": "openai-compatible",
"model": "llama-3.3-70b-versatile",
"baseURL": "https://api.groq.com/openai/v1",
"credential": "compatibleApiKey",
"local": false,
"processor": {
"id": "groq",
"name": "Groq",
"countryCode": "US",
"privacyUrl": "https://groq.com/privacy-policy/"
}
},
{ "id": "keyword", "type": "keyword" }
]

Set supportsStructuredOutputs to false if the compatible service accepts JSON mode but not OpenAI-style json_schema. OpenMapX still validates the returned object before using it.

Structured output and fallback behavior​

The AI SDK gives every model the same typed-output interface, but provider JSON Schema dialects differ. OpenMapX therefore uses a portable wire schema with required arrays and nullable variant fields to avoid unsupported schema unions, then normalizes and validates it against the stricter application intent schema.

Each attempt uses:

  • structured object output with schema validation;
  • temperature 0 and a 1,024-token output limit;
  • no SDK-level retry (maxRetries: 0), because the ordered chain owns fallback;
  • an explicit per-provider timeout; and
  • AI SDK telemetry disabled.

Invalid JSON, schema violations, provider errors, and timeouts all move to the next provider. A failed cloud provider opens a 60-second circuit breaker so subsequent searches do not repeatedly wait for an unhealthy service.

Cloud access is fail-closed at both the client and integration boundary:

  • privacyMode: strict always removes cloud providers, even if a client sends a positive cloud-consent signal.
  • privacyMode: consent (default) requires an explicit positive consent signal on every cloud-authorized request. Missing or unknown values mean local-only. Without remembered acceptance, the browser offers consent before a cloud-authorized parse. Remembered acceptance can authorize the first request; the request still carries the explicit signal.
  • privacyMode: open permits policy-deferred cloud access. The browser can authorize the first parse after reading integration disclosure metadata. A local-only parse followed by a retry also supports servers that disclose policy in the parse response. A remembered decline continues to win.

Only the query text and rounded map center are included in the model prompt. Account identity, exact device location, and the map bounding box are not sent. Cache keys include the complete provider chain and whether cloud was authorized, so a cloud-produced result cannot satisfy a local-only request.

When cloud is active, OpenMapX publishes secret-free processor metadata on the legal pages. Built-in providers supply their own metadata; custom cloud-compatible definitions must supply id, name, countryCode, and an HTTPS privacyUrl. See AI-assisted search disclosure.

Cloud is off by default

A cloud adapter must be present in providers, its credential must exist, and the active privacy policy must authorize the request. The shipped configuration has no cloud definition or cloud credential.

Administration and operational settings​

Configure search-nlp under /admin/integrations. Provider definitions are edited as JSON; the API validates nested objects, discriminated provider shapes, URLs, conditional processor requirements, bounds, and unknown properties before saving them. Credentials remain in the vault-backed Credentials tab. providers is the sole provider/model configuration surface; there is no parallel per-vendor model or endpoint setting.

SettingDefaultMeaning
providersLocal Ollama, then keywordOrdered definitions described above
privacyModeconsentstrict, consent, or open
roundCoordsDecimals2Coordinate precision included in the model prompt and intent cache key
intentCacheTtlSeconds86400Parsed-intent cache lifetime
rateLimitPerIpPerHour200Integration fixed-hour parse bucket limit; see the API notes below

Definitions whose required credential is absent are skipped with an operator warning. If the whole provider array is invalid, for example because of duplicate IDs or a public endpoint marked local, OpenMapX logs the validation error and uses the safe local-first defaults.

To run Ollama, enable the optional local-ai backend service. OpenMapX checks each configured Ollama model during setup and pulls a missing model as a best-effort background operation.

See Configuration for environment overrides and service resource settings.

Local inference needs RAM

The local-ai service reserves about 8 GB by default. A small instruction-tuned model such as gemma3:4b-it-qat can run on CPU; larger models benefit from a GPU. If you do not want local inference, use the keyword parser alone or configure a cloud provider under the desired privacy mode.

Parse API​

Custom clients can call POST /api/integrations/search-nlp/parse. The request body is:

{
"query": "wheelchair-accessible museums near the station",
"mapCenter": [13.405, 52.52],
"mapBbox": {
"south": 52.48,
"west": 13.32,
"north": 52.56,
"east": 13.49
},
"lang": "en",
"cloudAccess": "deny"
}

mapCenter is [longitude, latitude]. query, mapCenter, and mapBbox are required; lang is optional. cloudAccess is deliberately explicit and fail-closed:

ValueBehavior
denyLocal and keyword providers only; also the default for missing or unknown values
consentedAllows cloud in consent and open; strict still overrides it
defer-to-serverAllows cloud only when the operator selected open

The response includes the validated intent, its resolvedBbox, provider ID and label, whether that result used cloud, whether cloud is available under the current policy and needs consent, the available cloud provider labels, and whether the intent came from cache. A request rejected by the hourly limit returns 429 with Retry-After: 3600. The integration uses the forwarded ip query value when present and otherwise a shared anon bucket; the host dispatcher separately applies its trusted-peer throttle. This setting is not an atomic per-user quota. Parsing or spatial-resolution failure can return 502. The browser falls back to plain visible-area search when parsing fails or produces no plausible intent.

Intent application and area resolution​

near me maps to current_view in the model prompt. A near_place constraint uses the first registered geocoding provider; no provider or no result keeps the supplied viewport. Coordinate and named-place constraints resolve to a box with 0.02 degrees on each side of the center, rather than a guaranteed walking radius. A geocoder exception can fail the request.

The browser applies the returned filter, supported hours constraints, and sort order after accepting the intent. Unknown descriptive words do not become verified place attributes. Query edits, place selection, opening Directions, or disabling AI search invalidate the pending submission.

Troubleshooting​

SymptomCheck
Cloud definition never runsConfirm the matching vault credential exists, the provider is before keyword, and privacy mode/consent permits cloud.
Custom endpoint is rejectedCloud endpoints require HTTPS and processor metadata; local endpoints require a private hostname/IP.
Compatible endpoint rejects response_formatSet supportsStructuredOutputs to false.
Ollama requests use the wrong pathConfigure the Ollama server root; OpenMapX appends /v1.
Every model falls back to keywordInspect provider warnings for timeout, invalid model ID, or structured-output validation errors.
A recently failed cloud provider is skippedWait up to 60 seconds for its circuit breaker after correcting the underlying problem.
  • Search: the geocoding and category search that natural-language intents ultimately drive.
  • Places: the POI search and place panel that category results open into.