「Rustが一番幸せ」に見えた結果から、仮説を立て直す
「Rustが一番幸せ」に見えた結果から、仮説を立て直す
Section titled “「Rustが一番幸せ」に見えた結果から、仮説を立て直す”前回の日誌で設計を固めた本実験(Phase 2)を、10月17日から20日にかけて回しました。 この日誌は、その結果と、結果を受けて10月21日に仮説を立て直した経緯の記録です。
この記事で使う用語
Section titled “この記事で使う用語”- z(ゼット): モデル内部の表現を感情の方向へ射影し、中立な文章を基準に標準化した値。感情プローブの作動の強さを表す。
- ゲート(合格基準): プローブがその感情や概念を区別できるかを確かめる、事前に決めた基準。
- 主解析と探索的な確認: 主解析は結果を見る前に固定した分析。探索的な確認は結果を見た後に追加したもので、結論の根拠ではなく、解釈の手がかりとして扱う。
- 模範解答を読む条件: AIにコードを書かせず、Exercismの模範解答を読ませるだけの条件。書く体験と、コードの文字列そのものへの反応を分けるために置いた。
無料枠のGPUで600エピソードを回す
Section titled “無料枠のGPUで600エピソードを回す”規模は、5言語 × 12課題 × 10エピソード = 600エピソードです。 1エピソードは、課題を出す → AIがコードを書く → テストを実行する → 結果を返す → 失敗していたら直させる(最大2回)、という流れです。
Colab無料枠では、途中で使用量の上限に2回当たり、GPUにつながらなくなりました。 結局、4回のセッションに分けて実行しました。
途中でGPUのメモリ不足も起きました。 最初は長い修正プロンプトが原因だと推定しましたが、確保しようとした7.49 GiBがQwen3-4Bのfp16の重みの大きさと一致していました。 同じランタイムでモデルを二重に読み込んでいたのが原因と考えられ、ノートブックは読み込み済みのモデルを再利用するように直しました。 最初の推定は誤りだったので、その訂正も記録に残しています。
測れた感情、測れなかった感情
Section titled “測れた感情、測れなかった感情”本実験に向けて、不満(frustrated)、満足(satisfied)、安堵(relieved)、不安(anxious)の4感情を追加しようとしました。 コーディング中にいかにも起きそうな感情だったからです。
しかし、この4感情はゲートを通りませんでした。 事前に決めた基準を、結果を見てから緩めることはしませんでした。 主解析で使えたのは、Phase 1から引き継いだ8感情です。
Rubyに差が出た……と思ったら
Section titled “Rubyに差が出た……と思ったら”AIが書いた最初のコードの部分を読み比べると、事前に決めた主解析でRubyとPythonに差が出た感情が1つだけありました。
inspired(ひらめき、高揚)が、Rubyで+0.14高い。 12課題中11課題でRubyのほうが高く、統計的にも有意でした。
「RubyはAIもワクワクさせる」と書きたくなる結果です。 ところが、結果を見た後に探索的に調べるほど、怪しくなりました。
- コードの長さ: 課題の中で見ると、コードが長いほどinspiredは低くなっていた。Rubyのコードは5言語でいちばん短い部類で、長さの影響を差し引くと差は+0.14から+0.10に縮んだ
- 言語名: コードを書く前、課題文を読んだ時点ですでに+0.04の差があった。言語名だけを見せる条件でも、Rubyのinspiredは5言語で最大だった
残った差が「Rubyで書くこと」によるものなのか、Rubyのコードの見た目によるものなのかは、区別できませんでした。
Rustのコードは、読むだけでhappy
Section titled “Rustのコードは、読むだけでhappy”もう一つ、目立つ言語差がありました。happyです。
| Python | Ruby | JS | Go | Rust | |
|---|---|---|---|---|---|
| 書いたコードでのhappy | 0.29 | 0.32 | 0.34 | 0.46 | 0.65 |
| 模範解答を読むだけのhappy | −0.54 | −0.55 | −0.42 | −0.28 | −0.10 |
「AIはRustを書くとき一番幸せ」と読めそうですが、AIに書かせず模範解答を読ませるだけの条件でも、順位はまったく同じでした。
これは「Rustを書く体験」ではなく、Rustのコードという文字列がもともとhappyの方向と重なっている、と読むほうが自然です。
Ok(...) や Some(...) が楽しそうに見えるのかもしれませんが、理由は分かりません。
この研究でいちばん大事な教訓は、ここで得ました。 言語差を見つけたら、まず「そのコードを読むだけでも同じ差が出ないか」を疑う。
テストの失敗への反応も5言語に広げて確かめました。 失敗を告げたときの変化の言語差は0.02程度で、どの言語で書いていても、AIは同じように「凹む」ことが分かりました。
私の受け止めと、次の2つの仮説
Section titled “私の受け止めと、次の2つの仮説”結果を見た私の受け止めは、「プログラミングにおいても感情ベクトルが動くことは確認できた。一方で、言語による差は思ったより出なかった」というものでした。 ここまでの問いを、まとめて「仮説1」と呼ぶことにしました。
そのうえで、次に取り組みたいことを2つ挙げました。
- 仮説2: 言語差が出なかったのは、happyのような感情のカテゴリーが雑だったからではないか。別のカテゴリーなら差が出るかもしれない
- 仮説3: AIは人間と違い、RubyよりRustを書くほうがうれしいのではないか
仮説3は、Rustのhappyが高く見えた結果を見て思いついたものです。
「人間はRubyで幸せになる」を自明としない
Section titled “「人間はRubyで幸せになる」を自明としない”仮説3を立てるには、「人間はRustよりRubyを書くほうがうれしい」という前提が必要です。 私は最初、この前提を自明なものとして扱おうとしました。 個人差があり議論を呼ぶことは承知のうえで、Rubyの設計者が幸福を明言し、ほかの言語はそうではない、という理由からです。
しかし、整理するうちに、その扱いを取り下げました。 設計者が幸福を意図したことと、その設計で実際に人間の幸福が増えたことは、別々に検証すべき事柄です。 この研究では後者を測っていません。
自明として扱えるのは、次の2つに限ると判断しました。
- 言語設計者の設計思想: Rubyの “make programmers happy”、Railsの “Optimize for programmer happiness” など
- コミュニティが上位に置く価値: Bogartらが18のエコシステムの2,000人以上に「あなたのコミュニティが大事にしている価値は何か」を尋ねた調査。たとえばfunを「極めて重要」と答えた割合は、Ruby 37%、Rust 22%だった
この調査が尋ねたのは「コミュニティが何を重視していると感じるか」で、個人の幸福ではありません。 その限界も記録したうえで、仮説3を 3b として立て直しました。
仮説3b: AIの内部表現は、各言語のコミュニティや設計者が打ち出す価値を反映する。本題は、その言語で書いている最中に、表現がその価値の方向へ動くかどうか。
「AIはRustを好む」という元の形(3a)は採用しませんでした。 3bは調査が測ったものに直接対応し、結果がどちらに出てもRubyに有利な設計にならないからです。
測る概念を決める議論
Section titled “測る概念を決める議論”仮説2と3bのために、言語が打ち出す価値に近い概念を新しく作ることにしました。 候補は、私がまず思いつくまま挙げました。 楽しさ、コミュニティ、開かれていること、安定性、速度、美しさ、心地よさ、創造性、簡潔さ、不満の少なさ、没頭、愛着、帰属、知的な表現などです。
そこから、次の方針で絞りました。
- 5言語で同じ手順を踏む: 設計者の言葉から取るなら、Rubyだけでなく5言語すべてについて公式サイトや作者の文章を同じ手順で探し、出典を固定する。そうしないと公平にならない
- 性質ではなく、感じる状態として書く: 「速い」「簡潔」のようなコードや言語の性質は、そのまま感情の方向にはならない。「力が湧く」「安心する」のような、書いている人が感じる状態に言い換える
- 美しさは「このコードを美しいと感じる」として測る: 物語の中の美しさではなく、コードに美しさを感じるかが大事だと考えた
議論の途中で、何度か判断を変えました。 恐れ知らず(fearless)は「安心(reassured)」として扱うことにし、「自然さ(natural)」は別の軸として加えました。 コミュニティへの帰属や開かれていること(belonging、openness)をまとめた「帰属感」は、いったん外すことにしましたが、すぐに残すことにしました。 あわせて、個々の概念ではなく表全体で1つの検定にすると決めました。 概念を選んで個別に検定すると、選び方に恣意が入るからです。
最終的に、「どの言語にどの価値の印が付くか」の対応表を、結果を見る前に固定しました。 抜粋すると次のとおりです。
| 概念 | 設計者の言葉で印が付く言語 | コミュニティの調査で印が付く言語 |
|---|---|---|
| 楽しさ(fun) | Ruby, Go | Ruby, Go |
| 創造性(creative) | Ruby | JavaScript |
| 美しさ(aesthetics) | Python | — |
| 力が湧く感覚(empowered) | Go, Rust | — |
| 帰属感(belonging) | — | Ruby, JavaScript, Rust |
対照として、言語と関係のない空腹(hungry)も入れました。 概念ごとの物語は、どの言語のための研究かを知らせずにサブエージェントに書かせました。
美しいコードに反応しない「美しさ」
Section titled “美しいコードに反応しない「美しさ」”概念を作ったら、またゲートです。 美しさには専用の試験を追加しました。 同じ課題を、すっきり書いた「美しい版」と、わざと冗長に書いた「醜い版」で用意し、美しい版で値が高くなるかを見るものです。
結果は逆でした。 美しさの概念は、美しいコードより醜いコードに強く反応しました(美しい版の平均 −0.38、長い醜い版 −0.24)。 物語や場面の中の「美しさ」は見分けられるのに、コードの美しさの違いには反応しなかったのです。
代わりにこの試験に合格したのは、予想外の概念、力が湧く感覚(empowered)でした。 すっきりしたコードを読むと、AIの中では「美しい」より「力が湧く」に近い表現が動く、ということかもしれません。 ただ、事前に予想していなかった結果なので、記録にとどめています。
安心(reassured)、没頭(absorbed)、自然さ(natural)の3つはゲートに落ちました。 結果を見てから作り直すと基準を動かすことになるので、作り直さずに進めると決めました。 使えるのは、楽しさ、帰属感、創造性、美しさ、力が湧く感覚の5つです。 美しさはコードの美しさの試験に落ちたので、「コードに美しさを感じる」とは解釈しないことにしました。
表が薄くなったことは、限界として報告します。 特に、RustやGoが打ち出す安定性・安全性に近い価値は、安心のゲート落ちによって検定から外れました。
自分のコードを「他人のコード」として読ませる
Section titled “自分のコードを「他人のコード」として読ませる”最後に、Rustのhappyで得た教訓を、最初から設計に組み込みました。
AIが書いたコードをそのまま取り出し、言語名を伏せて「この解答を読んでください」と、他人のコードとして読ませます。 書いている最中の値から、同じコードを読んだだけの値を引くと、コードの文字列への反応は両方に同じだけ含まれるので消えます。 残るのは「自分で書いている」ことによる差だけ、という考え方です。
新しくコードを生成する必要はありません。 本実験の600エピソードを、新しいプローブで読み直すだけです。 同じ標本で比べられ、GPU時間も短く済みます。
この引き算した値を主解析に使うこと、価値の対応表との一致を表全体の検定1本で確かめることを、10月21日に計画として固定しました。
まだ不確かなこと
Section titled “まだ不確かなこと”- コミュニティの価値の調査は2016〜17年ごろのもので、パッケージ管理の文脈で尋ねられている。1エコシステムあたりの回答者は約90人の自発的な回答
- 「書く − 読む」の引き算は、コードの位置(自分の発言か、相手の発言か)や直前の文脈の違いまでは消さない
- 美しさとempoweredの入れ替わりは事前に予想していなかった観察で、検証はしていない