記事
· 6 hr 前 10m read

IRIS開発における生成AIの活用について

はじめに

生成AIを活用したアプリケーション開発は、Python、JavaScriptなどのメジャー言語による体験記事がよく見られます。一方、IRISのObjectScriptの開発に言及された記事は比較的少ないのが現状です。そこで、本記事では生成AIがObjectScriptの開発にどこまで活用できるのかを検証しました。

特にDevOpsのプロセスにおいて、生成AIは様々なシーンでの活用が期待できます。今回は開発工程に注目し、以下の観点から生成AIの有効性を調査しました。

  • 開発
    • コードの自動生成
    • 環境構築のアシスタント(テーブルの作成)
  • 検証
    • テストデータ生成のサポート

環境

本記事の検証は以下の環境で行いました。

開発環境

  • OS: macOS Sonoma
  • IRIS: 2023.4 (linux)

開発ツール
IRISの開発にはStudioやVSCodeなどが利用可能ですが、今回は生成AIの活用に特化したエディタ「Cursor」を使用しました。

Cursorを選定した理由
Cursorは、生成AIによる支援機能に特化したコードエディタで、以下の特徴があります:

  • 生成AIの支援:コードの自動生成や提案、バグの検出、修正提案を行います。また、外部のドキュメントや複数のソースを指定し、生成内容に反映させる簡易なRAG機能も搭載されています。

  • VSCodeとの互換性:VSCodeをフォークして作られており、VSCodeユーザーはスムーズに移行できます。拡張機能もそのまま利用可能です。

IRISではv2024よりStudioは廃止となり、VSCodeが標準ツールとなります。そこで、VSCodeと互換性があり、生成AIとの親和性が高いCursorを選定しました。

選択した生成AIモデル
GPT-4を使用しましたが、Claudeでも検証を行ったところ、どのモデルも大差ない結果となりました。
利用しやすいモデルを選んで試してみてください。

検証内容

今回は以下の内容を検証しました。

  • 簡単なプログラムの生成とターミナルでの実行
  • IRISのREST通信機能を使った商品情報検索APIの作成

サンプルプログラムの作成

まず、ユーザーに名前を入力させ、挨拶を返す簡単なルーチンを生成します。CursorでCommand+Lを押してチャットウィンドウを開き、以下のプロンプトを入力します。

あなたはObjectScriptの開発者です。
{仕様}をもとにコードを作成してください。
#仕様
- 以下の処理を実行するRoutineを作成する。
- macファイル名は"TEST.mac"とする。
1. ユーザーに名前の入力を促します。
2. 入力された名前が空であればエラーメッセージを表示します。
3. 名前が入力された場合、その名前を使って挨拶メッセージを表示します。

image

生成されたルーチンをTEST.macにコピーし、ターミナルで実行して動作を確認します。

image

REST APIの作成

簡易なプログラムの生成が確認できたので、次はより複雑なアプリケーションを作成してみます。

アプリケーションの仕様
IRISのREST通信機能を利用したAPIを作成します。ユーザーからのリクエストに基づき、サーバー上のデータベースから該当する商品情報をJSON形式で返します。

テーブルの作成
まずは、テーブルを作成しましょう。DDLの作成をAIに依頼します。

InterSystemsのIRISで{テーブル}を作成するためのDDLを出力してください
#テーブル
##名前
- Sample.Product
##列
- JanCd VARCHAR(13)
- ProductName VARCHAR(100)
- Price INT
## プライマリキー
- JanCd

image

生成されたDDLをターミナルから実行し、テーブルが正常に作成されたことを確認します。

image

テストデータの作成
テストデータの作成もAIにアシストしてもらいましょう。

image

テストデータが正常に登録されたことを確認します。

image

APIの作成
準備が整ったので、APIクラスを生成します。以下のプロンプトを使ってコードを作成します。

あなたはObjectScriptの開発者です。
{仕様}をもとに"Api.Product"クラスを作成してください。
#仕様
- REST通信でJSON形式で商品情報を返す。
- apiのURLは/products/:jancd
- %CSP.RESTクラスを継承する。
- Jsonデータの生成は%DynamicObjectクラスを利用する。
- レスポンスコードは、%responseを利用する。
1. jancdが指定されなかった場合、404を返す。指定された場合、以降の処理を続行する。 
2. "Sample.Product"テーブルをSQLで検索する。
- 取得項目: JanCd,ProductName,Price
- 検索条件: :jancdが指定された場合、テーブルをJanCdが一致するレコードを検索する。
3. 検索結果をJSON形式でREST通信結果として出力する。

image

生成されたコードを確認し、必要に応じて修正を加えます。クエリ結果の取得箇所で%Next()が実行されていなかったため、以下の修正を行いました。

Set tResult = tStatement.%Execute(jancd)
// -*-*-*-*- 処理を追加しました -*-*-*-*-
Do tResult.%Next()

If tResult.%SQLCODE = 100 {

curlコマンドを使用してAPIの動作を確認し、正常にJSONデータが返却されることを確認します。

image

最終的なソースは以下の通りです。今回は一部修正が必要でしたが、基本的な部分は生成AIが正しく対応していました。

  Class Api.Product Extends %CSP.REST
  {

  /// URLマッピング
  XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
  {
  <Routes>
      <Route Url="/products/:jancd" Method="GET" Call="GetProductInfo"/>
  </Routes>
  }

  /// 商品情報を取得するメソッド
  ClassMethod GetProductInfo(jancd As %String) As %Status
  {
      // jancdが指定されていない場合、404を返す
      If jancd = "" {
          Set %response.Status = 404
          Quit $$$OK
      }

      // "Sample.Product"テーブルをSQLで検索する
      Set tStatement = ##class(%SQL.Statement).%New()
      Set tSQL = "SELECT JanCd, ProductName, Price FROM Sample.Product WHERE JanCd = ?"
      Set tStatus = tStatement.%Prepare(tSQL)

      If $$$ISERR(tStatus) {
          Set %response.Status = 500
          Quit tStatus
      }

      Set tResult = tStatement.%Execute(jancd)
      Do tResult.%Next()

      // 検索結果がない場合、404を返す
      If tResult.%SQLCODE = 100 {
          Set %response.Status = 404
          Quit $$$OK
      }

      // 検索結果をJSON形式で出力する
      Set tProduct = ##class(%DynamicObject).%New()
      Do tProduct.%Set("JanCd", tResult.%Get("JanCd"))
      Do tProduct.%Set("ProductName", tResult.%Get("ProductName"))
      Do tProduct.%Set("Price", tResult.%Get("Price"))

      Write tProduct.%ToJSON(),!

      Quit $$$OK
  }

  }

既存コードの活用

次に、生成したAPIに商品名を部分一致で検索するメソッドを追加します。Cursorの外部ファイル参照機能を使い、先ほど生成したクラスを参考にしながら新しいメソッドを作成します。プロンプトは以下の通りです。

@Api.Product.cls 
以下の{仕様}で、"Api.Product"クラスにメソッドを追加してください。
#仕様
- GetProductInfo()の処理を参考にすること。
- apiのURLは/products/name/:productname
- Sample.ProductテーブルからAPIで指定された値が、ProductNameと部分一致するレコードを検索し、検索した結果をJson形式で返す。
- 検索結果は配列にして返す。

image

生成したコードは以下になります。(追加部分のみ抜粋)

  Class Api.Product Extends %CSP.REST
  {
      // ... 既存のコード ...

      /// URLマッピング
      XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
      {
      <Routes>
          // ... 既存のルート ...
          <Route Url="/products/name/:productname" Method="GET" Call="GetProductInfoByName"/>
      </Routes>
      }

      // ... 既存のコード ...

      /// 商品名で商品情報を取得するメソッド
      ClassMethod GetProductInfoByName(productname As %String) As %Status
      {
          // productnameが指定されていない場合、404を返す
          If productname = "" {
              Set %response.Status = 404
              Quit $$$OK
          }

          // "Sample.Product"テーブルをSQLで検索する
          Set tStatement = ##class(%SQL.Statement).%New()
          Set tSQL = "SELECT JanCd, ProductName, Price FROM Sample.Product WHERE ProductName LIKE ?"
          Set tStatus = tStatement.%Prepare(tSQL)

          If $$$ISERR(tStatus) {
              Set %response.Status = 500
              Quit tStatus
          }

          Set tResult = tStatement.%Execute("%" _ productname _ "%")

          // 検索結果がない場合、404を返す
          If tResult.%SQLCODE = 100 {
              Set %response.Status = 404
              Quit $$$OK
          }

          // 検索結果をJSON形式で出力する
          Set tProducts = ##class(%DynamicArray).%New()
          While tResult.%Next() {
              Set tProduct = ##class(%DynamicObject).%New()
              Do tProduct.%Set("JanCd", tResult.%Get("JanCd"))
              Do tProduct.%Set("ProductName", tResult.%Get("ProductName"))
              Do tProduct.%Set("Price", tResult.%Get("Price"))
              Do tProducts.%Push(tProduct)
          }

          Write tProducts.%ToJSON(),!

          Quit $$$OK
      }

      // ... 既存のコード ...
  }

生成されたコードを確認し、curlコマンドで動作を確認します。正常に実行されました。外部ファイル参照機能の利用により、自動生成の精度が向上していることがうかがえます。
image

開発上の課題と解決策

自動生成の精度向上
基本コマンドを用いたプログラムは高い精度を発揮しますが、クラスを利用した複雑な処理では精度が低下する印象を受けました。プロンプトの指示を工夫することで、精度を高めることができそうです。
また、Cursorの外部ドキュメント、ファイル参照機能には大きな可能性を感じました。この機能を使えば、既存のリソースやAIが未学習のライブラリを活用が期待できます。

セキュリティとプライバシー
Cursorはプライバシーモードを備えており、データをサーバーに保持しない設定が可能です。しかし、Cursorに限らず生成AIの業務利用には慎重な調査が必要です。

所感

今回の検証を通じて、生成AIのコード生成能力が向上していることを実感しました。特に、テストデータやDDLの生成は、開発の効率を大幅に向上させる可能性があります。アジャイル開発で迅速なモックアップの作成が求められる場面では、生成AIの効果的な活用が期待できそうです。一方で、既存システムの小規模な改修には、効果が限定的であるという印象を受けました。

この記事を作成したきっかけは、ObjectScriptの初学者向け演習問題を生成AIで作成した際、その問題と解答の品質が非常に高かったことです。業務での活用も十分可能であると思い、今回の検証を行いました。生成AIは、工夫次第でさらなる幅広い活用が期待できるツールだと感じています。

参考資料

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください