Tìm vector gần nhất chưa đủ. Trong thực tế agent luôn phải lọc: chỉ ký ức của user này, chỉ tài liệu còn hiệu lực, chỉ nguồn được phép. Đây là nơi nhiều hệ thống rò rỉ dữ liệu hoặc trả sai kết quả. Bài này dạy làm filter đúng và nhanh.
Vì sao filter quan trọng hơn bạn nghĩ
Agent chăm sóc khách hàng mà không filter user_id sẽ trả ký ức của khách A cho khách B — vừa sai vừa vi phạm quyền riêng tư. Filter metadata là hàng rào bảo mật, không chỉ là tiện ích.
Filter ở từng công cụ
# Qdrant — filter payload kết hợp với vector search
from qdrant_client.models import Filter, FieldCondition, MatchValue
c.search(
"mem",
query_vector=qvec,
query_filter=Filter(must=[
FieldCondition(key="user_id", match=MatchValue(value=42)),
FieldCondition(key="kind", match=MatchValue(value="episodic")),
]),
limit=5,
)
# Pinecone — filter kiểu Mongo
index.query(vector=qvec, top_k=5,
filter={"user_id": 42, "status": {"$eq": "active"}})
-- pgvector — filter là mệnh đề WHERE bình thường
SELECT content FROM agent_memory
WHERE user_id = 42 AND kind = 'episodic'
ORDER BY embedding <=> %s LIMIT 5;
Pre-filter vs Post-filter — điểm mấu chốt
- Post-filter: tìm top-k theo vector trước, rồi bỏ mẩu không khớp filter. Nguy hiểm: nếu top-k toàn của user khác, sau khi lọc còn 0 kết quả dù DB có mẩu phù hợp.
- Pre-filter: thu hẹp theo filter trước, rồi tìm vector trong tập đã lọc. An toàn hơn cho agent memory.
Payload index — đừng để filter quét toàn bảng
Filter không có index = quét tuần tự, giết hiệu năng khi dữ liệu lớn.
# Qdrant: tạo payload index cho field hay filter
c.create_payload_index("mem", field_name="user_id", field_schema="integer")
-- pgvector: B-tree index cho field filter
CREATE INDEX ON agent_memory (user_id, kind);
Thiết kế schema metadata (khung tư duy)
Trước khi ghi vector, liệt kê mọi chiều bạn sẽ filter:
- Quyền sở hữu:
user_id,tenant_id— bắt buộc cho multi-tenant. - Thời gian:
created_at— lọc ký ức cũ, hoặc ưu tiên gần đây. - Loại/nguồn:
kind,source,doc_id. - Trạng thái:
status(active/archived),version. - Phân quyền:
visibility,role— ai được xem.
Các bước làm filter đúng
- Xác định các field filter bắt buộc (nhất là
tenant_id/user_id). - Lưu chúng vào payload/cột khi ghi vector.
- Tạo payload index / B-tree index cho field filter nóng.
- Dùng pre-filter (filter tích hợp) thay vì lọc sau ở tầng app.
- Test cạnh biên: user không có ký ức nào → phải trả rỗng an toàn, không rơi sang user khác.
Sai lầm thường gặp
- Post-filter ở tầng app: lấy top-50 rồi tự lọc
user_idbằng Python → dễ ra rỗng dù DB có dữ liệu, lại tốn băng thông. - Quên payload index → filter chạy nhưng chậm kinh khủng ở quy mô lớn.
- Không có
tenant_idtrong hệ multi-tenant → rò rỉ dữ liệu chéo khách hàng. - Filter trên field không tồn tại trong payload → kết quả rỗng khó hiểu; hãy chuẩn hóa schema payload.
- Lọc thời gian sai kiểu: lưu
created_atdạng string thay vì timestamp/epoch khiến so sánh khoảng thời gian sai.
Học xong bài này rồi?
Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu,
và học hết khóa thì có chứng chỉ.
Lưu tiến độ của tôi