Metadata filters: who may see which documents
Staff documents must not reach customers through the assistant. A metadata filter limits retrieval to chunks the asker may see.
A staff-only document joins the help centre, in its own folder:
# Refund approvals (staff only)
Refunds over 200 need a team lead's approval before they are paid. Refunds for customers flagged for abuse must be sent to the fraud team.from llama_index.core import Settings
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
Settings.embed_model = HuggingFaceEmbedding(model_name="sentence-transformers/all-MiniLM-L6-v2")
import os
from llama_index.core import SimpleDirectoryReader, VectorStoreIndex
def with_audience(path):
audience = "staff" if "/staff/" in path else "customer"
return {"file_name": os.path.basename(path), "audience": audience}
documents = SimpleDirectoryReader(".", recursive=True, required_exts=[".md"], file_metadata=with_audience).load_data()
for document in documents:
document.excluded_embed_metadata_keys = ["audience"]
document.excluded_llm_metadata_keys = ["audience"]
index = VectorStoreIndex.from_documents(documents)with_audience marks each file staff or customer by its folder. recursive=True reads both folders. The audience key is excluded from embedding and from the prompt: it controls access, it is not content.
retriever = index.as_retriever(similarity_top_k=2)
print("no filter: ", [n.metadata["file_name"] for n in retriever.retrieve("Who approves a large refund?")])
from llama_index.core.vector_stores import ExactMatchFilter, MetadataFilters
customers_only = MetadataFilters(filters=[ExactMatchFilter(key="audience", value="customer")])
retriever = index.as_retriever(similarity_top_k=2, filters=customers_only)
print("customer: ", [n.metadata["file_name"] for n in retriever.retrieve("Who approves a large refund?")])Unfiltered, a customer asking about large refunds gets the staff approval rules first, internal fraud process included. With filters, the staff document is not a candidate at all, so it cannot be retrieved however similar it is.
Filter by who is asking, on the server. The filter must come from the logged-in user's role, set by your application, never from something the user can type. The SSO, OAuth and RBAC topic covers where that role comes from.
MetadataFilters interface; check yours before relying on one.- Make a filter for
staffand ask the same question. - Add a third audience,
partner, and a document for it. - Use the customer filter in a query engine with
ExtractiveLLM.
You understood something today that you didn't yesterday.