Lesson 8 / 25

Retrieval Settings: Search Mode, Top K and Threshold

Tune what comes back.

Vector, full-text or hybrid

The knowledge retrieval node searches the knowledge base with the query. Settings typically include search mode (vector/semantic, full-text keyword, or hybrid combining both, optionally with a reranker model), top K (how many chunks to return) and a score threshold (drop weak matches). Keyword matching fails on synonyms and can latch onto common words; vector search handles paraphrases but can miss exact codes and names, which is why hybrid search with reranking is a common default for production. Dify's node names, menus and options change between versions; check the current Dify documentation.

Keyword retrieval with top K and a threshold, run

I ran this with plain Python 3 (scikit-learn 1.9.1 where imported). It models or tests one piece of a Dify app locally; Dify itself was not running. A TF-IDF model of keyword search over five chunks: reset password correctly returns the password chunk (0.69). How many days for a refund ranks the shipping chunk first because both mention days, and an off-topic office address question still matches the password chunk (0.25) through the word your. The fixes are hybrid search, a reranker and a well-chosen threshold.

import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
chunks = ["Refunds are issued within 14 days of receiving the returned item.",
          "Shipping inside India takes 3 to 5 working days.",
          "To reset your password open Settings, then Security, then Reset password.",
          "Enterprise plans include priority support with a 4-hour response time.",
          "Invoices can be downloaded as PDF from the Billing page."]
vec = TfidfVectorizer().fit(chunks)
def retrieve(query, top_k=3, threshold=0.2):
    s = (vec.transform([query]) @ vec.transform(chunks).T).toarray()[0]
    ranked = sorted(enumerate(s), key=lambda x: -x[1])[:top_k]
    return [(i, round(float(sc), 2)) for i, sc in ranked if sc >= threshold]
for q in ["how many days for a refund", "reset password", "what is your office address"]:
    print(f"{q!r:<30} -> {retrieve(q)}")

Output:

'how many days for a refund'   -> [(1, 0.32), (0, 0.25)]
'reset password'               -> [(2, 0.69)]
'what is your office address'  -> [(2, 0.25)]

Test retrieval separately

Use the knowledge base's retrieval test (hit testing) with real questions before wiring it into an LLM node.

Quick check: Why can keyword search return the wrong chunk for "how many days for a refund"?

  • Refund chunks cannot be indexed
  • Keyword search always returns nothing
  • It matches shared words like "days" without understanding meaning
  • Top K must be zero
Answer

It matches shared words like "days" without understanding meaning — Hybrid search and reranking help.