fluffychat/.github/instructions/token-info-feedback-v2.instructions.md
wcjord 0e681c4d68
feat: phonetic transcription v2 migration (#5640)
* docs: add PT v2 and token-info-feedback design docs

- Add phonetic-transcription-v2-design.instructions.md (client PT v2 migration)
- Add token-info-feedback-v2.instructions.md (client token feedback v2 migration)

* fix: update applyTo path for token info feedback v2 migration

* feat: Refactor phonetic transcription to v2 models and repository (in progress)

* feat: PT v2 migration - tts_phoneme rename, v1 cleanup, disambiguation, TTS integration

* feat: Update phonetic transcription v2 design document for endpoint changes and response structure

* docs: fix stale _storageKeys claim in pt-v2 design doc

* style: reformat PT v2 files with Dart 3.10 formatter (Flutter 3.38)

* feat: add speakingRate to TTS request model (default 0.85)

Passes speaking_rate to the choreo TTS endpoint. Default preserves
current behavior; can be overridden for single-word playback later.

* feat: use normal speed (1.0) for single-word TTS playback

The 0.85x slowdown is helpful for full sentences but makes single
words sound unnaturally slow. tts_controller._speakFromChoreo now
sends speakingRate=1.0. Full-sentence TTS via pangea_message_event
still defaults to 0.85.

* style: clean up formatting and reduce line breaks in TtsController

* fix: env goofiness

* formatting, fix linter issues

* don't return widgets from functions

---------

Co-authored-by: ggurdin <ggurdin@gmail.com>
Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>
2026-02-10 16:29:26 -05:00

162 lines
7.9 KiB
Markdown
Raw 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.

---
applyTo: "lib/pangea/token_info_feedback/**, lib/**"
---
# Token Info Feedback — v2 Migration (Client)
Migrate the token info feedback flow to use the v2 endpoint and v2 phonetic transcription types. This is a client-side companion to the choreo instructions at `2-step-choreographer/.github/instructions/token-info-feedback-pt-v2.instructions.md`.
## Context
Token info feedback lets users flag incorrect token data (POS, language, phonetics, lemma). The server evaluates the feedback via LLM, conditionally calls sub-handlers, and returns updated fields. The client applies the updates to local caches and optionally edits the Matrix message.
**Why migrate**: The phonetics field currently sends a plain `String` and receives a `PhoneticTranscriptionResponse` (v1 nested types). The v2 endpoint expects `PTRequest` + `PTResponse` and returns `PTResponse` (flat v2 types). This aligns token feedback with the broader PT v2 migration.
**Staleness detection**: The server compares the client-sent phonetics against its CMS cache. If they differ and the LLM didn't request changes, the server returns the CMS version as `updatedPhonetics` so the client refreshes its local cache. This means `updatedPhonetics` may be non-null even when the user's feedback didn't trigger phonetic changes.
---
## 1. Endpoint URL
**v1**: `{choreoEndpoint}/token/feedback`
**v2**: `{choreoEndpoint}/token/feedback_v2`
Update `PApiUrls.tokenFeedback` (or add a new constant) in [urls.dart](lib/pangea/common/network/urls.dart).
---
## 2. Request Changes
### Replace `phonetics` with `ptRequest` + `ptResponse`
**v1**: `phonetics: String` — a rendered transcription like `"hái"`, extracted by `PhoneticTranscriptionBuilder.transcription` (the first token's `phoneticL1Transcription.content`).
**v2**: Two new fields replace `phonetics`:
- `ptRequest: PTRequest?` — the PT request used to fetch phonetics (surface, langCode, userL1, userL2). The server passes this directly to `pt_v2_handler.get()` when feedback triggers a phonetics re-evaluation.
- `ptResponse: PTResponse?` — the cached PT response containing `List<Pronunciation>`. The server uses `ptResponse.pronunciations` for the evaluation prompt and staleness detection.
This means `TokenInfoFeedbackRequestData` drops `phonetics: String` and adds `ptRequest: PTRequest?` + `ptResponse: PTResponse?`.
### What feeds into `ptRequest` / `ptResponse`
The data flows through this chain:
1. **`PhoneticTranscriptionBuilder`** resolves a `PhoneticTranscriptionResponse` (v1) → extracts a `String`.
2. **`TokenFeedbackButton`** receives the string via `onFlagTokenInfo(lemmaInfo, transcript)`.
3. **Call sites** (`reading_assistance_content.dart`, `analytics_details_popup.dart`) put the string into `TokenInfoFeedbackRequestData(phonetics: transcript)`.
After v2 migration, this chain must change:
1. **`PhoneticTranscriptionBuilder`** resolves a v2 response → exposes both the `PTRequest` it used and the `PTResponse` it received.
2. **`TokenFeedbackButton`** callback signature changes: `Function(LemmaInfoResponse, PTRequest, PTResponse)`.
3. **Call sites** pass both objects into the updated request data: `TokenInfoFeedbackRequestData(ptRequest: ptReq, ptResponse: ptRes)`.
### `toJson()` serialization
v1:
```json
{ "phonetics": "hái" }
```
v2:
```json
{
"pt_request": {
"surface": "还",
"lang_code": "zh",
"user_l1": "en",
"user_l2": "zh"
},
"pt_response": {
"pronunciations": [
{ "transcription": "hái", "ipa": "xaɪ̌", "ud_conditions": "Pos=ADV" },
{ "transcription": "huán", "ipa": "xwaň", "ud_conditions": "Pos=VERB" }
]
}
}
```
All other request fields (`userId`, `roomId`, `fullText`, `detectedLanguage`, `tokens`, `selectedToken`, `lemmaInfo`, `wordCardL1`) are unchanged.
---
## 3. Response Changes
### `updatedPhonetics` field
**v1**: `PhoneticTranscriptionResponse?` — deeply nested v1 types with `phoneticTranscriptionResult.phoneticTranscription[0].phoneticL1Transcription.content`.
**v2**: The v2 response type (e.g., `PhoneticTranscriptionV2Response` with `pronunciations: List<Pronunciation>`). Deserialized via the v2 model's `fromJson()`.
**New behavior**: `updatedPhonetics` may be non-null in two cases:
1. The LLM evaluated user feedback and generated new phonetics (same as v1).
2. The server detected that the client's cached phonetics are stale compared to CMS. In this case, the server returns the current CMS version so the client can refresh.
Either way, the client should apply the update to its local cache (see §4).
All other response fields (`userFriendlyMessage`, `updatedToken`, `updatedLemmaInfo`, `updatedLanguage`) are unchanged.
---
## 4. Cache Side-Effects in `_submitFeedback`
The dialog applies server updates to local caches. The phonetic cache write must change:
### v1 (current)
```dart
Future<void> _updatePhoneticTranscription(
PhoneticTranscriptionResponse response,
) async {
final req = PhoneticTranscriptionRequest(
arc: LanguageArc(l1: ..., l2: ...),
content: response.content,
);
await PhoneticTranscriptionRepo.set(req, response);
}
```
This constructs a v1 `PhoneticTranscriptionRequest` to use as the cache key, then writes the v1 response.
### v2 (target)
Construct the v2 cache key (`surface + lang_code + user_l1`) and write the v2 response to the v2 PT cache. The exact implementation depends on how the PT v2 repo's `set()` method is designed during the broader PT migration. The key pieces are:
- **Cache key inputs**: `surface` = the token's surface text, `langCode` = `this.langCode` (from the dialog), `userL1` = `requestData.wordCardL1`.
- **Response type**: The v2 response containing `List<Pronunciation>`.
- **Cache target**: The v2 PT cache (not the v1 `phonetic_transcription_storage`).
---
## 5. Files to Modify
| File | Change |
|------|--------|
| `token_info_feedback_request.dart` | Drop `phonetics: String`. Add `ptRequest: PTRequest?` + `ptResponse: PTResponse?`. Update `toJson()`, `==`, `hashCode`. |
| `token_info_feedback_response.dart` | `updatedPhonetics: PhoneticTranscriptionResponse?` → v2 response type. Update `fromJson()`, `toJson()`, `==`, `hashCode`. Remove v1 `PhoneticTranscriptionResponse` import. |
| `token_info_feedback_dialog.dart` | Update `_updatePhoneticTranscription` to use v2 cache key/types. Remove v1 `PhoneticTranscriptionRequest`, `PhoneticTranscriptionResponse`, `LanguageArc`, `PLanguageStore` imports. |
| `token_info_feedback_repo.dart` | Update URL to `PApiUrls.tokenFeedbackV2` (or equivalent). |
| `token_feedback_button.dart` *(outside this folder)* | Change callback from `(LemmaInfoResponse, String)` to `(LemmaInfoResponse, PTRequest, PTResponse)`. Update how the PT objects are extracted from the builder. |
| Call sites *(outside this folder)* | `reading_assistance_content.dart`, `analytics_details_popup.dart` — update `onFlagTokenInfo` to pass `PTRequest` + `PTResponse` into `TokenInfoFeedbackRequestData`. |
| `urls.dart` *(outside this folder)* | Add `tokenFeedbackV2` URL constant. |
---
## 6. Dependency on PT v2 Migration
This migration **depends on** the core PT v2 models existing on the client:
- `Pronunciation` model (with `transcription`, `ipa`, `ud_conditions`)
- V2 response model (with `pronunciations: List<Pronunciation>`)
- V2 repo with a `set()` method that accepts the v2 cache key
These are created as part of the main PT v2 migration (see `phonetic-transcription-v2-design.instructions.md` §3). Implement the core PT v2 models first, then update token info feedback.
---
## 7. Checklist
- [ ] Replace `phonetics` field with `ptRequest` + `ptResponse` in request model
- [ ] Update `updatedPhonetics` field type in response model
- [ ] Update `_updatePhoneticTranscription` cache write in dialog
- [ ] Update `TokenFeedbackButton` callback signature to `(LemmaInfoResponse, PTRequest, PTResponse)`
- [ ] Update call sites to pass `PTRequest` + `PTResponse`
- [ ] Update URL to v2 endpoint
- [ ] Remove all v1 PT type imports from token_info_feedback files