diff --git a/docs/voyage-upgrades-plan.md b/docs/voyage-upgrades-plan.md index 042e447..acfba20 100644 --- a/docs/voyage-upgrades-plan.md +++ b/docs/voyage-upgrades-plan.md @@ -163,7 +163,73 @@ queries בשעה במקרה רגיל) — מתחת ל-1% מהמכסה. --- -## שלב C — voyage-multimodal-3.5 (לביצוע בשיחה החדשה) +## שלב C — voyage-multimodal-3 (✅ בוצע 2026-05-03) + +> **תיקון שם המודל מהתכנית המקורית**: השם הסופי הוא +> `voyage-multimodal-3` (לא 3.5). הוצמד לזה ש-POC #3 הריץ. + +### מצב סופי בייצור + +- `MULTIMODAL_ENABLED=true` ב-Coolify env +- Schema V9 ב-DB (document_image_embeddings + precedent_image_embeddings) +- 419 page-image embeddings על 8174-24 (146) + 8137-24 (273) +- 819 text chunks קיבלו page_number (100% retrofit) +- RRF hybrid merge עם boost text+image פעיל + +### שינויים מהתכנית המקורית — שני תיקונים אמפיריים + +1. **Score scaling — Reciprocal Rank Fusion במקום weighted sum.** + ה-cosine של voyage-3 (~0.4-0.5) שיטתית גבוה מ-voyage-multimodal-3 + (~0.20-0.25). A/B ראשון על 7 שאילתות הראה: עם 0.65/0.35 weighted + sum ו-MULTIMODAL_ENABLED=true, **0** image rows הופיעו ב-top-5, + image side פשוט הוצף. עברנו ל-RRF (`rrf_score = w / (k + rank)`) + שעמיד לסקיילים שונים. תוצאה: 5/5 results עם image contribution + בכל שאילתה. + +2. **Page tracking — chunker חדש + retrofit ל-819 chunks קיימים.** + ה-chunker הישן זרק את ה-page_number של chunks. בלעדיו ה-boost + text+image (join על `(document_id, page_number)`) לא יכול לפעול. + נוסף `page_offsets` ל-`extractor.extract_text` (משלשה במקום זוג — + מעודכן ב-6 callers); chunker מקבל אותו ומסמן page לכל chunk לפי + offset של התווים הראשונים שלו. retrofit ל-chunks קיימים + (`scripts/backfill_chunk_pages.py`) עובד **בלי re-OCR** — + משתמש ב-stored extracted_text כמקור (matches existing chunk + content verbatim) ו-PyMuPDF direct text reads כעיגוני page + boundaries; pages סרוקים ללא טקסט ישיר עוברים אינטרפולציה. + +### למה NOT לעשות re-OCR ב-retrofit + +ניסיון ראשון השתמש ב-`extractor.extract_text` להפיק page_offsets +חדשים. תוצאה: 1/29 chunks נמצאו (28 not found), כי OCR של Google +Vision לא דטרמיניסטי — ה-OCR החדש שונה מה-OCR שהפיק את ה-chunks +המקוריים. הגרסה החדשה משתמשת ב-stored `documents.extracted_text` +שמתאים לחלוטין לתוכן ה-chunks. עלות: $0 (לעומת ~$0.0015/page). + +### Files שהשתנו (יחסית למה שהמסמך הזה תיכנן) + +קוד שנכתב/שונה (5 commits, 242f668 → 8a815ec): +- `mcp-server/src/legal_mcp/config.py` — flags MULTIMODAL_* +- `mcp-server/src/legal_mcp/services/extractor.py` — render + page_offsets +- `mcp-server/src/legal_mcp/services/embeddings.py` — embed_images +- `mcp-server/src/legal_mcp/services/db.py` — schema V9 + 4 store/search funcs +- `mcp-server/src/legal_mcp/services/chunker.py` — page tracking +- `mcp-server/src/legal_mcp/services/processor.py` — ingest integration +- `mcp-server/src/legal_mcp/services/precedent_library.py` — same +- `mcp-server/src/legal_mcp/services/hybrid_search.py` — חדש, RRF orchestrator +- `mcp-server/src/legal_mcp/tools/search.py` — wired to hybrid +- `mcp-server/src/legal_mcp/tools/documents.py` + `tools/workflow.py` + `web/app.py` — extract_text triple unpack +- `scripts/multimodal_backfill.py` + `scripts/backfill_chunk_pages.py` — חדשים + +### מה נשאר (deferred) + +- UI thumbnails בתוצאות חיפוש (לא חוסם — דפנה מקבלת page numbers) +- Backfill על שאר הקורפוס (מעבר ל-2 התיקים): לא דחוף, אפשר per-case +- `text_weight` תיאום: כרגע 0.5 (vanilla RRF). אם דפנה תגיד שהיא רואה + יותר מדי image-influence, מעלים ל-0.55-0.6 דרך env בלי deploy. + +--- + +## שלב C המקורי (תכנון, לרפרנס) ### הבעיה שהוא פותר