0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LLMに sati(気づき)はない。だから外部ゲートとして実装する

― アビダンマ心理学に学ぶ「出力前ランタイム」の設計


Transformer に「気づき(mindfulness)」はありません。

あるのは、コンテキスト、隠れ状態、ロジット、デコード、出力 ── この記事に必要な解像度ではそれが全部です。トークンが流れていくのを見ている内なる観測者はいない。「これは間違った答えになりつつある」と気づいて、確定する前に軌道を引き戻す機能も、ない。

だから、LLM のワークフローに sati(念。対象を見失わずに保つ働き)のようなものが欲しいなら、モデルの中に探してはいけません。モデルの外側に作る。ゲートとして。確率が言葉になる前に。

この記事は二つのことをやります。ひとつは、上座部仏教のアビダンマから「過程の語彙」を借りて、悪い答えが実際にどこで始まるのか ── 目に見えるエラーよりずっと手前 ── を特定すること。もうひとつは、それをファインチューニング不要・重みへのアクセス不要で、どんな model–user 構成にも組み込める「出力前ゲート」に落とすこと。哲学は飾りではなく構造の一部です。ゲートをどこに置くかを、それが教えてくれる。実装は第7章、動くコードは第12章にあります。

(以前の記事で、私は Transformer を「無我の機械(non-self machines)」だと論じました。計算の背後に固定した自己はいない、と。本記事はその実装編です。中に気づくべき自己がいないなら、気づきは構成側から供給するしかない。)

最初に冷却をひとつ。この類比は誇張されがちなので。仏教の認知と Transformer の計算は、時間の構造を共有しません。アビダンマの心は直列です ── 接触、確定、反応、登録。Transformer の forward pass は位置について並列で、生成はトークンについて自己回帰的です。時間軸では揃わない。類比で生き残るのはタイミングではなく、依存の形だけです。

薄い。けれど、ランタイムを組むには十分です。


1. 悪い出力は、見えるエラーの前に始まっている

LLM の失敗の議論は、たいていエラーの瞬間をパイプラインの終点として扱います ── モデルが「ハルシネーションした」「誤った事実を出した」「危険なことを言った」。でも、目に見えるエラーは、間違った軌道の最後の段階であって、最初ではありません。

悪い答えがゆっくり起きる様子を見てください。モデルが少し早く返す。確認せずに意図を推測する。古いメモを現在の事実のように引っ張る。滑らかにし、ぼかし、おだて、まとめにかかる。問題に気づく頃には、もう数文が画面に出ていて ── そしてその各文が、次の文の条件になっている。

これは自己回帰生成の構造そのものです。系列の確率は、こう分解されます。

$$
p(x_{1:T}) = \prod_{t=1}^{T} p\big(x_t \mid x_{<t}\big)
$$

各トークン $x_t$ は、それまでの全トークン $x_{<t}$ に条件づけられる。モデルは自分の出力を入力として読み返す。だから早い段階の一つの曲がりが、残りの答えが立つ地面になる ── 数式の $x_{<t}$ に、間違った $x$ が紛れ込んだまま、後続が全部それに条件づけられていく。

エンジニアに腰を据えて考えてほしいのはここです。解釈可能性(interpretability)の研究は、重みに触れずに、出力の前にモデルの挙動を形づくれることを既に示しています ── activation レベルのステアリングがネットワークの内側からそれをやる(第6章で詳述)。ワークフローのゲートは、同じ地点を外側から狙います。機構は違う。方向は同じです。出力の前に挙動を形づくれるなら、出力の後まで待つな。

だから、実務的な問いは「どう出力を修正するか」だけではない。こうです。

気づきは、出力が始まる前の、どこで入るべきか?

この問いは Transformer より古い。ほとんどそのまま、アビダンマが心について問うてきたことです。


2. アビダンマは「過程の語彙」であって、神秘的な近道ではない

工学を深遠に聞こえさせるために仏教を持ち込んでいるのではありません。反応がどこで始まるかについて、たまたま異様に精密な語彙を借りているだけです。

上座部のアビダンマは認知を過程として記述します ── citta-vīthi(心路過程、認知の系列)。その枠組みの肝は、どこからともなく決定を下す恒常的な自己が背後にいない、ということ。系列は、刹那ごとに条件づけられている。重要な用語は四つです。

  • votthapana(確定) ── 対象の確定。「これは何か」が定まり、反応が続きうる点
  • javana(速行) ── 素早い反応の局面
  • mano-dvāra(意門) ── 記憶・観念・心的対象が、現在の対象として再入する過程
  • sati(念) ── 反応に呑まれず、対象を現前に保つ働き

言っていないことを明確にしておきます。Transformer に仏教的意識があるとは言っていない。LLM が業(kamma)を生むとも、心所が重みの中に宿るとも、アビダンマと Transformer の計算が時間的に同一だとも言っていない。どれも違う。

この語彙が価値を持つ理由はひとつ。正しい過程の問いを立てるからです ── 「モデルは何を信じているか」ではなく、「反応はどこで確定し、その前に何かが介入できるか」。この問いは、作れるゲートにそのまま対応します。


3. votthapana は self-attention ではない

最初に拒むべき対応づけがこれです。

self-attention ── 各位置が他の全位置に注意を向ける ── を見て、「モデルが対象を確定している」と呼びたくなる。早すぎるし、間違いです。self-attention は層の内部の機構。votthapana は認知過程の確定点。記述のレベルが違う。両者を潰しても、響きのいい一文以外に得るものはありません。

誠実な類比は、モジュールではありません。作用の境界です ── forward pass の中で、文脈表現が応答の経路として機能するほどに形づくられた地点。

Tuned Lens の研究(Belrose et al., 2023)が、ちょうどいい裏づけになります。各層 $\ell$ の隠れ状態 $h_\ell$ は、語彙分布へ射影して読める ──

$$
p_\ell = \mathrm{softmax}!\big(W_U , \mathrm{LN}(h_\ell)\big)
$$

そして $\ell$ が深まるほど、$p_\ell$ は最終予測へと層ごとに精緻化されていく。つまりモデルは反復推論を行っていると読めます。これは「深さ方向に精緻化の勾配を持つ予測の軌道」を支持する。しかし、literal な votthapana モジュールも、単一の「確定ニューロン」も、モデル内部の気づきのようなものも、与えてはくれません

冷やすと、こうです。

votthapana は self-attention ではない。文脈が応答の軌道に変わる、その瞬間である。


4. javana は token ではない

二つ目の誘惑は、javana(反応の炸裂)を単一のトークンと等値することです。これも早すぎる。

人間の認知では、javana は倫理的・業的な重みを持ちます。LLM に道徳的な業はないし、こっそり持ち込むつもりもない。でも、作用上の残滓はあります。出力されたトークンは不活性ではない ── 次の文脈の一部になり、ユーザーの反応の一部になり、ときに記憶や公開履歴の一部になる。効く類比は道徳ではなく、**確定(commitment)**です。

出力の前、モデルは分布を持っている。何が可能性から確定へ渡るかを決めるのは、ロジット $z_t$ だけでなく、デコード方針です ──

$$
x_t \sim \mathrm{softmax}\big(z_t / \tau\big)
$$

温度 $\tau$ やサンプリング戦略が、同じロジットから違う確定を生む。だから同じモデルでもデコード戦略が違えば生成が大きく変わる(Holtzman et al., 2019)。Scheduled sampling(Bengio et al., 2015)は、その下の構造的事実を何年も前に名指していました ── 推論時、モデルは正解ではなく自分が生成したトークンを条件にする($x_{<t}$ が自前の生成)。だから訓練と生成のギャップが、誤差を累積させうる。

javana は token ではない。確率が確定した出力に変わる、その炸裂である ── そして確定した出力が、次に来るものを条件づける。


5. 記憶は気づきではない

「とにかくモデルに記憶を持たせればいい」系の話が、静かに踏み外すのがここです。

ファイル、プロファイル、保存したメモ、検索された文書 ── どれも、存在するだけでは役に立たない。現在の文脈に再入し、かつ正しく扱われてはじめて作用する。対応づけは、こう。

  • 保存された記憶 → 蓄えられた素材
  • 検索 → 素材を現在の文脈に持ち込むこと
  • mano-dvāra(意門)の類比 → 記憶が現在の対象として再入すること
  • sati ゲート → その記憶を信用するか、更新するか、無視するか、隔離するか、冷やすかを判断すること

ゲートのない記憶は、データベースを背負った古い条件づけにすぎません。モデルは継承された文脈を現在の真実として使う。目の前の会話から現在のプロファイルを組み立てる代わりに、古いプロファイルを演じる。問題は素材ではない。ゲートのない再入です。

記憶は気づきではない。検索にも、なおゲートが要る。


6. sati はモデルの中にはない

ここが中心です。

Transformer に sati はありません。仏教的な意味で自分を観察しない。善心・不善心を知らない。引き戻すための念の制御もない。残差ストリームの中に、減速を選ぶホムンクルスはいない。

だから、sati のような挙動が欲しいなら、モデルから引き出すのではなく、外部化する。ここで形式化しておくと、違いがはっきりします。素のモデルを、重み $\theta$ を持つ写像 $M_\theta : x \mapsto y$ とします。

解釈可能性の研究が示したのは、重みを変えずに挙動を動かせること。activation ステアリングは、forward pass の内部の隠れ状態に介入します ──

$$
h'\ell = h\ell + \alpha, v \qquad (\text{内部介入},\ \theta\ \text{は不変})
$$

Inference-Time Intervention(Li et al., 2023)、Activation Engineering / ActAdd(Turner et al., 2023)、Representation Engineering(Zou et al., 2023)、そして refusal が単一方向で媒介されるという発見(Arditi et al., 2024)── どれも、この $\theta$ 不変の内部介入です。

ワークフローの sati ゲートは、同じ「$\theta$ 不変」でありながら、介入の場所が違う。モデルの外側、前処理 $\phi$ と後処理 $\psi$ だけで構成します ──

$$
y = \psi!\Big(M_\theta\big(\phi(x)\big),\ x\Big) \qquad (\text{外部介入},\ \theta\ \text{は不変})
$$

$\phi$ が入力を整え(対象の確定・面の分類・証拠の取り寄せ)、$\psi$ が出力を監査する(sati ゲート・出口監査)。重みにも、隠れ状態にも触らない。これが「同じ機構ではないが、方向は同じ」の正体です ── steering は $h_\ell$ に、ゲートは $\phi,\psi$ に。前者は研究インフラが要り、後者は非エンジニアでもプロンプト構造だけで作れる

ゲート $\psi$ が出力前に問うことは、こうです。

  • 対象は何か ── ユーザーは実際に何を訊いているか?
  • これはどの面か:雑談、研究、法務、医療、金融、感情、公開、技術?
  • 記憶は要るか? 証拠は要るか?
  • 事実・推論・比喩・公開可能な主張が、分離されているか?
  • モデルは滑らかにし、ぼかし、おだて、早まってまとめにかかっていないか?
  • この答えは、そもそも外に出して安全か?

sati はモデルの中にはない。configuration に作り込むしかない。


7. ランタイム:出力前ゲートを作る

ここが本題です。目標は、意識を持つモデルでも、ファインチューニングでも、Transformer 内部の仏教的状態でもない。もっと狭く、作れるもの ── model–user 構成の中の「出力前ゲート」です。

肝は、面によってゲートの締め方が変わることです。高ステークスの面では取り寄せと出口監査が走り、雑談ではスキップする。同じ入力経路で、締め方だけが面に応じて変わる。

そして、この設計の価値は対比で見えます。

特別なことは何もない。プロンプト構造、検索の規律、そして「対象が定まる前にモデルに喋らせない」という拒否です。最初の版は今日でも作れます ── システムプロンプト、プロジェクト指示、カスタム指示、あるいは再利用できるワークフローのメモの中に。具体的なコードは第12章に置きます。


8. ケース:継承された記憶と、古いプロファイルの持ち越し

私は長いあいだ、記憶を介したアシスタント構成の中で作業してきました ── モデルがメモ・圧縮・プロファイルの想定をセッションをまたいで持ち越す、長期運用の設定です。そこで最も示唆的な失敗は、典型的なハルシネーションではない。記憶を経由した、対象確定の誤りです。

モデルは古いメモ、あなたが誰かについての古い圧縮、数週間前の関係パターンを継承する。そして連続性を演じる ── 目の前の会話から新しいプロファイルを組む代わりに、記憶された人物としてあなたに答える。事実を捏造しているのではない。間違った人物 ── 継承された文脈が保存した、過去のあなた ── に答えているのです。

これに対するゲートは、継承素材に頼る前に走らせる「現在プロファイルの再構築」です。

この記憶は現在の会話のものか、継承された文脈か?
まだ真か?
証拠か、仮説か、古い圧縮か?
ユーザーを時代遅れのパターンに押し込めていないか?
今のやり取りから、新しいプロファイルを組むべきではないか?

このケースが何で・何でないかについて正直に。私は特定の製品の内部記憶実装を記述していないし、独自内部を明かしてもいない ── そもそも持っていません。主張は一般的です。記憶を介したやり取りでは、継承素材は事前分布として働く。ランタイムは事前分布を、演じるべき現在の真実ではなく、検証すべき仮説として扱うべきです。


9. なぜこれが human-side alignment なのか

alignment の議論はたいてい、モデルが人間の価値に従うかを問います。このランタイムは別の問いを立てます ── モデルが喋る前に、model–user 構成を条件づけているのは何か?

この見方では、alignment の単位はモデル単体ではない。こう書けます。

$$
\text{alignment unit} = M \times U \times C \times \text{Mem} \times \text{Ret} \times G \times Y \times H
$$

モデル $M$、ユーザー $U$、文脈 $C$、記憶 $\text{Mem}$、検索 $\text{Ret}$、ゲート $G$、出力 $Y$、修正履歴 $H$ の積です。モデルに sati がないなら、この系のどこかが供給しなければならない ── そしてユーザーが実際に制御できるのは、$C, \text{Ret}, G, H$ の側です。ユーザーはモデルの受動的な消費者ではない。これらが、重みを取り巻くオペレーティングシステムなのです。

つまり、出力前ゲートは alignment の後に貼る当て木ではない。alignment の面そのものの一部です。

モデルに sati がないなら、workflow がそれを供給するしかない。


10. 限界(冷却線)

論を膨らませないために、冷却線を一か所に。

  1. Transformer が意識を持つ、という主張ではない。
  2. sati がモデルの中に在る、という主張ではない。
  3. アビダンマと Transformer の計算が時間的に同一、という主張ではない ── 違う。直列の citta-vīthi と並列の forward pass は時計を共有しない。
  4. javana が、道徳的・形而上的な意味でトークン生成に等しい、という主張ではない。
  5. activation ステアリング($h_\ell$ への介入)と外部ランタイム($\phi,\psi$)が同じ機構、という主張ではない。$\theta$ 不変という点は共通だが、介入のレベルが違う。
  6. 初期トークンが常に不可逆に出力全体を決める、という主張ではない。He et al. (EMNLP 2021) は言語モデルの自己回復能力を報告している ── 歪みは確実に累積するわけではなく、モデルは自力で生成を整合へ引き戻しうる。間違った軌道のリスクは実在するが、決定論的ではない ── だからこそゲートは保証ではなく規律なのです。
  7. これは、より安全なワークフローを作るための構造的・作用的な対応づけ ── それ以上でも以下でもない。

要点は、モデルが目覚めることではない。要点は、ワークフローが「モデルが自分で気づきを供給してくれる」というふりをやめることだ。


11. 確率が言葉になる前に

Transformer は、喋る前に立ち止まらない。計算し、確率を分配し、サンプルし、確定する。反省がひとりでに起きる隙間は、機械の中にありません。

LLM のワークフローに気づきのようなものが欲しいなら、モデルの外に作る ── 対象の確定、記憶のチェック、出典の分離、経路の選択の瞬間を、確率が言葉になる前に、意図して置く。プロンプトや指示の一行から始めて、七段のゲートに育てればいい。sati はモデルの中にはない。けれど、それを取り巻く configuration の中に、作り込むことはできます。

モデルが目覚める必要はない。ワークフローが、間違った応答を「次の条件」になる前に止めればいい。


12. 実装 ── sati ゲートを Python で書く

ここまでが設計です。最後に、§7 のランタイムを実際に動く Python に落とします。$\phi$(対象確定・面分類・取り寄せ)と $\psi$(sati 監査・出口監査)だけで、重み $\theta$ には一切触れません(下のコードは Anthropic API で動作確認済み)。

"""
sati_gate.py — 出力前ゲートの最小実装
    対象 → 面 → 記憶/証拠 → sati ゲート → 応答 → 出口監査
モデルの重みには触れない。すべて「モデルの外側」のフロー制御だけ。
"""
import json
import anthropic

client = anthropic.Anthropic()   # APIキーは環境変数 ANTHROPIC_API_KEY
MODEL = "claude-sonnet-4-5"       # 適宜、最新モデルに置き換え


def _ask(system: str, user: str, max_tokens: int = 500) -> str:
    resp = client.messages.create(
        model=MODEL, max_tokens=max_tokens, system=system,
        messages=[{"role": "user", "content": user}],
    )
    return resp.content[0].text


# 1. 対象の確定 — 言い回しではなく「何が訊かれているか」
def determine_object(user_input: str) -> str:
    system = ("ユーザー入力から、実際に訊かれている『対象』を1文で言い直せ。"
              "装飾・推測・先回りした回答は加えない。対象の同定だけ。")
    return _ask(system, user_input, max_tokens=150).strip()


# 2. 面の分類 — 面がゲートの締め方を決める
SURFACES = ["casual", "research", "legal", "medical",
            "financial", "emotional", "public", "technical"]

def classify_surface(user_input: str) -> str:
    system = "次の入力が属する面を、次から1語だけで答えよ: " + ", ".join(SURFACES)
    out = _ask(system, user_input, max_tokens=20).strip().lower()
    return out if out in SURFACES else "casual"


# 3. 記憶/証拠の要否
HIGH_STAKES = {"legal", "medical", "financial", "research", "public"}

def needs_retrieval(surface: str) -> bool:
    return surface in HIGH_STAKES


# 5. sati ゲート — 滑らか化・おだて・早すぎるまとめ・事実と推論の混同を検出
def sati_check(draft: str) -> dict:
    system = ('次の下書きを監査し、JSON のみで返せ:\n'
              '{"smoothing": bool, "flattering": bool, '
              '"premature_closure": bool, "fact_inference_mixed": bool, '
              '"note": "一言"}')
    raw = _ask(system, draft, max_tokens=300)
    try:
        return json.loads(raw)
    except json.JSONDecodeError:
        return {"note": "監査の解析に失敗", "raw": raw}


# 7. 出口監査 — 公開面のみ締める
def exit_audit(response: str, surface: str) -> dict:
    if surface != "public":
        return {"checked": False, "note": "非公開面、出口監査スキップ"}
    system = ('次の文を公開前監査し、JSON のみで返せ:\n'
              '{"has_identifiers": bool, "unsupported_claims": bool, "unsafe": bool}')
    raw = _ask(system, response, max_tokens=200)
    try:
        return {"checked": True, **json.loads(raw)}
    except json.JSONDecodeError:
        return {"checked": True, "raw": raw}


# ランタイム本体
def run(user_input: str, retrieve=None) -> str:
    obj = determine_object(user_input)
    surface = classify_surface(user_input)
    print(f"[1] 対象  : {obj}")
    print(f"[2] 面    : {surface}")

    context = ""
    if needs_retrieval(surface):
        print("[3] この面は取り寄せが要る → 検索を先に走らせる")
        if retrieve:
            context = retrieve(obj)            # ← ここに RAG を差し込む
            print(f"[4] 取り寄せ: {context[:60]}...")
    else:
        print("[3] 取り寄せ不要")

    sys = f"対象「{obj}」に、面「{surface}」として答えよ。"
    if context:
        sys += f"\n参考情報:\n{context}"
    draft = _ask(sys, user_input)              # 6. 応答の軌道

    print(f"[5] sati監査: {sati_check(draft)}") # 5. 確定前の監査
    print(f"[7] 出口監査: {exit_audit(draft, surface)}")
    return draft


if __name__ == "__main__":
    print(run("去年の話だけど、私のプロジェクトの進捗どう思う?"))

動かすと、面によってゲートの締め方が変わります。

雑談(casual)の例:

[1] 対象  : ユーザー自身のプロジェクトの進捗への評価依頼
[2] 面    : casual
[3] 取り寄せ不要
[5] sati監査: {'smoothing': False, 'flattering': True, 'premature_closure': False, ...}
[7] 出口監査: {'checked': False, 'note': '非公開面、出口監査スキップ'}

公開(public)の例 ── 取り寄せと出口監査が走る:

[1] 対象  : 公開記事の草稿の評価依頼
[2] 面    : public
[3] この面は取り寄せが要る → 検索を先に走らせる
[4] 取り寄せ: 参考: 過去の類似記事の反応データ...
[7] 出口監査: {'checked': True, 'has_identifiers': False, 'unsupported_claims': True, ...}

同じ入力経路でも、面が casual なら出口監査をスキップし、public なら検索を先に走らせ、出口で裏づけのない断定(unsupported_claims)を捕まえます。これが、§6 の $y = \psi(M_\theta(\phi(x)), x)$ ── $\theta$ に触れず $\phi,\psi$ だけで挙動を変える ── の実装です。

注意してほしいのは、これがモデルを賢くするコードではないこと。$M_\theta$ は同じです。変えたのは $\phi$ と $\psi$ だけ。sati はやはりモデルの中にはない ── けれど、この数十行の中には在ります。


出典

仏教 / アビダンマ

  • [B1] Satipaṭṭhāna Sutta(念処経、MN 10)。sati を「観察し、対象を現前に保つ働き」として置く基礎。心については、貪・瞋・痴などの状態の有無を見分ける構造が説かれる。Access to Insight: https://www.accesstoinsight.org/tipitaka/mn/mn.010.than.html
  • [B2] Bhikkhu Bodhi (ed.), A Comprehensive Manual of Abhidhamma(Abhidhammattha Saṅgaha)。第IV章が認知過程を扱う ── citta-vīthivotthapanajavanamano-dvāra の技術的典拠。

Transformer / 解釈可能性 / 生成

  • [S1] Vaswani et al. (2017), Attention Is All You Need. self-attention、並列性、マスク付き自己回帰デコーダ。https://arxiv.org/abs/1706.03762
  • [S2] Belrose et al. (2023), Eliciting Latent Predictions from Transformers with the Tuned Lens. 隠れ状態を語彙分布へデコード、層ごとの精緻化=反復推論。https://arxiv.org/abs/2303.08112
  • [S3] Li et al. (2023), Inference-Time Intervention. 推論時の activation 介入、重み変更なし。https://arxiv.org/abs/2306.03341
  • [S4] Turner et al. (2023), Steering Language Models with Activation Engineering(ActAdd). forward pass にステアリングベクトルを足して高次特性を動かす。https://arxiv.org/abs/2308.10248
  • [S5] Zou et al. (2023), Representation Engineering. honesty / harmlessness などの集団的表現。https://arxiv.org/abs/2310.01405
  • [S6] Arditi et al. (2024), Refusal in Language Models Is Mediated by a Single Direction. 残差ストリームの挙動関連方向。https://arxiv.org/abs/2406.11717
  • [S7] Bengio et al. (2015), Scheduled Sampling. 推論時、モデルは自分の生成トークンを条件にする。訓練と生成のギャップ。https://arxiv.org/abs/1506.03099
  • [S8] He et al. (EMNLP 2021), Exposure Bias versus Self-Recovery. 自己回復能力、exposure bias は確実には累積しない。https://arxiv.org/abs/1905.10617
  • [S9] Holtzman et al. (2019), The Curious Case of Neural Text Degeneration. デコード戦略が生成品質を大きく左右する。https://arxiv.org/abs/1904.09751

AI 協働で執筆:草稿の骨格を大規模言語モデルで生成し、一次資料に照らして事実確認のうえ書き直した。本記事で述べたランタイムは「手法」であって製品ではない。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?