Slide 1

Slide 1 text

AIコーディングの弱点 やっぱりプログラミングは人間が(も)勉強しよう 2025-11-14 YAPC::Fukuoka 2025 LINEヤフー きしだ なおき

Slide 2

Slide 2 text

2 Agenda ● AIについて ● AIの仕組み ● AIの弱点 ● プログラミング言語 ● プログラミングに必要なこと ● プログラミング言語機能の概要 ● プログラムの最適化 ● まとめたい

Slide 3

Slide 3 text

AIについて ● AIの仕組み ● AIの弱点

Slide 4

Slide 4 text

AIの仕組み ● AIとは ● Transformer ● ChatGPTの進化からみる技術 ● AIの計算 ● AIの学習

Slide 5

Slide 5 text

5 AIってなに? ● LLMを中心とした反応システム ● LLM=大規模言語モデル ● 言語を扱う大規模なニューラルネットワーク ● Transformerを基本とする ● 仕組み的には、文章の続きを生成

Slide 6

Slide 6 text

Transformer ● 2017にGoogleが発表 ● Attention is All You Need ● アテンション ● 文章中の単語がどの単語を注目しているか ● O(n^2)

Slide 7

Slide 7 text

7 Transformerの発展 ● AIが賢くなったというときには技術発展がある GPT3 スケーリング則で学習コストをかけて性能をあげる GPT3.5 チャット対応とRLHFで対話が可能に GPT4 MoEで実行時リソースを削減 Function Callingで外部機能呼び出し o1 Reasoningによる推論時スケーリング o3 エージェントで推論の並列化

Slide 8

Slide 8 text

スケーリング則(GPT-3) ● 言語モデルの性能がパラメータ数、データセットサイズ、計算予 算を変数としたべき乗になる ● OpenAIが予算をつぎ込むキッカケになった Scaling Laws for Neural Language Models (Jared Kaplan, Sam McCandlish et al., 2020-01-23)

Slide 9

Slide 9 text

チャット対応とRLHF(GPT-3.5) ● チャットに対応するファインチューニング ● 指示応答モデル ● 使いやすくなって爆発的人気 ● RLHF(Reinforcement Learning from Human Feedback) ● 人間の評価による強化学習 ● やりとりの心地よさ

Slide 10

Slide 10 text

MoE(Mixture of Experts) (GPT-4) ● FFNは知識をうけもつ ● すべての知識を同時に使うことはない ● 多数の専門家モデルを持っておいて、 推論時に必要なモデルだけを呼び出 すことでリソースを節約 ● GPT-oss 120B ● エキスパート数 128 ● アクティブパラメータ数5.1B

Slide 11

Slide 11 text

Function Calling ● LLMから外部関数を呼び出す ● OpenAI、Google、Hugging HaceはFunction Calling ● Anthropic、AWSはTool Use ● AIが幅広い機能をもつようになった ● MCP ● JSON-RPCを使ってリモートでFunction Calling ● MCPサーバーは状態を持つので、JSON-RPCによる分散オブジェクト

Slide 12

Slide 12 text

Reasoningと推論時スケーリング(o1) ● CoT(Chain or Thought) ● 「段階的に考えて」 ● ユーザーに応答を出す前に考察過程を入れる ● 推論時にリソースを使うことでも 思考力がスケールする ● 推論時スケーリング

Slide 13

Slide 13 text

なぜReasoningが効くか ● Transformerでは、トークン同士の関係を見た後でモデルの知識を利用し て回答 ● ひとつの層ではアテンションでトークン同士の関係、FFNに知識 ● 全体では浅い層でトークン同士の関係、深い層で知識 ● トークン同士の関係を見るときに知識が 活かされない ● Reasoningで知識を出させておくと ユーザー入力と知識がトランスフォーマに 投入される

Slide 14

Slide 14 text

Agentによる複雑な推論(o3) ● o3(恐らく)やGemini Deep ThinkではReasoningを並列に行って一番いいも のを採用して回答 ● チャットの中で複数のアイデアを出すのとは違う ● コンテキスト(=チャット履歴)の分離が重要 ● エージェント=コンテキスト ● マルチエージェント ● ツール呼び出しや判定を組み入れて複数コンテキストを 管理するシステム

Slide 15

Slide 15 text

AIの計算 ● 226-68= ? ● 人間だと ● 150くらいになりそう ● 偶数だな? ● そのあとちゃんと計算して158を求める

Slide 16

Slide 16 text

AIの計算 ● 226-68=? ● LLMだと(Llama3-8B) ● 3桁までの数字は1トークンで扱う ● 24層の12439番目のニューロンは引き算が150~180のときに発火 ● 30層の1582番目のニューロンは引き算が8で終わるときに発火 ● どんどん出現比率をあげて、 最終的に158の確率が高まる ● ヒューリスティックを積み上げて 答えの確率を高めていく Arithmetic Without Algorithms: Language Models Solve Math with a Bag of Heuristics https://arxiv.org/abs/2410.21272

Slide 17

Slide 17 text

AIの学習 ● AIの学習は都合のいいランダムを選ぶ仕組み ● ユニットテストが書けるものは賢くなる ● ユニットテストが書きにくいものは苦手

Slide 18

Slide 18 text

AIの学習は都合のいいランダムを選ぶ仕組み ● AIの学習は当たりが出やすいようパラメータを調整する仕組み ● ハズレの確率が減っていくことを「学習が進む」という ● 答えが定義できれば、正解の確率が高まるようパラメータを調整していけ る ● 問題と答えを自動生成できれば どんどん賢くなる(人工データ) ● 教師を超えることはない ● テキストのみで学習なら人類を 超えない(個人は超える) ● 機械判定できるなら人類を超える

Slide 19

Slide 19 text

LLMはユニットテストが書けるものは賢くなる ● ユニットテストが定義できる問題は学習が進みやすい ● ユニットテストが定義できるならテストが通るまで再試行できる ● コードとテストが自動生成できるならもっと賢くなる ● 部分的なユニットテストが通れば全体もだいたい動くといった コードも書ける ● シーケンシャルな処理

Slide 20

Slide 20 text

ユニットテストが書きにくいものは苦手 ● 学習ができない ● テストが通るまでやりなおす戦略も使えない ● 部分が正しくても全体が正しいわけではないものも苦手 ● つまり非機能要件 ● ユーザビリティ ● API設計 ● セキュリティ ● メンテナンス性

Slide 21

Slide 21 text

AIの弱点 ● コンテキスト処理能力 ● 知らないことが多い

Slide 22

Slide 22 text

コンテキスト処理能力 ● 長いコンテキストに対応できない ● コンテキストの汚れに弱い

Slide 23

Slide 23 text

長いコンテキストに対応できない ● 長コンテキスト対応といっても性能出るのは30Kトークンくらい ● アテンションはO(n^2)なので長くできない ● ウィンドウなどなんらか範囲を限定してる ● 学習データがそんなに長くない ● プロジェクト全体を一気に把握することができない

Slide 24

Slide 24 text

コンテキストの汚れに弱い ● AIにコードを書かせると、「修正しました!」といって2つ前の バグコードを出してきて「アホか!」と暴言を吐きたくなる

Slide 25

Slide 25 text

なぜ同じ失敗が続くのか ● 間違い同士で注目して、大事な情報だと認識してしまう 関係 ありそう めちゃ関係 ありそう 関係 ありそう 関係 ありそう めちゃ関係 ありそう 関係 ありそう

Slide 26

Slide 26 text

コンテキストエンジニアリング ● コンテキストをコンパクトに保つ ● コンテキストが必要な情報だけ持つように管理する ● コンテキストは汚れに弱い ● 関係ありそうで関係ない情報があると性能劣化 ● まったく関係ない話が混じると逆に性能よくなるという説も

Slide 27

Slide 27 text

知らないことが多い ● プログラムの動きを知らない ● ソースファイルと解説しか知らない ● プログラムの成長を知らない ● 完成品しかみてない ● 大きなプログラムを知らない ● ファイル単位で学習している

Slide 28

Slide 28 text

プログラミング言語 ● プログラム言語に必要な機能 ● 言語機能の分類 ● プログラムの最適化と構成

Slide 29

Slide 29 text

プログラミング言語に必要な機能 ● プログラムでやること ● プログラムの構成に求めること

Slide 30

Slide 30 text

プログラムでやること ● 機能 ● 性能 ● 使いやすさ ● 安全性

Slide 31

Slide 31 text

プログラムの構成に求めること ● 機能が追加変更できる ● 機能を破壊しない ● 機能や変更が明確

Slide 32

Slide 32 text

言語機能の分類 ● 実行のための機能 ● 構成のための機能 ● 関数とオブジェクト ● 計算以外の機能

Slide 33

Slide 33 text

実行のための機能 ● 逐次実行 ● 関数 ● 関数とループ

Slide 34

Slide 34 text

構成のための機能 ● 構造体 ● 抽象データ型 ● 部分型とインタフェース ● 継承

Slide 35

Slide 35 text

関数とオブジェクト ● 実行と構成の機能 ● オブジェクトによる関数 ● 関数によるオブジェクト ● 関数と型での証明

Slide 36

Slide 36 text

計算以外の機能 ● メモリ管理 ● 例外処理 ● スレッド

Slide 37

Slide 37 text

メモリ管理 ● スタックとヒープ ● 手動でのメモリ管理 ● 自動的メモリ管理 ● 完全自動 ● スコープによる管理

Slide 38

Slide 38 text

例外処理 ● 復帰可能な例外と復帰不能な例外 ● 戻り値による例外処理 ● ジャンプによる例外処理 ● 構造的例外処理 ● 例外処理の使い分け

Slide 39

Slide 39 text

並列処理 ● スレッドの利用 ● データ並列処理 ● 非同期処理 ● コールバック ● 言語による直列記述 ● VMによる直列記述

Slide 40

Slide 40 text

プログラムの最適化 ● 処理の重複の排除 ● 記述の重複の排除 ● 変更発生源をまとめる ● 依存を減らす ● 処理最適化と構成最適化

Slide 41

Slide 41 text

処理の重複の排除 ● 基本は値を使いまわす ● キャッシュ ● スコープの最小化

Slide 42

Slide 42 text

キャッシュ ● 変数による値の使いまわし ● hashmapによるキャッシュ func(list) { print("合計": list.sum()); print("平均": list.sum() / list.count()); } func(list) { var sum = list.sum(); print("合計": sum); print("平均": sum / list.count()); }

Slide 43

Slide 43 text

スコープ最小化 ● 関数引数やループ変数に依存しない処理を外に出す func() { for (int i = 0; i < 10; ++i) { var n = init(); proc(n, i); } } func() { var n = init(); for (int i = 0; i < 10; ++i) { proc(n, i); } }

Slide 44

Slide 44 text

記述の重複の排除 ● 処理の重複を排除すると減る ● 関数を活用する ● 多態を活用する

Slide 45

Slide 45 text

関数を活用する ● 処理の共通化は関数の主目的

Slide 46

Slide 46 text

多態を活用する ● 部分型による多態を活用 ● テンプレートメソッド abstract class Base { abstract void before(); abstract void after(); void proc() { before(); println("はろー"); after(); } } class School extends Base { @Override void before() { println("起立"); } @Override void after() { println("着席"); } }

Slide 47

Slide 47 text

関数による実装 ● 高階関数だとすっきり書けることも多い void proc(Runnable before, Runnable after) { before.run(); println("はろー"); after.run(); } proc(() -> println("起立"), () -> println("着席"));

Slide 48

Slide 48 text

変更発生源をまとめる ● 単一責務の原則 ● 責務はクラスではなくクラス利用者の責務 ● たとえば入荷処理・価格決めがある ● ふつうは入荷、値付けでわける ● それぞれすべての商品を扱う

Slide 49

Slide 49 text

変更発生源をまとめる ● 単一責務の原則 ● 責務はクラスではなくクラス利用者の責務 ● たとえば入荷処理・価格決めがある ● 商品で担当が分かれていれば ● 商品ごとに処理をわける

Slide 50

Slide 50 text

依存の適正化 ● 使ってない変数が見えないようにする foo(int a, int b) { for(int i = 0; i < a; ++i) { ..割と長い処理 } for(int i = 0; i < b; ++i) { ..割と長い処理 } } fooa(int a) { for(int i = 0; i < a; ++i) [ ..割と長い処理 } } foob(int b) { for(int i = 0; i < b; ++i) { ..割と長い処理 } } foo(int a, int b) { fooa(a); foob(b); }

Slide 51

Slide 51 text

原則 ● スコープの適正化 ● 不要なものをスコープに入れない ● 必要なものをスコープにまとめる ● SOLIDなどの「原則」はあとからついてくる

Slide 52

Slide 52 text

まとめ ● AIは基本的に機能実装しかできない ● 非機能要件は人間ががんばる ● プログラミングを知る必要がある ● がんばりましょう