
YAMLのいじり方(2)
はじめに:Gemini Code Assistすごいね
私自身まだ、Gemini Code Assist(以下「GCA」)を使い始めて一週間にもなっていませんが、断言します。GCAを使うことはPython初心者・学習者にとって、ぶっこわれ「チートスキル」を手に入れたようなものだ!!!
自身、最初に試したのが2月26日でした。
ちょうどネット記事にも紹介されていました。
データの構成や処理方法を指示するだけで、コードを書いてくれる。適切にコメントも入っていて、整理された、とても分かりやすいコードが出力される。「自分のやりたいこと」を通して「自分の勉強」になる。すごい。
今回やってみること・・データ構造定義
さて前回の
・・・では、「繁体字中文の単語カード」という想定で作業を進め、キー名などを決めました。
しかし、今後、中学生が英単語や歴史の年表、元素記号など、様々な科目の暗記に使えるように、汎用的なフラッシュカードアプリにしたいと考えています。そのためゼロからデータ設計を見直すことにしました。
まず、YAMLデータ構造定義の仕様指示はどうしたらよいか聞いたら、こんな回答でした。(この指示構成は今後も活用できると思います。)
GeminiにYAMLデータ構造を生成してもらうためには、以下の点を明確に整理し、Geminiに伝えることが重要です。具体的に整理すべき仕様を段階的に説明します。
1. 全体の概要・目的の明確化:
・何のデータ構造なのか?: まずは、作成したいYAMLデータ構造が何を表すのかを明確にしましょう。例えば、「ユーザー情報」「設定ファイル」「商品情報」「タスクリスト」など、大まかな目的や内容を伝えましょう。
・データの利用目的は?: そのYAMLデータがどのように使われるのか、利用目的も明確にすると、より適切な構造を生成できます。例えば、「アプリケーションの設定を読み込む」「APIのレスポンスとして返す」「データ分析に使う」などです。
2. データ構造の詳細の定義:
・キーと値の関係:
YAMLはキーと値のペアで構成されます。どのようなキーが必要で、それぞれのキーにどのような値を格納するのかを定義します。
・・キー名: 各キーの名前を決定します。わかりやすく、一貫性のある名前を使いましょう。例:name, email, age
・・値のデータ型: 各キーに格納される値のデータ型を明確にします。
・・・文字列 (string): テキストデータ ("example", "Hello World")
・・・数値 (integer, float): 整数や浮動小数点数 (10, 3.14)
・・・真偽値 (boolean): 真 (true) または偽 (false)
・・・リスト (list/array): 複数の値の順序付きリスト ([1, 2, 3], ["apple", "banana"])
・・・マップ/辞書 (map/dictionary): キーと値のペアを複数持つデータ構造 ({name: "John", age: 30})
・・・null: 値がない場合 (null)
・・キーの必須/任意:キーが必須かどうかを明確化します。
・構造の階層化: データ構造が複雑な場合、どのように階層化するのかを決めます。
・・ネスト(入れ子): マップやリストの中に、さらにマップやリストを入れることで階層構造を作ります。例:user: {name: "John", address: {city: "Tokyo", country: "Japan"}}
・リストの表現:リストの要素がどの様な構造を持つかを記述します。
3. データ例の提供 (任意ですが強力):
・具体的なデータ例: 可能であれば、想定されるデータ例をいくつか提供すると、Geminiはより正確なYAML構造を生成できます。例を示すことで、データ型や構造の理解を深めることができます。
4. 追加の制約や要件:特定のフォーマット:
・特定のフォーマット(例えば、ISO 8601形式の日付)を使用したい場合は、それを明記します。
・値の制約: 値に制約がある場合(例えば、年齢は0以上120以下)は、それを伝えます。
・コメントの追加:生成されたYAMLファイルにどの様なコメントを入れて欲しいかを指定します。
Geminiへの指示の例:
上記の仕様をGeminiに伝える際の指示の例です。
以下の仕様に基づいて、YAMLデータ構造を生成してください。
## 仕様
### 概要
- ユーザー情報を管理するためのデータ構造を作成します。
- ユーザーID、名前、メールアドレス、年齢、住所を格納します。
- 住所には、都道府県、市区町村、番地を入れます。
### キーと値
- user_id: ユーザーID (整数、必須)
- name: ユーザー名 (文字列、必須)
- email: メールアドレス (文字列、必須)
- age: 年齢 (整数、任意、0以上120以下)
- address: 住所 (マップ、必須)
- prefecture: 都道府県 (文字列、必須)
- city: 市区町村 (文字列、必須)
- street: 番地 (文字列、必須)
### データ例
以下のようなデータが格納されることを想定しています。
- ユーザーID: 1, 名前: 山田太郎, メール: taro.yamada@example.com, 年齢: 30, 住所: 東京都, 新宿区, 1-1-1
- ユーザーID: 2, 名前: 田中花子, メール: hanako.tanaka@example.com, 住所: 大阪府, 大阪市, 2-2-2
### 追加要件
- 生成されたYAMLに各キーの意味をコメントとして追加して下さい。
###出力形式
生成されたYAMLデータ構造を出力して下さい。
このプロンプトの構成は応用がききそうです。
フラッシュカードのデータ設計
では上の例を参考に、自分なりに「フラッシュカード」データの仕様を書いてみます。
自作の仕様書
以下の仕様に基づいて、YAMLデータ構造を生成してください。
## 仕様
### 概要
- 出題に対応した解答を暗記するための「フラッシュカード」のデータ構造を作成します。
- カード表の出題文字列、カード裏の解答文字列、暗記定着度、最終学習日時を格納します。
### キーと値
- front: カード表の出題文字列 (文字列、必須)
- back: カード裏の解答文字列 (文字列、必須)
- retention_rate: 暗記定着度 (整数、任意、0以上5以下)
- learned_datetime: 最終学習日時(日時、任意)
### データ例
以下のようなデータが格納されることを想定しています。
- 表: 獨居, 裏:一人暮らし, 暗記定着度: 1, learned_datetime: '2025-03-04 18:39:58'
- 表: 長輩, 裏:年長者,
- 表: 聚餐, 裏:会食, 暗記定着度: 2, learned_datetime: '2025-03-03 23:19:14'
- 表: 圍爐, 裏:囲炉裏を囲む,
### 追加要件
- 生成されたYAMLに各キーの意味をコメントとして追加して下さい。
###出力形式
生成されたYAMLデータ構造を出力して下さい。
Gemini回答
以下、ご提示いただいた仕様に基づき生成したYAMLデータ構造です。
# フラッシュカードのデータ構造
cards:
- # カード1枚目
front: 獨居 # カード表の出題文字列
back: 一人暮らし # カード裏の解答文字列
retention_rate: 1 # 暗記定着度 (0〜5の整数)
learned_datetime: '2025-03-04 18:39:58' # 最終学習日時 (YYYY-MM-DD HH:MM:SS形式)
- # カード2枚目
front: 長輩 # カード表の出題文字列
back: 年長者 # カード裏の解答文字列
retention_rate: null # 暗記定着度 (0〜5の整数) 未設定時はnull
learned_datetime: null # 最終学習日時 (YYYY-MM-DD HH:MM:SS形式) 未設定時はnull
- # カード3枚目
front: 聚餐 # カード表の出題文字列
back: 会食 # カード裏の解答文字列
retention_rate: 2 # 暗記定着度 (0〜5の整数)
learned_datetime: '2025-03-03 23:19:14' # 最終学習日時 (YYYY-MM-DD HH:MM:SS形式)
- # カード4枚目
front: 圍爐 # カード表の出題文字列
back: 囲炉裏を囲む # カード裏の解答文字列
retention_rate: null # 暗記定着度 (0〜5の整数) 未設定時はnull
learned_datetime: null # 最終学習日時 (YYYY-MM-DD HH:MM:SS形式) 未設定時はnull
解説:
cards::このキーは、フラッシュカードのリストを表します。
-:ハイフンはYAMLにおけるリストの要素を表します。つまり、-で始まる各ブロックが1枚のフラッシュカードを表しています。
front:カードの表側(問題)の文字列です。
back:カードの裏側(解答)の文字列です。
retention_rate:暗記定着度です。データ例では0〜5の整数が想定されているため、そのように設定できます。また、任意とあったため、未設定のカードにはnullを設定しています。
learned_datetime:最終学習日時です。データ例ではYYYY-MM-DD HH:MM:SS形式が想定されているため、そのように設定しています。また、任意とあったため、未設定のカードにはnullを設定しています。
コメント: #を使用して行末に追記しています。
null: 未設定を表現する為にnullを使用しています。
補足:
データ例では retention_rate と learned_datetime が未設定の場合もありましたが、YAMLでは値を省略することができないため、明示的に null を設定しています。これにより、値が「未設定」であることを明確に表現できます。
データはリスト構造を取っているので、いくらでも追加する事ができます。
以上が、ご指示に基づいて生成したYAMLデータ構造です。他に修正点や追加のご要望があればお気軽にお申し付けください。
再質問
>データ例では retention_rate と learned_datetime が未設定の場合もありましたが、YAMLでは値を省略することができないため、明示的に null を設定しています。これにより、値が「未設定」であることを明確に表現できます。
とのことですが、以前Geminiから
>learned: true なら「覚えた」、learned: false なら「まだ覚えていない」とします。 または、learned: true があれば「覚えた」、このキーがなければ、「まだ覚えていない」としてもよいです。
と教わりました。最初からretention_rate と learned_datetimeをいちいちnull設定するのも無駄な気がするので、キーが無ければnullという扱いにしたいと思うのですが?
Gemini再回答
承知いたしました。過去のやり取りもコンテキストとして一旦クリアにします。今回の「retention_rate と learned_datetime のキーがない場合は null と解釈したい」というご要望を最優先として理解しました。
つまり、以下の要件でYAMLデータ構造を生成したいということですね。
要件の再確認
キーがない場合、nullとみなす: retention_rate や learned_datetime のキー自体が存在しない場合は、その値がnull(未設定)であると解釈する。
キーがある場合のみ、値を入れる: retention_rate や learned_datetime のキーが存在する場合は、そこに設定された値を使用する。
それ以外のキーは前回の指定の通り
修正されたYAMLの例
上記を踏まえて、修正したYAMLのデータ構造を以下に示します。
content_copyaddcompare_arrowsopen_in_full# フラッシュカードのデータ構造
cards:
- # カード1枚目
front: 獨居 # カード表の出題文字列
back: 一人暮らし # カード裏の解答文字列
retention_rate: 1 # 暗記定着度 (0〜5の整数)
learned_datetime: '2025-03-04 18:39:58' # 最終学習日時 (YYYY-MM-DD HH:MM:SS形式)
- # カード2枚目
front: 長輩 # カード表の出題文字列
back: 年長者 # カード裏の解答文字列
- # カード3枚目
front: 聚餐 # カード表の出題文字列
back: 会食 # カード裏の解答文字列
retention_rate: 2 # 暗記定着度 (0〜5の整数)
learned_datetime: '2025-03-03 23:19:14' # 最終学習日時 (YYYY-MM-DD HH:MM:SS形式)
- # カード4枚目
front: 圍爐 # カード表の出題文字列
back: 囲炉裏を囲む # カード裏の解答文字列
解説
カード2枚目と4枚目からキーが削除: retention_rate と learned_datetime のキーがカード2枚目と4枚目から完全に削除されています。これにより、これらのカードの暗記定着度と最終学習日時は「未設定」(つまりnull)であることを表現します。
カード1と3枚目:前回指定通りデータが存在しています。
カード2枚目と4枚目は暗記定着度と最終学習日時が未設定: データが無い事を意味します。
コメント:前回指定通りです。
メリット
データ量の削減: 不必要な null の設定が不要となり、データサイズが小さくなります。
可読性の向上: データが明確に設定されているキーのみに注目できるため、可読性が向上します。
効率的な処理: YAMLを読み込むアプリケーション側で「キーが存在しない場合はnullである」というルールで処理することで、効率的なデータ処理が可能になります。
アプリケーション側の実装
このYAMLを読み込むアプリケーション側では、以下のロジックで処理することになります。
retention_rate キーが存在するかチェックする。
存在すればその値を使い、存在しなければnull(未設定)とみなす。
learned_datetime キーも同様に、存在するかをチェックし、存在すればその値を使い、存在しなければnull(未設定)とみなす。
まとめ
これで、ご要望通りの「キーが存在しなければnullとみなす」というYAMLデータ構造が完成しました。より効率的で可読性の高いデータ構造になったと思います。
他に修正点や追加のご要望がありましたら、お気軽にお申し付けください。
今回のデータ構造を導く仕様書
今回のデータ構造を導くのに必要十分な仕様書もGemini自身に出力してもらいました。
以下の仕様に基づいて、YAMLデータ構造を生成してください。
### 仕様
- フラッシュカードのデータ構造を作成します。
- 各カードは、表側の出題文字列 (`front`)、裏側の解答文字列 (`back`)、暗記定着度 (`retention_rate`)、最終学習日時 (`learned_datetime`) を持ちます。
- `front` と `back` は必須の文字列です。
- `retention_rate` は0から5までの整数で、任意です。キーが存在しない場合、未設定(null)とみなします。
- `learned_datetime` は日時で、任意です。キーが存在しない場合、未設定(null)とみなします。
- データはリスト構造にしてください。
- 各キーの意味をコメントで追記して下さい。
### データ例
以下のようなデータが格納されることを想定しています。
- 表: 獨居, 裏:一人暮らし, 暗記定着度: 1, learned_datetime: '2025-03-04 18:39:58'
- 表: 長輩, 裏:年長者
- 表: 聚餐, 裏:会食, 暗記定着度: 2, learned_datetime: '2025-03-03 23:19:14'
- 表: 圍爐, 裏:囲炉裏を囲む
###出力形式
生成されたYAMLデータ構造を出力して下さい。
感想
いい感じで作ってくれました。
これまでのように自分一人で考えるのだったら、ここに至るまで何日かかることでしょうか?