Skip to content
V-Smart.

A private search engine for your model, with no middleman accounts

A language model knows the world up to the day its training ended. To answer questions about today, it has to be able to search. We built our own search engine for this on the same machine — and along the way measured how much work it takes to get results in Polish, our native language.

How the model searches at all

Contrary to appearances, the model has no access to the internet. It works differently, and it is worth understanding, because it affects the privacy of the whole setup.

At the start, the model is told that two tools exist: one returns a list of search results, the other fetches the content of a given page. When it decides a question needs fresh data, it does not execute anything itself — it writes out a request: “call the search with phrase X”. A program on the user’s side carries out that request, queries our search engine and pastes the results back into the conversation. The model reads them like ordinary text and forms an answer.

All the traffic therefore goes through our machine. No model provider sees the question, or what was done with the answer.

What sits underneath

The search layer is SearXNG — an open-source metasearch engine that we run ourselves. It queries an external source (in our case the official Brave search API, on a key) and returns a unified list of results. The external provider sees the query, but not who is asking, or why, or what happened earlier in the conversation. There is no user account, no history, no profiling.

One configuration trap worth noting, because it cost us some time: we chose an engine that uses the official API, not one that scrapes the results page automatically. The latter approach is often the default in similar installations and gets blocked after a dozen or so queries.

Results in your language take two settings, not one

By default such an installation answers with English-language results, even to a Polish query. We measured this on a technical phrase, counting the Polish results among the first twenty:

Language settingPolish results out of 20
none / “all”0
language code only (“pl”)10
full locale (“pl-PL”)17

The difference between “pl” and “pl-PL” is not cosmetic — it is seven results out of twenty. The same applies to whatever locale you use at home. And you have to set two layers: the server’s default value and the parameters passed to the engine itself. Changing only one of them is not enough, because the other gets overridden by the client.

The model can override this for a single query — and does so sensibly, switching to English when it looks for technical documentation.

The default result was too thin — so we patched the engine

The standard version of the engine keeps only a short description from each result — two sentences, often cut off mid-key-sentence. Meanwhile, the provider also returns extra excerpts from the page’s content that nobody asked for and that were simply being thrown away.

We replaced that piece with our own version, which stitches these excerpts together and attaches them to the result. The effect is about 4.7 times more text per result. The model gets real content instead of a teaser, so it more often answers right away, without fetching whole pages.

The second change is small but solves a frequent problem: in front of every result we prepend the publication date. Without it, the model has no way to tell a five-year-old guide from this year’s, and it regularly confused software versions.

When the model digs deeper

Our system instruction includes a rule: if the excerpts are cut off, contradictory, or missing the specific fact being sought — fetch the whole page. This resolves the situations where the results list pretends to be an answer but does not contain one.

A detail worth imitating: we describe the rule by the tool’s role, not its name (“takes an address, returns content”). Different programs name this tool differently, and an instruction tied to the name stops working after a change of client.

What it costs in context

Fresh data is not free — it takes up room in the conversation’s memory:

  • one search with full excerpts: about 4 thousand tokens,
  • fetching a whole page: as much as a dozen-plus thousand.

With a context of 262 thousand tokens that is a comfortable position: a dozen or so searches in one conversation barely registers. On a machine with a small context, this is exactly where the fun would end — and it is one of the reasons it was worth fighting for context capacity.

What this gives you in practice

Three things, in order of importance for a home user:

Freshness. The model stops making things up when asked about new developments, because it has a way to check.

Privacy. Queries build no advertising profile and no history tied to an account. The only thing that leaves the house is the search phrase itself, without the context of the conversation.

Independence. The search engine is replaceable — the source can be swapped without touching the models and without waiting for a provider to change its mind about pricing or terms.


Our own setup, on the same machine as the models. The result-language measurements were made on our own instance.