公開日:2025-02-18
みなさん。こんにちは。前回bookmarkletの記事を書いたよなしろです。
またbookmarkletの話が少しでてきます。最近お気に入りなんです…
ChatGPTなどの生成AIに bookmarkletやkintoneのカスタマイズ、その他kintone JavaScript API(とか)を呼び出すようなコードを 作ってもらう際に困ることがあります。
生成AI側は各種APIの仕様を考慮せずにコードを生成しているんじゃないか疑惑。です。
たまたま生成AIが学習したプログラムがkintone JavaScript APIを呼び出すようなコードだったりして、 それを真似して生成している。のかもしれません。
実際には何かしらの方法を使用してkintone JavaScript APIなどを学習していて、それを参照しながらコードを生成している。のかもしれません。
そこはChatGPT他、生成AIの中のAIのみぞ知る世界。
それだとたまたま仕様通りのコードが生成されたとしても、「たまたま」なだけで、生成されるコードの精度が安定しづらいことになります。
逆に言うと、kintone JavaScript APIはこういう仕様なんだ。 っていうことを明示的に指示してあげたらそれを参考にして作ってくれることが期待できて、 生成されるコードの精度は上がるかも…と期待できます。
それがうまくいけば、開発の負担を大幅に軽減できます。
本記事では、生成AIをより正確に活用するための方法として、APIドキュメントを与えて精度を向上させるテクニックや、 さらに、その手法を使用して生成AIを活用してどんな便利プログラムが生成できるのか、活用方法をお伝えします。
ただし、今回の記事はkintoneアプリのカスタマイズ(kintoneアプリにJavaScriptを登録して使用する奴)については取り扱いません。
kintoneアプリのカスタマイズのためのJavaScript生成には、 もっと便利なgusuku Customineを使用してノーコードで生成して手間を減らすことをおすすめします。
カスタマイズのコード生成についても、kintoneのAPIを考慮したコードを生成しますし、 外部連携もお手の物、Job Runnerをつかえば定期実行処理もサーバー運用不要でできますので、 実務で使うような使うような用途には是非gusuku Customineをご利用ください!


生成AIでkintone JavaScript APIを呼び出すようなコードを生成する際のポイント
なぜそのままではうまく動かないのか?
生成AIは一般的なプログラミングの知識を持っていますが、kintone特有のAPIの挙動は理解していません。 例えば、単純に「kintoneのレコードを取得するJavaScriptを書いて」と依頼すると、kintone JavaScript APIの呼び出し方が間違っていたり、データの取得方法が間違っている場合などがあります。
また、kintone関連のAPIだと、kintone JavaScript API・REST API・User API(必要だったらGaroon APIも)と活用すると便利なAPIがいくつかあります。
これらのAPIを綺麗に連携させてやることで、なんかすごい便利なものが作れそうな気がしませんか…?
このあたりは、それぞれのAPIの仕様をちゃんと理解させてあげることで回避できそうな気がします。
APIドキュメントを渡すと精度が向上する
生成AIの出力を改善する方法として、kintoneのAPIドキュメントを事前に提供するのが有効です。
とはいうものの、Cybozu Developer Network で kintone APIは公開されていますが、(Deep Search等を使用しない限り)クローリングしてデータを取ってくるなどの対応は難しいです。
また、(知らないだけかもしれないですが)単一のファイルとしてkintone APIドキュメントが公式から提供されているわけでもありません。
となったら…頑張って作るしかないですね。
生成AIに渡すことができる形でのkintone APIドキュメントを作る
というわけで、kintone APIドキュメントを生成AIに渡すことができる形(=単一のファイル)で作成することとします。
クローラープログラムを作ってダウンロードして整形して…としたいところですがここで問題が…
ページの内容によって文書構造が異なるやないかい!!!!!
(具体的にはkintone JavaScript APIと、User APIで構成が違う。そもそも関数とREST APIの仕様の記述なのでそもそも異なっていてあたりまえ)
その違いを考慮して1つのファイルにまとめるために…
ここでおまたせbookmarkletの出番です!
bookmarkletを使ってAPIドキュメントを作成する
bookmarkletを使って、次のような手順でAPIドキュメントを簡単に取得できます。
- kintoneのJavaScript API・REST APIのドキュメントのページを開く
- ブックマークレットを実行する
- 必要なAPI情報がMarkdown形式でクリップボードにコピーされる
- ファイルに貼り付ける!
この方法を使えば、(1ページずつ開いてbookmarkletを実行して、ファイルに貼り付ける…というまぁまぁ大変な作業はありますが…) 単一ファイルのkintone JavaScript API・REST API・User APIのドキュメントが完成します!
ドキュメントごとにフォーマットの異なる内容を整形してもらうbookmarkletを作ってもらうには?
これはもう単純に、特定のページのHTMLをダウンロードして、ファイルを添付し、欲しい内容を指示します。
実際に作成した際のプロンプトの最初では
DOMのクラスで「main--content--article--section--api-docs--content」が指定されているDOM要素をMarkdownで整形するJavaScript関数を生成してください。
テーブルもMarkdownのテーブルで出力し、UL/OLはネストしている場合は適切にレベリングするようにしてください。
という風にプロンプトを記述していました。
やりとりを重ねて、kintone JavaScript APIのページをMarkdownに整形するブックマークレットを作成しました。
javascript:(function(){function extractAndConvertToMarkdown(){const wholeId="section.main--content--article--section";const wholeDom=document.querySelector(wholeId);const titleElem="h2";const title=wholeDom?wholeDom.querySelector(titleElem)?.innerText:%22Untitled%22;const%20contentElement=document.querySelector(%27.main--content--article--section--api-docs--content%27);if(!contentElement){console.error(%27%E6%8C%87%E5%AE%9A%E3%81%95%E3%82%8C%E3%81%9F%E3%82%AF%E3%83%A9%E3%82%B9%E3%81%AEDOM%E8%A6%81%E7%B4%A0%E3%81%8C%E8%A6%8B%E3%81%A4%E3%81%8B%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93%27);return%27%27;}function%20getTextFromElement(element){return%20Array.from(element.childNodes).map(node=%3E{if(node.nodeType===Node.TEXT_NODE){return%20node.textContent.trim();}else%20if(node.nodeType===Node.ELEMENT_NODE){return%20getTextFromElement(node).trim();}return%27%27;}).join(%27%20%27);}function%20convertTableToMarkdown(table){const%20rows=Array.from(table.querySelectorAll(%27tr%27));const%20headerRow=rows[0];const%20bodyRows=rows.slice(1);const%20headers=Array.from(headerRow.querySelectorAll(%27th%27)).map(th=%3EgetTextFromElement(th));const%20headerLine=`|%20${headers.join(%27%20|%20%27)}%20|`;const%20separatorLine=`|%20${headers.map(()=%3E%20%27---%27).join(%27%20|%20%27)}%20|`;const%20bodyLines=bodyRows.map(row=%3E{const%20cells=Array.from(row.querySelectorAll(%27td%27)).map(td=%3EgetTextFromElement(td));return`|%20${cells.join(%27%20|%20%27)}%20|`;});return[headerLine,separatorLine,...bodyLines].join(%27\n%27);}function%20convertListToMarkdown(list,level=0){return%20Array.from(list.children).map(item=%3E{const%20prefix=%27%20%20%27.repeat(level)+%27-%20%27;const%20content=item.querySelector(%27:scope%20%3E%20p%27)?.innerText||item.innerText;const%20nestedList=item.querySelector(%27ul,%20ol%27);const%20nestedMarkdown=nestedList?%27\n%27+convertListToMarkdown(nestedList,level+1):%27%27;return`${prefix}${content.trim()}${nestedMarkdown}`;}).join(%27\n%27);}function%20convertCodeBlockToMarkdown(codeContainer){const%20preElements=codeContainer.querySelectorAll(%27pre%27);const%20secondPreElement=preElements[1];const%20codeContent=secondPreElement?secondPreElement.innerText:%27%27;return%20codeContent?`\u0060\u0060\u0060\n${codeContent.trim()}\n\u0060\u0060\u0060`:%27%27;}function%20convertElementToMarkdown(element){if(element.tagName===%27TABLE%27){return%20convertTableToMarkdown(element);}else%20if(element.tagName===%27UL%27||element.tagName===%27OL%27){return%20convertListToMarkdown(element);}else%20if(element.classList.contains(%27codeblock-container%27)){return%20convertCodeBlockToMarkdown(element);}else%20if(element.tagName===%27H3%27||element.tagName===%27H4%27||element.tagName===%27H5%27){return`###%20${element.innerText.trim()}%60;}else%20if(element.tagName==='P'){return%20element.innerText.trim();}return'';}const%20markdown=Array.from(contentElement.children).map(child=%3EconvertElementToMarkdown(child)).join('\n');const%20cleanedMarkdown=markdown.replace(/(\n\s*){2,}/g,'\n');return%60##%20${title}\n${cleanedMarkdown}%60;}async%20function%20copyToClipboard(text){try{await%20navigator.clipboard.writeText(text);alert(%22Markdown%E5%86%85%E5%AE%B9%E3%82%92%E3%82%AF%E3%83%AA%E3%83%83%E3%83%97%E3%83%9C%E3%83%BC%E3%83%89%E3%81%AB%E3%82%B3%E3%83%94%E3%83%BC%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F%EF%BC%81%22);}catch(e){console.error(%22%E3%82%AF%E3%83%AA%E3%83%83%E3%83%97%E3%83%9C%E3%83%BC%E3%83%89%E3%81%B8%E3%81%AE%E3%82%B3%E3%83%94%E3%83%BC%E3%81%AB%E5%A4%B1%E6%95%97%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F:%22,e);alert(%22%E3%82%B3%E3%83%94%E3%83%BC%E3%81%AB%E5%A4%B1%E6%95%97%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F%E3%80%82%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%BC%E3%83%AB%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%97%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84%E3%80%82%22);}}const%20markdownOutput=extractAndConvertToMarkdown();if(markdownOutput){copyToClipboard(markdownOutput);}})();
…なんだこれは…
これをブックマークに登録して、kintone REST APIリクエストを送信する を開いてブックマークレットを起動すると…
## kintone REST APIリクエストを送信する
kintone REST APIおよびUser APIを実行します。
- このAPIは非同期なAPIです。同期的に処理したい場合は、次のページを参照してください。
(以下実際に試してみてくださいね!)
がクリップボードに入ります。それを1つのファイルに全ページ分実行すれば…APIドキュメントの完成!!!!
といいたいところですが、ページによって構成が異なるため、ブックマークレットを微調整しないと思ってるフォーマットにならないケースがあります。そこはよしなに調整してもらってください。
さぁ、ここまで来たら、このAPIドキュメントを添付して、生成APIに、「このドキュメントの仕様に従って××するプログラムを作ってください!」って指示を出せば…
だいたいどうにかできそうなプログラムを吐いてくれます。
APIドキュメントを活用して実際に作った便利なプログラム
実際にこの方法を使って、生成AIを活用して作成したkintone向けのスクリプトを紹介します。
先に記述していますが、ここで紹介するものはkintoneアプリカスタマイズのためのプログラムではありません。
二つのアプリの差分を取得してMarkdownにフォーマットしてクリップボードに格納するJavaScript関数
とあるアプリの開発用アプリと本番アプリの差分を知りたい。っていう時に生成しました。
開発中のものを本番に反映するためには、gusuku Deploitを使用することでトラブルなく反映できるのですが、 差分を知りたかっただけなので、生成してもらってブラウザの開発者ツールのコンソールで実行しました。
その時のプロンプトは
kintoneの画面を開いているときに開発者ツールのコンソールから実行できるプログラムを作成してください。
要件は下記の通りです
・即時実行関数として作成する
・2つの引数を受ける。1つは開発環境のアプリID、もう1つは本番環境のアプリID
・2つのアプリのプロセス管理で使用するステータスの差分を取得して、「開発環境にはあって、本番環境にないもの」「本番環境にあって、開発環境にないもの」を出力してください。
のように記述していました。
実際にはそのあとに「Markdownにして」とか、「フィールドの違いも」「アクセス権の違いも」「××が正常に動いてない」とかやりとりしながら生成していってました。
これができるのはkintone JavaScript APIだけではなく、REST APIの仕様も合わせて指示できているからですね。
逆に言えば僕自身がどのAPIを使用したらこの情報が取れるかを理解しており、 そのAPIの仕様をまとめた情報を生成AIにわたして実装してもらっている。ということなので、 何も知らない状態ではこのようなプログラムを精度よく生成することは難しいかもしれません。
近い未来ではDeep Search等が解決してくれるかもしれませんが、確実に動くコードを作ってもらおうとするなら多少の開発の学習は必要になると思います。
(どの情報がどこにあって、どうやったら取得できる。っていうのをまとめてあげれば、生成AI的にも助かるはず…そこは今のところは人間が学習して、生成AIに情報提供してあげることが必要かと思っています)
まとめ
生成AIを活用すれば、プログラムを生成する際には、「こういう仕様で」ということを明確に示してあげることで、精度よくコードを生成してくれる可能性が高くなります。
今回はkintone関連のAPIを呼び出すケースでの例示でしたが、他のAPIを呼び出すようなコード生成の際にも、同様に仕様を提示することで精度の高いコード生成をしてくれます。
一度APIドキュメントを作っておけば何かコードを生成したいときにペっと添付するだけで使用可能となるので、生成AIの力を借りながら作成しておくと開発の手助けになるかと思います。
投稿者プロフィール

- 沖縄で業務しています。オンプレ生まれ・クラウド育ち。
最新の投稿
hack-tips2025年2月18日生成AIを活用してkintoneを便利に使うためのプログラムを精度よく生成するには?
kintone2025年1月30日kintoneアプリの転記、面倒くさくない? 昔ながらの技で効率アップ!
kintone2023年8月24日kintoneのフィールドに入っている名前を姓名で分割する
kintone2023年8月24日カスタマインでできないことをするには