はじめに(読み飛ばしOKです)
生成AIが、誰でも簡単に「上手な絵」や「きれいな文字」を生み出せる時代になりました。
そんな世界で、子どもが時間をかけて練習し、上達する意味はどこにあるのでしょうか。
私は二児の母として子育てをしながら、生成AIエンジニアとして働いています。今年小学校に入学する長男の描いた絵を見て「上手になったね」と声をかけたとき、この問いが急に現実味を帯びて迫ってきました。
生まれたときから生成AIが身近にある、いわゆる「生成AIネイティブ」の子どもたちにとって、AIは学びを代替する存在になるのか、それとも学びを支える存在になりうるのか。
親として、そしてエンジニアとして、この問いは避けて通れないものだと感じています。
生成AIは反復性や個別対応に優れており、児童一人ひとりの得意・不得意や興味関心に寄り添った学びと相性の良い技術です。しかし、大人の使い方次第で、「子どもの成長の芽を摘むもの」にも、「一人ひとりの成長を支える味方」にもなり得ます。
そんな前提に立ったとき、生成AIを学びを代替する存在ではなく、学びを支援する存在として使えないかと考え、まずは自分にできる形で手を動かしてみたのが、この「生成AIなぞり字・書き順アプリ」です。
アプリの説明
前置きが長くなりましたが、このなぞり字・書き順アプリの使い方は下記のとおりです。
①保護者または児童本人が興味があるものを単語で入力
お子さんの興味関心のある分野について単語で入力し、OKを押します。
なお、文字を学習中の子供にテキストで入力することを求めるのはUIUX的にそぐわないため、将来的に音声入力などの別の入力手段に置き換える想定です。(実装の都合で現状は一旦文字入力になっています)
②生成AIの提示した3つの候補から、なぞり字をしたい単語を選択

生成AIが①で入力された単語に基づき、近似する語句で且つ児童の興味関心が高そうな単語を3個抽出し、ボタンとして表示します。
単語はひらがなで描いたとき3-6文字のレンジに収まるものに限定して出力されます。また、「まえにもどる」ボタンで興味関心の入力画面に、「つくりなおす」で抽出した3個の単語のリフレッシュ(再生成)ができます。
③選んだ単語のなぞり字を行う

②で選んだ語句のなぞり字練習画面にが表示されます。次になぞるべき線は書き順に基づき赤くハイライトされ、書く流れの通りにアニメーションしています。
1文字正しく書き終わると①で入力した興味関心に基づいて生成されたキャラクターのイラストが線の上を走っていくアニメーションが再生されます(※デモのため、現在は電車で固定されています)。

単語を構成するすべての文字を書ききると、はなまるのアニメーションが表示されます。
技術仕様
構成は下記のとおりです。
実装はすべてReactで行っています。

Azure OpenAIへの関連語句群リクエスト
まず、1画面目で入力された興味関心語句をAzure OpenAIに送信し、関連語句(たとえば「でんしゃ」という興味関心語句であれば「ふみきり」「せんろ」、「どうぶつ」であれば「きりん」「ぺんぎん」など)を10語取得します。
投げているプロンプトは下記のとおりです。
(興味関心語句)に関係する単語を10語選んで出力してください。
条件:
- ひらがなで(カタカナ・漢字は使わない)
- 3文字以上6文字以下
- 就学前〜小1が知っている単語
- なるべく具体的(固有名詞寄り歓迎)
- できるだけ重複しない
出力形式はJSONのみ:{"words":["...","..."]}`;
2画面目ではAzure OpenAIのリクエスト結果である10個の単語(以下「関連語句群」)を用いて、3つボタンを作成・表示します。
なお、「つくりなおす」ボタンを押すとボタンの内容を更新できますが、押下時に再度関連語句群を生成する仕様にすると、子供が連打した際にAPI課金が大量発生しまうため、最初に一度だけ関連語句群(10個)をプールしています。
「つくりなおす」ボタンを押すとプールされた関連語句群の中からランダムに3つがボタンとして設定される作りです。
今回のバージョンではひらがなにしか対応していないため、関連語句がカタカナで帰ってきてしまった場合はひらがなに変換しています。
なぞり字画面の描画
2画面目で選択したボタンの語句はURLパラメタとして3画面目であるなぞり字練習画面に送信されます。3画面目のなぞり字練習画面は、各ひらがな1文字ずつが「なぞり字モジュール」として独立している仕様となっており、URLパラメタとして渡ってきた単語を分解して1文字ずつ該当するひらがなのモジュールを呼び出して横並びに表示します。
なぞり字モジュールは
- ラベル(例:"あ")
- ローマ字対応(例:"a")
- viewbox(なぞり字領域の大きさ)
- 書き順:(書き順管理用のパス。1画ごとにJSON形式のSVGパスの値を画数分)
- ストローク:(グレーの文字表示用のパス。1画ごとにJSON形式のSVGパスの値を画数分)
- ヒント文言:(例:"パス順に1画ずつ")
の値で構成されています。データとしては下記のような形式です。
import type { KanaSpec } from "../types";
const spec: KanaSpec = {
label: "DUMMY_GLYPH",
romaji: "dummy",
viewBox: "0 0 1024 1024",
paths: [
// 1画目
"m 150 200 l 250 150 l -200 200 l 300 150 l -250 250",
// 2画目
"m 800 150 c -200 150, -200 250, -50 350 c 150 100, 50 250, -150 350",
// 3画目
"m 250 850 c 250 -200, 450 -100, 550 -250 c 100 -150, -200 -200, -350 -150 l -150 200",
],
strokes: [
{
mode: "shape",
guideD: "m 150 200 l 250 150 l -200 200 l 300 150 l -250 250",
tol: 120,
},
{
mode: "shape",
guideD: "m 800 150 c -200 150, -200 250, -50 350 c 150 100, 50 250, -150 350",
tol: 120,
},
{
mode: "shape",
guideD: "m 250 850 c 250 -200, 450 -100, 550 -250 c 100 -150, -200 -200, -350 -150 l -150 200",
tol: 120,
},
],
hint: "記事用ダミー文字",
};
export default spec;
※本稿のSVGパスは、構造説明のためのダミーデータです。
実在の字形・フォント等とは無関係で復元もできません。
なお、このなぞり字モジュールのもととなるひらがなの書き順データについては、下記のstrokesvg(License: SIL Open Font License 1.1)を使わせていただきました。本当にありがとうございます!
使ってもらった感想・見えてきた課題
一通りの実装が済んだので、実際に長男(6歳)に使ってもらいました。
下記のような感想や改善点が得られました。
- 楽しそうに何度もチャレンジする様子が見られ、正しい書き順でなぞり字ができていた。
- 書き順自体は意識しやすい模様。
- ただし、書き始めと書き終わりの区別がつかず逆流することがある。
- 書き始め、書き終わりをよりわかりやすいUIにする、アニメーションをもう少しわかりやすくするなどのUI的工夫を入れたい。
- 書き順を学ぶという観点では有効そうだが、現行の判定が甘すぎて正しい字が書けたかの判定が実質できていない。
- 線を適当に描いてもOKになってしまうので難易度調整が必要。
- 成功体験を積ませるのを優先するかどうかで難易度が変わる。現状は成功体験重視で判定を甘めに設定していた。
- 自分の書いた線の上を画像がアニメーションするのが楽しいようで、わざとぐちゃぐちゃに書くことがある。
- 画面の拡大縮小を切らないと、指で書くときに手の甲などが接触してしまい、想定外の誤操作を起こす。
- 指ではなくタッチペンのほうがいいかもしれない。
- 1文字ずつにする・書いていない字はグレーアウトさせる・縦書きにするなど、UIの工夫がいりそう。
- となりのボックスに指が干渉してしまって想定外の線を引いてしまったり、ボタンを押してしまったりする。
- 描いた文字をログとして残せるようにしたい。どれくらいうまくなったかあとから振り替えられるようにしたい。(※親視点のコメント)
- 画面キャプチャ機能→印刷できてもいいのかも
おわりに
今回は「なぞり字・書き順」という小さなテーマでしたが、生成AIを使って、子ども一人ひとりの興味関心に寄り添う学びの形を具体的に作ることができました。
実際に使ってもらう中で、UIや判定ロジックなど多くの課題も見えてきましたが、
生成AIは子どもの学びを奪うものではなく、使い方次第で学びを支える道具になり得るという手応えは確かに感じています。
生成AI時代の学びに正解はありませんが、子どもの成長に寄り添う形で技術を設計することは、私たち大人にできる大切な役割だと思っています。
今後も試行錯誤を続けながら、子どもたちの学びを支える生成AIの使い方を探っていきたいと考えています。


