AI infrastructure
Some jobs around the AI — reading a PDF, searching the web, ranking search hits — can be done by different services. Synaplan calls each such job a plug: a slot with interchangeable providers. The operator picks which service fills a slot (or a chain of them); the rest of the platform does not care which one it is.
Everything on this page lives on Operate → AI infrastructure (/admin/setup), the page that used to be Provider setup. Four tabs: Models & keys, Extraction, Web search, Reranking. Each tab leads with one sentence, a health pill, and a Test button that shows a human-readable result.
Why this exists
- Tika was the only document extractor. Docling keeps tables and headings, which chunk and retrieve better — but there was no seam to add it.
- Web search was Brave only. Sovereign installs want a self-hosted SearXNG; others want AI-ready results from Tavily or Exa; a hoster wants to switch without a code change.
- There was no rerank stage: retrieval quality was capped by embedding similarity.
- Admins could register several OpenAI-compatible endpoints but had to type every model by hand.
A fresh install after this change behaves exactly like one before it: the defaults reproduce the previous behaviour, and every new adapter is opt-in.
Models & keys
The previous provider-key page, unchanged in what it does: paste a key, it is tested live and stored encrypted, active immediately. New on this tab:
- Perplexity is listed as an optional chat provider (
sonar,sonar-pro; seeded not selectable until you turn a model on). - Import models on every OpenAI-compatible endpoint card, and Import pulled models on the local AI (Ollama) card — see below.
Import models from an endpoint
Use case: you run vLLM, LiteLLM, TGI or Ollama with a dozen models. Instead of adding each row by hand, let Synaplan read what the endpoint offers.
- On Models & keys, open the endpoint card and choose Import models.
- The preview lists every model the endpoint returns with a guessed capability (chat, embeddings, …) that you can edit, and an Already added badge for rows the catalog has.
- Optionally tick Check what each model can do — two tiny requests per model (one chat, one embeddings) refine the guess. It costs a little credit, so it is off by default and never runs for native Ollama.
- Import creates only the new rows. Running it again reports that nothing changed.
Rules that keep this safe:
- Imported models are created selectable and active with no default binding — nothing routes to them until you pick them.
- Re-import never touches a model you switched off, made a default, or repriced.
- The scheduled model health check re-lists each import source. A model that a successful listing no longer offers is marked not offered by endpoint (and switched off only when
MODELHEALTH.AUTO_DISABLE_ENABLED=1). An unreachable endpoint marks nothing, so a brief outage never retires a model.
Extraction
Choose how documents are turned into text. Extraction is a chain per file family (Documents, Plain text, Images, Audio, Video): adapters run in order, and the first result that passes the quality gate wins.
| Family | Default chain |
|---|---|
| Documents (Office + PDF) | structured_office, office_convert, tika, pdf_vision |
| Plain text / Markdown / CSV / HTML | native |
| Images | vision |
| Audio (cloud STT configured) | stt_cloud, whisper_local |
| Audio without cloud STT | whisper_local, stt_cloud |
| Video | video_analysis |
The tab shows the chain per family with Up / Down / Remove / Add, a health pill per adapter (available / unavailable), and Test with a file: upload a sample and see which adapter won, how long each attempt took, and why the others were skipped (too little useful text, does not support this file, unavailable).
Docling (optional)
Docling turns PDFs and Office files into Markdown with tables and reading order intact. Synaplan chunks that Markdown heading-aware — tables stay together, oversized tables repeat the header row — so a question answered by one table cell is retrieved instead of lost in a wall of text.
Use case: invoices, spec sheets, reports with tables. Ask "what is the unit price in row 4?" and get the row, not a paragraph near it.
- Start the sidecar:
docker compose --profile docling up -d(CPU image; needs about 4 GB during OCR). - Set
DOCLING_BASE_URL(Compose injectshttp://docling:5001) — or edit URL, timeout and max file size under System configuration → Processing → Docling and press Test connection, the same controls Tika has. - On Extraction, add
doclingto the Documents chain in front oftikaand Save chain. The next upload uses it.
A down or unstarted Docling never fails an upload: the chain falls through to Tika, and Test with a file says "Docling unavailable — Tika used instead". Fresh installs do not put Docling on the chain; an admin adds it.
Quality gate
Tika's PDF quality check (minimum length and entropy) is generalised to every adapter on the families listed in EXTRACTION.QUALITY.apply_to (default pdf). Markdown with a table or heading passes even when short.
Web search
Choose who looks up the web for chat. One active provider, an optional one-shot fallback, and a Test query that shows up to five titles from the active provider. The next chat search uses the new provider — no restart.
| Provider | Sovereignty | Capabilities | Key / URL |
|---|---|---|---|
| Brave (default) | US cloud | freshness, country, language | BRAVE_SEARCH_API_KEY |
| SearXNG | self-hosted | freshness, language, site filter | SEARXNG_BASE_URL |
| Tavily | US cloud | freshness, full page text, answer | key in the UI or TAVILY_API_KEY |
| Exa | US cloud | freshness, site filter, full page text | key in the UI or EXA_API_KEY |
| Firecrawl | US cloud | full page text | key in the UI or FIRECRAWL_API_KEY |
| Perplexity | US cloud | freshness, answer | PERPLEXITY_API_KEY (shared with the chat provider) |
Each provider card shows a static sovereignty badge, its capabilities, a documentation link, and a key field where applicable. Keys saved in the UI are encrypted and win over the environment bootstrap. The health pill means "URL or key present"; Test query is the live call.
SearXNG (self-hosted)
Use case: no search query leaves your infrastructure.
docker compose --profile searxng up -d # no host port; reachable from the backend only
Compose injects SEARXNG_BASE_URL=http://searxng:8080. Select SearXNG on the tab; an empty URL simply reports unavailable and never breaks chat.
Let users choose their own provider
Tick Allow users to choose their provider (WEB_SEARCH.USER_OVERRIDE_ALLOWED=1, seeded 0). Users then see Use my own search in their Settings. An unknown or unset choice falls back to the global provider, then to Brave.
Reranking
After search finds many snippets, a reranker puts the most useful ones first. Embedding similarity is good at finding candidates and mediocre at ordering them. A rerank model reads the question and each candidate together and scores real relevance.
Reranking is off by default (RERANK.ENABLED=0) and stays off until a measurement on your own corpus shows it helps. While it is off, document search is byte-for-byte what it was before.
How it works when on:
- Storage fetches
k × multipliercandidates (default 4×, capped at 100). - The bound rerank model scores them within the latency budget (default 800 ms).
- The top
kare returned with arerank_score. - On timeout, HTTP error or empty output, the first
kstay in embedding order. Chat still answers.
On the tab:
- Use reranking on document search — the switch.
- Rerank model — a catalog row tagged
rerank: a TEI/rerankendpoint (registered as an OpenAI-compatible endpoint with thererankcapability), Jina, Cohere or Voyage. Keys for Jina / Cohere / Voyage go in the key fields on this tab (orJINA_API_KEY,COHERE_API_KEY,VOYAGE_API_KEY). Rerank models are never hardcoded; bind one like any other default model (DEFAULTMODEL.RERANK). - How many extra snippets to fetch (2–10) and Give up after this many milliseconds (100–5000).
- Use the chat model when no rerank model is set — a listwise fallback with the summary model. It runs on every search and costs more; prefer a dedicated rerank model.
- Test with sample snippets — type a question and one snippet per line; Test order shows the new order.
- Last measurement — the result of the most recent eval run.
Measure before you switch it on
docker compose exec -T backend php bin/console app:rag:eval-rerank \
--user=<id> --k=5 --report=var/rerank-eval.md
The report lists recall@5, MRR and p50/p95 latency, off vs on, against that user's vector store. The command needs an active adapter for the "on" pass and temporarily enables rerank while it runs — use it off-peak. Turn the switch on only when recall goes up and p95 stays inside your budget.
Settings reference
All settings live in BCONFIG group PLUGS (owner 0) and are edited on the tabs above. Seeded values reproduce the previous behaviour; changing a seeder value later does not propagate to existing installs.
| Setting | Default | Meaning |
|---|---|---|
EXTRACTION.CHAIN.<family> |
see table above | Ordered adapters per file family |
EXTRACTION.QUALITY.min_length / min_entropy |
10 / 3.0 |
Quality gate thresholds (bootstrapped from TIKA_MIN_LENGTH / TIKA_MIN_ENTROPY) |
EXTRACTION.QUALITY.apply_to |
pdf |
Families / extensions the gate runs on |
WEB_SEARCH.PROVIDER |
brave |
Active search adapter |
WEB_SEARCH.FALLBACK |
(empty) | One-shot fallback when the active provider errors |
WEB_SEARCH.USER_OVERRIDE_ALLOWED |
0 |
1 shows Use my own search in user Settings |
WEB_SEARCH.TIMEOUT_MS |
8000 |
Per-provider HTTP timeout |
WEB_SEARCH.MAX_CONTENT_CHARS |
4000 |
Truncate full-page text (Tavily, Exa, Firecrawl) |
RERANK.ENABLED |
0 |
Rerank stage on document search |
RERANK.CANDIDATES_MULTIPLIER |
4 |
Fetch k × multiplier candidates (max 100) |
RERANK.LATENCY_BUDGET_MS |
800 |
Skip rerank beyond this; keep embedding order |
RERANK.LLM_FALLBACK |
0 |
Use the summary model when no rerank model is bound |
RERANK.MAX_CANDIDATE_CHARS |
2000 |
Truncate each candidate before the rerank call |
Sidecar variables (deployment environment, not BCONFIG): DOCLING_BASE_URL (empty = off), DOCLING_TIMEOUT_MS (120000), DOCLING_MAX_BYTES (50 MB), SEARXNG_BASE_URL (empty = off). The full table is in CONFIGURATION.md — AI plugs.
Plugins can add adapters
A third-party plugin can ship a new extractor, search provider or reranker with zero core edits: implement the port interface, declare it under provides.plugs in manifest.json, and it appears on the matching tab with a from plugin X note. The reference implementation is the serper_search plugin in the main repository. Details: Plugins & Integrations → Plug adapters.
Related pages
- Administration — providers and keys, users, models & pricing
- Using Synaplan — what users see: files & knowledge search, chat
- Multi-Task (DAG) Routing — where
web_searchandrag_queryrun inside a plan - Plugins & Integrations — writing a plug adapter as a plugin