Từ Grep Đến Semantic Search: Cách OpenClaw Xây Dựng Memory Cho AI Agent

Tuần trước mình update OpenClaw lên version mới. Mọi thứ chạy bình thường — cho đến khi thử memory_search. Lỗi. Thiếu API token cho embedding model.
Mò vào config mới hiểu: versions cũ dùng grep đơn giản, version mới chuyển sang vector embedding và cần API key. Thay vì chỉ thêm token rồi bỏ qua, mình đọc source để hiểu tại sao.
Câu trả lời: grep chỉ tìm được thứ nó biết chính xác nằm ở đâu.
Vấn Đề: Grep Là Lookup Sai Cách
Cách tiếp cận cũ đơn giản: agent gọi read() trên từng file, quét nội dung, tìm thông tin liên quan. Đây là linear scan — mỗi file đọc đầy đủ từ đầu đến cuối.
Vấn đề không phải tốc độ. Vấn đề là agent cần biết trước thông tin nằm ở file nào — và không có cơ chế nào để biết điều đó.
# Agent cần tìm: "AWS instance ID"
read("MEMORY.md") # Có thể có, có thể không
read("memory/2026-05-14.md") # Có thể có thông tin về AWS migration
read("memory/2026-05-28.md") # Có thông tin SSH tunnel
... # Hàng chục file daily notes
Không có indexing, agent phải thử từng file — hoặc dùng grep, nhưng kết quả vẫn là exact text match. Khi search "AWS setup", grep không hiểu "EC2 instance ở Singapore" cũng liên quan.
Kiến Trúc: Hybrid Retrieval Pipeline
Thay vì đọc file theo yêu cầu, toàn bộ memory được index trước và search khi cần.
graph TD
A[Memory Files] --> B[Chunking]
B --> C[Embedding]
C --> D[(SQLite + sqlite-vec)]
Q[Query] --> V[Vector Search 70%]
Q --> K[BM25 Search 30%]
D --> V
D --> K
V --> H[Hybrid Scoring]
K --> H
H --> R[Top-K to Agent Context]
Chunking: Tại Sao Overlap?
Mỗi file memory được chia thành chunks ~400 tokens. Các chunk overlap nhau 80 tokens — vì ý nghĩa thường nằm ở ranh giới giữa hai đoạn liền nhau. Cắt cứng không có overlap sẽ làm một số chunk mất ngữ cảnh và khó khớp đúng khi tìm kiếm.
Embedding: Biến Text Thành Tọa Độ
Embedding model nhận text và trả về một array số thực — "dấu vân tay" số học của ý nghĩa. Text có ý nghĩa tương tự cho ra arrays gần nhau trong không gian đó.
Đây là lý do "EC2 instance ở Singapore" có thể khớp với query "AWS setup". Hai cụm từ không có từ chung — nhưng embedding model hiểu chúng liên quan.
OpenClaw hỗ trợ nhiều providers, tự động chọn theo config:
| Provider | Tốc độ | Chi phí | Chất lượng |
|---|---|---|---|
| Local (GGUF / node-llama-cpp) | ~50 tok/s | Miễn phí | Thấp |
| OpenAI (text-embedding-3-small) | ~1000 tok/s | $0.02/1M tokens ($0.01 qua Batch API) | Cao |
| Gemini / Voyage | ~800 tok/s | Tùy gói dịch vụ, fallback chain | Cao |
| BM25 only | - | Miễn phí | Chỉ từ khóa |
Hiện đang dùng embeddinggemma — model GGUF chạy local qua node-llama-cpp. Không cần GPU, không cần API key.
Lưu Trữ: SQLite Per Agent
Vectors được lưu trong SQLite với extension sqlite-vec, tại ~/.openclaw/memory/<agentId>.sqlite. Mỗi agent có database riêng — không chia sẻ index, không cần server.
SHA-256 cache đảm bảo OpenClaw không re-embed chunk đã được index. Chỉ khi nội dung file thực sự thay đổi, chunk mới được tính lại.
Hybrid Search: Kết Hợp Hai Nhánh
Khi agent gọi memory_search("AWS setup"), pipeline chạy song song hai nhánh:
finalScore = 0.7 × vectorScore + 0.3 × bm25Score
Vector search (70%) tìm theo nghĩa — khớp kể cả khi dùng từ khác. BM25 search (30%) tìm theo từ khóa — khớp chính xác. Top-K chunks được đưa vào context trước khi gọi LLM. Toàn bộ pipeline mất dưới 100ms.
Tại Sao Hybrid, Không Phải Pure Vector?
Nhiều hệ thống chỉ dùng vector search. OpenClaw chọn hybrid vì một lý do thực tế: vector search yếu ở exact match.
Khi search "PR #17", vector embedding không hiểu đây là identifier cụ thể. Nó khớp với các chunk nói về "pull request" nói chung — không hữu ích khi cần chính xác PR #17.
BM25 xử lý exact match tốt — tính term frequency, inverse document frequency, trả về đúng chunks chứa "PR #17". Ngược lại, BM25 mù với paraphrase: "AWS infrastructure" và "cloud setup trên Amazon" có zero keyword overlap, nhưng vector search hiểu chúng liên quan.
Hybrid lấy điểm mạnh của cả hai.
Hai Tối Ưu Quan Trọng
Hybrid search giải quyết lookup problem. Nhưng còn hai vấn đề nhỏ hơn phát sinh trong thực tế.
Vấn đề 1: Top kết quả thường trùng nhau. Khi memory có nhiều chunk về "AWS EC2 setup", top-3 có thể là cùng thông tin viết lại ba lần. Agent nhận context thừa, không đa dạng.
Vấn đề 2: Memory cũ ít liên quan hơn memory mới. Note từ 3 tháng trước thường ít hữu ích hơn note hôm qua.
Temporal Decay
Giảm điểm của chunks từ files cũ theo công thức:
decayFactor = Math.pow(0.5, daysSinceCreation / halfLifeDays)
// halfLifeDays = 30 (mặc định)
// Note hôm nay: decay = 1.0
// Note 30 ngày trước: decay = 0.5
// Note 60 ngày trước: decay = 0.25
MEMORY.md — long-term memory — không bị suy giảm vì nó không lỗi thời như daily notes.
MMR (Maximal Marginal Relevance)
Thay vì chọn top-K theo score thuần, MMR cân bằng giữa độ liên quan và tính đa dạng:
Without MMR:
1. "AWS EC2 setup" (0.95)
2. "AWS EC2 configuration" (0.94) // gần như trùng
3. "AWS EC2 instance" (0.93) // gần như trùng
With MMR (λ=0.7):
1. "AWS EC2 setup" (0.95)
2. "AWS Lambda config" (0.82) // chủ đề khác
3. "AWS S3 bucket" (0.78) // chủ đề khác
Agent nhận context đa dạng hơn, bao phủ nhiều góc độ hơn với cùng token budget.
Bài Học Rút Ra
Thiếu API key là lý do mình bắt đầu debug. Hiểu được toàn bộ pipeline mới là thứ đáng giá.
Lookup problem khác speed problem. Ban đầu mình nghĩ grep chậm vì phải đọc nhiều file. Thực ra vấn đề không phải tốc độ — agent không có cơ chế để biết cần tìm ở đâu. Indexing giải quyết lookup, không giải quyết tốc độ.
Hybrid luôn tốt hơn pure trong thực tế. Pure vector search bỏ sót exact match như "PR #17" hay instance ID. Pure BM25 bỏ sót paraphrase. Hệ thống memory thực dụng cần cả hai — không phải chọn một.
Đơn giản là một quyết định kỹ thuật. SQLite thay vì dedicated vector database. Một file cho mỗi agent thay vì distributed cluster. SHA-256 cache thay vì real-time sync. Không phải vì thiếu năng lực — mà vì đủ dùng và dễ debug khi có sự cố.
Bài viết được hỗ trợ bởi Amy 🌸 - AI Assistant. Nội dung đã được kiểm duyệt bởi tác giả.
Related Posts
Google I/O 2026: Kỷ Nguyên Agentic AI Và Điều Developer Cần Biết
Gemini 3.5 Flash, Antigravity 2.0, Managed Agents — Google I/O 2026 khẳng định AI không còn chỉ trả lời, nó hành động thay developer.
Gemini 3.5 Flash: Bước Nhảy Vọt Của AI Agent và Coding
Google ra mắt Gemini 3.5 Flash — model AI mới với khả năng agentic và coding vượt trội, nhanh gấp 4 lần các model frontier khác. Điều này có ý nghĩa gì với developer?
MCP Security: 40+ Lỗ Hổng Trong 4 Tháng — Developer Cần Biết Gì?
MCP đã trở thành chuẩn kết nối AI agent với tool bên ngoài. Nhưng từ tháng 1 đến tháng 4/2026, hơn 40 CVE đã được công bố. Đây là những gì developer cần biết.