プログラマじゃない人でもAI対話用にJSONを学ぶのが最高効率という提案
この文章はプログラマじゃない人向けに JSON を知ってもらうメリット、とくにAIとの効率的な対話方法を説明し、そしてあわよくばプログラマとも JSON の水準で会話してもらえたら嬉しい…というものです。
あなたは誰
- UI を作るのが専門のエンジニアです。
- エンジニア以外が使うノーコードのエディタを作ったりしてました
プログラマじゃない人が JSON を知る利点
プログラマとして、プログラマじゃない人向けのノーコードなどを作っていたんですが、わかったことがあります。それは、「抽象的なロジックを記述するには訓練が必要だが、眼の前のデータとUIに対応したものは簡単に変更・記述できる」ということです。
自分の考える、もっとも成功したノーコードエディタこと Google Form
JSON はよく知られているデータを記述する方法の一つです。特定の言語などとは関係ありません。
で、今現在 JSON というデータ構造は、とくに AI に対する入力として有用だと自分は考えています。
JSONは難しくありません!ちょっとしたルールを覚えるだけです。本当です。信じてください!
{
"こんにちは": "これはJSONです",
"data": [1, -1, 3.14, true, false, "テキスト", null, ["入れ子", "の配列"]]
}
AI は、要は自然言語をJSONに落としてから、考えてるプログラマだと思ってください。AI を制御するのに、JSON の入力、出力を例示してあげるのは、わかりやすい精度の向上が見込めます。
よくあるプログラミング学習では大抵最初のフェーズで「データ構造とアルゴリズム」というものを学ぶのですが、JSONはこの「データ構造」のうち、頻出パターンだけを取り出したものだと思ってください。
JSON を知ることでできること
- AI の入力・出力を詳細にコントロールできる
- JSON を通して考えることで仕様の実現性を認識できる
- プログラマ相手により効率的に会話できる(してもらえると、プログラマが嬉しいい…)
期待値コントロール
先に言っておきます。 「AIが発達したら(この記事で言われているような)~は不要になる」みたいなことを言う人が確実にでますが、絶対に無理です。これはノーコードエディタの開発経験から、自信を持って言えます。仮になくなるとしても、確認ステップが挟まるだけです。
どれだけAIが進化しても、一定以上の水準で本質的な抽象思考・ロジック定義は必ず残ります。今のプログラマの仕事の一つは、抽象思考を認識・定義し、それを具体のコードに変換することで、AIが後者を不要にする可能性があっても、抽象思考の部分は必要です。
JSONで物事を考えることは、ロジックではない眼の前のデータについてのみ考えることです。これによってある程度物事を単純化できます。
もしコレ無しでも実現できたじゃん!となっても、それはAIが勝手に要件を補完しているだけで、その勝手に補完された部分を認識せずにAIと付き合うのは、意図しない不確実性であると認識したほうがいいです。
プログラマの方へ
- 正確性より伝わりやすさを重視しているため、不正確な記述があります。
- 例えば、不鮮明な記述を減らすのに jsonschema の
required
を省いています。
では、具体的に JSON とは何かを説明します。
JSON について
「データ」を表現するための、事実上の標準です。
JSON (JavaScript Object Notation)は、軽量のデータ交換フォーマットです。人間にとって読み書きが容易で、マシンにとっても簡単にパースや生成を行なえる形式です。
元々は JavaScript というプログラミング言語の一部の文法を切り出したものですが、今では異なる言語間で通信する時の事実上の標準となっています。
プログラミング言語だ、と警戒しないでください!JSON単独なら、そう難しいものではありません。
およそあらゆる考えられる全てのプログラミング言語がJSONをサポートしています。
JSONの簡単な例
{
"value": 1
}
{...}
で挟まれるデータは、辞書構造(Dictionary)です。 "
で囲われるキーに対して、 値が入っています。
辞書の {
から }
の範囲では、キーと値は必ずペアになっています。
1個以上のキーと値のペアを入れたい場合、 ,
で区切ります。
{
"key1": 1,
"key2": 2
}
このとき、” “ '
のような類似の符号を使うことはできません。必ず "
や ,
です。
AI は賢いのでこの表記の揺れを吸収してくれるかもしれませんが、正式なものではありません。プログラマやプログラミング処理系に渡すと怒られます。
ちょっと複雑なもの: 入れ子の辞書
{
"key1": 1,
"key2": 2,
"xxx": {
"yyy": 3
}
}
辞書の {
は、必ず対応する深さの }
に対応します。
なので、次のようなデータは不正なJSONです。
{
"x": 1
}}
不正なデータは、プログラマやプログラミング言語は受理しません。読み取れるだけ読み取る、みたいなことはありません。
「JSONとはそういう世界である」ということ言うことを受け入れてもらう必要があります。
値の種類
キーとペアになる値を書く方法。
{
"pi": 3.14,
"str": "文字",
"bool1": true,
"bool2": false,
"nothing": null
}
主にこれらを知っておけば、大抵のケースで十分です。
-
数値型
: 数を表します。 正の1
,-1
のような負の値,3.14
のような小数(厳密には浮動小数点という概念が必要ですが略) -
文字列型
:"
で始まり、"
で終わる区間です。JSONの文字列は直接改行ができません!代わりに\n
という「制御文字」で代替する必要があります。 - 真偽値型:
true
またはfalse
です - null 型: 存在しないことを示す値です。ぬるぽガッのぬるです。
- 辞書型: キーと値のペアのグループ。辞書それ自体が値になるので、入れ子にできます。
- 配列型: 後述
ここで大事なのは、 JSON(の元になってるJavaScript)のような言語は、 キーワード
や予約語
という概念があります。
以上の例でいうと、 {
, }
, true
, false
, null
が文法的に予約されている単語になります。
配列: データの並びを表現する
{
"numbers": [1, 2, 3]
}
[
, ]
で囲われ、 ,
で区切られる「値の列」です。
辞書とは違って、順序に意味があるデータを入れる事が多いです。
実践: AI と JSON で話す方法
JSON が何に使えるかと言うと、AIへのデータの例示です。
ヒマラヤの一番高い場所は?
解答例
{
"location": "Fuji",
"height": 3700
}
ChatGPT (4o) の回答例
{
"location": "Mount Everest",
"height": 8848.86
}
何のデータがほしいかを JSON のサンプルとして例示することで、データの取りこぼしを防ぎ、正確性を向上させることができます。
このようにデータを例示するテクニックを Few Shot, とくに一回だけの場合を One Shot といいます。つまり、何も考えずに質問するのは Zero Shot です。
モダンな LLM は自然言語より厳密なプログラミング言語をそこそこに習熟しており、プログラマと同じ水準で考えさせる、そして可能なら自分もその水準で喋るというのは、品質向上のわかりやすいアプローチです。
JSONを理解することで、何ができるか?
これがすべてではないにしろ、 JSON(相当のデータ定義)はプログラマの思考水準の一つです。プログラマは自然言語で説明された仕様を、 「文字」「数値」「真偽値」「辞書」「配列」で考えてます。
逆に言うと、 そもそも JSON で表現できないものは、要件定義として失敗している可能性が高いです。
そして、AIがコード生成を考えているときも、おそらくこの水準が土台になります。今の AI は、プログラマの一人だと考えてください。
jsonschema の紹介: パワフルな要件定義
JSONSchema はデータそのものではなく、データのパターン(型)を記述する方法です。
JSON はデータそのものを記述しますが、データのとりうるパターン、可能性を考慮できるわけではありません。
JSONSchema を知っていると、 LLM の Function Calling という機能を経由して、AIとプログラマに同時に要件定義ができます。(残念ながら、要件定義ができるだけで、即座に実装されるわけではありませんが…)
現在、 ChatGPT や Claude は Function Calling という機能に対応しています。これは、 入力を JSONSchema で定義した Function を事前に定義しておくと、それが必要なタイミングで呼び出してくれる、といったものです。
(この実装を行うには、現状コードを書く必要があります。将来的にはその場でAI自身が Function を生成できるかもしれませんが、セキュリティや諸々の都合でシュッと作るのは難しいとだけ言っておきます)
例えば、 [1, 2, 3]
はプログラマの言葉で「長さ3の数値型の配列」ですが、これだけ知ったところで「実際に3以外の長さが入力される可能性」や「もしかして別のタイミングでは文字列も入るんじゃないか?」ということを表現できてはいません。
(難しいので、ここまでで頭が痛くなってる人は飛ばしても構いません)
jsonschema は、 json 自身のデータ構造を使って、 json の取りうる可能性(プログラマの言葉では、型)を記述する方法です。
JSON Schema の例です。
{
"type": "object",
"properties": {
"foo": {
"type": "number"
}
}
}
これを満たすJSONの例
{
"foo": 1
}
本当にそうなってるかは、ここで確認できます。
JSONSchema はデータそのものではなく、「データが取りうる可能性を記述する」ものです。この時点ではほぼ1:1に対応していますが、少し複雑な例を見てみましょう。
{
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"oneOf": [
{
"type": "string"
},
{
"type": "number"
}
]
}
}
}
}
要約すると、これは「items というキーで数値もしくは文字列の配列のオブジェクト」になり、この条件を満たすデータは複数パターン存在します。
ここで新しいルールを2つ使っています。
-
"type": "array"
のitems
以下で、何を満たす配列か、を指定 -
"items"
の"oneOf"
で、複数の型の条件のうち、いずれかを満たすことを指定
こんなの理解できない!と悲観する必要がありません。大抵のプログラマもうろ覚えで、都度調べながら書いています。僕もググりながら書きました。AI があるんなら、AIに聞いて下さい。
先程の定義を満たす JSON の例
{
"items": [1, "hi", 3]
}
{
"items": [1]
}
{
"items": []
}
{
"items": ["hi", "abc"]
}
このように、 JSON は構文を満たす限り自由に記述できるものでしたが、 JSONSchema は比較的(プログラミング言語的な)厳密なパターンがあります。
大事なのは、 JSONSchema には最終的にどのぐらいの表現力があるか?という大雑把な認識は必要です。これにより、自分の概念が JSON/JSONSchema 上どの概念で記述できるか?というイメージを持つことができます。
JSONSchema をプロンプトとして使う
出力するパターンを JSONSChema で例示します。
以下を満たすサンプルデータを出力してください
{
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"oneOf": [
{
"type": "string"
},
{
"type": "number"
}
]
}
}
}
}
o4 の応答例
以下のサンプルデータを生成しました:
```json
{
"items": [
"apple",
42,
"banana",
3.14,
"grape",
7
]
}
```
ただし、現状はこのデータがあってるかどうかは確認できません。 https://jsonschema.dev/ にデータを入れて、その結果で確認する必要があります。
もしエラーが出た場合も、今のLLMの性能なら、エラーを貼り付ければ自動で修正できます。
JSONSchema の応用例: Function Calling
こっちが本命。
JSONSchema を記述して Function Calling で呼び出すことで、こういうことができるようになります。
- プログラマが今日のお天気を問い合わせする Function の入力スキーマを定義しておく
{ "type": "object", "properties": { "location": {"type": "string"} } }
- ユーザー「今日の東京の天気は?」
- LLM が今定義されているスキーマを認識し、
{ "location": "東京" }
という入力で Function を呼び出す - 実行して、
晴れ
という結果を受け取る - LLMの応答「今日の東京は晴れです」
なので、プログラマに対する仕様の要求として、エクセルや自然言語ではなく JSONSchema を書くのが一番嬉しいです。(が、それから要件がこぼれ落ちてしまうようだったら自然言語もセットではあります)
たぶん、最初はプログラマに渡したら「~の定義が足りない」と突っぱねられると思いますが、それを考えるのが仕様を考える人の責務ではあります。プログラマはできないとダダを捏ねているのではなく、その要求から自然と湧いてきている「現象」にたいしてコメントしていると思ってください。
Function Calling や JSON で表現できないこと
入出力以外に発生する「副作用」や「状態」を表現できません。同じ Function の呼び出しでも A => B => C と呼び出すたびに状態が変わる「状態の仕様」は、 JSON や JSONSChema で表現する対象ではありません。
例えば、「Xにポストしたい内容」を定義できても、「X に実際に Post する」といったことは、実際にリクエストを投げるコードを書かなければ実現できません。
より単純な例を出します。
自身が呼び出された回数を数える counter(input)
という機能があるとします。これは入力を無視します。このとき、このときに入力に含まれない「状態」を外部(いわゆるデータベースなど)に保持する必要があるので、例示したところで簡単に実装できるわけではありません。
以下に概念的な疑似コードを示します。
counter(x) => 0
counter(y) => 1
counter(z) => 2
これに対し、与えられた数値を +1 した add1
のFunctionを作るのは、状態を保つ必要がないので実装が簡単です。
add1(1) => 2
add1(2) => 3
add1(100) => 101
要件次第ですが、基本的にプログラマは状態がないものを好みます。
これをプログラマの言葉で参照透過性といいます。
jsonschema の応用例: フォームの自動生成
jsonschema という厳密なデータを使えば、ある程度簡単な受付フォームを自動生成できます。だいたいのプログラミング言語それ相当のライブラリがあり、なくても自力で実装するのは(プログラマなら)さほど難しくありません。
フロントエンド(React)の例です。
勿論、細かいUIの変更は対応しておらずプログラマが頑張るしかないんですが、プロトタイピングには十分です。これも一つのローコードではあります。
まとめ
- AI は JSON に詳しいし、自然言語より厳密で、使いやすい
- JSON は難しくない
- JSON を知るとプログラマでなくても高品質なプロンプトが書ける
- JSON を知ると要求の実現性が(間接的に)わかる
- 人間にも伝わる
というわけで、プログラミングを覚えるほどではないが、 「AI時代にコスパ良く学べるI対話術」として JSON に触れることをおすすめします。
Discussion