Skip to content

feat(core): PR-G — learned surface is #1 (cheapest learned path first) - #363

Merged
send merged 10 commits into
mainfrom
feat/history-learned-top1
Sep 29, 2026
Merged

send merged 10 commits into
mainfrom
feat/history-learned-top1

Conversation

@send

@send send commented Sep 29, 2026 •

Copy link
Copy Markdown
Owner

概要

PR-G (rank 2+ ゴミ候補プログラム)。候補列の #1 を「この読みで学習済みの表記」の中から選ぶ。

  • G1 学習ブースト段 (history_rerank_at): 価格順に並べたあと、学習済みの経路 (whole_path_boost > 0、ScoredPath::is_learned) のうち最安のものを index 0 に置く。残りは価格順のまま。学習済み同士の順は価格 (decay 込み) で決まる
  • G7 Override 段 (数字 / カタカナ) が生成・再価格する経路にも同じ helper (apply_history_boost) で学習ブーストをかける。学習済みの数詞複合語やカタカナは、学習済みの Add IME app with romaji-to-kana and Rust FFI bridge #1 と価格で争う
  • 単一の正準形 reranker::learned_first: 最安の学習済みを index 0 に置き、置き換えられた学習済みの index 0 は価格の位置に戻す。学習ブースト段と Override 段の最後の両方で呼ぶ
  • G1′ Override 段は、保持する index 0 (学習済み) を身元で外してから候補を入れ、未学習の候補では押し出さず、再価格もしない。同じ表記の候補は学習状態も同じなので、学習済みの候補は index 0 も再価格できる。重複した表記のどちらの価格を採るかは履歴前の価格で決め、決まった経路を自身の分節でブーストし直す
  • explain は Override 段が付けた経路のブースト内訳を報告する (以前は 0 と表示していた)
  • replay-commit-log に < 0 (learned #1) 行を追加した。学習済みの Add IME app with romaji-to-kana and Rust FFI bridge #1 より安い表記を選んだ件数 (= 再訂正) で、出荷後の撤回条件の計数器になる
  • SPEC: §ブースト計算 を学習済み Add IME app with romaji-to-kana and Rust FFI bridge #1 の規則の単一ソースにし、適用範囲と限界を明記した。パイプライン / Rewriters / 自動確定 / replay の記述は §ブースト計算 への参照に置き換えた

動機: PR-E (#353) の計測で、学習済みの #1 が経路の価格差で未学習の表記に負ける退行が 3 件出た。PR-E の前提として PR-G を先に入れる。

宣言する挙動変更

計測 (凍結した commit-log 6448 行 / rank>0 468 / distinct 434 読み。個人内容は載せず件数のみ。main = eb15ead、PR-G = e366305)

項目 main PR-G
accuracy 109 pass / 28 skip 109 / 28 (同一)
accuracy-history (新ケース込み) 10/11 (おむろん → OMRON だけ fail) 11/11
履歴なしの出力 (570 読みの 1-best / N-best 先頭 / 候補列 #1、141 読みの n=1 / n=20 / 候補列 n=40) — main とバイト一致
候補列 #1 の変化 (--history、434 読み) — 80 = 昇格 (未学習 → 学習済み) 79 + 学習済み → 学習済み 1 (G7)。非昇格 0
昇格の学習の証拠 — 確定 2 回以上 or 7 日以内 1 / 単発かつ 7 日超 78 / commit-log に読み全体の確定なし 0
昇格した表記の履歴後の価格差 (G7 前、80 件) — ≤2000: 50 / ≤5000: 26 / ≤10000: 4。最後の選択が 30 日超前 74。旧 #1 をその後に確定した読み 0
旧 #1 が admission で候補列から消えた読み — 1
新 #1 が main で index ≥ 9 または候補列に無い — 2
141 コーパス読みの昇格 (--history) — 10
自動確定 / そのまま確定だけの読み (434 外、distinct 2907) の #1 変化 — 25 (全件昇格)
学習済みのかなが学習済みの #1 の下 (570 読み、(v)) 32 33
replay-commit-log --history (main の baseline 比) — lost 0 / 頁外への降格 0 / 頁内の降格 1 (学習済み同士で数詞複合語が価格で #1 に、G7) / 改善 65 / < 0 0
replay-commit-log 履歴なし — 468 件すべて変化なし

幅 (1-best ≠ 候補列 #1、履歴あり): hard rule の例外を 1 件受け入れる

  • 570 読み: main 20 → PR-G 3 (main と共通 2、新規 1)。main の 18 件は解消する
  • 新規 1 件: 候補列の Add IME app with romaji-to-kana and Rust FFI bridge #1 は学習済みの表記で、1-best の母集団 (oversample 30) にはその表記が無い。oversample と structure filter のどちらで落ちたかは、explain に filter の脱落情報が無いため未確定
  • 救済案 1: 1-best の履歴あり oversample を常に 60 (候補列と同じ) にする。割れは 0 になるが、1-best 履歴ありが +50〜190% 遅くなるため不採用
  • 救済案 2: 読みに学習記録があるときだけ 60 にする。記録ありの読みで 1-best が 2.2 倍 (p50 0.62 → 1.38 ms、採用条件の 1 ms を超える) で、打鍵途中の読みの 52% に記録があるため不採用
  • 毎打鍵の hot path を 2 倍にしてまで、1 読みで「候補到着時に表示が 1 回変わる」のを消す価値はない。残る幅の不一致は母集団の問題として 1-best vs N-best top-1 mismatch comes from argmin population width, not the structure filter (PR-E2) #361 (PR-E2) で扱う
  • 既知の限界: 数字 (非複合語)・カタカナの方針価格は n 本に絞った後の最悪値が基準なので、これらが学習済み同士で Add IME app with romaji-to-kana and Rust FFI bridge #1 を争う読みでは、1-best と候補列で勝者が割れることがある。570 読みではこの機構による割れは 0 件

速度

  • 1-best 履歴あり (実辞書 + 実履歴、439 読み、main と交互に 2 回): 記録ありの読み 比 1.002 (p50 619.8 → 617.7 µs)、記録なしの読み 0.997
  • N-best n=10 (実辞書、5 入力 × 200 回、交互に 3 回): 最小値で −1.3%〜+0.7%
  • criterion (convert_1best / _history / _10best × 4 入力): 計測時にマシン負荷で ±30% 揺れ、実行順で符号が反転したため、上の交互計測を正とする

出荷後の撤回条件 (事前登録)

  • マージ時点の commit-log の行数を起点 (--from-line) にし、その時点の学習履歴 (user_history.lxud + .wal) を凍結コピーする。現在の履歴を渡すと、選び直した表記も学習済みになって 0 件になるため
  • 次の rank>0 200 行を、replay-commit-log --history <凍結コピー> --from-line <起点> で再生する
  • < 0 (learned #1) の件数 = 固定された学習済みの Add IME app with romaji-to-kana and Rust FFI bridge #1 を避けて、それより安い (出荷時点で未学習の) 表記を選び直した件数。出どころは問わない
  • 10 件以上なら PR-G を revert し、述語の強化 (期間 / 頻度) を別設計で再検討する

Test plan

  • mise run test (lint + workspace tests)、cargo test -p lex-core --features trace,neural、msrv 1.88.0 check
  • mise run accuracy / mise run accuracy-history
  • compile-swift / test-swift、read-pin / task-screen / check-sources / audit
  • 変異検査 (各テストが落ちることを確認)
テスト 落ちる変異
T-G1 history_puts_cheapest_learned_first / T-G4 m0 (main の並び: rotate なし + Override 凍結なし)、m1 (rotate なし)
T-G2′ learned_paths_order_by_price_not_by_boost m0、m1、m3 (ブースト最大の学習済みを 0 に)
T-G5 (a) viterbi_best_reinserted_below_learned_top / (b) displaced_fragment_top_is_dropped_by_admission m0、m1
T-G6 learned_surface_outranks_number_compound m2 (Override 凍結なし)、学習済み候補の凍結
T-G7′ test_explain_paths_match_production_nbest m0、m1
T-G8′ おむろん → OMRON (accuracy-history、差 29060 > ブースト 18000) m0、m1 (このケースだけ fail)
T-G9′ auto_commit_and_stability_follow_learned_top m0、m1
T-G10 learned_number_compound_outprices_stale_learned_surface Override 段のブーストなし、Override 段の learned_first なし
override_price_is_chosen_before_history 重複の価格をブースト後の価格で比べる
learned_candidate_undercutting_learned_top_demotes_it_to_its_price learned_first の demote なし、Override 段の learned_first なし
learned_index0_takes_its_compound_price 学習済み候補も凍結する
repriced_learned_duplicate_demotes_the_learned_top_to_its_price (Codex R1) 再価格した学習済みを index 0 に直接挿入する (旧実装)
held_head_does_not_pass_to_the_next_path 凍結を位置で表す (旧実装: head を外すと次の経路が凍結され rewriter 順で結果が変わる)
displaced_learned_head_precedes_equal_prices demote を同価格の後ろに置く

🤖 Generated with Claude Code

send and others added 9 commits September 30, 2026 01:59
…-G1..T-G9, SPEC)

History reranking moves the cheapest learned path (whole_path_boost > 0)
to index 0; the Override stage leaves a learned index 0 alone.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… ScoredPath::single

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Numeric / Katakana paths are created after history reranking, so they were
never learned: a stale learned surface stayed #1 over a number compound the
user commits. The Override stage now boosts what it creates with the same
helper as history reranking; a learned created path takes index 0 from an
unlearned one or undercuts a learned one, and explain reports its boost.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
, stale docs

Replay's gap is measured from the list's #1, which can now be a learned
path priced above what follows: a negative gap is a re-correction and is
counted apart (gap_below_top), the counter PR-G's post-ship revert trigger
reads. Docs that still said the list is cheapest-first, that decay keeps
stale history from dominating, or that a number compound always takes
index 0 now state the learned-first rule; the 1-best oversample comment
records why it stays at 30 (#361).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ts limits

§ブースト計算 now holds the rule once, with where it does not reach: learned
surfaces outside the history-stage population (injected, #361 for the
1-best), user dictionary words, the kana rescue price, and what Fn+Delete
falls back to. Pipeline, Rewriters and CostFunction lines point to it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ring

T-G9′ (first-segment reading differs, session built with the history),
T-G2′ (price order ≠ boost order), T-G5 (a)/(b) through the pipeline,
T-G7′ (explain on a rotated list) and T-G8′ (おむろん → OMRON, gap 29060
over an 18000 boost) each fail with the rotate removed; the boost-reorder
test is back to measuring boost size.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The Override stage now inserts in cost order below a learned index 0 and
then applies the same learned_first as history reranking (cheapest learned
first, a replaced learned index 0 back at its price), instead of comparing
each candidate with index 0 only. A duplicate's price owner is chosen on
pre-history prices before the resolved path is boosted again, so a
candidate with fewer segments no longer raises the path. Tests give the
stage a boost as production does; stale comments and the replay label
width fixed; SPEC notes that Rewriters can move the returned #1 to 3rd.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…rride price

A same-surface Override candidate is learned exactly when the path it
duplicates is, so the frozen prefix (which keeps unlearned candidates off
a learned index 0) no longer stops a learned one from repricing it;
learned_first then settles #1. Before, only index 0 missed the compound
price, and adding another learned path changed which learned surface won.

Docs: replay's re-correction count needs the history frozen at the window
start; SPEC states the auto-commit tracker follows the list's #1, the kana
move below a learned #1, where decay applies, and that worst-based policy
prices can split learned-vs-learned #1 between the 1-best and the list.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@send

send commented Sep 29, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-29T18:31:59.140291Z 966addb Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e366305ff5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread engine/crates/lex-core/src/converter/reranker.rs
A learned duplicate repriced below the learned index 0 was inserted at
index 0 directly, so learned_first saw the cheapest learned already first
and left the replaced learned #1 at index 1 (Codex R1). The re-gate then
found the root: the frozen prefix was a position, and removing the head to
reprice it froze the next path instead, making results depend on the
rewriters' order.

The stage now takes the held head (Model: always; Override: a learned
index 0) out of the list while candidates go in, reprices it in place for
a same-surface learned candidate, puts it back, and learned_first alone
decides index 0. A displaced learned #1 goes back before equal prices, as
Override inserts. Regression tests for the R1 case, rewriter-order
independence and the tie rule each fail on the previous implementation.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@send

send commented Sep 29, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Can't wait for the next one!

Reviewed commit: 966addbb65

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@send

send commented Sep 29, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: 966addbb65

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@send
send merged commit 450fa55 into main Sep 29, 2026
16 checks passed
@send
send deleted the feat/history-learned-top1 branch September 29, 2026 23:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant