1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AIにコードを丸投げせず、自力実装とAIレビューでPython CLIを作った記録

1
Posted at

AIにコードを丸投げせず、自力実装とAIレビューでPython CLIを作った記録

これは、AIで爆速開発した記録ではなく、AIをレビュー役にして自力で開発し己の理解不足を観測した記録です。

※この記事はzennで投稿したもの↓のqiita版になります。
https://zenn.dev/sonnerie_9695/articles/47cd95355cfcca

想定読者

この記事は、次のような人に向けて書いています。

  • AIコーディングに興味がある非エンジニア
  • PythonやCLIツール作成を学び始めた初心者プログラマ
  • AIを使って個人開発を進めたい初学者エンジニア
  • AIに全部任せる前に、自分でも実装を理解できるようになりたい人
  • 「AIを使えば簡単に作れる」と言われるけれど、実際どこで詰まるのか知りたい人

この記事で扱わないこと

この記事では、AIコーディングの具体的な手順や、効率的な勉強法そのものは扱いません。

たとえば、次のような内容は主題ではありません。

  • AIにどうプロンプトを書けばよいか
  • AIコーディングツールの比較
  • 最短でアプリを作る方法
  • Pythonの体系的な学習ロードマップ
  • 初心者向けの勉強法ノウハウ

この記事で書くのは、AIにコードを丸投げせず、自分で実装してみたときに何が起きたか、どこで詰まったか、何が見えてきたか、という生の開発記録です。

本題:開発背景とアプローチ

AIでコードが書ける時代に、あえて最初からAIにコードを書かせず、自分でPython CLIツールを実装する、ということをやってみました。

作ったのは notemation というローカルCLIツールです。

Obsidianなどで書いたMarkdown原稿を読み込み、Gemini APIでnote向けに整形し、Playwrightでnoteの下書きエディタへ入力する、という投稿補助ツールです。

ただし、この記事は「AIで爆速開発しました」という類の話ではありません。

むしろ逆です。

AIを使いこなして開発を進めるための勉強として、

  • 最初からAIにコードを生成させず
  • まずは自分で実装して
  • 詰まったところをAIにレビューしてもらい
  • 本当に分からなくなったところだけ助け舟を出してもらう

...という形で進めました。

その結果、単にツールができただけではなく、

  • 自分が何を理解していないのか
  • 実装でどこに詰まりやすいのか
  • 「動く」と「人に渡せる」の間に何があるか
  • AIを先生役・レビュー役として使うとはどういうことか

がかなり見えてきました。

作ったもの

作ったもの:notemation は、Markdown原稿からnote下書き作成までの作業を補助するCLIツールです。

処理の大まかな流れは次の通りです。

  1. 指定フォルダからMarkdownファイルを読み込む
  2. frontmatterからタイトルやタグなどを取り出す
  3. Gemini APIでnote向けの本文に整形する
  4. 整形済みMarkdownをローカルに保存する
  5. Playwrightでnoteの下書きエディタを開く
  6. タイトルと本文を入力する
  7. 公開は自動化せず、人間が確認する

最初から投稿まで全自動化するのではなく、下書き作成までに留めました。

これは技術的にできるかどうかとは別に、投稿事故や外部サービスの利用規約、UI変更リスクを考えると、「どこを自動化しないか」も設計の一部だと感じたからです。

現物

現時点では、リポジトリはプライベートのままにしています。

理由は、まだベータ版で既知のバグがあり、noteやGemini API、ローカル認証情報の扱いについて、利用者側にも確認してもらうべき点が多いためです。

その代わり、この記事では実際のターミナルでの起動画面のスクショ構成やREADMEに書いた制限事項、詰まったポイントのコード例を抜粋して載せます。

起動後&ヘルプ表示後の画面はこんな感じです。

CLIツールの起動画面とヘルプ表示

中身を次のようなPythonパッケージとして作りました。

notemation/
  loadMarkdown.py
  articleFormatter_gemini.py
  saveArticles.py
  publishVianote.py
  config.py
  setup.py
  pathes.py
  data/
    main_menu.txt
    settings_default.json
pyproject.toml
README.md

pyproject.toml では、CLIコマンドとして notemation を定義しています。

[project.scripts]
notemation = "main:notemationActivate"

起動後のメニューは、だいたいこのような形です。

【メインメニュー】
f : 記事を処理する
p : 記事を投稿する
e : エクスプレス投稿
s : 初回セットアップ
h : ヘルプ
c : 設定
x : 終了

READMEには、できることだけでなく、できないこと・しないことも明記しました。

  • note への公開操作の自動化
  • note の非公式 API・内部 API の利用
  • 大量投稿やスパム投稿の補助
  • note 上のデータのスクレイピング

なぜ作ったか

きっかけは、note投稿そのものというより、投稿前後の地味で単調な作業を減らしたかったことでした。

私がやっていた記事の書き方はというと:

  1. Obsidianで原稿を書く(適宜AI壁打ちを挟む)
  2. 意味の切れ目ごとに空白を入れたり、改行したりしてnote向けに読みやすく整える。
  3. タイトルやタグを確認する。
  4. ブラウザを開く。
  5. 本文を貼り付ける。
  6. 下書きとして保存する。

ひとつひとつは小さい作業ですが、
創作や開発、思考の前後に挟まると、
地味にバカにならない量の脳のリソースを食います。

特に内部障害を抱える私にとって、疲労は死活問題。
他の全部の行動が止まってしまうから。
そんなつまらないもので自分の行動を止めたくない。

自動化したかったのは、もちろん創作そのものではありません。
創作や思考に戻るために、その周辺の摩擦を減らしたかった。
それがnotemationの出発点でした。

AIに全部書かせなかった理由

今なら、要件を渡せばAIがかなりのコードを書いてくれます。

実際、このツールも最初からAIに「作って」と頼めば、もっと早く動くものは出てきたかもしれません。

でも、今回の目的は最短で完成させることだけではありませんでした。

自分で実装しながら、

  • ファイルを読むとはどういうことか
  • パスを扱うとはどういうことか
  • APIキーをどこに置くべきか
  • 例外処理はどこまで書くべきか
  • Playwrightで外部サービスの画面を操作する怖さは何か
  • 配布するならREADMEに何を書くべきか

を身体で理解したかった。

AIには主に、次の役割を任せました。

  • 書いたコードのレビュー
  • バグ原因の切り分け
  • 設計案の比較
  • 例外処理やパス操作の考え方の説明
  • 本当に詰まったときの助け舟

AIを「コードを書く装置」としてではなく、「設計理由を問う学習装置」として使うイメージです。

開発の流れ

開発はかなり小さいところから始めました。

最初にやったのは、Markdownを読むだけです。

いきなりGemini APIにも、Playwrightにも、noteにも触りませんでした。

まずはローカルのMarkdownファイルを読み込み、frontmatterと本文を分ける。
そのあと、記事データとして扱いやすい形にする。
そこから少しずつ、Gemini整形、保存処理、note下書き入力へ広げていきました。

ざっくりした流れはこうです。

1. Markdown読み込み
2. frontmatter解析
3. Gemini APIによる整形
4. 整形済みファイルの保存
5. 処理済みファイルの移動
6. Playwrightによるnote下書き入力
7. CLIメニューと初回セットアップ
8. APIキーや認証状態の保存場所見直し
9. "pyproject.toml" によるパッケージ化
10. READMEで制限事項や禁止用途を整理

進めてみると、「Markdownを読むだけ」の時点でも、学ぶことはかなりありました。

実装で詰まったこと

特に詰まったのは、派手なAI連携よりも、もっと地味な部分でした。

例えば、

  • Path.is_dir に () を付け忘れて、メソッドオブジェクトを条件判定してしまったり。
  • frontmatterの tags を読むべきところで title を読んでいたり。
  • Path.resolve() を存在確認のように捉えていたり。
  • except: を広く書きすぎて、自分で投げた例外まで別の例外に潰してしまったり。

上記の「詰まり」を説明用に簡略化したdiffで提示すると:

- if directory_path.is_dir:
+ if directory_path.is_dir():
      files_found = directory_path.glob("*.md")

is_dir は真偽値ではなくメソッドなので、() を付けて呼び出す必要がありました。
こういうミスは地味ですが、経験の浅い自分にはかなりの頻度で発生。

frontmatterでも、キーの取り違えがありました。

- tags = metadata.get("title", None)
+ tags = metadata.get("tags", None)

コードとしては小さな差ですが、後続処理に渡るデータの意味が変わってしまいます。

また、Path.resolve() を存在確認のように捉えていた時期もありました。

- target_path = Path(target_directory).expanduser().resolve()
+ target_path = Path(target_directory).expanduser()
+ if not target_path.exists():
+     raise AnErrorHasOccurred(f"Path does not exist: {target_path}")
+ if not target_path.is_dir():
+     raise AnErrorHasOccurred(f"Path is not a directory: {target_path}")

例外処理も、最初は広く捕まえすぎていました。

- except:
-     raise UnknownError("原因不明のエラーが発生しました")
+ except OSError as e:
+     raise AnErrorHasOccurred("ファイル操作に失敗しました") from e

広すぎる except は、原因を調べるための情報まで潰してしまいます。
AIレビューで、raise ... from e を使うと元の例外を残せることを学びました。

Gemini APIやPlaywrightももちろん難しかったのですが、実際にはその手前にある、

- ファイルを探す
- パスを正規化する
- 設定ファイルを読む
- 例外を残して止める
- 処理対象がないときに先へ進まない

といった基礎部分が、ツール全体の安定性をかなり左右していました。

Pythonの基本が実コードの中で必要になった

教材では、iffor、辞書、関数、例外処理などは単独で出てきます。
でもnotemationでは、それらが実際の処理の中で必要になりました。

  • 条件分岐は、点数判定ではなく、APIキーがないまま処理を進めないために使う。
  • ループは、数字を表示するためではなく、複数のMarkdown原稿を順番に処理するために使う。
  • 辞書は、架空のプロフィールではなく、設定ファイルや記事メタデータを扱うために使う。
  • 関数は、コードを短くするためだけではなく、「どこで失敗したか」を分かりやすくするために分ける。
  • 例外処理は、エラーを消すためではなく、「どこで何が壊れたか」を残して止めるために使う。

このあたりは、自分で一度書いてみないと腹落ちしにくい部分でした。

AIレビューで見えたこと

AIレビューが特に役立ったのは、正解コードをもらうことではなく、自分のコードの危ないところを言語化してもらう場面でした。

たとえば、Markdown読み込み処理については、

- 読む
- 解析する
- 変換する

を分けた方がよい、と整理できました。

パスまわりの不具合では、glob("**/*.md") が悪いと決めつける前に、環境変数、パス解決、ディレクトリ存在確認、globパターンを順に見る必要があると分かりました。

例外処理では、広すぎる except が原因を潰すこと、raise ... from e で元の原因を残せることを学びました。

AIにコードを出してもらうより、自分の試作を見せて「どこが危ないか」を聞く方が、学習としてはかなり効いた感覚があります。

「動く」と「人に渡せる」は別物だった

ベータ版として形にする段階で、一番強く感じたのはここです。

自分の環境で動くことと、人に渡せることはまったく違いました。

人に渡すなら、少なくとも次のことを考える必要があると感じます。

  • APIキーをどこに保存するか
  • noteのログイン状態をどこに保存するか
  • リポジトリに秘密情報が入らないか
  • 外部サービスに何の情報が送信されるか
  • noteの画面変更で壊れる可能性をどう伝えるか
  • 公開操作を自動化しない理由をどう説明するか
  • 利用規約まわりを断定しすぎていないか
  • 何ができて、何ができないツールなのか

このあたりまで来ると、もはや「ちょっと自作スクリプトを書いた」というより、小さなプロダクト開発に近くなります。

正直なところ、プログラミングをしたことのない一般の人に「こうすればいいですよ」と気軽におすすめできるものではない、と感じました。
それがAI駆動開発であっても同様に。

ですが、その感覚自体が大事な発見でした。

「できる」と「勧められる」の間には、大きな距離があります。

AI時代の学び方として感じたこと

今回の開発で、AIを使った開発は簡単になる、というより、分からなさと向き合う速度が上がるものだと感じました。

初めからAIに全部書かせれば、はるかに早く進んだかもしれません。

でも、自分で書いてからAIにレビューしてもらったことで、

  • 自分がどこで雑に理解していたか
  • どの処理を分けるべきか
  • どこに失敗の原因が残りやすいか
  • どこからユーザーへの説明責任が生まれるか

が見えました。

AIコーディング時代に必要なのは、AIに全部書かせる技術だけではないと思います。

自分で小さく実装し、AIにレビューしてもらい、分からないところを言語化しながら進む。

そういう学び方も、かなり有効だと感じています。

今後、個別記事にできそうなこと

今回の開発ログからは、複数の個別記事も書けそうです。

  • Python CLIでMarkdown原稿を読み込む
  • Gemini APIでMarkdown本文を整形する
  • Playwrightでnoteの下書き入力を補助する
  • pyproject.toml でCLIパッケージ化する
  • APIキーとブラウザ認証状態をローカル保存する
  • 初学者が実コードの中でPython基本文法を理解する
  • AIに丸投げせず、レビュー役として使う開発の進め方

この記事は、その入口になるハブ記事として書いています。

まとめ

notemationは、誰にでもおすすめできる万能ツールではありません。

むしろ、作ってみたことで「一般の人に気軽に勧めるには重すぎる」と分かった部分も多いです。

でも、AIと一緒に個人ツールを作る過程で、

  • どこに実装の壁があるのか
  • どこに設計判断が必要なのか
  • どこから安全性や規約の話が出てくるのか
  • AIを学習相手として使うとはどういうことか

を観測する題材としては、かなり濃いものになりました。

AIでコードを書ける時代だからこそ、あえて自分で書いてみる。
そのうえで、AIにレビューしてもらう。

今回の開発は、自分にとってその練習でもありました。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?