Watch
1
0
Fork
You've already forked Seyyed_arc
0
forked from hesabix/arc
Seyyed_arc/docs/ai-agent/phase-11-index-quality-canary.md
2026-08-21 00:15:57 +00:00

275 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Phase 11 — Candidate Index Quality Hardening & Independent Canary
**وضعیت:** Metadata پنج miss پوشش داده شد. Candidate Recall@100 = ۱۰۰٪. Canary ایندکس در کد آماده است و Production روی ۰٪ مانده. Adaptive K همچنان HOLD. Hybrid OFF.
**تاریخ:** ۲۱ اوت ۲۰۲۶
**نتایج:** [`evals/phase-11/latest.json`](evals/phase-11/latest.json)
**Dataset:** `2026-08-19.v1` (بدون تغییر Gold)
> Do not compensate for metadata gaps by making the candidate pool larger. Fix coverage, then keep the index small and fast.
> Candidate retrieval may reduce the search universe, but the existing ranker remains the authority for relevance.
> Candidate indexing, Adaptive K, Hybrid Search, and Schema Loading are independent control planes.
Production flags بعد از این Phase:
```text
PROGRESSIVE_SCHEMA_LOADING = False
ADAPTIVE_DISCOVERY_K = False
ADAPTIVE_K_ROLLOUT_PERCENT = 0
HYBRID_TOOL_DISCOVERY = False
INDEXED_CANDIDATE_RETRIEVAL = False
INDEXED_CANDIDATE_ROLLOUT_PERCENT = 0
VECTOR_CANDIDATE_RETRIEVAL = False
Analyzer = 48 / Autonomous = 128
```
---
## 1. Five Metadata Misses
Phase 10 روی N=۲۰/۵۰/۱۰۰/۲۰۰ اشباع شد (۹۸.۸۷٪). پنج miss باقی‌مانده **Metadata Gap** بودند نه کمبود ظرفیت ایندکس. Gold عوض نشد.
| Gold | Query | Tool | Classification | Why the index missed |
|------|-------|------|----------------|----------------------|
| `ppl-05` | مانده حساب علی چقدر است | `get_person_balance` | missing alias / keyword | توکن `مانده` در search text نبود. دامنه `people` بود؛ intent اغلب `financial` است پس domain expansion هم کمکی نمی‌کرد. |
| `acc-21` | لیست ارزها | `list_currencies` | missing alias + query parsing | Alias فقط `ارز` بود؛ stemming نداریم پس `ارزها` جدا است. UI label همان «لیست ارزها» است. `expects_tools` برای query کوتاه False بود. Tokenizer بازنویسی نشد. |
| `hard-gen-01` | یک گزارش کلی از اوضاع بده | `get_business_dashboard` | wrong domain + missing keyword | دامنه فقط `financial` بود در حالی که capability `reports.overview` است. Alias فقط داشبورد؛ `گزارش کلی` / `اوضاع` نبود. |
| `plat-01` | اطلاعات این کسب‌وکار | `get_business_info` | missing alias | UI «اطلاعات کسب‌وکار». ZWNJ، `کسب‌وکار` را به `کسب` + `وکار` می‌شکند و `اطلاعات` در search text نبود. |
| `exp-158` | اطلاعات کسب‌وکار نشست | `get_business_info` | missing alias | همان شکاف `plat-01`. |
جزئیات هر Tool قبل از Fix:
| Tool | capability | domain | namespace | ranking |
|------|------------|--------|-----------|---------|
| `get_person_balance` | `people.person` | `people` | `people` | Phase 6 lexical؛ بدون همپوشانی توکن با query |
| `list_currencies` | `financial.currency` | `financial`, `products_write` | `financial` | بدون توکن `ارزها` |
| `get_business_dashboard` | `reports.overview` | `financial` | `reports` | `گزارش` به ابزارهای گزارش فروش می‌رسید نه داشبورد |
| `get_business_info` | `platform.settings` | `misc` | `platform` | بدون `اطلاعات` |
Gold این پنج query درست است. Dataset version افزایش نیافت.
---
## 2. Metadata Fixes
فقط پوشش زبان واقعی اضافه شد. Alias/example ساختگی انباشته نشد. `گزارش` برهنه به داشبورد اضافه نشد تا با `get_sales_report` و تست گردش‌کار تداخل نکند.
| Tool | Change |
|------|--------|
| `get_person_balance` | alias: `مانده حساب`, `مانده شخص` · keyword: `مانده` · example: query طلایی |
| `list_currencies` | alias: `ارزها`, `لیست ارزها` در کنار `ارز` / `currency` / `واحد پول` |
| `get_business_dashboard` | domain: `financial` + `reports_meta` · keyword: `گزارش کلی`, `اوضاع`, `خلاصه وضعیت`, `نمای کلی` · examples شامل query طلایی |
| `get_business_info` | alias: `اطلاعات کسب‌وکار`, `مشخصات کسب‌وکار` · keyword: `اطلاعات` · example: `اطلاعات این کسب‌وکار` |
Pipeline بعد از Fix:
```text
Registry / Manifest → Search Meta merge → search_text → inverted postings
```
Rebuild کامل و incremental upsert برای کاتالوگ آزمایشی معادل شدند.
---
## 3. Candidate Recall
پس از Fix، روی ۴۴۳ query دارای gold label (بدون no-match):
| N | Phase 10 | Phase 11 |
|---|----------|----------|
| 20 | 94.58% | **95.49%** |
| 50 | 98.65% | **99.55%** |
| 100 | 98.87% | **100.00%** |
| 200 | 98.87% | **100.00%** |
هدف `Candidate Recall@100 >= 99%` رسید. Miss@100 = ۰. N بزرگ‌تر نشد (`CANDIDATE_RETRIEVAL_N = 100`).
پنج miss قبلی همگی در مجموعهٔ کاندیدا@۱۰۰ هستند و rank ایندکس آن‌ها ۱ است.
---
## 4. Index Consistency
سه مسیر برای کاتالوگ شش‌تایی (`search_invoices`, `list_accounts`, `get_person_balance`, `list_currencies`, `get_business_dashboard`, `get_business_info`):
| Path | Result |
|------|--------|
| Full rebuild (`load_many`) | مرجع |
| Incremental upsert | معادل |
| Incremental disable + re-enable | معادل |
Property tests: Unicode ی/ي ک/ك ZWNJ، alias تکراری، metadata خالی، disable/deprecate، collision هم‌نام، `is_stale` روی version.
---
## 5. Candidate vs Ranker Contract
```text
Candidate Index
↓ must maximize candidate recall
Final Ranker (Phase 6)
↓ must maximize relevance
Adaptive K
↓ controls final tool surface (HOLD / off)
Schema Loader
↓ controls LLM context (off)
Security
↓ authorizes everything (before index)
```
ایندکس فقط Candidate Generator است. `discover_tools(apply_indexed=True)` کاندیدا را تنگ می‌کند؛ Top-K نهایی همچنان `score_tool_for_query` / `rank_and_cap` است. Adaptive K و Hybrid از این مسیر روشن نمی‌شوند.
---
## 6. Canary Architecture
Canary فقط `INDEXED_CANDIDATE_RETRIEVAL` را عوض می‌کند (از طریق percent مستقل، نه flag سراسری).
```text
SHA256("indexed-retrieval-v1" + business_id + user_id) % 100
↓
bucket < INDEXED_CANDIDATE_ROLLOUT_PERCENT
```
Salt جدا از Adaptive (`adaptive-k-v1`) است. شناسه‌ها فقط برای assignmentاند و لاگ نمی‌شوند.
`AIService.get_available_functions` هر دو assignment را جدا resolve می‌کند:
```text
apply_adaptive=assignment.enabled
apply_indexed=indexed.enabled
```
---
## 7. Control / Experiment
```text
Control
Authorized Set → Phase 6 Ranker over full authorized set → K=48/128
Experiment
Authorized Set → Indexed Candidate Retrieval (N=100)
→ Phase 6 Ranker → K=48/128
```
فقط Candidate Generation فرق می‌کند. Ranker، Adaptive K، Hybrid، Schema Loader دست‌نخورده‌اند.
---
## 8. Fallback
فقط برای Canary (`INDEXED_CANDIDATE_FALLBACK = True`):
```text
Indexed Candidate Search
↓
No / low candidate
↓
Fallback to existing full authorized ranker
```
Silent failure نیست. Fallback هرگز Global Registry را به Ranker نمی‌دهد؛ همان Authorized Set است.
رویدادها:
- `candidate_index_hit`
- `candidate_index_empty`
- `candidate_index_fallback`
---
## 9. Security
```text
Global Index → Authorized Set → Candidate Retrieval
```
ایندکس permission نگه نمی‌دارد. Tool غیرمجاز وارد candidate set نمی‌شود. Disable از postings حذف می‌کند؛ Deprecate از active candidates؛ Re-enable postings را برمی‌گرداند.
`indexed_retrieval_miss` جدا از `retrieval_miss` (قطع Top-K / Adaptive K) است: ابزار مجاز در stage-1 ایندکس نبود و fallback هم رخ نداد.
---
## 10. Latency
Control = rank خطی روی کل کاتالوگ. Experiment = lookup ایندکس + rank روی N=۱۰۰.
| Size | Control p50 | Control p95 | Indexed p50 | Indexed p95 |
|------|-------------|-------------|-------------|-------------|
| 180 | 7.8ms | 8.1ms | 3.4ms | 3.5ms |
| 1,200 | 18.6ms | 18.8ms | 3.9ms | 3.9ms |
| 5,000 | 58.8ms | 61.1ms | 4.6ms | 4.8ms |
| 10,000 | 110.8ms | 112.5ms | 6.1ms | 6.6ms |
هدف سریع‌تر کردن Ranker نبود. هدف این است Ranker روی کل کاتالوگ اجرا نشود. در ۱۰k ایندکس ≈ O(lookup) می‌ماند؛ کنترل ≈ O(N).
---
## 11. Live Metrics
نمونه زنده هنوز صفر است. آستانهٔ تصمیم: `INDEXED_CANDIDATE_MIN_LIVE_SAMPLES = 500` در هر بازو.
متریک‌های آماده:
- `retrieval_latency`, `candidate_count`, `final_tool_count`
- `tool_discovery_miss`, `schema_miss`, `unknown_tool`, `rediscovery`
- `tool_execution_success` / `tool_execution_failure`
- `candidate_index_hit` / `empty` / `fallback`
- `indexed_retrieval_miss` (جدا از Adaptive K miss)
---
## 12. Results
| Gate | Value |
|------|-------|
| Five metadata misses | resolved (all hit@100, index rank 1) |
| Candidate Recall@100 | **100%** (>= 99%) |
| Final Recall@10/15/20/48 indexed | 96.16 / 98.19 / 98.87 / 98.87 |
| Same-metadata full ranker | identical — no index/ranker-boundary regression |
| vs Phase 6 baseline | improved (metadata), not degraded |
| Incremental consistency | PASS |
| Security tests | PASS |
| Gold dataset | unchanged `2026-08-19.v1` |
Final Recall نسبت به Phase 6 بالا رفته چون پوشش متادیتا بهتر شده، نه چون N بزرگ شده. Indexed و Control روی همان متادیتا برابرند.
---
## 13. Rollout Decision
**Gold: Case A.** Candidate Recall ≥ ۹۹٪ و Final Recall پایدار.
**Live: HOLD at 0%.** متریک زنده نیست؛ مثل Phase 9 بدون ترافیک promote نمی‌شود.
پیشنهاد stage بعد از مشاهدهٔ زنده:
```text
0% → 5% → 10% → 25% → 50% → 100%
```
هر stage فقط بعد از بررسی stage قبلی. Flag سراسری `INDEXED_CANDIDATE_RETRIEVAL` خاموش می‌ماند تا percent عمداً بالا برود.
---
## 14. Adaptive K Status
**HOLD.** `ADAPTIVE_K_ROLLOUT_PERCENT = 0`. این Phase دربارهٔ Adaptive K تصمیم نمی‌گیرد.
---
## 15. Hybrid Status
**OFF.** `HYBRID_TOOL_DISCOVERY = False`. وجود زیرساخت vector/ANN به معنی روشن بودن Hybrid نیست.
---
## 16. Phase 12 Recommendation
1. Canary زندهٔ Indexed Retrieval از ۵٪ با fallback و `indexed_retrieval_miss` جدا.
2. اگر fallback و discovery miss در ۵٪ سالم بود، ۱۰٪ سپس ۲۵٪.
3. Adaptive K را فقط بعد از دادهٔ زندهٔ Phase 9 جدا بررسی کن.
4. برای ۱۰۰k: فشرده‌سازی posting / shard، نه بزرگ کردن N.
5. Hybrid را canary نکن مگر lexical miss باقی‌مانده پس از metadata ثابت شود.