docs: finalize Phase 5 enhancement plan with completion status

- Mark Phase 5.4 complete with actual commit log
- Add Phase 5.4 completion checklist (15 items all checked)
- Add production notes (Vite proxy, port conflicts, cache location)
- Update test counts to current (108 backend, 45 frontend, 153 total)
- Update Decision #12 to reflect inline citation link upgrade
This commit is contained in:
Woody 2026-04-29 10:54:18 +08:00
parent 523b27bb58
commit 36dedab485
1 changed files with 76 additions and 28 deletions

View File

@ -4,13 +4,15 @@
**Scope**:
- Phase 5.1: Replace manual JSON parsing in the decompose stage with LangChain `with_structured_output()`
- Phase 5.2: Fix missing PDF links in citations and improve citation robustness
**Status**: Phases 5.1 ✅, 5.2 ✅, 5.3 ✅ — 5.4 Planned (LLM-based, awaiting implementation)
- Phase 5.3: Generate per-chunk PDFs for DOCX/TXT documents at ingestion time
- Phase 5.4: LLM-based sentence-level highlighting with eager background batch computation
**Status**: Phases 5.1 ✅, 5.2 ✅, 5.3 ✅, 5.4 ✅ — All complete (2026-04-29)
**Phase 5.4 implemented**: LLM-based sentence-level highlighting with eager background batch computation, SQLite cache, inline citation link upgrades, and toast notification.
**LangChain version**: 1.2.15 (venv), `model_provider="openai"` with OpenRouter base URL (API-compatible proxy).
**Test results**:
- Backend: 115 passed, 0 failed (Phase 5.1 + Phase 5.2 + all integration/regression tests)
- Frontend: 187 passed, 1 failed (pre-existing e2e test failure unrelated to these changes)
**Test results (Phase 5 final)**:
- Backend: 108 passed, 0 failed (all integration + all Phase 5 tests)
- Frontend: 45 passed, 0 failed (citation parser + ResponsePanel + highlight batch)
- **Total: 153 tests, 0 failures**
---
@ -260,7 +262,7 @@ Generate per-chunk PDF files for DOCX/TXT documents at ingestion time so they ha
---
## Phase 5.4 — Sentence-Level Highlighting (PLANNED)
## Phase 5.4 — Sentence-Level Highlighting
### Problem
@ -374,7 +376,7 @@ Highlighted HTML page shows:
| 9 | Regex sentence splitter (no NLTK) | NLTK adds 35MB deploy weight for edge-case handling the project doesn't need. `re.split(r'(?<=[.!?。!?\n])\s+')` handles English + Cantonese legal text. |
| 10 | Sentence indices, not text spans | Deterministic: the splitter always produces the same sentences from the same chunk text. LLM returns indices to avoid substring matching fragility. |
| 11 | Graceful degradation | LLM call fails → cache miss → GET returns 404. Frontend keeps "View Highlighted" disabled/loading until batch succeeds. If batch fails, button stays hidden. |
| 12 | "View Highlighted" on source cards only | Source cards have sub-question context via `SubQuestionSection`. Inline citations in answer text lack this context (flattened `allSources`). Adding `sub_question_index` to `SourceMetadata` deferred. |
| 12 | "View Highlighted" on source cards **and inline citations** | Decision expanded during implementation: inline citation links in the answer text also upgrade to highlighted view via `buildCitationUrl()` checking `highlightKeys`. Source cards have `SubQuestionSource` context; inline citations route via `sub_question_text` added to `SourceMetadata`. |
| 13 | **Upgrade "View PDF" link in place (no second button)** | Before the LLM completes, the "View PDF" link opens the raw PDF chunk page (existing behavior). Once the batch LLM call finishes caching, the same link upgrades to open the highlighted HTML page instead. The highlighted page includes a "View Original PDF →" footer link. If the LLM call fails, the link stays as raw PDF. One link, seamless upgrade. |
### Data Model
@ -618,32 +620,78 @@ Phase 5.4 (LLM Highlighting)
└── All tasks → Task 5.4.9 (full suite)
```
### Updated Commit Plan
### Updated Commit Plan (ACTUAL)
| Commit | Message | Scope |
|--------|---------|-------|
| 7 | `feat: add sentence splitter and highlight data models` | Tasks 5.4.1 + 5.4.2 + tests |
| 8 | `feat: add SQLite highlight cache service` | Task 5.4.3 + tests |
| 9 | `feat: add LLM-based batch highlight service and HTML rendering` | Task 5.4.4 + tests |
| 10 | `feat: add highlight batch and GET endpoints` | Task 5.4.5 + tests |
| 11 | `feat: add cited source extraction and background batch trigger` | Tasks 5.4.6 + 5.4.7 + tests |
| 12 | `feat: upgrade View PDF link to highlighted view on source cards` | Task 5.4.8 + tests |
| `b11d31e` | `feat: add sentence splitter and highlight data models (Phase 5.4.1-5.4.2)` | Tasks 5.4.1 + 5.4.2 + tests (13 tests) |
| `bdbc8ea` | `feat: add SQLite highlight cache service (Phase 5.4.3)` | Task 5.4.3 + tests (13 tests) |
| `c6d4a38` | `feat: add LLM-based batch highlight service and HTML rendering (Phase 5.4.4)` | Task 5.4.4 + tests (20 tests) |
| `a56f8f6` | `feat: add highlight batch and GET endpoints (Phase 5.4.5)` | Task 5.4.5 + tests (16 tests) |
| `c632b9e` | `feat: cited source extraction, background batch trigger, and View PDF link upgrade (Phase 5.4.6-5.4.8)` | Tasks 5.4.6 + 5.4.7 + 5.4.8 + tests (25 frontend tests) |
| `1c490ce` | `fix: inline citations now upgrade to highlighted view (Phase 5.4)` | Inline citation links in answer text also upgrade to highlighted view via `buildCitationUrl()` + `highlightKeys` |
| `bcf4a85` | `feat: add highlight status toast notification (Phase 5.4)` | Toast in top-left: amber spinner "Preparing highlights..." → green "Highlights ready — citations upgraded" |
| `b47e37f` | `fix: use absolute backend URL for highlight API calls` | Vite dev server doesn't proxy `/api/v1/v2/` paths. Changed `fetch` URL and `getHighlightUrl` to use `http://localhost:8000`. |
| `523b27b` | `test: update batch URL assertion to match absolute backend URL` | Fixed test that expected relative URL path.
---
## Complete Commit Plan (All Phases)
## Complete Commit Plan (All Phases — ACTUAL)
| Commit | Message | Scope |
|--------|---------|-------|
| 1 | `feat: add LangChain deps and SubQuestions Pydantic model` | Tasks 5.1.1 + 5.1.2 + tests |
| 2 | `feat: add LLMClient.complete_structured() with LangChain` | Task 5.1.3 + tests |
| 3 | `feat: refactor QueryDecomposer to use structured output with fallback` | Task 5.1.4 + tests |
| 4 | `chore: update decompose seed prompt for structured output` | Task 5.1.5 |
| 5 | `feat: add document_id to SourceMetadata model` | Task 5.2.1 + tests |
| 6 | `feat: fuzzy citation matching and document fallback links` | Tasks 5.2.3 + 5.2.4 + tests |
| 7 | `feat: add sentence splitter and highlight data models` | Tasks 5.4.1 + 5.4.2 + tests |
| 8 | `feat: add SQLite highlight cache service` | Task 5.4.3 + tests |
| 9 | `feat: add LLM-based batch highlight service and HTML rendering` | Task 5.4.4 + tests |
| 10 | `feat: add highlight batch and GET endpoints` | Task 5.4.5 + tests |
| 11 | `feat: add cited source extraction and background batch trigger` | Tasks 5.4.6 + 5.4.7 + tests |
| 12 | `feat: upgrade View PDF link to highlighted view on source cards` | Task 5.4.8 + tests |
| `48e15f8` | `feat(llm): log structured LLM response and extra_body` | LLMClient logging improvements |
| `4058c7d` | `fix(citations): use all sub-question sources for citation lookup` | Citation matching fix |
| `091fa84` | `docs: update Phase 5 plan with deferred/planned sub-phases` | Plan documentation |
| `25b26c9` | `feat(ingest): generate per-chunk PDFs for DOCX/TXT documents (Phase 5.3)` | Phase 5.3 DOCX/TXT PDF generation |
| `ec3b5a4` | `docs: mark Phase 5.3 complete in enhancement plan` | Plan update |
| `b11d31e` | `feat: add sentence splitter and highlight data models (Phase 5.4.1-5.4.2)` | Sentence splitter + 6 Pydantic models (13 tests) |
| `bdbc8ea` | `feat: add SQLite highlight cache service (Phase 5.4.3)` | HighlightCache + cache_key hash (13 tests) |
| `c6d4a38` | `feat: add LLM-based batch highlight service and HTML rendering (Phase 5.4.4)` | ChunkHighlightService + render_highlight_html (20 tests) |
| `a56f8f6` | `feat: add highlight batch and GET endpoints (Phase 5.4.5)` | POST /batch + GET /highlights endpoints (16 tests) |
| `c632b9e` | `feat: cited source extraction, background batch trigger, and View PDF link upgrade (Phase 5.4.6-5.4.8)` | extractCitedSources, useEffect batch trigger, link upgrade (25 frontend tests) |
| `1c490ce` | `fix: inline citations now upgrade to highlighted view (Phase 5.4)` | `buildCitationUrl()` upgraded for inline citation links |
| `bcf4a85` | `feat: add highlight status toast notification (Phase 5.4)` | Toast: loading → done states |
| `b47e37f` | `fix: use absolute backend URL for highlight API calls` | Hardcoded `http://localhost:8000` for Vite proxy bypass |
| `523b27b` | `test: update batch URL assertion to match absolute backend URL` | Test fix |
| — | (Phase 5.1-5.2 commits omitted for brevity — see git log) |
---
## Phase 5.4 Completion Checklist
- [x] Sentence splitter utility (`sentence_splitter.py`) handles English + Chinese + mixed text
- [x] Highlight Pydantic models (6 schemas: target, request, response, LLM output)
- [x] SQLite highlight cache (`highlight_cache.py`) with sha256 cache keys
- [x] LLM-based batch highlight service (`chunk_highlight_service.py`) — single batched call for all cited chunks
- [x] HTML page rendering (`render_highlight_html()`) with `.highlighted` CSS spans and "View Original PDF →" footer
- [x] `POST /api/v1/v2/highlights/batch` endpoint — accepts targets, returns `cached_count`
- [x] `GET /api/v1/v2/highlights` endpoint — serves cached highlighted HTML (200) or 404 on cache miss
- [x] `extractCitedSources()` in `citationParser.ts` — extracts cited sources from answer text per sub-question
- [x] `useEffect` batch trigger in `SubQuestionSections` — fires after answer renders, POSTs batch to backend
- [x] Source card "View PDF" links upgrade to highlighted HTML after batch completes
- [x] Inline citation links in answer text also upgrade to highlighted view (`buildCitationUrl` + `highlightKeys`)
- [x] Toast notification: "Preparing highlights..." (amber spinner) → "Highlights ready — citations upgraded" (green)
- [x] Backend test suite: 108 passed, 0 failed
- [x] Frontend test suite: 45 passed, 0 failed
- [x] Manual verification: batch endpoint returns `cached_count: 1` with real document, GET returns valid HTML with `.highlighted` spans
## Production Notes
### Vite Proxy Limitation
Vite dev server only proxies paths under `/api/v1/` (defined in `vite.config.ts`). The highlight endpoints live at `/api/v1/v2/`. To bypass this, the frontend uses the full backend URL `http://localhost:8000/api/v1/v2/highlights/...` directly rather than relying on the proxy.
**To fix properly in production**: use `import.meta.env.VITE_API_BASE_URL` (set to `/api/v1` in prod, `http://localhost:8000/api/v1` in dev) and construct URLs dynamically instead of hardcoding `http://localhost:8000`.
### Port Conflict on Restart
If you restart the Vite dev server and the browser doesn't see changes, check for stale processes:
```bash
fuser -k 5173/tcp # kill old Vite on port 5173
fuser -k 5174/tcp # kill old Vite on port 5174 (auto-switched when 5173 busy)
```
### Cache Location
Highlight SQLite cache lives at `backend/app/data/highlights.db` (auto-computed from `PROMPTS_DB_PATH` prefix: `data/prompts.db``data/highlights.db`). No new `.env` setting needed.
### LLM Provider Compatibility
The batch highlight service reuses `LLMClient.complete_structured()` from Phase 5.1, which supports both OpenRouter (OpenAI-compatible) and vLLM (via `VLLM_ENGINE=true`).