10 KiB
Phase 10 — Scalable Tool Index for 1,200–10,000+ Tools
وضعیت: ایندکس مشتقشده در کد است. Retrieval Production هنوز همان Ranker کامل روی Authorized universe است.
تاریخ: ۲۱ اوت ۲۰۲۶
نتایج: evals/phase-10/latest.json · evals/tool-scale/latest.json
Scale the candidate retrieval layer, not the LLM tool surface.
The model should remain unaware of the size of the global Tool Catalog.
Fast retrieval finds candidates; the existing ranker decides relevance; Security decides authorization; the LLM only sees the final small schema set.
Vector retrieval is a candidate generator, not an authorization mechanism and not the final ranking authority.
1. Phase 9 findings
- Adaptive K روی Gold ارزان است (Avg K ≈ ۱۰.۱۹، Recall ۹۶.۶۱٪) ولی HOLD ماند چون ترافیک زنده صفر بود.
- Hybrid از Keyword بهتر نیست → OFF.
- Semantic linear در ۱۰٬۰۰۰ Tool ≈ ۲s → برای Production ممنوع.
- Inverted prototype در Bench حدود ۱۲ms بود — فقط Prototype داخل
ai_tool_scale_bench، نه ایندکس واقعی.
Production flags بعد از Phase 9 (و این Phase) بدون تغییر:
PROGRESSIVE_SCHEMA_LOADING = False
ADAPTIVE_DISCOVERY_K = False
ADAPTIVE_K_ROLLOUT_PERCENT = 0
HYBRID_TOOL_DISCOVERY = False
INDEXED_CANDIDATE_RETRIEVAL = False
VECTOR_CANDIDATE_RETRIEVAL = False
Analyzer = 48 / Autonomous = 128
2. Scaling problem
| Size | Keyword linear | Inverted query | Semantic linear |
|---|---|---|---|
| 180 | ~۴۰ms | ~۶ms | ~۳۸ms |
| 1,200 | ~۹۱ms | ~۶ms | ~۲۴۲ms |
| 5,000 | ~۲۹۳ms | ~۹ms | ~۹۹۹ms |
| 10,000 | ~۵۴۷ms | ~۱۳ms | ~۲۰۵۹ms |
| 100,000 | skipped | ~۱۱۰ms | skipped |
O(N) semantic و حتی keyword scan برای ۵k+ روی مسیر آنلاین قابل قبول نیست. Schema Top-15 همچنان ~۴ms است. گلوگاه جستجو است نه JSON Schema.
3. Target architecture
Tool Registry (source of truth)
│
▼
Security Boundary
│
▼
Candidate Retrieval (derived index)
/ \
/ \
Inverted Index Vector ANN (optional, off)
\ /
\ /
▼ ▼
Candidate Merge
│
▼
Existing Ranker (Phase 6, unchanged)
│
▼
Adaptive K (flag off)
│
▼
Progressive Schema (flag off)
│
▼
LLM
Candidate Retrieval ≠ Final Ranking. Index score فقط برای برش Top-N است.
4. Inverted index
قبل از این Phase:
| قطعه | نقش |
|---|---|
ai_tool_index.ToolIndex |
metadata مشتق (domain / alias / write) — posting list نیست |
ai_tool_scale_bench.build_inverted_index |
Prototype Bench |
ai_tool_embedding.ToolEmbeddingIndex |
hashed n-gram خطی، authorized-only |
الان:
ai_tool_retrieval_index.ToolRetrievalIndex — Derived Data از Manifest.
Index میکند: name, aliases, keywords, description/extra, capability, domain, namespace, examples.
Tokenizer (ai_tool_text): اعداد از smart_normalize_numbers، ZWNJ/ZWJ، ي→ی، ك→ک، lower-case. Ranker Phase 6 (tokenize_query) عوض نشد.
وزن نهایی با Ranker است نه با TF-IDF ایندکس.
5. Candidate retrieval
retrieve_candidates(query, authorized, n):
- Intersection با Authorized universe (permission داخل ایندکس نیست)
- Keyword postings ∪ capability exact ∪ domain (اگر query ابزار میخواهد)
- Optional vector merge اگر
VECTOR_CANDIDATE_RETRIEVAL - برش Top-N
- Forced / prefer همیشه میمانند
- Disabled / deprecated از posting خارجاند
- No-match میتواند تهی باشد؛ False-empty با Gold اندازه گرفته شد
INDEXED_CANDIDATE_RETRIEVAL در Production خاموش است؛ KeywordIntentStrategy همان Ranker کامل را صدا میزند.
6. Candidate Recall
Gold 2026-08-19.v1، ۴۴۳ query دارای Tool مورد انتظار:
| N | Candidate Recall | p50 | p95 |
|---|---|---|---|
| 20 | ۹۴.۵۸٪ | ۰.۷۶ms | ۱.۰۰ms |
| 50 | ۹۸.۶۵٪ | ۰.۸۴ms | ۱.۱۴ms |
| 100 | ۹۸.۸۷٪ | ۰.۸۵ms | ۱.۳۴ms |
| 200 | ۹۸.۸۷٪ | ۰.۸۶ms | ۱.۳۵ms |
هدف ۹۹٪+ با هیچ N ای نرسید. N=۱۰۰ و N=۲۰۰ یکیاند: پنج miss باقیمانده اصلاً در posting/domain نیستند (get_person_balance / list_currencies / get_business_dashboard / get_business_info×۲) — مشکل metadata است نه اندازهٔ N.
Candidate N انتخابی برای مسیر opt-in: ۱۰۰ (نقطهٔ اشباع). Production همچنان کل Authorized را rank میکند تا این gap بسته شود.
No-match (۳۰ query): ۵۰٪ candidate set تهی. بقیه معمولاً توکن ضعیفی مثل «امروز» دارند. False-empty کامل نیست؛ با fallback Production (اگر flag روشن شود) Ranker فعلی حفظ میشود.
7. Vector ANN
ارزیابی:
| گزینه | تصمیم |
|---|---|
| pgvector HNSW | برای knowledge chunks موجود است. جدول Tool نساز. charngram برای pgvector مناسب نیست. |
| FAISS | وابستگی جدید؛ بدون embedding عصبی ارزش ندارد. |
| New vector DB | ممنوع در این Phase. |
| In-process hashed n-gram | Baseline.eval؛ O(N) بالای VECTOR_BRUTE_FORCE_MAX=512 عمداً اجرا نمیشود. |
Neural embedding: Benchmark نشد (بدون مدل versioned در CI). charngram-hash-v1 در Phase 8 از Keyword بهتر نبود → Production نشد.
8. Hybrid candidate merge
Keyword Index ──┐
├──→ Candidate Merge → Existing Ranker
Vector ANN ─────┘
VECTOR_CANDIDATE_RETRIEVAL = False. Hybrid Tool Discovery همچنان OFF.
9. Existing Ranker
score_tool_for_query / rank_and_cap_tool_names دستنخوردهاند.
مسیر indexed (فقط eval): Candidate N → discover_tools(permissioned_names=candidates, limit=K).
Final Recall با N=۱۰۰:
| K | Indexed | Baseline (full authorized) |
|---|---|---|
| 10 | ۹۵.۰۳٪ | ۹۵.۴۹٪ |
| 15 | ۹۷.۰۷٪ | ۹۷.۵۲٪ |
| 20 | ۹۷.۷۴٪ | ۹۸.۱۹٪ |
افت ~۰.۴–۰.۵ نقطه همان ۵ miss کاندیداست. برای همین flag Production خاموش ماند.
10. Incremental updates
upsert / remove / disable / is_stale(search_text_hash, version, schema_version).
load_many برای rebuild انبوه (mutable سپس freeze) تا O(N²) copy-on-write رخ ندهد. Upsert تکی همچنان copy-on-write روی postingهای Frozenset است.
11. Versioning
هر رکورد: version, schema_version, search_text_hash, indexed_at. اگر Manifest عوض شود و hash فرق کند، رکورد stale است و باید upsert شود. منبع حقیقت همچنان Manifest/Registry است.
12. Multi-tenant security
ایندکس سراسری است. Permission encode نمیشود.
Global Tool Index
↓
Authorized Universe (tenant / role / mode / side_effect)
↓
Candidate Retrieval ∩ authorized
Unauthorized هرگز candidate نمیشود. Security قبل و روی intersection سخت است.
13. Performance
هدف اولیه candidate retrieval < ۵۰ms:
- ۱۸۰…۱۰٬۰۰۰: p50 تکدرخواستی حدود ۶–۱۳ms — برقرار است.
- ۱۰۰٬۰۰۰ metadata: ~۱۱۰ms تکدرخواستی — بالای ۵۰ms؛ برای این مقیاس postingهای داغ باید فشرده/شارد شوند (Phase 11).
Index memory تخمینی: ۱۸۰ Tool ≈ ۱۲۰KB posting؛ ۱۰k ≈ چند MB.
14. Stress test
تکدرخواستی @10k: p50 ≈ ۶–۱۴ms (زیر هدف ۵۰ms).
Burst در یک فرآیند CPython (GIL):
| Concurrency | p50 | p95 | wall |
|---|---|---|---|
| 1 | ~۱۶ms | ~۱۶ms | ~۱۹ms |
| 10 | ~۸۷ms | ~۱۳۸ms | ~۲۲۷ms |
| 50 | ~۱.۴s | ~۱.۵s | ~۱.۶s |
| 100 | ~۲.۸s | ~۳.۰s | ~۳.۲s |
این Burst معادل QPS پایدار نیست. ۵۰–۱۰۰ thread همزمان روی یک interpreter محدود به GIL است. مسیر آنلاین فعلی هنوز Ranker کامل است؛ ایندکس opt-in است.
15. Benchmark
حفظ شد: ۱۸۰ / ۵۰۰ / ۱٬۲۰۰ / ۵٬۰۰۰ / ۱۰٬۰۰۰ + ۱۰۰٬۰۰۰ (بدون semantic).
هیچ Tool مصنوعی وارد Registry Production نمیشود.
16. Production status
UNCHANGED.
LLM همان K=۴۸/۱۲۸ و Ranker Phase 6 را میبیند. ایندکس آمادهٔ opt-in است، روشن نیست. Adaptive K HOLD. Hybrid OFF.
17. Phase 11 recommendation
- بستن ۵ miss کاندیدا با alias/example روی Manifest (نه با بزرگ کردن N).
- بعد از Candidate Recall ≥ ۹۹٪ روی Gold، Canary جدا برای
INDEXED_CANDIDATE_RETRIEVAL(مثل Phase 9، مستقل از Adaptive K). - اگر Neural embedding versioned آمد: pgvector HNSW روی همان Postgres بهعنوان generator دوم — نه جایگزین Keyword.
- فشردهسازی posting برای ۱۰۰k+.
- Adaptive K را فقط وقتی Live Canary Phase 9 اجازه داد Promote کنید.