Skip to content
TÜBİTAK 1812 BİGGEnterprise AI with a source on every sentence

Engineering notesDecided

Turkish search: stems and meaning together

Semantic search alone misses clause numbers; keyword search alone misses suffixes. We fuse the two and rerank with a model evaluated on Turkish.

In Turkish the same word appears in dozens of forms: sözleşme, sözleşmede, sözleşmenin, sözleşmelerinden. Keyword search that does not reduce these forms to a stem cannot find the right page. Semantic search solves that but is weak elsewhere: rare, exact expressions such as clause numbers, names of laws and amounts.

So the two searches run together. On the semantic side a multilingual embedding model (bge-m3) turns every passage into a vector. On the keyword side OpenSearch has a Turkish analyzer with stemming; a query for "sözleşmede" finds the passage that says "sözleşmenin". The two lists are merged into one by reciprocal rank fusion (RRF).

Then reranking. The top thirty passages of the merged list are given to a cross-encoder together with the question, and the eight most relevant come to the top. We corrected a mistake of ours here: the model we first chose was trained English-first and did not rank Turkish. Today's model (bge-reranker-v2-m3) is multilingual; its int8 build agrees with the full build at 0.97 rank correlation on a Turkish gold set and ranks thirty passages in about 7 seconds on a laptop CPU.

The permission filter is not a step outside this flow; it travels to both engines with the query. A passage the user may not see never enters the candidate list. The returned list is checked a second time in the database.

On your own servers there is no external reranking service; the local model is the only leg. If the local model is missing too, the system does not hide it: it reports in the diagnostics that the ranking stayed fused.

Measure it on your own documents.

A two-week pilot: your sources are connected, the result is measured with your questions, and the report is yours.