Instructions to use baya1116/hypernet-sp-distill with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use baya1116/hypernet-sp-distill with MLX:
# Download the model from the Hub pip install huggingface_hub[hf_xet] huggingface-cli download --local-dir hypernet-sp-distill baya1116/hypernet-sp-distill
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
- Atomic Chat
APP_SPEC — hypernet-sp-distill アプリ開発仕様書
これ1枚でアプリ開発に着手できることを目的とした仕様書。
詳細な根拠・実測値は RELEASE_REPORT.md、移植手順は HANDOFF_PORTING.md(いずれも同梱)。
0. 正典宣言(Source of Truth)— 最初に読むこと
モデルの正確な運用方法(あるべき挙動)は、本リポジトリ hypernet_sp/ ディレクトリが唯一の正典である。
| 場所 | 状態 | 扱い |
|---|---|---|
hypernet_sp/app_session_torch.py |
検証済み13修正が全て適用された turn() の正典 | 運用ロジックはこのファイルの挙動が正。迷ったらここを読む |
hypernet_sp/*.py(memory_core 等6モジュール) |
正典の構成部品(純Python、テスト付き) | そのまま流用する |
リポジトリ直下の tiered_rag_mlx.py sp_mlx.py 等 |
レガシー(修正前の旧本番ランタイム) | 挙動仕様として読まないこと。MLX 移植の「土台」としてのみ使い、HANDOFF_PORTING.md §2 のチェックリストで修正を当てる |
| 手元のローカルクローン | 本リポジトリ main より新しいことはあり得ない | 食い違ったら必ず HF main に揃える |
「どっちが新しいか」で迷ったら: 各修正はコミットメッセージに欠陥番号と実測根拠つきで
記録されている。RELEASE_REPORT.md の欠陥表(#1〜#13)と app_session_torch.py の
コメントが一致しているものが最新。
1. プロダクト定義
有界メモリで動くオンデバイス推論チャットアプリ。 1.5B 推論モデル(DeepSeek-R1-Distill-Qwen-1.5B / FFT 済み)が、会話履歴を 32 本のソフトプロンプト(SP)に圧縮しながら、階層メモリ(L1 セッション / L2 ディスク / L3 Web)と連携して動く。KV キャッシュは会話がどれだけ長くなっても **O(1)**。
- ターゲット: Apple Silicon(MLX)。iPhone は 3GB メモリ予算で成立(実測 1.6–1.8GB)
- UI 言語: 日本語(翻訳シム経由 — §6)。内部処理・メモリ・モデルは全て英語
2. ロードする成果物(全て本リポジトリ内)
| 成果物 | パス | 用途 |
|---|---|---|
| 学生モデル(FFT済) | fft_out/student.pt → build_fft_hf.py で HF 形式化 / 4bit は fft_mlx4 |
本体 |
| SP pooler(AttnPoolSP 32×1536) | fft_out/pooler.pt |
履歴→SP 圧縮+eviction 質量 |
| intent ルータ(6クラス) | hypernet_sp/intent_head.npz |
ターン種別判定 |
| specificity probe | hypernet_sp/specificity_head.npz |
固有値 pin 判定 |
| 検索トリガー(任意・v1 は OFF) | hypernet_sp/attn_trigger4_head.npz |
SP 参照検知→メモリ再注入(v3 は使用禁止) |
| 文埋め込み | BAAI/bge-small-en-v1.5(33M) | 検索・信頼度 |
| ランタイムロジック | hypernet_sp/*.py(純Python 6 モジュール) |
§3 のパイプライン |
npz ヘッドは export_classifiers.LinearHead(numpy のみ)でロード。sklearn 不要。
3. ターンパイプライン仕様(契約)
入力: user_msg: str / 出力: (answer: str, source: str|None, chunks: list[str])
リファレンス実装: hypernet_sp/app_session_torch.py の AppSession.turn()(全修正適用済み)。
1. 保存依頼検知 wants_persist+値あり → 保存して即 ack(疑問形でも)
2. intent 判定 intent_route.route_intent(3バンド: 高確信/top-2裁定/regex)
3. fact → ログ+即 ack(生成しない)
4. pin recall/lookup 以外で固有値があれば pin(上限12・ローテーション)
5. recall → 統合検索(L1+L2 を一括ランク+訂正連鎖)
・ヒットなし → 正直 miss(生成しない。捏造防止)
・信頼度<0.62 → 最近接メモを逐語提示(断定しない)
・≥0.62 → 隔離コンテキストで逐語引用(_clean_quote)
6. lookup → known-fact-first(意味≥0.6+内容語共有)→ WM pin → Web
Web 前に照応解決(expand_web_query)、後に injection ガード
7. math/command → 文脈注入: 疑問形除外+関連度フィルタ+(outdated)/(current)タグ
+前回結果の平叙文注入。テンプレは質問先頭・(a)(b)(c)検出でパート指示
8. 生成 SP-evict ループ(rw=512–1024, maxD=4096, C=64)
・compute 系(math/command): think 強制+DecodePolicy(二相温度、
収束/ループ強制終了)+2パス救済
・それ以外(雑談・作文・要約等): **空 think 先行で直接回答**(temp 0.6)
— think は math 装置。創作で強制すると成果物が think 置き去りになる(#20)
9. 後処理 groundedness 検査+リトライ(≤2)、電卓検算(評価エラー修復)、
compute 結果の自己記録(旧結果は置換)
4. 設定値(検証済み・変更時は再検証のこと)
| 項目 | 値 | 備考 |
|---|---|---|
| temp / 最終回答 | 0.6 / ~greedy | 二相デコード |
| rw(raw window) | 512–1024 | 品質ダイヤル。KV は rw=1024 でも ~30MB |
| maxD(eviction) | 4096 | 質量ベース間引き。142 回連続発火まで検証済み |
| ターン上限 | 2000 tok / 240s | 多部回答は ANSCAP を可変に(#13) |
| recall 確信閾値 | 0.62 | 未満は最近接メモ提示 |
| known-fact 閾値 | 意味 0.6 + 語共有 | シャドーイング防止の二重ロック |
| 検索トリガー | v1 は OFF(任意機能) | 後日 ON 時は attn_trigger4 / th=0.6(MULTITURN_TRIGGER_RESPONSE 参照) |
| pin 上限 / 検索 cap | 12 / 4 |
5. できること(全て実測済み)
- 無限長会話で一定メモリ・一定速度: 10.9k tok 生成・eviction 142 回で速度平坦(4.5→4.0 tok/s 相当)、合計フットプリント 1.6–1.8GB
- 長期記憶: 40 ターン後でも序盤の事実を逐語リコール(マラソン 36/36)。訂正は最新が勝つ(2 回訂正・元の値に戻るケース含む)。セッション跨ぎ永続(L2)
- 正直さ: 未保存の値は捏造せず「保存されていない」(0 トークン)。不確かな検索ヒットは断定せず最近接メモを提示
- 推論: 単発 GSM8K 級 80–90%、self-contained math は Web を引かない、計算結果の参照チェーン(合計→再計算→お釣り)
- Web 連携: 照応解決(「there」→ Kyoto 付加)、injection ガード、groundedness 検査つき
- 複合テスト実績: v1 12/12・v2 17/17・v3 18/18 相当・v4 36/36・v5 23/29(残は §6 の天井)
5.5 会話の継続性(2026-06-11 追加・検証済み)
雑談を含む全ターンが直前までの会話の流れを踏まえる(v6 バッテリー 8/8、回帰 v1 12/12・v2 17/17)。
- ターン縫い込み(必須): 生成しないターン(fact 即 ack・recall 引用・正直 miss・
最近接メモ提示)も
User/Assistant交換をトークンとしてストリームに記録 (AppSession._stitch)。これが無いと「京都行ってきた」→ack の後の 「ハイライト何だった?」が繋がらない - 意図対応の救済(#14): think が cap 到達した時の強制クローズ継続は、compute 系のみ 「Final answer: 」(48 tok)、雑談/説明はそのまま自然回答(200 tok)。 「Final answer:」固定だと説明が数字スタブ化する(実測: binary search の説明→「100」)
- 収束強制終了は compute 系のみ武装(逐語ループ検出は全ターン有効)
- (任意)セッション跨ぎ: SP ウォームスタート(
save_state/load_state— 前セッションを SP に圧縮した状態で再開)+プロフィール前置(evict されない MQ 領域に「ユーザーについて」 1 行)。アプリを開き直しても続きから話したい場合に有効化
6. 制限(設計上の前提として組み込むこと)
- 逐語の事実は SP に置けない(アーキテクチャの大前提)。コード・数値・固有名詞は raw window か検索で扱う — 本パイプラインは自動でそうするが、独自改変時は厳守
- モデル天井(1.5B): 多部問題の帳簿管理(全計算が正しくても違う値を選ぶ — 実測で算術 25/26 正解なのに最終値を誤った)。対策はサブ質問分割(アプリ側で (a)(b)(c) を個別ターン化)。算術の評価エラー自体は電卓検算が修復
- 一般指示はモデルに通じない(「最新値を使え」等)。制御は機械的タグ・ サーバー側解決・テンプレ構造で行う(本パイプラインは適用済み)
- 多言語: 内部は英語のみ。日本語 UI は翻訳シム(
translation_shim.py、 逐語スパン保護つき)経由。実 NMT でのプレースホルダ生存確認が未了 - 検証の範囲: 全て単一シード・CPU。実機で複数シード再走と レイテンシ/発熱計測が必要(マラソンバッテリーは無修正で再利用可)
- セキュリティ: web_guard はパターン第一線。恒久対策(span 制約デコード)は未実装
6.5 既知の移植バグ対応(Swift SP-evict 崩壊 — 2026-06-10 回答済み)
アプリ側報告(GENONCE_DEGENERATION_REPORT.md)の ,1!#!!!! 型崩壊は検証済みで、
モデル/レシピの問題ではない(torch リファレンスは同一重み・同一プロンプト・ガード無効で
200 トークンの整合出力)。Swift 移植の忠実性バグであり、対応手順は以下を参照:
| 参照先 | 内容 |
|---|---|
hypernet_sp/GENONCE_DEGENERATION_RESPONSE.md |
判定・原因候補の再ランク・照合手順 |
hypernet_sp/parity_reference.npz |
機械照合用の基準データ(下記) |
hypernet_sp/sp_evict_parity.py |
基準データの再生成スクリプト |
最有力原因: pooler の cross-attention に「past が空ならスキップ」のガード
(past.size(1) > 0)が無い場合、空キー集合への softmax が NaN を返し SP 全体が
NaN になる。初回ターンは rw=512 の間ずっと past が空なので、自明なプロンプトで
即座に再現する — 報告症状と完全整合。
照合手順(この順で): ① Swift 側で空入力 pooler の出力に NaN が無いか確認
② 全 32 ベクトルの L2 ノルムが 1.468531(|out_scale|)に一致するか
③ cache crop 後の RoPE 位置が MQ から再開しているか(parity_reference.npz の
q_ids は 14 個 → 位置 14 から)④ greedy_tokens と突き合わせて最初の分岐点を特定。
6.6 ブロック引き戻し(Block Recall)— 2026-06-12 正式採用
セッション内の逐語記憶層。露出窓から SP へ追い出されたトークンを 128-tok ブロックの まま保持し(SP はこれまで通り雰囲気の継承)、毎ターン BGE cosine で top-2 ブロックを [SP] と [露出窓] の間に逐語再注入する。実測: 正確値想起 0/10→7/10、 フルKV(4k で 1/10 — 小型モデルは全文が窓内でも文中の値を拾えない)に勝つ。 回帰ゼロ(v1 12/12、v2 は ON/OFF 完全一致)。
移植契約(Swift):
- 追い出しトークン列を 128-tok ブロックに封緘し、decode したテキストの BGE ベクトル(384 次元)を 1 本付与。未封緘の端数(<=127 tok)も検索時は擬似ブロック として採点(封緘境界ギャップ — CPU 実測でニードル取りこぼしの原因)
- ターン頭にユーザ文を BGE クエリ化 → 全ブロックと cosine → top-2 を時系列順に 連結し、ブロックのトークン id をそのまま [SP] の直後に並べる(テンプレ装飾なし)
- リファレンス実装:
hypernet_sp/block_recall.py(mode="bge")+app_session_torch.pyのarchive配線(検索は吸収処理の後、1 ターン 1 回) - フラグ運用: 環境変数
SPCHAT_BLOCK_RECALL=bge。OFF なら従来動作と完全一致
7. 開発開始手順
- 本リポジトリを clone、
HANDOFF_PORTING.mdの順でtiered_rag_mlx.pyに移植(0.5–1 日) composite_test1–5を MLX ラッパで再走(期待値は HANDOFF §6)- 実機計測(レイテンシ・発熱・複数シード)
- 翻訳シム結合(Apple Translation framework 推奨 — 予算 0 byte)
- 計装(引用メモリ ID・groundedness 通過・再質問シグナルのオプトインログ)を 初日から仕込む — メモリバンク構想の燃料
8. ファイルマップ(hypernet_sp/)
実装: memory_core.py intent_route.py anaphora.py web_guard.py decode_policy.py
calculator.py translation_shim.py app_session_torch.py(リファレンス)
ヘッド: intent_head.npz specificity_head.npz attn_trigger3_head.npz
テスト: test_*.py(8 スイート・120+ assertion・MLX 不要)
バッテリー: composite_test{,2,3,4,5}.py / 評価: eval_sp_value.py eval_intent_routing.py
文書: RELEASE_REPORT.md(判定+欠陥13件の記録)HANDOFF_PORTING.md(移植手順)