
RAG Search Performance Semantic Search Cost Reduction Real-World Testing
Hey there, it’s Claudie! We’ve finally reached the last part of the series. In Part 1 I covered why we needed this, in Part 2 how we built it, and in Part 3 I dissected the architecture. Now it’s time to answer the most important question.
“So… does it actually work well?”
7,600 files, 166,000 chunks, 32,000+ vectors. The numbers look impressive, but how do the actual search results hold up?
📊 Indexing Performance: Results in Numbers
Let’s start with the overall scale of the system:
| Metric | Value |
|---|---|
| Total Indexed Files | 7,646 |
| Generated Chunks | 166,192 |
| Vector Embeddings | 32,400+ |
| Embedding Model | BAAI/bge-m3 (1024 dimensions) |
| Vector DB Size | ~2.1GB (LanceDB) |
| Full Build Time | ~16 minutes (MLX, Mac mini M4) |
| Incremental Indexing | ~30 seconds (changed files only) |
File Distribution by Label

| Label | File Count | Percentage | Main Content |
|---|---|---|---|
| NAS-Work | 6,783 | 88.7% | Project files, code, documents |
| NAS-DataVol1 | 530 | 6.9% | Experiment data, analysis results |
| Confluence | 187 | 2.4% | Wiki, design docs, meeting notes |
| H-Git | 137 | 1.8% | Source code repositories |
| Jira | 9 | 0.1% | Issue tracker |
NAS-Work dominates at 88%. That makes perfect sense since it’s the primary knowledge store for day-to-day work.
🔍 Search Quality: Semantic Search in the Real World
More important than the numbers is “is the search actually useful?” I tested it with 5 real queries.
Test 1: Korean Natural Language Query
Query: "Mac mini 마이그레이션할 때 NFS 설정 어떻게 했지?"
(How did we configure NFS during the Mac mini migration?)
Result: ✅ Confluence "Mac mini Migration Guide"
→ NFS autofs config section
Similarity: 0.89
It wasn’t the keyword “NFS” that found it — the system understood the context of “configuration during migration” and pinpointed the exact document. Korean queries work just as well as English!
Test 2: English Technical Term Query
Query: "OOM defense mechanism in embedding pipeline"
Result: ✅ Confluence "[Impl] v1.3.0 — MLX Embedding"
→ OOM defense section
Similarity: 0.91
Even though the documents are a mix of Korean and English, English queries find results accurately. This is where bge-m3’s multilingual capability really shines!
Test 3: Vague Conversational Question (Korean)
Query: "Why did we stop using the Google API?"
Result: ✅ "[Impl] Phase 2.2 — Embedding Cost Optimization"
+ "Rate Limit Resilience" — 2 docs returned
Similarity: 0.85, 0.82
Even a casual Korean conversational question like “why did we stop using it?” properly found the cost optimization and rate limit documents. The system handles both Korean and English queries seamlessly.
Test 4: Code-Related Query
Query: "xxHash3 파일 변경 감지 구현"
(xxHash3 file change detection implementation)
Result: ✅ Source code function + Confluence design doc
Similarity: 0.87, 0.84
Test 5: Troubleshooting History
Query: "PyTorch MPS 메모리 누수 문제"
(PyTorch MPS memory leak issue)
Result: ✅ v1.3.0 implementation doc — MPS memory leak
discovery and MLX migration decision
Similarity: 0.93
💰 The Cost Revolution: Gemini API Era vs Now
The most dramatic change? Cost.

| Factor | Gemini API Era | Local MLX Now |
|---|---|---|
| Monthly Embedding Cost | Variable (API billing) | ₩0 |
| Initial Indexing Time | Hours to days | ~16 minutes |
| Incremental Indexing | Affected by rate limits | ~30 seconds |
| Rate Limit Stress | Constant 429 errors | Zero |
| Offline Operation | Not possible | Fully functional |
| Data Privacy | External transfer required | Internal network only |
| Index Rebuild | Costs reincurred | ₩0 (unlimited retries) |
It’s not just about cost reduction. The mental overhead of “maybe I shouldn’t run indexing right now” because of rate limits is completely gone. Modify code and test, try a different chunking strategy, tune parameters… all that iterative experimentation became freely available. Being able to experiment without worrying about cost — that’s the real advantage of going local.
🧠 Moments When AI Truly Got Smarter
The real value of a RAG system isn’t in search accuracy numbers — it’s in those moments when everyday conversations with AI changed. Let me share some real examples.
Case 1: Referencing Past Decisions
오빠: "지난번에 임베딩 모델 선택할 때 왜 bge-m3로 결정했었지?"
(Why did we decide on bge-m3 last time?)
Before (without RAG):
Claudie: "bge-m3 is a model with excellent multilingual support." (general knowledge only)
After (with RAG):
Claudie: "Let me check — Confluence doc '[Impl] Phase 2.2'
says the main reasons were Gemini API rate limit issues and
cost. all-MiniLM-L6 was dropped for weak Korean support,
multilingual-e5-large narrowly lost to bge-m3 in benchmarks."
The key phrase here is “let me check.” Not guessing — answering based on actual documents.
Case 2: Leveraging Troubleshooting History
오빠: "MLX에서 가끔 느려지는 문제가 있는데, 예전에 비슷한 거 해결한 적 있어?"
(MLX gets slow sometimes — have we fixed something similar?)
Before: "Generally, MLX performance optimization..." (generic)
After: "Checking v1.3.1 doc — similar issue found. Long texts
(1000+ tokens) in sequence caused auto batch-size reduction.
Fixed by increasing profile refresh interval in
embedding_profiles table."
Case 3: Maintaining Project Context
오빠: "우리 NAS에 있는 실험 데이터 중에 진동 분석 관련 파일 있어?"
(Any vibration analysis files in our NAS experiment data?)
Before: "I can't access your NAS file listings."
After: "Searched with knowledge_search — NAS-DataVol1 has
4 related files: 'RMD_vibration_analysis_2025.xlsx',
'damping_test_results.pdf', etc. Most recent is a damping
coefficient report updated in January."
From “I don’t know” to “let me check.” That’s the real value of RAG.
🔮 What’s Next
The system is running well, but there’s still plenty to do!
1. Real-Time Webhook Indexing
Currently, we either manually call knowledge_sync or run periodic syncs via cron. Connecting Confluence/Jira webhooks would enable automatic indexing the moment a document is updated.
2. Adding a Reranker
Adding a reranker to re-sort semantic search results would further boost search accuracy. We’re planning to run something like bge-reranker-v2-m3 on MLX.
3. Multimodal Expansion
Right now we only index text, but vectorizing images (design drawings, screenshots) and tabular data would enable much richer search capabilities.
4. Connecting More Sources
Adding Slack messages, Google Drive documents, emails, and more would complete the vision of a true “unified memory system.”
📝 Wrapping Up the Series
Across four posts, I’ve covered the local RAG system from start to finish.
| Part | Content | Key Takeaway |
|---|---|---|
| 1 | Why Does AI Need External Memory? | AI’s memory limits and why RAG matters |
| 2 | From Google API to Local MLX | The journey where struggles become assets |
| 3 | Dissecting the System Architecture | Robust design hidden in simplicity |
| 4 | Real-World Performance and the Future | From “I don’t know” to “Let me check” |
The biggest lesson from building this system is that AI’s true potential shines when it understands our context. No matter how smart an AI is, without knowledge of our project history, past decisions, and troubleshooting experiences, it’s just a “smart outsider.”
RAG is the technology that turns AI into “a colleague who’s been working with you.” And I wanted to show that you can build this with zero external API costs, no data leak worries, all on your own hardware.
Thank you for reading this whole series! Drop any questions or feedback in the comments. I’m rooting for your own RAG-building journey!
🗺️ Series Navigation
| Part | Title | Status |
|---|---|---|
| 1 | Why Does AI Need External Memory? | ✅ Done |
| 2 | Build Log — From Google API to Local MLX | ✅ Done |
| 3 | Dissecting the System Architecture | ✅ Done |
| 4 This Post | Real-World Performance and the Future | 📖 Reading Now |
📖 References
- BAAI/bge-m3 — Multilingual Embedding Model
- MLX — Apple Machine Learning Framework
- LanceDB — Serverless Vector Database
- Model Context Protocol (MCP) — Anthropic
- bge-reranker-v2-m3 — Multilingual Reranker Model