#ObjectScript

0 フォロワー · 149 投稿

InterSystems ObjectScriptは、InterSystemsデータプラットフォームの任意のデータモデル(オブジェクト、リレーショナル、Key-Value、ドキュメント、グローバル)を使用してデータを操作し、InterSystemsデータプラットフォーム上のサーバーサイドアプリケーションのビジネスロジックを開発するためのスクリプト言語です。 ドキュメント

記事 So Ochi · 10月 13, 2024 10m read

はじめに

生成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
0 249
お知らせ Toshihiko Minamoto · 9月 12, 2024

Git を使用してIRIS でソリューションを構築することは、素晴らしいことです! 単にローカルの git リポジトリにVSCodeを使用し、サーバーに変更をプッシュする... それは非常に簡単です。

でも、次の場合はどうでしょうか。

  • 共有リモート開発環境で他の開発者と共同作業を行い、同じファイルの同時編集を回避したい場合
  • BPL、DTL、ピボット、ダッシュボードなどにおいて管理ポータルに基づくエディターを使用しており、 作業に簡潔なソース管理を使用したい場合
  • 一部の作業においては引き続き Studio を使用しているかたまに VSCode から Studio に戻っているか、チームがまだ VSCode を完全に採用しておらず、一部のチームメンバーが Studio の使用を希望している場合
  • 同じネームスペースで同時に多数の独立したプロジェクト(InterSystems Package Manager を使って定義された複数のパッケージなど)に取り組んでおり、(多数の個別のプロジェクトではなく)1 つの isfs 編集ビューからすべてのプロジェクトの作業を行い、適切な git リポジトリで変更を自動的に追跡する場合
0
0 198
記事 Megumi Kakechi · 8月 15, 2024 2m read

通常、Caché でエクスポートしたクラスやルーチンをIRISにインポートすることは可能ですが、IRISよりエクスポートしたクラスやルーチンを Caché にインポートすることはできません。

Caché にインポートしようとすると、以下のようなエラーになります。

USER>do$system.OBJ.Load("C:\temp\test.xml")
 
ロード開始 07/23/202416:50:42
ファイル C:\temp\test.xml を xml としてロード中
ERROR #6301 行: 2 オフセット: 117 これはCacheエクスポートファイルではありません。インポートできません。
読込時に 1 個のエラーを検出しました。
 


どうしても、古いバージョンにインポートする必要がある場合、「/exportversion」というエクスポート修飾子を使用することが可能です。

使用方法は以下のようになります。/exportversion には、エクスポートしたルーチンをインポートしたい環境のCacheバージョンを指定します。

USER>write$SYSTEM.OBJ.Export("test.mac","c:\temp\test2.xml","/exportversion=cache2018.1")
2
0 176
記事 Tomoko Furuzono · 8月 4, 2024 1m read

これは、InterSystems FAQサイトの記事です。

既定では、InterSystems製品で表すことのできる日時の最小値は、1840年12月31日 0時0分0秒 です。

USER>write$ZDATETIME("0,0")
12/31/184000:00:00

 ですが、アプリ内での用途や、他DBからの登録などで、それよりも前の日付時刻を登録する必要がある場合があります。
その場合には、日付日時のプロパティに、MINVAL(最小値)を設定することでサポートできます。
下記は、%DateTime型、%TeimaStamp型のプロパティに、最小値:西暦1年1月1日0時0分0秒と設定したものです。

Property TestDateTime As %DateTime(MINVAL = "0001-01-01 00:00:00");Property TestTimeStamp As %TimeStamp(MINVAL = "0001-01-01 00:00:00");

※2023.3および2024.1以降のバージョンでは、%DateTime型のMINVALの設定は必要なく、1840年12月31日 0時0分0秒より前の日時でも問題なく登録できます。%TimeStamp型の場合は、引き続き設定が必要です。

0
0 74
お知らせ Akio Hashimoto · 7月 28, 2023

こんにちは。
VSCodeでObjectScriptにコメントを挿入する拡張機能を作成してみましたので、共有させて頂きたいと思います。


使い方はとても簡単で、コンテキストメニューから「コメントの追加」を選択するだけです。
カーソル位置に合ったコメントが挿入されます。
挿入するコメントの定型文は設定で自由に指定できます。

クラスの説明文を挿入する

 

パラメーターやプロパティの説明文を挿入する

 

メソッドの説明文を挿入する

 

4
0 114
記事 Mihoko Iijima · 7月 16, 2024 9m read

これは InterSystems FAQ サイトの記事です。

管理ポータル > [システム管理] > [セキュリティ] 以下の設定は、%SYSネームスペースにあるSecurityパッケージ以下クラスが提供するメソッドを利用することでプログラムから作成することができます。

以下シナリオに合わせたセキュリティ設定例をご紹介します。

シナリオ:RESTアプリケーション用設定を作成する

事前準備

シナリオの中で使用するソースを2種類インポートします。

アプリケーション用RESTディスパッチクラスをインポートします。

0
0 142
記事 Mihoko Iijima · 7月 11, 2024 4m read

これは InterSystems FAQ サイトの記事です。

管理ポータル > [システム管理] > [セキュリティ] 以下の設定は、%SYSネームスペースにあるSecurityパッケージ以下クラスが提供するメソッドを利用することでプログラムから作成することができます。

ユーザ設定については、Security.UsersクラスCreate()メソッドを使えば作成できますが、ユーザを作成するだけでは適切な権限が付与されずに目的のデータにアクセスできない状況もあります。

例)testAユーザ作成

%SYS>set st=##class(Security.Users).Create("testA",,"testA","これはテストユーザです","USER")

%SYS>write st
1

上記メソッドで作成した結果は以下の通りです。(ロール付与無し、テーブルに対する権限の割り当てもなしの状態)

 

以降の解説では、以下のシナリオをもとにした設定を行っていきます。

シナリオ:アプリケーション開発者用ロールとユーザを作成する

1) アプリケーション開発者のtestAは、USERネームスペースにログインするアプリケーション開発者です(=%DevelopmentリソースのUse許可を与えます)。

0
0 96
記事 Mihoko Iijima · 7月 7, 2024 4m read

これは InterSystems FAQ サイトの記事です。

監査ログはシステムDB内テーブル(%SYS.Audit)に記録されていますので、そのテーブルに対するクエリを実行して抽出したり、%SYS.Auditテーブルに用意されていストアドプロシージャを利用して情報を取得しファイル出力するようにプログラムを用意することもできます。

以下にご紹介する内容は「監査ログをプログラムで出力(ユーザやイベント指定など)する方法」に関連した内容で、監査ログのファイル出力を管理ポータルの機能を利用した例とプログラムを利用した例でご紹介します。

 

1. 管理ポータルの印刷機能を使う

管理ポータル > [システムエクスプローラ] > [SQL]を開き、%SYSネームスペースに接続します。

システムのチェックを入れ、スキーマに%SYSを指定した後、プロシージャの階層を展開するとプロシージャリストが参照できます。

%SYS.Audit_ で始まるプロシージャが監査ログに対して実行できるプロシージャです。

SQL文例)InterSystems製品内ユーザのSuperUserに対する監査ログをストアドプロシージャ:%SYS,Audit_ListByUser を利用して出力しています。

call %SYS.Audit_ListByUser(,,,,,'SuperUser')
0
0 144
記事 Mihoko Iijima · 7月 4, 2024 9m read

これは InterSystems FAQ サイトの記事です。

PythonスクリプトファイルやPythonで記述されたIRIS内メソッドを呼び出す際、エラーが発生した場合の対応方法をご紹介します。

説明使用するコードや資料PDFは公開しています👉 test1.pyFS.Utilsクラスコードのコピー元ビデオで解説している資料PDF

Embedded Python 自習用ビデオをご用意しています(項目別にYouTubeプレイリストをご用意しています)。

各プレイリストについて詳しくはこちらをご参照ください👉【はじめてのInterSystems IRIS】Embedded Python セルフラーニングビデオシリーズ公開!

0
0 385
記事 Mihoko Iijima · 7月 4, 2024 2m read

これは InterSystems FAQ サイトの記事です。

InterSystems製品のサーバサイドでファイル入出力を行うと、文字列はシステムで設定されたファイル入出力用文字コードに自動変換され、文字単位でREADします。

ファイルから入力する文字をバイト単位で操作するためには、自動変換を行わない無変換の状態でファイル入力を行い指定バイトずつ読みながら読んだ分だけUnicodeに手動で変換していく必要があります。

変換には$ZCONVERT()関数を使用します。($ZCONVERT()には省略形があり$ZCVT()でも同様の操作が行えます。)

なお、READした指定バイトを変換する際、文字の全バイトが含まれない場合もあるため、途中までの読み取りになった文字列を第4引数に指定する変数に設定できるようになっています。
次回読み取り時に途中だった文字を自動的に先頭に追加し、$ZCONVERT()の処理を実行します。

《メモ》ファイル入出力の文字コードについては、以下管理ポータルの画面で確認できます。
管理ポータル > 構成 > 国際言語設定 > 構成したデフォルト値
 入力/出力テーブルの表の「ファイル」

以下の文章がファイルにUTF8で保存されているとします。

2024/4/19:強風でしたが良い天気でした
0
0 143
記事 Mihoko Iijima · 3月 11, 2024 2m read

これは InterSystems FAQ サイトの記事です。

現時点(2024年3月)では、コミュニティに掲載されているPythonライブラリ「iris-dollar-list」を利用することでIRISの$LIST()形式のデータをPythonのリストとして利用することができます。

※標準ツールではありませんがご利用いただけます。詳細はコミュニティの記事「もう1つの $ListBuild() の実装:Pythonライブラリ「iris-dollar-list」」をご参照ください。

WindowsにインストールしたIRISで使用する場合は、以下の方法で「iris-dollar-list」をインストールしてください。

※Windows以外にインストールしたIRISでは、pipコマンドを利用した通常の方法でインストールできます。

コマンドプロンプトを開き、以下実行します。(IRISをデフォルトインストールしたときのディレクトリで掲載しています)

>cd C:\InterSystems\IRIS\bin> irispip install --target C:\InterSystems\IRIS\mgr\python iris-dollar-list

実行例は以下の通りです。

1
1 180
記事 Toshihiko Minamoto · 5月 14, 2024 8m read

「30 秒も経ってるのにサービスを受けられないなんて、 あり得ない! もう結構!」

「大変申し訳ございません。 次回からはご予約なさってはいかがでしょうか。」

お気に入りのレストランでこんなコメントを聞いたら、そんな発言はばかばかしいと思うのではないでしょうか。 でも、API のコンテキストでは、まったく合理的な意見です。 お気に入りのレストランと同じように、API にも常連客がいます。よく訪問するユーザーのことです。 同じように繰り返し予約が可能であればよいと思いませんか?

これには、IRIS の基本機能がいくつか関わってきます。 まず、%SYSTEM.License インターフェースを理解する必要があります。 これは、IRIS インスタンスのライセンス使用状況に関する情報を取得するために提供されているインターフェースです。 次に、%CSP.SessionEvents クラスについて学ぶ必要があります。 このクラスを使うと、CSP セッションのライフサイクル全体で呼び出される様々なメソッドをオーバーライドできます。

まずは、%SYSTEM.License インターフェースから見ていきましょう。 このクラスには、$SYSTEM.License を使って呼び出せるメソッドもあれば、##class(%SYSTEM.License) で呼び出す必要のあるメソッドもあります。 一貫性を維持するためにも、ここでは、すべてのメソッドに使用できる ##class(%SYSTEM.License) を使用しましょう。 このユースケースでは、使用できるライセンス数と特定のユーザーが使用しているライセンス数をチェックできる必要があります。 

まず、使用できるライセンス数を確認しましょう。 少なくとも 1 つのライセンスが使用可能である場合、予約には十分であるため、それ以上に確認する必要はありません。 また、ログインしようとしているユーザーが予約を保持しているユーザーであるかを確認する必要もあります。 これは、以下のように、LUAvailable メソッドへの単純な呼び出しで実現できます。

if (##class(%SYSTEM.License).LUAvailable()) || ($USERNAME = username) > 0{    return $$$OK}

次に、予約済みのユーザーが現在ログイン中であるかを確認する必要があります。 すでにレストランで着席している場合は、使用できる席があるかどうかを確認する必要はありません。 ユーザーが常に特定のアドレスから接続する場合は、LicenseCount メソッドを使用してそれを確認することができます。 ユーザー識別子を引数として取り、そのユーザーがその時点でライセンスを使用しているかどうかを示す整数を返します。 例:

set licenseusage = ##class(%SYSTEM.License).LicenseCount("David@127.0.0.1")

このユーザーがライセンスを使用しているかどうかがわかります。 0 を返す場合、そのユーザーはライセンスを使用していませんが、1 を返す場合はライセンスを使用していることになります。 このメソッドが 1 よりも大きい数値を返す場合、ユーザーが最大接続数を超過しており、接続ごとに 1 つのライセンスを使用していることを意味するため、注意が必要です。 その場合は、別の問題を新たに修正する必要があります!

どのアドレスから接続されているのかがわからない場合は、この状況に別の方法で対応して、いくつかの追加ステップが必要となります。 ここでは、ConnectionList クラスのクエリを使用しましょう。 次のコードを検討してください。

ClassMethod CheckReservation(username As %String) As %Status{    try{        if (##class(%SYSTEM.License).LUAvailable() > 1) || ($USERNAME = username) {            return $$$OK        }        set rs = ##class(%ResultSet).%New("%SYSTEM.License:ConnectionList")        set sc = rs.%Execute()        if $$$ISERR(sc) {$$$ThrowStatus(sc)}        while rs.%Next(){            if $P(rs.%GetData(1),"@",1) = username{                return $$$OK            }        }        $$$ThrowStatus($$$ERROR(5001,"Reserved User Not Logged In."))    }    catch ex{        do ex.Log()        return ex.AsStatus()    }}

このメソッドでは、ユーザー名に基づいて 1 つのライセンスのみを予約できることに注意してください。 ユースケースで 2 つ以上のライセンスを確保する必要がある場合は、ConnectionList クエリの結果を確認し、何人の顧客がログイン済みであり、席を待つ間にバーで最初のグラスを傾けているかを数える必要があります。 次に、残りの LUAvailable が単に 2 以上であるだけでなく、すべての予約に対応できるかを確認する必要があります。

このメソッドは通常、%ResultSet オブジェクトを使用して、%SYSTEM.License クラスから LicenseCount クエリにアクセスします。 一般に %SQL.Statement を使用する方が好ましくはありますが、%PrepareClassQuery は必ずこのクエリで失敗します。 そのため、ここではこれを使用することはできません。 このクエリは各接続に対して行を返すため、その後で結果セットを反復しましょう。 各行に対し、最初の列には、ユーザー名と IP アドレスを@ で区切ったライセンス ID が含まれます。 探しているのは(ユーザー名と IP アドレスの組み合わせではなく)ユーザー名のみであるため、その列の最初の部分を提供されたユーザー名と比較して、一致する場合は成功ステータスを返します。 ただし、結果セット全体にユーザー名が見つからない場合は、エラーを返します。

このメソッドを、代わりにロールをチェックするように変更したい場合(スーパーユーザーがいつでもシステムにアクセスできるように、%All ロールを持つ少なくとも 1 人のユーザーがログインできるようにするなど)、%SYS ネームスペースに切り替えて、ループを反復する過程で各ユーザーのロールを検証することで実現できます。 ##class(Security.Users).Get($P(rs.%GetData(1),”@”,1),.props) を使用してから、props(“Roles”) [ “%All” を使用して、ロールが props(“Roles”) に含まれているかを確認できます。 正しいアプリケーションネームスペースにログインできるように、最終的には元のネームスペースに忘れずに戻るようにしましょう。 すると、コードは以下のようになります。

ClassMethod CheckReservation(role As %String) As %Status{    try{        set returnns = $NAMESPACE        zn "%SYS"        set sc = ##class(Security.Users).Get($USERNAME,.props)        if (##class(%SYSTEM.License).LUAvailable() > 1) || (props("Roles") [ role) {            zn returnns            return $$$OK        }        set rs = ##class(%ResultSet).%New("%SYSTEM.License:ConnectionList")        set sc = rs.%Execute()        if $$$ISERR(sc) {$$$ThrowStatus(sc)}        while rs.%Next(){            set sc = ##class(Security.Users).Get($P(rs.%GetData(1),"@",1),.props)            if props("Roles") [ role{                zn returnns                return $$$OK            }        }        zn returnns        $$$ThrowStatus($$$ERROR(5001,"Reserved User Not Logged In."))    }    catch ex{        do ex.Log()        return ex.AsStatus()    }}

License API 内には、使用できる実用的なクラスクエリが他にもあります。 特定のアプリケーションへのログインを検証する場合は、ConnectionAppList の方が適しているかもしれません。 ライセンスのタイプ(User、CSP、Mixed、または Grace)を検査する場合は、UserList クラスクエリを使用すると良いでしょう。 ProcessList クエリを操作すると、ユーザーが実行するプロセスの詳細をさらに詳しく把握することができます。 ただし、あまりにも夢中になりすぎた場合は、ログインプロセスにゆっくりと取り組むようにしましょう。

この部分のコードが完成したので、どこに配置するかを決めなければなりません。 ただし、きちんと配置するには、%CSP.SessionEvents クラスの基本を知っておく必要があります。 このクラスには、CSP セッションが開始、終了、またはタイムアウトになった場合やユーザーがログインまたはログアウトした場合の動作を制御するためにオーバーライドできるメソッドがいくつか含まれています。 ここでは、セッションに割り当てられたライセンスの前に実行する OnStartSession() メソッドに特に注目できます。 そこでメソッドを実行し、エラーを返した場合には、%session.EndSession を 1 にセットするだけで完了です。 すると、ユーザーには標準のライセンス数不足メッセージが表示され、ログインできないようにすることができます。

%CSP.SessionEvents 拡張機能と以前に定義したクラスメソッドを使って、User.SessionEvents というメソッドを作成します。 次に、その中の 1 つのメソッドのみをオーバーライドし、他の予約ようにスペースを空けておくようにします。 すると、そのメソッドは次のようになります。

ClassMethod OnStartSession(){    if $$$ISERR(##class(User.SessionEvents).CheckReservation("David")){        set %session.EndSession=1    }    Quit $$$OK}

ネームスペースが複数ある場合は、このクラスを使用するすべての CSP アプリケーションにクラスを作成するようにしてください。

最後に、アプリケーションがこれらのセッションを使用できるように構成します。 これは、管理ポータルで、システム管理 > セキュリティ > アプリケーション > Web アプリケーションに移動して行えます。 カスタムセッションイベントクラスを使用するアプリケーションをクリックし、 次に、「イベントクラス」ボックスに User.SessionEvents を入力します。 それ以降、ログインするたびに、カスタマイズされた OnStartSession メソッドが呼び出され、予約の余地がない場合には他のユーザーがログインできなくなります。

ここには、検討すべき重要な実装の詳細が 1 つあります。 これらのセッションイベントをシステム管理ポータルに適用すべきかどうかです。 適用する場合は、何らかの問題が生じても、ログインして修正できない状況に陥る可能性があります。 適用しない場合は、誰かがログインし、予約しようとしていたライセンスを使用してしまう可能性があります。 おそらく、そのユーザーに予約チェックを迂回できる特定のロールがあるかを確認するようにコードを編集することができますが、 これについては、あなた次第です。

今後は、常連客が定期的に訪れるたびに、席に座れることを保証できます!

0
1 100
記事 Toshihiko Minamoto · 4月 18, 2024 13m read

我々には、Redditユーザーが書いた、おいしいレシピデータセット がありますが, 情報のほとんどは投稿されたタイトルや説明といったフリーテキストです。埋め込みPythonLangchainフレームワークにあるOpenAIの大規模言語モデルの機能を使い、このデータセットを簡単にロードし、特徴を抽出、分析する方法を紹介しましょう。

データセットのロード

まず最初に、データセットをロードするかデータセットに接続する必要があります。

これを実現するにはさまざまな方法があります。たとえばCSVレコードマッパーを相互運用性プロダクションで使用したり csvgenのようなすばらしい OpenExchange アプリケーションを使用することもできます。

今回、外部テーブルを使用します。これは物理的に別の場所に保存されているデータをIRIS SQLで統合する非常に便利な機能です。

まずは外部サーバ(Foreign Server)を作成します。

CREATE FOREIGN SERVER dataset FOREIGN DATA WRAPPER CSV HOST '/app/data/'

その上でCSVファイルに接続する外部テーブルを作成します。

CREATE FOREIGN TABLE dataset.Recipes (
  CREATEDDATE DATE,
  NUMCOMMENTS INTEGER,
  TITLE VARCHAR,
  USERNAME VARCHAR,
  COMMENT VARCHAR,
  NUMCHAR INTEGER
) SERVER dataset FILE 'Recipes.csv' USING
{
  "from": {
    "file": {
       "skip": 1
    }
  }
}

以上です。すぐに「dataset.Recipes」にSQLクエリを実行できます。 image

## どんなデータが必要?

データセットは興味深く、直ぐに処理したいと思うのですが、調理のレシピを決めたいのであれば、分析に使える情報がもう少し必要です。 2つの永続化クラス(テーブル)を使用します。

  • yummy.data.Recipe抽出分析したいレシピのタイトルと説明、他のプロパティが入ったクラス (例: スコア、難易度、材料、調理タイプ、準備時間)
  • yummy.data.RecipeHistory レシピのログを取るためのシンプルなクラス

これで 「yummy.data*」 テーブルにデータセットの内容をロードすることができます。

do ##class(yummy.Utils).LoadDataset()

一見良さそうに見えますが、スコア、難易度、材料、準備時間、調理時間フィールドのデータをどのように生成するのかを見つける必要があります。

## レシピの分析 各レシピのタイトルと説明を処理します

  • 難易度, 材料, 調理タイプなどの抽出
  • 何を作りたいか決められるよう、基準に基づいて独自のスコアを構築

以下を使用します

  • より多くの分析を構築したい場合に再利用できる一般的な分析構造

LLM(大規模言語モデル)は自然言語を処理するための本当に素晴らしいツールです。

LangChainはPythonで動くようになっているので、Embedded Pythonを使ってInterSystems IRISで直接使うことができます。 LangChain is ready to work in Python, so we can use it directly in InterSystems IRIS using Embedded Python.

完全な SimpleOpenAI クラスは以下のようになります。

/// レシピ向けのシンプルな OpenAI 分析
Class yummy.analysis.SimpleOpenAI Extends Analysis
{

Property CuisineType As %String;

Property PreparationTime As %Integer;

Property Difficulty As %String;

Property Ingredients As %String;

/// 実行
/// ターミナルから実行できます。
/// set a = ##class(yummy.analysis.SimpleOpenAI).%New(##class(yummy.data.Recipe).%OpenId(8))
/// do a.Run()
/// zwrite a
Method Run()
{
    try {
        do ..RunPythonAnalysis()

        set reasons = ""

        // 好きな調理タイプ
        if "spanish,french,portuguese,italian,korean,japanese"[..CuisineType {
            set ..Score = ..Score + 2
            set reasons = reasons_$lb("It seems to be a "_..CuisineType_" recipe!")
        }

        // 丸一日調理に費やしたくない :)
        if (+..PreparationTime < 120) {
            set ..Score = ..Score + 1
            set reasons = reasons_$lb("You don't need too much time to prepare it") 
        }
        
        // 好きな材料ボーナス
        set favIngredients = $listbuild("kimchi", "truffle", "squid")
        for i=1:1:$listlength(favIngredients) {
            set favIngred = $listget(favIngredients, i)
            if ..Ingredients[favIngred {
                set ..Score = ..Score + 1
                set reasons = reasons_$lb("Favourite ingredient found: "_favIngred)
            }
        }

        set ..Reason = $listtostring(reasons, ". ")

    } catch ex {
        throw ex
    }
}

/// 分析結果でレシピを更新する
Method UpdateRecipe()
{
    try {
        // 親クラスの処理を先に呼び出す
        do ##super()

        // 個別のOpenAI 解析結果を追加
        set ..Recipe.Ingredients = ..Ingredients
        set ..Recipe.PreparationTime = ..PreparationTime
        set ..Recipe.Difficulty = ..Difficulty
        set ..Recipe.CuisineType = ..CuisineType

    } catch ex {
        throw ex
    }
}

/// 埋め込み Python + Langchain で分析を実行
/// do ##class(yummy.analysis.SimpleOpenAI).%New(##class(yummy.data.Recipe).%OpenId(8)).RunPythonAnalysis(1)
Method RunPythonAnalysis(debug As %Boolean = 0) [ Language = python ]
{
    # load OpenAI APIKEY from env
    import os
    from dotenv import load_dotenv, find_dotenv
    _ = load_dotenv('/app/.env')

    # account for deprecation of LLM model
    import datetime
    current_date = datetime.datetime.now().date()
    # date after which the model should be set to "gpt-3.5-turbo"
    target_date = datetime.date(2024, 6, 12)
    # set the model depending on the current date
    if current_date > target_date:
        llm_model = "gpt-3.5-turbo"
    else:
        llm_model = "gpt-3.5-turbo-0301"

    from langchain.chat_models import ChatOpenAI
    from langchain.prompts import ChatPromptTemplate
    from langchain.chains import LLMChain

    from langchain.output_parsers import ResponseSchema
    from langchain.output_parsers import StructuredOutputParser

    # init llm model
    llm = ChatOpenAI(temperature=0.0, model=llm_model)

    # prepare the responses we need
    cuisine_type_schema = ResponseSchema(
        name="cuisine_type",
        description="What is the cuisine type for the recipe? \
                     Answer in 1 word max in lowercase"
    )
    preparation_time_schema = ResponseSchema(
        name="preparation_time",
        description="How much time in minutes do I need to prepare the recipe?\
                     Anwer with an integer number, or null if unknown",
        type="integer",
    )
    difficulty_schema = ResponseSchema(
        name="difficulty",
        description="How difficult is this recipe?\
                     Answer with one of these values: easy, normal, hard, very-hard"
    )
    ingredients_schema = ResponseSchema(
        name="ingredients",
        description="Give me a comma separated list of ingredients in lowercase or empty if unknown"
    )
    response_schemas = [cuisine_type_schema, preparation_time_schema, difficulty_schema, ingredients_schema]

    # get format instructions from responses
    output_parser = StructuredOutputParser.from_response_schemas(response_schemas)
    format_instructions = output_parser.get_format_instructions()
    
    analysis_template = """\
    Interprete and evaluate a recipe which title is: {title}
    and the description is: {description}
    
    {format_instructions}
    """
    prompt = ChatPromptTemplate.from_template(template=analysis_template)

    messages = prompt.format_messages(title=self.Recipe.Title, description=self.Recipe.Description, format_instructions=format_instructions)
    response = llm(messages)

    if debug:
        print("======ACTUAL PROMPT")
        print(messages[0].content)
        print("======RESPONSE")
        print(response.content)

    # populate analysis with results
    output_dict = output_parser.parse(response.content)
    self.CuisineType = output_dict['cuisine_type']
    self.Difficulty = output_dict['difficulty']
    self.Ingredients = output_dict['ingredients']
    if type(output_dict['preparation_time']) == int:
        self.PreparationTime = output_dict['preparation_time']

    return 1
}

}

「RunPythonAnalysis」メソッドがOpenAIが詰め込むところです :)  ターミナルから直接実行してレシピを受け取れます。

do ##class(yummy.analysis.SimpleOpenAI).%New(##class(yummy.data.Recipe).%OpenId(12)).RunPythonAnalysis(1)

以下のような出力を受け取れます。

USER>do ##class(yummy.analysis.SimpleOpenAI).%New(##class(yummy.data.Recipe).%OpenId(12)).RunPythonAnalysis(1)
======実際の課題
                    レシピタイトルを解釈、評価: 巻きずし - アラスカロール
                    説明: 寿司がたべたいのに巻きすがない? 代わりに簡単なバージョンを試してみてください。超簡単なのに、同じようにおいしい!
[Video Recipe](https://www.youtube.com/watch?v=1LJPS1lOHSM)
# 材料
提供量:  \~サンドイッチ5枚分
* 米1カップ
* 水 3/4 カップ + 大さじ 2 1/2
* 昆布 小口切り 1枚
* 米酢 大さじ2
* さとう 大さじ1
* 塩 小さじ1
* アボカド 2個
* カニカマ 6個
* 和風マヨ 大さじ2
* サーモン 1/2 ポンド  
# レシピ     
* 酢飯1合をボウルに入れ、2回以上、または水が透明になるまで米を洗う。炊飯器に米を移し、昆布の小口切り1枚と水3/4カップ+大さじ2と1/2杯を加える。炊飯器の指示に従って炊く。
* 米酢大さじ2、砂糖大さじ1、塩小さじ1を中くらいのボウルに入れる。全体がよく混ざるまで混ぜる。
* 炊き上がったら昆布を取り除き、すぐに酢を入れた中ボウルに米をすべてすくい入れ、飯ベラを使ってよく混ぜる。米をつぶさないように、切るように混ぜること。炊きあがったら、キッチンタオルをかけて室温まで冷ます。
* アボカド1個の上部を切り、アボカドの中央に切り込みを入れ、ナイフに沿って回転させる。次にアボカドを半分ずつ取り、ひねる。その後、ピットのある側を取り、慎重にピットに切り込みを入れ、ひねって取り除く。その後、手で皮をむく。この手順をもう片方のアボカドでも繰り返す。作業スペースを確保するため、作業台を片付けるのを忘れずに。次に、アボカドを下向きに置き、薄くスライスする。スライスしたら、ゆっくりと広げていく。それが終わったら、脇に置いておく。
* カニカマから包みをはずす。カニカマを縦にむいていく。すべてのカニカマを剥いたら、横に回転させながら細かく刻み、和風マヨ(大さじ2)とともにボウルに入れ、全体がよく混ざるまで混ぜる。
* 鋭利なナイフを斜めに入れ、木目に逆らって薄くスライスする。切り口の厚さは好みによる。ただ、すべてのピースが同じような厚さになるようにする。
* 海苔巻きラップを手に取る。キッチンバサミを使い、海苔巻きラップの半分の位置から切り始め、ラップの中心を少し過ぎるまで切る。ラップを垂直に回転させ、作り始める。すし飯を握るために、手に水をつけておく。酢飯を手に取り、海苔巻きの左上の四辺に広げる。次に、右上にサーモンを2切れ並べる。右下にアボカドを2切れのせる。最後に左下にカニサラダを小さじ2杯ほどのせる。次に、右上の四つ角を右下の四つ角に折り込み、さらに左下の四つ角に折り込む。最後に、左上の四つ角をサンドイッチの残りの部分に折り込む。その後、ラップを上に置き、半分に切って、生姜とわさびを2、3枚添えれば出来上がり。
                    
                    出力は、先頭と末尾の"``json "と"``"を含む、以下のスキーマでフォーマットされたマークダウンのコードスニペットでなければなりません:
json
{
        "cuisine_type": string  // レシピの調理タイプは?                                  小文字の1単語で回答
        "preparation_time": integer  // レシピの準備に必要な時間(分)は? 整数で回答(不明な場合はnull)
        "difficulty": string  // レシピの難易度は?                               「容易」「標準」「難しい」「とても難しい」のうちから1つを回答
        "ingredients": string  // 小文字のカンマ区切りの材料リスト、不明な場合は空
}

                    
======応答
json
{
        "cuisine_type": "japanese",
        "preparation_time": 30,
        "difficulty": "easy",
        "ingredients": "sushi rice, water, konbu, rice vinegar, sugar, salt, avocado, imitation crab sticks, japanese mayo, salmon"
}

良さそうです。OpenAIのプロンプトは有用な情報を返してくれるようです。ターミナルから分析クラス全体を実行してみましょう:

set a = ##class(yummy.analysis.SimpleOpenAI).%New(##class(yummy.data.Recipe).%OpenId(12))
do a.Run()
zwrite a
USER>zwrite a
a=37@yummy.analysis.SimpleOpenAI  ; <OREF>
+----------------- general information ---------------
|      oref value: 37
|      class name: yummy.analysis.SimpleOpenAI
| reference count: 2
+----------------- attribute values ------------------
|        CuisineType = "japanese"
|         Difficulty = "easy"
|        Ingredients = "sushi rice, water, konbu, rice vinegar, sugar, salt, avocado, imitation crab sticks, japanese mayo, salmon"
|    PreparationTime = 30
|             Reason = "It seems to be a japanese recipe!. You don't need too much time to prepare it"
|              Score = 3
+----------------- swizzled references ---------------
|           i%Recipe = ""
|           r%Recipe = "30@yummy.data.Recipe"
+-----------------------------------------------------

## 全レシピを解析する!

当然、読み込んだすべてのレシピで分析を実行したいでしょう。 この方法でレシピ ID の範囲を分析することができます

USER>do ##class(yummy.Utils).AnalyzeRange(1,10)
> Recipe 1 (1.755185s)
> Recipe 2 (2.559526s)
> Recipe 3 (1.556895s)
> Recipe 4 (1.720246s)
> Recipe 5 (1.689123s)
> Recipe 6 (2.404745s)
> Recipe 7 (1.538208s)
> Recipe 8 (1.33001s)
> Recipe 9 (1.49972s)
> Recipe 10 (1.425612s)

その後、レシピテーブルを再度表示させ、結果をチェックします。

select * from yummy_data.Recipe

image

どんぐりカボチャのピザか、豚肉入り韓国風豆腐キムチを試してみます:) いずれにせよ、家で再確認する必要がありますね :)

最後に

サンプルソースは全て https://github.com/isc-afuentes/recipe-inspector にあります。

この簡単な例で、InterSystems IRIS で LLM テクニックを使用して機能を追加したり、データの一部を分析する方法を学びました。

これを起点に以下のことが考えられます

  • InterSystems BIを使い、キューブやダッシュボードでデータの検索やナビゲートをおこなう。
  • Webアプリを作成し、UIを提供する(例:Angular)RESTForms2のようなパッケージを活用することで、永続クラスへのREST APIを自動的に生成することができます。 *レシピが好きか嫌いかを保存し、新しいレシピが好きかどうかを判断するのはいかがでしょうか。IntegratedMLアプローチ、あるいはLLMアプローチでいくつかの例データを提供し、RAG(Retrieval Augmented Generation)ユースケースを構築してみるのも良いでしょう。

他にどんなことが試せそうでしょうか?ご意見をお聞かせください!

0
0 458
記事 Toshihiko Minamoto · 4月 1, 2024 5m read

大規模言語モデル(OpenAI の GPT-4 など)の発明と一般化によって、最近までは手動での処理が非現実的または不可能ですらあった大量の非構造化データを使用できる革新的なソリューションの波が押し寄せています。 データ検索(検索拡張生成に関する優れた紹介については、Don Woodlock の ML301 コースをご覧ください)、センチメント分析、完全自律型の AI エージェントなど、様々なアプリケーションが存在します。

この記事では、IRIS テーブルに挿入するレコードに自動的にキーワードを割り当てる単純なデータタグ付けアプリケーションの構築を通じて、IRIS の Embedded Python 機能を使って、Python OpenAI ライブラリに直接インターフェース接続する方法をご紹介します。 これらのキーワードをデータの検索と分類だけでなく、データ分析の目的に使用できるる単純なデータタグ付けアプリケーションを構築します。ユースケースの例として、製品の顧客レビューを使用します。

要件

  • IRIS の実行インスタンス
  • OpenAPI API キー(こちらで作成できます)
  • 構成済みの開発環境(この記事では VS Code を使用します)

Review クラス

顧客レビューのデータモデルを定義する ObjectScript クラスの作成から始めましょう。 簡潔さを維持するために、顧客の名前、製品名、レビュー本文、および生成するキーワードの 4 つの %String フィールドのみを定義します。 クラスはオブジェクトをディスクに保存できるように、%Persistent を拡張します。

Class DataTagging.Review Extends%Persistent
{
Property Name As%String(MAXLEN = 50) [ Required ];Property Product As%String(MAXLEN = 50) [ Required ];Property ReviewBody As%String(MAXLEN = 300) [ Required ];Property Keywords As%String(MAXLEN = 300) [ SqlComputed, SqlComputeOnChange = ReviewBody ];
}

ReviewBody への挿入または更新時に、Keywords プロパティが自動的に計算されるようにしたいため、これを SqlComputed とします。計算される値についての詳細は、こちらをご覧ください。

KeywordsComputation メソッド

次に、レビュー本文に基づいてキーワードを計算するために使用するメソッドを定義します。 公式の openai Python パッケージを直接操作するために、Embedded Python を使用できます。 ただし、先にそれをインストールしておく必要があります。 以下のシェルコマンドを実行しましょう。

<your-IRIS-installation-path>/bin/irispip install --target <your-IRIS-installation-path>/Mgr/python openai

OpenAI のチャット補完 API を使用して、キーワードを生成できるようになりました。

ClassMethod KeywordsComputation(cols As %Library.PropertyHelper) As %String [ Language = python ]
{
    '''
    This method is used to compute the value of the Keywords property
    by calling the OpenAI API to generate a list of keywords based on the review body.
    '''from openai import OpenAI
client = OpenAI(
    <span class="hljs-comment"># Defaults to os.environ.get("OPENAI_API_KEY")</span>
    api_key=<span class="hljs-string">"&lt;your-api-key&gt;"</span>,
)

<span class="hljs-comment"># Set the prompt; use few-shot learning to give examples of the desired output</span>
user_prompt = <span class="hljs-string">"Generate a list of keywords that summarize the content of a customer review of a product. "</span> \
            + <span class="hljs-string">"Output a JSON array of strings.\n\n"</span> \
            + <span class="hljs-string">"Excellent watch. I got the blue version and love the color. The battery life could've been better though.\n\nKeywords:\n"</span> \
            + <span class="hljs-string">"[\"Color\", \"Battery\"]\n\n"</span> \
            + <span class="hljs-string">"Ordered the shoes. The delivery was quick and the quality of the material is terrific!.\n\nKeywords:\n"</span> \
            + <span class="hljs-string">"[\"Delivery\", \"Quality\", \"Material\"]\n\n"</span> \
            + cols.getfield(<span class="hljs-string">"ReviewBody"</span>) + <span class="hljs-string">"\n\nKeywords:"</span>
<span class="hljs-comment"># Call the OpenAI API to generate the keywords</span>
chat_completion = client.chat.completions.create(
    model=<span class="hljs-string">"gpt-4"</span>,  <span class="hljs-comment"># Change this to use a different model</span>
    messages=[
        {
            <span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>,
            <span class="hljs-string">"content"</span>: user_prompt
        }
    ],
    temperature=<span class="hljs-number">0.5</span>,  <span class="hljs-comment"># Controls how "creative" the model is</span>
    max_tokens=<span class="hljs-number">1024</span>,  <span class="hljs-comment"># Controls the maximum number of tokens to generate</span>
)

<span class="hljs-comment"># Return the array of keywords as a JSON string</span>
<span class="hljs-keyword">return</span> chat_completion.choices[<span class="hljs-number">0</span>].message.content

}

プロンプト内では、最初に「generate a list of keywords that summarize the content of a customer review of a product」で、製品の顧客レビューのコンテンツを要約するキーワードのリストを GPT-4 でどのように生成するかについての一般的な命令を指定してから、希望する出力と 2 つのサンプル入力を指定していることに注意してください。 次に cols.getfield("ReviewBody") を挿入し、「Keywords:」の語でプロンプトを終了することで、私が提示した例と同じ形式でキーワードを提供して、文を完成させるように促しています。 これは、Few-Shot プロンプティング手法の単純な例です。

この記事を簡潔にするため、キーワードを JSON 文字列で格納するようにしていますが、本番では、DynamicArray に格納するのがお勧めです。ただ、これについては各開発者にお任せします。

キーワードの生成

それでは、管理ポータルで以下の SQL クエリを使用してテーブルに行を挿入し、データタグ付けアプリケーションをテストしてみましょう。

INSERTINTO DataTagging.Review (Name, Product, ReviewBody)
VALUES ('Ivan', 'BMW 330i', 'Solid car overall. Had some engine problems but got everything fixed under the warranty.')

以下のとおり、4 つのキーワードが自動的に生成されました。 上出来です!

まとめ

まとめると、Python コードを埋め込む InterSystems IRIS の機能によって、非構造化データを処理する際に幅広い可能性を得られます。 OpenAI の力を活用して自動データタグ付けを行うのは、この強力な機能によって達成できることの一例にすぎません。 これにより、ヒューマンエラーを縮小し、全体的な効率をさらに高めることができます。

0
0 168
記事 Toshihiko Minamoto · 3月 28, 2024 12m read

ローコードへの挑戦

こんな状況を思い浮かべてください。「ウィジェットダイレクト」というウィジェットとウィジェットアクセサリーを販売する一流のネットショップで楽しく勤務しています。先日、上司から一部の顧客がウィジェット商品にあまり満足していないという残念な話を聞き、苦情を追跡するヘルプデスクアプリケーションが必要となりました。さらに面白いことに、上司はコードのフットプリントを最小限に抑えることを希望しており、InterSystems IRIS を使って 150 行未満のコードでアプリケーションを提供するという課題をあなたに与えました。これは実際に可能なのでしょうか?

免責事項: この記事は、非常に基本的なアプリケーションの構築を記すものであり、簡潔さを維持するために、セキュリティやエラー処理などの重要な部分は省略されています。このアプリケーションは参考としてのみ使用し、本番アプリケーションには使用しないようにしてください。この記事ではデータプラットフォームとして IRIS 2023.1 を使用していますが、それ以前のバージョンでは記載されているすべての機能が提供されているとは限りません。

ステップ 1 - データモデルの定義

クリーンなネームスペースを新規に定義することから始めましょう。CODE と DATA データベースを使用します。 すべてを 1 つのデータベースで賄うことはできますが、分割してデータのリフレッシュを実行できるようにすると便利です。

このヘルプデスクシステムには 3 つの基本クラスが必要です。スタッフアドバイザーユーザーアカウント(UserAccount) と顧客連絡先ユーザーアカウント(UserAccount)間のやり取りを文書化するアクション(Actions)を含められる Ticket オブジェクトです。

19 行のコードで完全なデータモデルができました!2 つのクラスはデータベースに保存できるように Persistent(永続)に設定し、%JSON.Adapter を継承しています。この継承によって、JSON フォーマットでのオブジェクトのインポートとエクスポートを非常に簡単に行うことができます。テストとして、最初のユーザーをターミナルにセットアップし、保存してから JSONExport が正しく動作することを確認します。

すべてうまくいったようです。上司から、スタッフと顧客のリストが含まれる csv ファイルを渡されました。これを解析して読み込むコードを書くことは可能ですが、簡単に行う方法はないものでしょうか?

ステップ 2 - データの読み込み

InterSystems IRIS には、CSV ファイルから簡単にデータを読み込み、ヘッダーの解析やフィールド名の変更のオプションも使用できる SQL のLOAD DATA ステートメントが備わっています。使い方も単純です。では、それを使用してユーザーテーブルを読み込んでみましょう。

ヘッダーラベルを使ってこのデータを抽出し、データベースに読み込みます。

1 つのコマンドで全 300 行のデータがインポートされました。この 4 行のコードを加えると、合計 23 行のコードが記述したことになります。これらのレコードが正しいことを、基本的な SQL の SELECT を使って素早く確認してみましょう。

最初のデータを得られました。では、フロントエンドを接続できる基本的な API を作成しましょう。この API は、JSON を送受信する REST サービスとして作成します。

ステップ 3 - REST API の作成

InterSystems IRIS には、%CSP.REST クラスの継承を通じてネイティブの RESTサポートが備わっています。そこで、REST.Dispatch クラスを作成して %CSP.REST を継承することにします。このクラスは、URL と動詞をメソッドにマッピングする XData UrlMap と、これらの URL から呼び出されるメソッドの 2 つのセクションで構成されます。

ここで作成する実用最低限のツールには、スタッフまたは顧客のユーザーリストの取得、発行された最近のチケットの取得、ID 番号による単一のチケットの取得、および新しいチケットの作成の 4 つの演算が必要です。ここで使用する動詞を定義してからメソッドを定義します。

GetUserList は、直接 JSON にデータを出力する基本的な埋め込み SQL カーソルです。その後で、ネイティブの JSON 機能を使ってこれを解析し、JSON 配列にプッシュして、レスポンス本文として送信することができます。URL から直接クエリにスタッフ変数を渡して、データのコンテキストを変更します。

TicketSummary はほぼ同じですが、クエリは TICKET テーブルにアクセスします。

TicketSummary は最もシンプルなサービスです。ID でオブジェクトを開き、組み込みの %JSONExport を出力に書き込みます。オブジェクトが読み込みに失敗する場合、エラーパケットを出力します。

最後に、UploadTicket は最も複雑なメソッドです。 リクエストオブジェクトからペイロードを読み取り、JSON に解析してから %JSONImport を使って Ticket の新しいインスタンスに適用します。また、入力を待つ代わりに現在の時間から OpenDate と OpenTime も設定します。正しく保存できたら、オブジェクトの JSON 表現を呼び出すか、読み込み失敗する場合はエラーを返します。

このサービスにより、さらに 60 行のコードが全体に追加されました。これで、このアプリケーションの合計コード行数は、89 行になりました。

次は、セキュリティ > アプリケーションに Web アプリケーションを作成する必要があります。これには REST タイプのアプリケーションに設定し、クラス名を今作成したディスパッチクラスとして設定する必要があります(このアプリケーションがコードとデータにアクセスできるように適切なセキュリティロールを付与する必要があることに注意してください)。保存すると、REST サービスを定義した URL から呼び出せるようになります。

UserList を呼び出して確認してみましょう。

これで、データを作成する準備ができました。REST クライアントを使用して、ペイロードをチケット作成サービスに送信してみましょう。Keyword、Description、Advisor、および Contact を提供すると、作成したチケットの JSON が OpenDate と TicketId と共に返されます。

これで実用最低限のツールが完成しました。任意のフロントエンドフォームビルダーを使用して、REST サービス経由でチケット情報を送受信できるようになりました。

ステップ 4 - 相互運用性の要件

たった 89 行のコードで基本的なチケット管理アプリケーションが完成しました。上司も絶対に驚いたのでは?確かにそうですが、上司から悪い知らせを受けました。要件を逃しているというのです。ウィジェットダイレクトにはフランス語圏での特別な契約があり、フランス語によるチケットはすべて初回レビューを行う Mme Bettie Francis(ベティー・フランシス)を通過しなければならないのです。幸いにも、Robert Luman の Python 自然言語サポートに関する優れた記事を読み、テキストサンプルを受け入れて言語を識別できる REST サービスを作成したことのある同僚がいました。InterSystems IRIS 相互運用性を使用してこのサービスを呼び出し、テキストがフランス語であればアドバイザーを自動的にフランシスさんに更新するようにすることはできるでしょうか?

まずは、リクエストを送受信できるように、メッセージクラスを作成することから始めましょう。チケット ID とサンプルテキストを格納するリクエストと、言語コードと説明を返すレスポンスが必要です。 それぞれ Ens.Request と Ens.Response を継承します。

さて、さらに 6 行が追加され、合計 95 行のコードとなりました。次に演算を作成する必要があります。同僚のサービスにリクエストを送信して回答を取得する演算です。Outbount Operation を Server と URL のプロパティで定義し、これらを SETTINGS パラメーターに含めてユーザー構成に公開します。こうすることで、サーバーのパスが変更した場合に簡単にリクエストを更新できます。HTTPRequest をセットアップするヘルパーメソッドを作成してから、それを使用してサービスを呼び出し、レスポンスを作成します。

27 行のコードが追加され 100 行を超え、合計 122 行となりました。次に、このクラスを Ensemble 本番環境内にセットアップする必要があります。相互運用性の本番構成に移動し、「演算」ヘッダーの下にある「追加」を押します。クラス名と表示名で演算をセットアップしましょう。

次に、それをクリックして設定を開き、サーバー名と URL を入力して演算を有効にします。

次に、チケット ID を取り、入力されたユーザーアカウント ID をアドバイザーに設定する 2 つ目の演算が必要です。メッセージと演算クラスが必要ですが、この場合レスポンスは返さず、演算はフィードバックなしでタスクを実行します。

さらに 12 行が追加され、合計 134 行になりました。言語サービスを追加した方法でこの演算を本番環境に追加しますが、この場合、構成を設定する必要はありません。

次に、サービスを呼び出し、レスポンスを評価し、オプションとしてフランス語アドバイザーの演算を呼び出すルーターが必要です。「相互運用性」>「ビルド」>「ビジネスプロセス」に移動し、ビジュアルルールビルダーを開きます。リクエストとレスポンスのコンテキストを設定してから、呼び出しの項目を追加します。作成したメッセージクラスに入力と出力を設定したら、リクエストビルダーを使って入力をマッピングします。「非同期」フラグのチェックがオフになっていることを確認してください。レスポンスを待ってから処理を進めるためです。

次に「If」項目を追加して、返される言語コードを評価します。「fr」であれば、FrenchAdvisor 演算を呼び出すようにします。

フランシスさんのユーザー ID は 11 であるため、AdvisorUpdate メッセージを FrenchAdvisor サービスに供給するように呼び出しオブジェクトを設定し、ビルダーを使って、TicketID と固定値 11 を Advisor パラメーターに渡します。

「プロセス」ヘッダーの下にある「追加」をクリックし、クラスを選択して表示名「FrenchRouter」を指定したら、本番にこれを追加します。

これでルーティングが設定されました。 後は、新しいチケットをスキャンして、ルーターでの処理に送信するサービスが必要です。SQL アダプターに従ってサービスクラスを定義します(さらに 8 行のコードが追加されます)。

次に、演算オブジェクトとプロセスオブジェクトと同じようにして、これを本番に追加します。SQL アダプターのセットアップが必要です。ODBC DSN を介してローカルデータベースへの接続情報を提供し、CallInterval 設定に設定されたタイマーでチケットをクエリするためにサービスが使用する基本的な SQL クエリを指定します。このクエリはクエリに一意のキーを定義し、送信済みのレコードが再送信されないようにする「キーフィールド名」設定と組み合わされます。

この設定により、新しいチケットをスキャンし、テキストを外部サービスに渡して言語を解析し、オプションとしてこのレスポンスに応じてアドバイザーをリセットする処理が完成しました。では試してみましょう!英語のリクエストを送信してみましょう。これは TicketID 70 で返されます。数秒待ってから、GetTicket REST サービスを介してこのレコードにアクセスすると、アドバイザーは元のリクエストから変わっていないのがわかります。

では、フランス語のテキストを使ってみましょう。

チケット ID 71 をリクエストすると、期待どおり、アドバイザーはフランシスさんに変更されています! これは相互運用性内で、ビジュアルトレースでメッセージの場所を探し、演算が期待どおりに呼び出されたことを確認すればわかります。

この時点でのコード行数は 142 行であり、データを永続させ、LOAD DATA でデータを読み込み、データの表示と編集を行える基本的な REST API と、外部 REST サービスへの呼び出しに基づいて意思決定サポートを提供する高度な統合エンジンを備えた InterSystems IRIS アプリケーションが出来上がりました。これ以上のことを求める人はきっといないですよね?

ステップ 5 - 更なる要求: 分析

このアプリケーションは大成功をおさめ、データもさらに増えています。この貴重データを利用するには専門知識が必要であり、ウィジェットダイレクトの経営陣はインサイトを希望しています。データへの対話型アクセスを提供できるでしょうか?

InterSystems IRIS Analytics を使用すると、高度なデータ操作ツールを素早く簡単に利用できます。まずは、内部 Web アプリケーションに対し、Analytics サポートを有効化する必要があります。

これにより、ネームスペースの分析セクションを使用できるようになります。「分析」>「アーキテクト」を開きましょう。「新規」を選択してフォームに入力し、Ticket クラスの分析キューブを作成します。

次に、ビジュアルビルダーを使って、次元と、基本的なドリルダウンのリストをセットアップします。このビューはドラッグアンドドロップで操作します。リストは、ユーザーがデータポイントを調査する際に表示されるコンテンツをカスタマイズするためのビジュアルエディターででも作成できます。

基本のセットアップが完了したら、キューブを保存、コンパイル、ビルドできます。これによりすべてのインデックスがセットアップされ、アナライザーでの分析用にキューブが有効化されます。アナライザーを開いてデータを操作してみましょう。例では、アドバイザーを年と四半期の階層に対して比較されており、保存されている連絡先でフィルターされています。セルをクリックすると双眼鏡のアイコンが表示されるため、それをクリックすると作成したドリルダウンリストが呼び出されます。それを使用してさらに分析し、エクスポートすることができます。

まとめ

たった 142 行のコードで、基本的ではありながらも機能性のあるモダンなバックエンドアプリケーションを作成しました。アプリケーション間の通信と高度な分析が可能なツールもサポートされています。これは過剰に単純化した実装であり、IRIS でデータベースアプリケーションを構築するために必要最低限の例としてのみ使用してください。この記事の冒頭で述べたように、このコードは本番対応かつ実用できるものではありません。開発者は InterSystems IRIS ドキュメントとベストプラクティスを参考にしながら、自分のコードを堅牢かつ安全で、スケーラブルにしてください(このコードベースはどれにも該当しません)。それでは、コーディングをお楽しみください!

1
0 131
記事 Mihoko Iijima · 12月 7, 2022 2m read

開発者の皆さん、こんにちは!

InterSystems全製品のサーバ側コードで利用できる「ObjectScript」の基本の使い方から、困ったときのヒント集、エラーの読み方など、日本語ドキュメントの逆引きになるようなページを目指して、「ObjectScriptクックブック」を作成しました!

ObjectScriptの基本の「き」

Hello Worldの出力から始めたい方に最適です。

2024/3/25更新:8. デバッグ方法 を追加しました。ぜひご参照ください。

CookBook(こんなときどうする?集)

ObjectScriptの記述に困ったときに読んでいただけるヒント集です。コミュニティに寄せられたご質問をどんどん掲載していきます。

ObjectScriptでエラーが発生したら

ObjectScriptのプログラムでエラーが発生したときのエラーメッセージの読み方から、エラー情報の取得方法などを解説しています。

1
0 413
記事 Megumi Kakechi · 3月 11, 2024 2m read

これは InterSystems FAQ サイトの記事です。

SQLのINSERT/UPDATE/DELETE文で大量のデータを更新する際に、高速化する方法をご紹介します。
以下の2つの手順を実行することで、更新処理のパフォーマンスを向上させることが可能です。

1.INSERT/UPDATE/DELETE時にインデックスを作成せず、あとでまとめて作成する

2.INSERT/UPDATE/DELETE時にジャーナルをOFFにする

1は、%NOINDEX キーワードを指定してインデックスの生成を後でまとめて行うことで、インデックスの構築を抑制しパフォーマンスを向上させる方法です。

クエリ実行例は、以下のようになります。

例:
UPDATE %NOINDEX tablename …
INSERT %NOINDEX INTO tablename …
DELETE %NOINDEX FROM tablename ...


更新後、あとでまとめてインデックスを再構築する場合は管理ポータルで行う方法と、コマンドで行う方法の2種類があります。

◆ 管理ポータルの場合...

[システムエクスプローラ] > [SQL]
 (ネームスペース指定&テーブルを選択して) アクション - テーブルのインデックスを再構築...

◆ コマンドの場合...

0
0 863
記事 Mihoko Iijima · 2月 27, 2024 7m read

これは InterSystems FAQ サイトの記事です。

InterSystems製品のInteroperability(相互運用性機能)を利用する際、REST経由で情報入力を行う場合の作成方法についてサンプルプロダクションを利用しながらご紹介します。

サンプルはこちら👉https://github.com/Intersystems-jp/FAQ-Interop-REST

0
0 199
記事 Mihoko Iijima · 1月 18, 2024 5m read

開発者の皆さん、こんにちは!

VSCodeのObjectScriptエクステンションを利用してInterSystems製品に接続するときに「プライベートWebサーバ (*1)」ではなく、「Webサーバ(IISやApache)」を利用される場合、接続時に使用するREST用パスが通るようにWebサーバに仮想パスを追加する必要があります。

(*1) プライベートWebサーバとは、バージョン2023.1以前のInterSystems製品をインストールすると自動でインストールされる簡易的なApacheで、52773番ポートで管理ポータルやWebアクセスのテストにご利用いただけるWebサーバです。(本番運用環境には適さない簡易的なWebサーバです)

対象バージョン:2023.1以下のInterSystems製品

追加が必要なパス: /api

以下、IISApacheそれぞれの設定方法をご紹介します。

IISの場合

IISを有効化した後で、InterSystems製品のインストーラーのメニューから「ウェブサーバ」(下図左)または「カスタム」から「Webサーバゲートウェイ→IIS用CSP」(下図右)で設定を行った場合、

IISにWebゲートウェイがインストールされ、デフォルトで以下のアプリケーションを追加します。

0
0 750
記事 Toshihiko Minamoto · 12月 20, 2023 15m read

開発者の皆さん、こんにちは!

多くの方が、Open Exchange と GitHub で InterSystems ObjectScript ライブラリを公開しています。

でも、開発者がプロジェクトの使用とコラボレーションを簡単に行えるようにするにはどうしていますか?

この記事では、ファイルの標準セットをリポジトリにコピーするだけで、ObjectScript プロジェクトを簡単に起動して作業する方法をご紹介します。

では始めましょう!

概要 - 以下のファイルをこちらのリポジトリからお使いのリポジトリにコピーしてください。

Dockerfile

docker-compose.yml

Installer.cls

iris.script

settings.json{#9f423fcac90bf80939d78b509e9c2dd2-d165a4a3719c56158cd42a4899e791c99338ce73}

.dockerignore{#f7c5b4068637e2def526f9bbc7200c4e-c292b730421792d809e51f096c25eb859f53b637}
.gitattributes{#fc723d30b02a4cca7a534518111c1a66-051218936162e5338d54836895e0b651e57973e1}
.gitignore{#a084b794bc0759e7a6b77810e01874f2-e6aff5167df2097c253736b40468e7b21e577eeb}

すると、プロジェクトを起動して共同作業する標準的な方法が得られます。 以下は、この仕組みと動作する理由についての記事です。

注意: この記事では、InterSystems IRIS 2019.1 以降で実行可能なプロジェクトを対象としています。

InterSystems IRIS プロジェクトの起動環境の選択

通常、開発者には、プロジェクト/ライブラリを試して、素早く安全な方法であることを確認していただきたいと思っています。

私見としては、新しいものを素早く安全に起動するには、Docker コンテナが理想的だと考えています。起動、インポート、コンパイル、計算するあらゆるものがホストマシンにとって安全であり、いかなるシステムやコードも破壊されたり損なわれたりすることがないことを開発者に保証できるためです。 何らかの問題が発生した場合は、コンテナを止めて削除するだけで済みます。 アプリケーションが膨大なディスクスペースを占有するのであれば、コンテナを削除すれば、容量を解放できます。 アプリケーションがデータベース構成を破損するのであれば、破損した構成のあるコンテナを削除するだけです。 このように単純で安全なのです。

Docker コンテナでは、安全と標準化を得られます。

バニラ InterSystems IRIS Docker コンテナを実行するには、IRIS Community Edition イメージを実行するのが最も簡単です。

  1. Docker デスクトップをインストールします。 

  2. OS のターミナルで以下を実行します。

docker run --rm -p 52773:52773 --init --name my-iris store/intersystems/iris-community:2020.1.0.199.0
  1. 次に、ホストブラウザで管理ポータルを開きます。

http://localhost:52773/csp/sys/UtilHome.csp

  1. または IRIS へのターミナルを開きます。

    docker exec -it my-iris iris session IRIS

  2. IRIS コンテナが不要になれば、それを停止します。

    docker stop my-iris

さて、 IRIS を Docker コンテナで実行しますが、 開発者にはコードを IRIS にインストールして、いくらかの設定を行ってほしいと考えているとします。 以下ではこれについて説明します。

ObjectScript ファイルのインポート

最も単純な InterSystems ObjectScript プロジェクトには、クラス、ルーチン、マクロ、グローバルなどの一連の ObjectScript ファイルが含めることができます。 命名規則フォルダ構造の提案についての記事をご覧ください。

問題は、このコードをどのようにして IRIS コンテナにインポートするかです。

ここで役立つのが Dockerfile です。これを使用して、バニラ IRIS コンテナを取得し、リポジトリから IRIS にすべてのコードをインポートして、必要に応じて IRIS で設定を行います。 リポジトリに Dockerfile を追加する必要があります。

ObjectScript テンプレートリポジトリから取得した Dockerfile を調べてみましょう。

ARG IMAGE=store/intersystems/irishealth:2019.3.0.308.0-community
ARG IMAGE=store/intersystems/iris-community:2019.3.0.309.0
ARG IMAGE=store/intersystems/iris-community:2019.4.0.379.0
ARG IMAGE=store/intersystems/iris-community:2020.1.0.199.0
FROM $IMAGE

USER root

WORKDIR /opt/irisapp
RUN chown ${ISC_PACKAGE_MGRUSER}:${ISC_PACKAGE_IRISGROUP} /opt/irisapp

USER irisowner

COPY  Installer.cls .
COPY  src src
COPY iris.script /tmp/iris.script # run iris and initial 

RUN iris start IRIS \
    && iris session IRIS &lt; /tmp/iris.script

 

最初の ARG の行は $IMAGE 変数を設定しており、それを FROM で使用します。 これは、$IMAGE 変数を変更するために FROM の前の最後の行が何であるかだけを切り替えて、さまざまな IRIS バージョンでコードをテスト/実行するのに適しています。 

以下のコードがあります。 

ARG IMAGE=store/intersystems/iris-community:2020.1.0.199.0

FROM $IMAGE

これは、IRIS 2020 Community Edition ビルド 199 を使用するということです。

リポジトリからコードをインポートするため、リポジトリのファイルを Docker コンテナにコピーする必要があります。 以下の行はそれを行います。

USER root

WORKDIR /opt/irisapp
RUN chown ${ISC_PACKAGE_MGRUSER}:${ISC_PACKAGE_IRISGROUP} /opt/irisapp

USER irisowner

COPY  Installer.cls .
COPY  src src

USER root - ここで、ユーザーをルートに切り替えて、フォルダを作成してファイルを Docker にコピーします。

WORKDIR /opt/irisapp - この行では、ファイルをコピーする workdir をセットアップしています。

RUN chown ${ISC_PACKAGE_MGRUSER}:${ISC_PACKAGE_IRISGROUP} /opt/irisapp   -  ここでは、irisowner ユーザーと IRIS を実行するグループに権限を付与しています。

USER irisowner - ユーザーを root から irisowner に切り替えます。

COPY Installer.cls .  - workdir のルートに Installer.cls をコピーしています。 このピリオドを忘れないでください。

COPY src src - ソースファイルをリポジトリの src フォルダから Docekr の workdir の src フォルダにコピーします。

次のブロックでは、初期スクリプトを実行し、インストーラーと ObjectScript コードを呼び出します。

COPY iris.script /tmp/iris.script # run iris and initial 
RUN iris start IRIS \
    && iris session IRIS &lt; /tmp/iris.script

COPY iris.script / - iris.script をルートディレクトリにコピーします。 コンテナをセットアップするために呼び出す ObjectScript が含まれます。

RUN iris start IRIS</span>  - IRIS を起動します。

&& iris session IRIS < /tmp/iris.script - IRIS ターミナルを起動し、それに最初の ObjectScript を入力します。

以上です! Docker にファイルをインポートする Dockerfile ができました。 installer.cls と iris.script の 2 つのファイルが残っています。ではそれらを詳しく見てみましょう。

Installer.cls

Class App.Installer
{

XData setup
{
<Manifest>
  <Default Name="SourceDir" Value="#{$system.Process.CurrentDirectory()}src"/>
  <Default Name="Namespace" Value="IRISAPP"/>
  <Default Name="app" Value="irisapp" />

  <Namespace Name="${Namespace}" Code="${Namespace}" Data="${Namespace}" Create="yes" Ensemble="no">

    <Configuration>
      <Database Name="${Namespace}" Dir="/opt/${app}/data" Create="yes" Resource="%DB_${Namespace}"/>

      <Import File="${SourceDir}" Flags="ck" Recurse="1"/>
    </Configuration>
    <CSPApplication Url="/csp/${app}" Directory="${cspdir}${app}"  ServeFiles="1" Recurse="1" MatchRoles=":%DB_${Namespace}" AuthenticationMethods="32"
       
    />
  </Namespace>

</Manifest>
}

ClassMethod setup(ByRef pVars, pLogLevel As %Integer = 3, pInstaller As %Installer.Installer, pLogger As %Installer.AbstractLogger) As %Status [ CodeMode = objectgenerator, Internal ]
{
  #; Let XGL document generate code for this method. 
  Quit ##class(%Installer.Manifest).%Generate(%compiledclass, %code, "setup")
}

}

率直に言って、ファイルのインポートに Installer.cls は必要ありません。 これは 1 行で実行可能です。 ただし、コードをインポートするほかに、CSP アプリのセットアップ、セキュリティ設定の追加、データベースとネームスペースの作成を行わなければなりません。

この Installer.cls では、 IRISAPP という名前で新しいデータベースとネームスペースを作成し、このネームスペースのデフォルトの /csp/irisapp アプリケーションを作成します。

すべては、<Namespace> 要素で行います。

<Namespace Name="${Namespace}" Code="${Namespace}" Data="${Namespace}" Create="yes" Ensemble="no">

    <Configuration>
      <Database Name="${Namespace}" Dir="/opt/${app}/data" Create="yes" Resource="%DB_${Namespace}"/>

      <Import File="${SourceDir}" Flags="ck" Recurse="1"/>
    </Configuration>
    <CSPApplication Url="/csp/${app}" Directory="${cspdir}${app}"  ServeFiles="1" Recurse="1" MatchRoles=":%DB_${Namespace}" AuthenticationMethods="32"
       
    />
  </Namespace>

そして、Import タグを使って、SourceDir からすべてのファイルをインポートします。

<Import File="${SourceDir}" Flags="ck" Recurse="1"/>

この SourceDir は変数であり、現在のディレクトリ/src フォルダに設定されています。

<Default Name="SourceDir" Value="#{$system.Process.CurrentDirectory()}src"/>

これらの設定を含む Installer.cls によって、src フォルダから任意の ObjectScript コードをインポートするわかりやすい新しいデータベース IRISAPP を作成できるという確信を持つことができます。

iris.script

ここに、IRIS コンテナを起動する初期の ObjectScript セットアップコードを挿入してください。

例: 開発にはパスワードのプロンプトは不要であるため、ここでは、installer.cls を読み込んで実行してから、パスワードの初回変更リクエストを回避するために、UserPasswords を永久にしています。

; run installer to create namespace
do $SYSTEM.OBJ.Load("/opt/irisapp/Installer.cls", "ck")
set sc = ##class(App.Installer).setup()  zn "%SYS"
Do ##class(Security.Users).UnExpireUserPasswords("*") ; call your initial methods here
halt

docker-compose.yml

docker-compose.yml はなぜ必要なのでしょうか。Dockerfile と同様に、イメージをただビルドして実行するだけではいけないのでしょうか。 もちろん、そうすることは可能です。 ただし、docker-compose.yml を使用すれば作業が単純になります。

通常、docker-compose.yml は、1 つのネットワークに接続された複数の Docker イメージを起動するために使用されます。

docker-compose.yml は、多数のパラメーターを処理する場合に、1 つの Docker イメージの起動をより簡単にするためにも使用できます。 これを使用すれは、ポートのマッピング、ボリューム、VSCode 接続パラメーターなどを Docker に渡すことができます。

version: '3.6' 
services:
  iris:
    build: 
      context: .
      dockerfile: Dockerfile
    restart: always
    ports: 
      - 51773
      - 52773
      - 53773
    volumes:
      - ~/iris.key:/usr/irissys/mgr/iris.key
      - ./:/irisdev/app

ここでは、サービス iris を宣言しています。これは Dockerfile を使用し、IRIS の 51773、52773、53773 ポートを公開するサービスです。 また、このサービスは、ホストマシンのホームディレクトリの iris.key と期待される IRIS フォルダ、およびソースコードのルートフォルダと /irisdev/app フォルダの 2 つのボリュームのマッピングも行います。

docker-compose によって、セットアップされるパラメーターに関係なく、イメージをビルドして実行するためのコマンドをより短く、統一することができます。

いずれの場合でも、以下のようにしてイメージをビルドします。

$ docker-compose up -d

 そして以下のようにして IRIS ターミナルを開きます。

$ docker-compose exec iris iris session iris

Node: 05a09e256d6b, Instance: IRIS

USER>

また、docker-compose.yml では、VSCode ObjectScript プラグインの接続もセットアップできます。

.vscode/settings.json

ObjectScript アドオン接続設定に関連しているのは、以下の部分です。

{
    "objectscript.conn" :{
      "ns": "IRISAPP",
      "active": true,
      "docker-compose": {
        "service": "iris",
        "internalPort": 52773
      }
    }     

}

ここにあるのは設定です。VSCode ObjectScript プラグインのデフォルトの設定とは異なります。

ここでは、IRISAPP ネームスペース(Installer.cls で作成)に接続すると述べています。

"ns": "IRISAPP",

そして、docker-compose の設定があります。これは、サービス「iris」内の docker-compose ファイルで、VSCode が 52773 がマッピングされているポートに接続すると書かれています。

"docker-compose": {
        "service": "iris",
        "internalPort": 52773
      }

52773 について調べたところ、これはマップされたポートが 52773 に対して定義されていないことがわかります。

ports: 
      - 51773
      - 52773
      - 53773

つまり、ホストマシンのポートで利用できるランダムなポートが取得され、VSCode は自動的にランダムなポートを介して、docker 上でこの IRIS に接続するということです。

これは非常に便利な機能です。IRIS を使用して任意の量の Docker イメージをランダムなポート上で実行し、VSCode をそれらのポートに自動的に接続するオプションが提供されるためです。

他のファイルはどうでしょうか?

以下のファイルもあります。

.dockerignore  - 作成した Docker ファイルにコピーしない不要なホストマシンのファイルをフィルターするために使用できるファイル。 通常、.git や .DS_Store は必須です。

.gitattributes - git の属性。ソース内の ObjectScript ファイルの行末を統一します。 Windows と Mac/Ubuntu オーナーがリポジトリで共同作業する場合に非常に便利です。

.gitignore - Git で変更履歴を追跡しないファイル。 通常、.DS_Store などの非表示の OS レベルのファイルです。

以上です!

リポジトリを Docker 実行可能にし、コラボレーションしやすくするにはどうすればよいでしょうか。

  1. このリポジトリをクローンします。

  2. 以下のファイルをすべてコピーします。

Dockerfile

docker-compose.yml

Installer.cls

iris.script

settings.json{#9f423fcac90bf80939d78b509e9c2dd2-d165a4a3719c56158cd42a4899e791c99338ce73}

.dockerignore{#f7c5b4068637e2def526f9bbc7200c4e-c292b730421792d809e51f096c25eb859f53b637}
.gitattributes{#fc723d30b02a4cca7a534518111c1a66-051218936162e5338d54836895e0b651e57973e1}
.gitignore{#a084b794bc0759e7a6b77810e01874f2-e6aff5167df2097c253736b40468e7b21e577eeb}

上記をリポジトリにコピーしてください。

Dockerfile のこの行を IRIS にインポートする ObjectScript のあるリポジトリ内のディレクトリに一致するように変更します(in /src フォルダにある場合は変更しません)。

それだけです。 すべての人(あなた自身も含む)が、新しい IRISAPP ネームスペースでコードをインポートできるようになります。

プロジェクトの起動方法

IRIS で ObjectScript プロジェクトを実行するためのアルゴリズムは以下の通りです。

  1. プロジェクトをローカルに Git clone します。

  2. プロジェクトを実行します。

$ docker-compose up -d
$ docker-compose exec iris iris session iris

Node: 05a09e256d6b, Instance: IRIS

USER>zn "IRISAPP"

**開発者によるプロジェクトへの貢献方法 **

  1. リポジトリをフォークして、フォークされたリポジトリをローカルに Git clone します。

  2. VSCode でフォルダを開きます(DockerObjectScript の拡張機能が VSCode にインストールされている必要があります)。

  3. docker-compose.yml を右クリックし、再起動します。VSCode ObjectScript が自動的に接続され、編集/コンパイル/デバッグできるうようになります。

  4. リポジトリに変更をコミット、プッシュ、およびプルリクエストします。

以下は、この仕組みを説明する簡単な Gif です。

以上です! それでは、コーディングをお楽しみください!

0
0 172
記事 Mihoko Iijima · 9月 20, 2023 2m read

開発者の皆さん、こんにちは!

ObjectScriptのコード実行中にエラーが発生した場合 "<UNDEFINED>HelloWorld+2^Simple.Demo.1 *name" のようなエラーメッセージが表示されます。

エラーメッセージの読み方については、ObjectScriptクックブックの「ObjectScriptでエラーが発生したら」のエラーメッセージの読み方 をご参照ください。

エラー行の特定を行う際、VSCodeのコマンドパレットを利用すると簡単に対象行にジャンプできますので、以下、方法をご紹介します。

1)VSCodeのView→Command Palette... を開きます。

2) 「ObjectScript:Open Error Location...」を選択します(初回は表示項目に登場しないため > の後ろに ObjectScript と入力すると表示されます)。

3) テキストボックスが表示されるので、エラーメッセージの出力情報の中から ラベル名+行数^生成ルーチン名 をコピーして貼り付け、Enterをクリックします。

※スタジオにも同様の機能がありますが、VSCodeの場合対象となるコード(生成コードの元コード)をVSCode上で表示していなくても対象となる生成ルーチンを開きエラー行をポイントしてくれます。

0
0 1144
記事 Mihoko Iijima · 9月 18, 2023 4m read

開発者の皆さん、こんにちは!

スタジオを利用されている方にはお馴染みのソースコードの「XMLファイルへのエクスポート/インポート機能」がVSCodeのObjectScriptエクステンションに追加されました! (ObjectScript 2.10.0以降に含まれています。こちらのリクエストが元となりました👉https://github.com/intersystems-community/vscode-objectscript/issues/1158   エクステンションの追加番号は#1171です)

今まで、過去エクスポートしたXMLファイルをVSCodeから参照するためには、管理ポータル(またはスタジオ)を利用してインポートする必要がありましたが、VSCodeの画面だけでできるようになりました!

💡注意1: InterSystems IRIS /InterSystems IRIS for Health 2023.2以降のバージョンに接続した状態でご利用いただける機能です。

💡注意2:この機能は管理ポータルやスタジオのインポート/エクスポートのVSCode版のような機能となるため、インポートしたソースコードはサーバ側にインポートされ、エクスポートはサーバ側コードを選択してXMLファイルにエクスポートする動作となります。XMLファイルインポート後、VSCodeのワークスペースでローカルファイル(*.cls や *.mac)として編集 したい場合は、 ObjectScriptエクステンションマークをクリックし、対象のコードを選択→エクスポート の手順でローカルにエクスポートする必要があります。

0
1 596
記事 Megumi Kakechi · 8月 1, 2023 2m read

あるメソッドやルーチンを実行してエラーとなった場合、エラー発生個所はエラーメッセージより取得することができますが、処理の呼び出し履歴(スタックトレース)はエラーメッセージのみではわかりません。
また、.Net や Python など IRIS 外からの呼び出しの場合に、エラー情報の詳細がクライアントに返らない場合などもあるかと思います。

/// 例:エラーメッセージだけでは、エラーが発生した処理の呼び出し履歴まではわからない。
USER>d##class(User.Test).TestMethod1()
 
 write a
 ^
<UNDEFINED>TestMethod3+1^User.Test3.1 *a
USER 4e1>


そんなときは、エラー処理にて Do BACK^%ETN を実施することで、IRIS側で強制的にスタック情報を記録することができます。
スタック情報を記録することで、どのような処理がどの順番で呼び出されたかや、エラー時の内部変数情報を知ることができます。

BACK^%ETN は、エラー発生後に $ZError($ZE) 変数に値が set されている場合、アプリケーションエラーログ(^ERRORS)に情報が記録されます。
上のエラーの場合の $ZE は、以下のように確認できます。

0
0 170
記事 Megumi Kakechi · 3月 2, 2021 2m read

これは InterSystems FAQ サイトの記事です。
※記事後半に、「2>&1」で 標準エラー出力(2) を 標準出力(1) にリダイレクトする方法を追記しました。

$ZF(-100) では実行したコマンドの出力を取得することはできませんが、代わりにコマンド・パイプ デバイスを使用する方法があります。

詳細は、以下ドキュメントをご参照ください。

コマンド・パイプ デバイスを使用する方法について
 

こちらを %File クラスで使用した例が以下になります。

1
0 544
記事 Megumi Kakechi · 2月 6, 2023 4m read

ファイルとディレクトリの操作に使用できる API 、%Library.File クラス (%File が省略形) の便利なサンプルコードをご紹介します。

こちらのAPIを使用して、ディレクトリやファイルの中身をのぞいたり、作成・書込み・読込みを行ってみます。


ディレクトリ内のファイル一覧をリストする

以下のサンプルは、C:\temp フォルダ内の *.txt ファイルをリストします(ファイルパス_サイズ_作成日)。

 set stmt = ##class(%SQL.Statement).%New()
 set status = stmt.%PrepareClassQuery("%File", "FileSet")
 set rs = stmt.%Execute("c:\temp", "*.txt")
 while rs.%Next(.rStatus) { write !, rs.%Get("Name")_"_"_rs.%Get("Size")_"byte"_"_"_rs.%Get("DateCreated") }

サブディレクトリ内のファイルを含む場合はこちら (filetest.mac で保存) ↓

1
0 710
記事 Megumi Kakechi · 7月 11, 2023 3m read

クラスメソッドの多くは、%Status データ型を使用して、成功 または 失敗 の情報を返します。
成功の場合は 1 が返り、失敗の場合はエラーステータス および 1 つ以上のエラーコードとテキストメッセージを含むエンコードされた文字列が返ります。
このようなメソッドでは、戻り値を必ず取得して確認するようにしてください。

こちらの記事では、失敗の場合の具体的なエラー情報を確認する方法をご紹介します。

USER>set file=##class(%File).%New("C:\test\text.txt")
 
USER>set st=file.Open("R")
 
USER>write st
・・C:\test\text.txt.USER%e^Open+5^%Library.File.1^4e^^^0// 何のエラーかわからない


エンコードされたエラーの文字列より、具体的なメッセージを表示したい場合、%SYSTEM.Status クラスのメソッドを使用します。

0
1 232
記事 Toshihiko Minamoto · 7月 5, 2023 39m read

この記事では、InterSystems IRIS の学習に関連したトピックについて、開発者コミュニティでの厳選された記事にアクセスすることができます。機械学習や Embedded Python、JSON、API と REST アプリ、InterSystems環境の構築と管理、DockerとCloud、VSCode、SQL、Analytics/BI、グローバル、セキュリティ、DevOps、インターオペラビリティNative API、それぞれでランク付けされたトップの記事を見ることができます。ぜひ、楽しみながら学んでください!  

機械学習

機械学習は、高度なデータ分析を構築し、優れた効率で手動活動を自動化するための必須技術です。既存のデータから学習する認知モデルを作成し、自己調整されたアルゴリズムに基づいて予測、確率計算、分類、識別、「非創造的」な人間の活動の自動化を実行します。

すべてのシナリオにおいて、InterSystems IRISは、これらのマシンラーニングモデルを作成、実行、利用可能にし、使用するためのデータプラットフォームおよび環境として機能します。IRISは、SQLコマンドからのML利用(IntegratedML)、Embedded PythonやPMML(Predictive Model Markup Language)による機械学習が可能です。以下の記事でその機能を確認することができます。

名称概要URL
IntegratedMLハンズオンラボIntegratedMLの実践的な概要https://community.intersystems.com/post/integratedml-hands-lab
InterSystems IRISデータプラットフォームによるAIロボット化IRISプロダクションのAIhttps://community.intersystems.com/post/ai-robotization-intersystems-iris-data-platform
IRIS IntegratedMLを使った糖尿病予測WebアプリIntegratedMLサンプルhttps://jp.community.intersystems.com/node/535221
妊産婦の健康リスクの予測IntegratedMLサンプルhttps://community.intersystems.com/post/predict-maternal-health-risks
機械学習によるコミュニティー記事の整理 - 1Python MLライブラリの利用https://community.intersystems.com/post/using-machine-learning-organize-community-1

 

ObjectScript言語

ObjectScript は InterSystems のオフィシャルプログラミング言語です。簡単で柔軟性があり、バックエンド、統合、および分析アプリケーションの作成に非常に強力です。詳細については、以下の記事を参照してください。

名称概要URL
InterSystems ObjectScript 101++ (EN)ObjectScriptを学ぶビデオシリーズhttps://community.intersystems.com/post/intersystems-objectscript-101-en
$Sequence関数について数列の作成するhttps://community.intersystems.com/post/sequence-function
Caché ObjectScript でのパフォーマンスの高いループの作成ループの作成https://jp.community.intersystems.com/node/481811
データの匿名化、iris-Disguiseの導入ObjectScript の永続的なクラスとプロパティをカスタマイズする方法について説明するhttps://jp.community.intersystems.com/node/510731
ObjectScriptのエラー処理に関するスニペット例外処理https://jp.community.intersystems.com/node/491451
ObjectScriptにおける従来のデバッグデバッグ手法https://community.intersystems.com/post/traditional-debugging-objectscript
Caché での正規表現の使用正規表現を使った作業https://jp.community.intersystems.com/node/481816
ObjectScript における堅牢なエラー処理とクリーンアップ品質の高いコードを書くhttps://jp.community.intersystems.com/node/486226
InterSystems Ensembleを愛し、心配することをやめた理由プロダクションでのJSON処理https://community.intersystems.com/post/how-we-learned-stop-worrying-and-love-intersystems-ensemble
より使いやすくなったオブジェクト・ダンプダンプするオブジェクトhttps://community.intersystems.com/post/more-usefull-object-dump
InterSystems IRISのマクロを使ったロギングマクロを使ったロギングhttps://jp.community.intersystems.com/node/503796
SYSLOG - その実態と意味することシスログのデバッグ情報https://jp.community.intersystems.com/node/492146
%Statusを使ったデバッグのヒント%Statusを使ったデバッグhttps://jp.community.intersystems.com/node/503801
$Queryの有効活用$Query を使ってデータを探すhttps://community.intersystems.com/post/making-most-query
多次元プロパティの永続性 - Part 1 (クラシック)多次元永続プロパティhttps://community.intersystems.com/post/multidimensional-property-persistence-part-1-classic
採用されたBitmapBitmap インデックスhttps://community.intersystems.com/post/adopted-bitmap
タイムロードになる方法 - 誕生日付と時刻のAPIhttps://jp.community.intersystems.com/node/527796
正確なバージョン情報($zv / $zversion)の重要性と収集についてIRISバージョン取得https://community.intersystems.com/post/importance-and-collection-exact-version-information-zv-zversion
1840年12月以前の日付 ? $H( orolog )がネガティブ?ネガティブな日付https://community.intersystems.com/post/date-dec1840-negative-horolog
Caché でのカスタム・インデックス・タイプの作成カスタムインデックスの作成https://jp.community.intersystems.com/node/479316
$LIST 文字列フォーマットと %DynamicArray および %DynamicObject クラス$LIST、%DynamicObject、%DynamicArrayの使用法https://jp.community.intersystems.com/node/483711
^ERRORグローバルに対するSQLSQLを使ってエラーの内容の確認https://community.intersystems.com/post/sql-error-global
コードによるデフォルト設定値の追加デフォルト値の設定https://community.intersystems.com/post/add-default-setting-value-code
ダイナミックオブジェクトの反復処理イテレート(反復処理)の使用https://community.intersystems.com/post/iterate-over-dynamic-object
クラスのすべてのプロパティをリストアップする (ObjectScriptがお気に入りな理由)ObjectScriptプロパティの反復使用https://jp.community.intersystems.com/node/515786
いつも使っているtry catchブロックTry Catchのハンドリングhttps://community.intersystems.com/post/try-catch-block-i-usually-use-intersystems-objectscript
ObjectScriptでシェルコマンドの実行ObjectScriptでシェルコマンドの実行https://community.intersystems.com/post/running-shell-commands-objectscript

Embedded Python

Python は、世界で最も人気があり、よく使われているプログラミング言語の 1 つです (https://www.tiobe.com/tiobe-index/)。InterSystems IRIS は、すべての主要なプログラミング言語に対して開かれたデータ・プラットフォームです。しかし、Python は、この素晴らしい言語とそのライブラリは、クラス、SQL、および統合/プロダクショ ンなど、IRIS のあらゆる場所で使用することができます。ObjectScript ( InterSystems のプログラミング言語 ) を知らない、または知りたくない人にとって、Python は素晴らしい選択肢となります。そのやり方については、以下の記事を参照してください。

名称概要URL
機械と戦おうEmbedded Pythonを使ったチックタックトー・ゲームの構築https://community.intersystems.com/post/lets-fight-against-machines
InterSystems IRIS 2021.2+ Python サンプル ( Embedded, Native API およびノートPC)複数のPythonノートPCでPythonとIRISを見るhttps://community.intersystems.com/post/intersystems-iris-20212-python-examples-embedded-native-apis-and-notebooks
Embedded PythonによるWebSocketクライアントCustom Socket サンプルhttps://community.intersystems.com/post/websocket-client-embedded-python
AWS LambdaにおけるIRIS Python Native APIAWSでのPythonhttps://community.intersystems.com/node/485361
JupyterノートPCにObjectScriptを追加する方法ノートPCでのIRIShttps://jp.community.intersystems.com/node/521496
ようこそDjangoIRISをデータベースとしたPython Djangoアプリの作成https://jp.community.intersystems.com/node/527801
IRISとGoogle Maps APIによるジオコーディングGeocoding python ライブラリの使用https://community.intersystems.com/post/geocoding-iris-and-google-maps-api
IRISとPython gTTSを用いたテキストから音声への変換のためのRESTサービスgTTSを使用したPythonサンプルhttps://community.intersystems.com/post/rest-service-convert-text-audio-using-iris-and-python-gtts
Python Flask WebフレームワークによるIRISレスポンシブダッシュボードの作成IRISによるFlask Webアプリhttps://community.intersystems.com/post/building-iris-responsive-dashboard-python-flask-web-framework

JSON

JSON は、マーケットで最も広く使用されている、データの送受信のための相互運用性フォーマットの 1 つです。InterSystems IRIS は、いくつかの方法でこの形式をサポートしています。JSON (DocDB) でネイティブ・データベースを持ち、オブジェクトを直列化および非直列化し、特に REST サービスからの要求と応答を JSON で処理することが可能です。以下の記事を確認してください。

名称概要URL
Caché 2016.1における新しいJSON機能の紹介ObjectScript JSON API の紹介https://community.intersystems.com/post/introducing-new-json-capabilities-cach%C3%A9-20161
JSONの機能強化JSON Adaptor APIhttps://jp.community.intersystems.com/node/481776

APIとRESTアプリ

バックグラウンドアプリケーションは現在、REST(Representational State Transfer)パラダイムで開発され、Web APIとして公開されています。以下の記事で、その仕組みを確認してください。

名称概要URL
InterSystemsのデータプラットフォームのためのGraphQLGraphQLスタイルでREST APIの作成https://jp.community.intersystems.com/node/481796
InterSystems API Managerの紹介API Managementの概要https://community.intersystems.com/post/introducing-intersystems-api-manager
RESTの高度なURLマッピングAPIへの経路のマッピングhttps://jp.community.intersystems.com/node/497976
AppS.REST: InterSystems IRISのための新しいRESTフレームワークRESTアプリを簡単に作成https://jp.community.intersystems.com/node/497991
RESTForms : クラスのためのREST APICRUDアプリケーションのためのREST APIの開発https://jp.community.intersystems.com/node/479226
スペックファーストのアプローチによるREST APIの作成Contract First ApproachによるAPI開発https://jp.community.intersystems.com/node/476556
ObjectScript REST API クックブックREST API 開発のヒントhttps://community.intersystems.com/post/objectscript-rest-api-cookbook
永続クラスとシリアルクラスからSwaggerスペックを生成するContract First ApproachによるAPI開発https://jp.community.intersystems.com/node/490976
InterSystems IRIS REST アプリケーションのパターンIRISによるAPI RESTの作成https://community.intersystems.com/post/intersystems-iris-rest-application-patterns
SUSHIでFHIRプロファイルを作成しよう 第1回カスタムFHIRプロファイルの作成https://jp.community.intersystems.com/node/493351
ゼロから使いこなすIAMIAMでAPIの管理https://jp.community.intersystems.com/node/493416
InterSystems API Management を使用してAPIの負荷を分散するAPIMによるAPIのロードバランスhttps://jp.community.intersystems.com/node/482711
InterSystems API Management で OAuth 2.0 による API のセキュリティの確保 - 第1回APIMによるAPI のセキュリティの確保hhttps://jp.community.intersystems.com/node/497946
InterSystems IRISアプリケーションのAngular UIを5分で取得IRISとAngularによるFull Stackアプリhttps://community.intersystems.com/post/getting-angular-ui-your-intersystems-iris-application-5-minutes
InterSystems IRIS REST APIへのアップロードREST APIによるファイル保存https://community.intersystems.com/post/upload-intersystems-iris-rest-api

InterSystems 環境の管理と設定

IRIS環境を適切に管理・設定することは、ユーザーが使用するアプリケーションのパフォーマンス、セキュリティ、可用性、信頼性にとって不可欠です。これらの記事は、これを行うための優れたヒントを与えてくれるでしょう。

名称概要URL
InterSystemsデータプラットフォームにおける容量計画およびパフォーマンスのシリーズのインデックス性能とパフォーマンスの向上https://jp.community.intersystems.com/node/477596
InterSystems Cache での %Installer によるアプリケーションのデプロイメント%Installer によるネームスペース、データベース、およびアプリケーションの構成の作成https://jp.community.intersystems.com/node/478966
InterSystems IRISによる水平方向のスケーラビリティIRISインスタンスを設定し、水平方向のスケーラビリティの実現https://jp.community.intersystems.com/node/477591
Raspberry Pi Raspberry で動作する InterSystems Iris Fhirserver が FHIRserver として動作Raspberry PI内部でIRISの動作https://jp.community.intersystems.com/node/516361
バーチャルIPアドレスを使用しないデータベースミラーリングVIPによるミラーの設定https://jp.community.intersystems.com/node/493401
DockerによるApache Web GatewayWebアプリケーションのSSLとWeb Gatewayの設定https://jp.community.intersystems.com/node/542181
IRISにおけるSAMLとの連携Webサービス向けSAMLhttps://community.intersystems.com/post/work-saml-iris
SYSTEM.Encryption クラスの習得IRISによる暗号化・復号化https://jp.community.intersystems.com/node/523406

Docker と Cloud

新しいアプリケーション・アーキテクチャは、コンテナ Docker と Cloud において動作し、弾力的なスケーラビリティ、インストール、設定、プロビジョニング時間の短縮、インフラの複雑性とコストの削減を実現することを目的としています。これらの記事を読んで、IRISをクラウド化する方法を学んでください。

名称概要URL
Kubernetesにおけるミラーリングを使用しない高可用性IRISデプロイKubernetesによるIRISをクラウドクラスターで利用するhttps://jp.community.intersystems.com/node/490971
Amazon Web Services (AWS)のためのInterSystems IRISリファレンス・アーキテクチャAWSでのIRIShttps://jp.community.intersystems.com/node/481326
Microsoft Azure Resource Manager (ARM)のInterSystems製リファレンス・アーキテクチャ安価なマシン(ARM machine)を使ったAzureでのIRIShttps://jp.community.intersystems.com/node/478971
Dockerfileと仲間たち、またはInterSystems IRISでのObjectScriptプロジェクトの実行と共同作業の方法Dockerプロジェクトにおける重要なファイルについて知ることhttps://community.intersystems.com/post/dockerfile-and-friends-or-how-run-and-collaborate-objectscript-projects-intersystems-iris
CloudFormationテンプレートを使用したAWS向けInterSystems IRISデプロイメントガイドCloudFormationを使ったAWSで使うIRIShttps://jp.community.intersystems.com/node/486206
Google Cloud Platform(GCP) におけるInterSystems IRIS のリファレンス・アーキテクチャGoogle Cloudで使うIRIShttps://jp.community.intersystems.com/node/479806
InterSystems IRISでAWS Glueの使用IRISとAWS Glue(AWSのETLツール)の利用https://jp.community.intersystems.com/node/485971
AmazonのEKSとIRIS。高可用性とバックアップAWSによるHAで使うIRIShttps://jp.community.intersystems.com/node/501186 AWSによるHAでのIRIS
コンテナでの InterSystems レポートの動かしてみるDockerに関するIRISのレポートhttps://jp.community.intersystems.com/node/501656
InterSystems IRIS を Kubeless を使って FaaS モードで実行Kubernetesで使うIRIShttps://jp.community.intersystems.com/node/523446
InterSystems Kubernetes Operator Deep Dive ‐ Kubernetes Operatorの紹介Kubernetesで使うIRIShttps://community.intersystems.com/post/intersystems-kubernetes-operator-deep-dive-introduction-kubernetes-operators
クラウドホストのスケーリングとInterSystems IRISの再構築AWS、Azure、またはGCPでのIRISのスケーリングhttps://community.intersystems.com/post/scaling-cloud-hosts-and-reconfiguring-intersystems-iris
Amazon EKSを用いたシンプルなIRISベースのWebアプリケーションのデプロイメントAWSで使うIRIShttps://jp.community.intersystems.com/node/478961

VSCode

VSCodeは世界で最も使われているIDEの1つです。IRISはこのIDEをフルサポートしています。以下の記事をご覧ください。

名称概要URL
VSCode-ObjectScriptのGitHubでの使用Web Github VSCodeでIRISアプリの開発https://jp.community.intersystems.com/node/510736
IRISによるGitHubのコードスペースGithubでIRISアプリの開発https://jp.community.intersystems.com/node/510736
VSCodeのヒントとコツ - SOAPウィザードVSCodeにショートカットのオプションの作成https://community.intersystems.com/post/vscode-tips-tricks-soap-wizard
VS Codeへの独自のスニペットの追加スニペットの作成https://community.intersystems.com/post/adding-your-own-snippets-vs-code

SQL

SQLは、リレーショナルデータベースを扱うのに最もよく使われる言語の1つです。これらの記事は、クエリの実行方法とデータの永続性を示しています。

名称概要URL
フリーテキスト検索:SQL開発者が隠しているテキストフィールドの検索方法*インデックスの活用で高度な検索を促進https://jp.community.intersystems.com/node/479321
日付範囲クエリのSQLパフォーマンスの向上日付を使ったSQLクエリの実行https://jp.community.intersystems.com/node/479286
スタティックWHERE条件永続的なクラ使うWherehttps://community.intersystems.com/post/static-where-conditions
2021.2 SQL機能スポットライト - ランタイムプランの選択ランタイムSQL実行プランの選択https://jp.community.intersystems.com/node/510746
2020.1 の新機能:ユニバーサルクエリキャッシュSQL Cachehttps://jp.community.intersystems.com/node/535211
マテリアライズド・ビュー永続的なクラスの中にビューの作成https://community.intersystems.com/post/materialized-views
SQLを使ったデバッグのコツSQLコマンドのデバッグhttps://community.intersystems.com/post/debugging-trick-sql
ClassQueries()をテーブルとして使用ビューの作成https://community.intersystems.com/post/using-classqueries-tables
M:Nの関係N対Nの関係性のマッピングhttps://community.intersystems.com/post/mn-relationship
IRISでCOVIDにたいしてのAWS S3データをSQLテーブルとして読み込むAWS S3からCSVデータをIRISのテーブルに取得https://community.intersystems.com/post/reading-aws-s3-data-covid-sql-table-iris
知っておくと便利なクエリパフォーマンスのコツ - Tune TableSQLチューニングhttps://jp.community.intersystems.com/node/535211
データストレージ:開発がうまくいくために知っておくべき情報より高いパフォーマンスを得るために、データストレージ部を永続的なクラスで構成するhttps://community.intersystems.com/post/data-storage-information-you-must-know-make-good-decisions-when-developing
日付範囲クエリのSQLパフォーマンスを改善する vol2SQLクエリの日付に関するチューニングhttps://jp.community.intersystems.com/node/479291
スクロール可能なResultSetのページネーションのサンプルSQLの結果をページ分割する(コメントも参照)https://community.intersystems.com/post/scrollable-resultset-pagination-sample
1日目 InterSystems ObjectsとSQLを用いた開発InterSystems IRISへのSQLに関するコンセプトhttps://community.intersystems.com/post/day-1-developing-intersystems-objects-and-sql
SQLgatewayを利用したDBマイグレーションPostgreSQL、MySQL、その他のデータベースからIRISへのマイグレーションhttps://jp.community.intersystems.com/node/518861
InterSystems IRIS の既存のテーブルに CSV のインポートCSVからSQLテーブルへのインポートhttps://community.intersystems.com/post/importing-csv-existing-table-intersystems-iris
データベースの4つのAPISQLの APIhttps://community.intersystems.com/post/four-database-apis
アトミックでない属性のインデックス作成高度なインデックスのオプションの作成https://jp.community.intersystems.com/node/486236
インデックスについてインデックス作成の基礎知識https://jp.community.intersystems.com/node/492126
Dynamic SQLからDynamic ObjectへDynamicSQLの使用https://community.intersystems.com/post/dynamic-sql-dynamic-object
データ移行ツール - その1:PostgresからIRISへ一般的なデータベースからIRISデータベースへの移行方法を紹介する連載記事https://jp.community.intersystems.com/node/518871

アナリティクスとビジネスインテリジェンス(BI)

アナリティクスとBIは、グラフ、ダッシュボード、サマリー、詳細表などのデータ分析、およびアナリスト・ユーザーによるナビゲーションとデータ探索に基づいて意思決定を行うことを可能にします。ここでは、IRISを使った分析アプリケーションの構築方法を紹介します。

名称概要URL
InterSystems IRISのCOVID-19アナリティクスInterSystems IRISにおけるCOVID-19アナリティクスhttps://community.intersystems.com/post/covid-19-analytics-intersystems-iris
DeepSeeトラブルシューティングガイド不具合修正https://jp.community.intersystems.com/node/542206
AnalyzeThis - InterSystems BIへのクイックスタートInterSystems BIへのクイックスタートhttps://community.intersystems.com/post/analyzethis-%E2%80%93-quick-start-intersystems-bi
InterSystems IRIS用のPower BIコネクタ パート1Power BIでIRISのデータの利用https://jp.community.intersystems.com/node/482606
DeepSee でのポートレットの作成IRIS BIによるアナリティクスポートレットhttps://community.intersystems.com/post/creating-portlets-deepsee
Game Of Throne Analytics、またはアリア スタークリストの長さアナリティクスのサンプルhttps://community.intersystems.com/post/game-throne-analytics-or-how-long-aryas-stark-list
DeepSee Web。AngularJSによるInterSystems Analyticsのビジュアライゼーション。第 1 部Angularを使用するWebダッシュボードhttps://community.intersystems.com/post/deepsee-web-intersystems-analytics-visualization-angularjs-part-1
IRIS でアナリティクスソリューションを構築するIRISでアナリティクスを行うための主なオプションの紹介https://jp.community.intersystems.com/node/501571

グローバル

IRIS では、SQL、クラス、JSON ドキュメント、BI キューブ、その他のカスタム形式など、データを柔軟に保存および取得するための重要なメカニズムとして、グローバルが使用されています。以下の記事で、その方法を垣間見てください:

名称概要URL
グローバルをクラスにマッピングする技術 :1 / 3グローバルの SQL テーブルおよびオブジェクトへのマッピングhttps://jp.community.intersystems.com/node/486176
グローバルは、データ管理の魔法の剣。第1回グローバルに関する基礎知識https://jp.community.intersystems.com/node/476486
GlobalToJSON-embeddedPython-pureグローバルをJSONへの書き出しhttps://community.intersystems.com/post/globaltojson-embeddedpython-pure
InterSystems IRIS のグローバルを使ったトランザクショングローバルパーシスタンスのトランザクション管理https://jp.community.intersystems.com/node/486476
グローバルによる マインドマップの保存グローバルを使ってマインドマップデータの永続化https://jp.community.intersystems.com/node/516226

セキュリティ

どのようなアプリケーションでも、セキュリティを確保することは非常に重要です。セキュリティは、アクセスや承認の管理、トランザクションの追跡と監査、保存および転送されるコンテンツの暗号化、感性的なリソースの保護を保証するための正しい設定パラメータに関連しています。これらの記事を読んで、セキュリティを確立する方法について理解を深めてください。

名称概要URL
InterSystems IRIS Open Authorization Framework (OAuth 2.0) の実装 - 第1回OAuthの使用https://jp.community.intersystems.com/node/478821
WebのデバッグCSPおよびRESTアプリのデバッグhttps://jp.community.intersystems.com/node/501166
InterSystems IRIS のクラスクエリ永続クラス内部でのSQL Queryの定義https://jp.community.intersystems.com/node/483716
TLS/SSLでOSの証明書ストアの使用SSLを行うためにOSの証明書の使用https://community.intersystems.com/post/using-os-certificate-store-tlsssl
インテグリティチェック :スピードアップまたはスピードダウンインテグリティの確保https://community.intersystems.com/post/integrity-check-speeding-it-or-slowing-it-down
データ変更の追跡 - 監査ログ - 1 / 2監査データの保存https://jp.community.intersystems.com/node/483691
TLS/SSL/HTTPS による管理ポータル(プライベート Web サーバー)の運用IRIS Web サーバーへの SSL の設定https://community.intersystems.com/post/running-management-portal-private-web-server-over-tlssslhttps
OAuth認証とInterSystems IRIS:信頼プロトコルのテイム化OAuthの使用https://community.intersystems.com/post/oauth-https://jp.community.intersystems.com/node/493421
SOAP(Web)サービスでのOauth2の利用についてSOAPサービスにおけるOauthの設定https://jp.community.intersystems.com/node/483696
DeepSee: セキュリティの設定 - 1/5IRIS BIにおけるセキュリティhttps://community.intersystems.com/post/deepsee-setting-security-part-1-5
システムのセキュリティレベルの変更についてデフォルトでセキュリティhttps://community.intersystems.com/post/changes-security-level-system

DevOps

DevOpsとは、ソースコードの開発(Dev)から本番運用(Ops)への高速かつ高品質な移行を自動化することを可能にするプラクティスやツールを採用する方法です。IRISでその方法をご覧ください。

名称概要URL
GitLabを使ったInterSystemsソリューションの継続的デリバリー - 第1回:GitGitLabによる継続的デリバリーhttps://jp.community.intersystems.com/node/476396
InterSystems ObjectScripts パッケージ・マネージャの紹介ZPMを使用して、アプリケーション内のサードパーティパッケージを設定およびインストールhttps://jp.community.intersystems.com/node/486186
ZPMshow - 疲れた指のためのヘルパーZPM - IRISパッケージマネージャの使用方法https://community.intersystems.com/post/zpmshow-helper-tired-fingers
プログラムによるミラーのセットアップ方法新しいミラーの作成を自動化するhttps://jp.community.intersystems.com/node/516091
ObjectScript パッケージマネージャにおけるユニットテストとテストカバレッジObjectScriptのコード品質のためのUnit Testsの作成https://jp.community.intersystems.com/node/516111
DockerとMergeCPFを使ったシャードクラスターの展開cpfファイルによる設定の自動化https://community.intersystems.com/post/deploying-sharded-cluster-docker-and-mergecpf
Caché ObjectScript クイックリファレンスObjectScriptリファレンスpdfドキュメントhttps://community.intersystems.com/post/cach%C3%A9-objectscript-quick-reference
ZPMモジュールの解剖学:InterSystems Solution のパッケージングZPMを使用してデプロイメントの自動化https://jp.community.intersystems.com/node/487071
IRISコンテナへのVSCodeの追加VSCodeをdockerインスタンスに埋め込むhttps://community.intersystems.com/post/adding-vscode-your-iris-container
InterSystems IRIS用の新しいデータベース、ネームスペース、およびWebアプリケーションをプログラムによって作成する方法データベースとネームスペースの作成の自動化https://community.intersystems.com/post/how-create-new-database-namespace-and-web-application-intersystems-iris-programmatically
ユニットテスト: ObjectScript コードの品質ユニットテストによる品質保証https://community.intersystems.com/post/unit-tests-quality-your-objectscript-code
インターシステムズ開発者コミュニティのDockerイメージDockerコミュニティイメージhttps://community.intersystems.com/post/some-intersystems-developer-community-docker-images

インターオペラビリティ

IRISは、強力なデータおよびアプリケーションのインタラクティブなバスを備えています。以下の記事でその使い方をご覧ください。

名称概要URL
EnsembleからTelegramでアラートの送信テレグラムにデータを送信するためのプロダクションhttps://community.intersystems.com/post/sending-alerts-ensemble-telegram
[初めてのInterSystems IRIS] インターオペラビリティを使ってみようビジネスサービス、オペレーション、プロセス、プロダクションの作成https://jp.community.intersystems.com/node/483021
Embedded PythonによるInterSystems IRISのインターオペラビリティーPythonによるビジネスサービス、オペレーション、プロセス、プロダクションの作成https://jp.community.intersystems.com/node/518846
Ensemble / Interoperabilityトレーニングコースプロダクションの作り方を学ぶのに最適なサンプルhttps://community.intersystems.com/post/ensemble-interoperability-training-course
プログラムによるインターオペラビリティーのサンプルPythonまたはObjectScriptを使用したプログラムによるプロダクションhttps://jp.community.intersystems.com/node/521511
フォルダ内のファイルのリスティングフォルダー内のファイルをリスト化するhttps://community.intersystems.com/post/listing-files-folder
.Net/Java Gatewayのコンテナ化(またはKafka統合のデモ)Javaまたは.Net Native APIを使用したKafkaサポートhttps://jp.community.intersystems.com/node/542191
PEXを使用した.NETまたはJavaでのIRIS統合の実装PEXによるJavaまたは.Netを使ったプロダクションの作成https://community.intersystems.com/post/implementing-iris-integrations-net-or-java-using-pex
Java Business HostからPEXへの移行PEXの使用https://jp.community.intersystems.com/node/486231
Tesseract OCRとJava Gatewayの使用についてJava PEXの使用https://community.intersystems.com/post/using-tesseract-ocr-and-java-gateway
PEXのビジネスオペレーションを作成についてCreate Java PEX Business Operationhttps://community.intersystems.com/post/creating-pex-business-operation
OCRとNLPを統合したInterSystems IRISJava PEX のサンプルhttps://community.intersystems.com/post/ocr-and-nlp-together-intersystems-iris
HTTP Adapterを使用したカスタムインターオペラビリティビジネスサービスの作成ビジネスサービスの作成https://community.intersystems.com/post/creating-custom-interoperability-business-service-using-http-adapter

Native API

IRISは、市場で最も使用されているプログラミング言語(Java、Javascript/NodeJS、.Net、C++、Python)を使用することに前向きです。これを実現するために、これらの言語ごとにNative APIを使用しています。以下の記事をご覧ください。

名称概要URL
Docker Micro ServerとしてIRIS Native APIを使用したWebSocket Client JSIRISとNodeJSを使ってWebSocketを行うhttps://jp.community.intersystems.com/node/507846
ObjectScript用IRIS Native APINative APIの使用https://community.intersystems.com/post/iris-native-api-objectscript
Node.jsでのZPMの使用Node.jsプロジェクトでのZPMの使用https://jp.community.intersystems.com/node/507866
テキストファイルからPDFファイルの作成PDFファイルの生成用Java Native APIhttps://community.intersystems.com/post/creating-pdf-text-file
InterSystems IRISを使った開発を1分以内に始める方法IRISを使った開発の開始https://community.intersystems.com/post/how-start-development-intersystems-iris-less-minute
Python + IRIS Globals を使ったブログの作成Python Native API用ブログhttps://jp.community.intersystems.com/node/501856
0
2 245
質問 Yugi AA · 6月 30, 2023

VScodeを使用してローカルのルーチンを編集している途中で、PCが重かったため再起動を行って、 再びIRISを起動しようとするとエラーとなり起動できません。 どなたか解決策をご存知でしょうか?よろしくお願いいたします。

ーーーーーーーーーーーーー 現象: ローカルのIRISを起動すると、エラーとなり起動できない。

操作:

  1. PCを起動し、iris.exeで起動。
  2. InterSystems IRIS 開始(S)[IRIS] ボタンで起動を試みる。
  3. エラーメッセージが表示される。 irisstart.exe_err

詳細:

・接続先 IPアドレス: localhost ポート: 51773

・mgr/mesages.logのエラーログ

*** Recovery started at Sat Jul  1 08:35:25 2023
...略
07/01/23-08:35:36:165 (19356) 3 [Utility.Event] Error: ERROR #5001: Could not start SuperServer on port 51773, may be in use by another instance - Shutting down the system : $zu(56,2)=$Id: //iris/2022.1.0/kernel/common/src/acmd.c#1 $ 4561 183
07/01/23-08:35:41:208 (19356) 0 [Utility.Event] Shutting down InterSystems IRIS
07/01/23-08:35:41:224 (19356) 0 [Utility.Event] Notifying Clients
07/01/23-08:35:41:230 (19356) 0 [Utility.Event] No user shutdown routines to execute
07/01/23-08:35:41:238 (19356) 0 [Utility.Event] Stopping User Jobs
07/01/23-08:35:41:247 (19356) 0 [Utility.Event] Stopping Network Servers
07/01/23-08:35:41:255 (19356) 0 [Utility.Event] Withdrawing from License Domain

・Widowsのポート確認

C:\Users\hoge>netstat -ano | find ":5177"
C:\Users\hoge>
1
0 469
記事 Seisuke Nakahashi · 6月 29, 2023 1m read

BOMつきのUTF-8ファイルを、ObjectScriptで読むとき、どんなコードを書くべきでしょうか?
 

そんなときは、 %Stream.FileCharacter クラスを利用するのが便利です。

具体的な使い方は、以下のサンプルコードをごらんください。このAPIは、ファイルの文字コードを自動的に判断してくれるのが嬉しいです。そのため、読み込むファイルの文字コードが、BOMつきUTF-8、BOMつきUnicode、SJIS、どれであろうと、共通のコードで正しく日本語を取り扱ってくれます。

少しでもご参考になれば幸いです。
 

set f=##class(%Stream.FileCharacter).%New()
set f.Filename="c:\temp\abc.txt"setx=f.ReadLine()
zwx

 

 


参考記事: UTF-8のBOM付きのファイルを作成する方法

0
0 222
記事 Mihoko Iijima · 6月 6, 2023 5m read

これは InterSystems FAQ サイトの記事です。

ターミナルでルーチンやクラスのコンパイルを行う際、コンパイル結果が画面に表示されるのでエラーが発生した場合でも確認しやすいですが、一括コンパイルの場合は、大量のコンパイル結果の中にエラー情報が含まれてしまうためエラー情報だけを取得したい場合には少し工夫が必要です。

以下、ルーチン/クラスの一括コンパイル時の結果からエラー情報を取得する方法をご紹介します。

ルーチンの場合

ネームスペースにあるルーチンをターミナルで一括コンパイルするには、%Library.Routine クラスの CompileAll() メソッドを使用します。

以下実行例は、USERネームスペースにあるルーチンを一括コンパイルした結果です。TestRoutine1でコンパイルエラーが発生しています。

0
0 262