08 / Administration
AI infrastructure
On this page 14
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 provider-key page: paste a key, it is tested live and stored encrypted, active immediately. Since 4.8 it is the web editor for instance provider keys — Operate → System configuration → AI services shows a status card per provider (set from the environment / Helm, or overridden here) instead of its own password fields, and points here. Keys that arrive from the environment or a Helm secret still load with zero UI clicks. Personal credentials (a user's own Higgsfield pair or Anthropic key) are a different page: Manage → Assistants → Your AI accounts.
New on this tab:
- A2Agent 🇨🇳 (a2agent.me) is a provider card: Qwen3.8 MAX / Flash, DeepSeek V4 Pro / Flash and MiniMax M3 through one gateway key (
A2AGENT_API_KEY). - Google covers speech-to-text as well as Gemini chat / vision, Imagen, Veo and Gemini TTS.
- 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