#Open Exchange

0 フォロワー · 94 投稿

 InterSystemsデータプラットフォームソリューションOpen Exchangeは、InterSystemsデータプラットフォーム(CachГ©、Ensemble、HealthShare、InterSystems IRIS、InterSystemsで開発されたソフトウェアソリューション、ツール、およびフレームワークのギャラリーです。 IRIS for Health)、またはInterSystems Data Platformで構築されたソリューションの開発、導入、サポートを支援することを目的としています。 公開されているアセットを使用するか、独自のツール、テクノロジーの例、ソリューションを公開できます。 Open Exchangeを体験してみましょう

記事 Toshihiko Minamoto · 10月 7, 2025 9m read

コミュニティの皆さん、こんにちは。
この記事では、私のアプリケーションである iris-AgenticAI をご紹介します。

エージェンティック AI の登場により、人工知能が世界とやりとりする方法に変革的な飛躍をもたらし、静的なレスポンスが動的な目標主導の問題解決にシフトしています。 OpenAI の Agentic SDK を搭載した OpenAI Agents SDK を使用すると、抽象化をほとんど行わずに軽量で使いやすいパッケージでエージェンティック AI アプリを構築できます。 これは Swarm という前回のエージェントの実験を本番対応にアップグレードしたものです。
このアプリケーションは、人間のような適応性で複雑なタスクの推論、コラボレーション、実行を行える次世代の自律 AI システムを紹介しています。

アプリケーションの機能

  • エージェントループ  🔄 ツールの実行を自律的に管理し、結果を LLM に送信して、タスクが完了するまで反復処理するビルトインのループ。
  • Python-First 🐍 ネイティブの Python 構文(デコレーター、ジェネレーターなど)を利用して、外部の DSL を使用せずにエージェントのオーケストレーションとチェーンを行います。
  • ハンドオフ 🤝 専門化されたエージェント間でタスクを委任することで、マルチエージェントワークフローをシームレスに調整します。
  • 関数ツール ⚒️ @tool で Python 関数をデコレートすることで、エージェントのツールキットに即座に統合させます。
  • ベクトル検索(RAG) 🧠 RAG 検索のためのベクトルストアのネイティブ統合。
  • トレース 🔍 リアルタイムでエージェントワークフローの可視化、デバッグ、監視を行うためのビルトインのトレース機能(LangSmith の代替サービスとして考えられます)。
  • MCP サーバー 🌐 stdio と HTTP によるモデルコンテキストプロトコル(MCP)で、クロスプロセスエージェント通信を可能にします。
  • Chainlit UI 🖥️ 最小限のコードで対話型チャットインターフェースを構築するための統合 Chainlit フレームワーク。
  • ステートフルメモリ 🧠 継続性を実現し、長時間実行するタスクに対応するために、セッション間でチャット履歴、コンテキスト、およびエージェントの状態を保持します。

エージェント

エージェントは、アプリの主要な構成要素です。 エージェントは大規模言語モデル(LLM)で、instructions と tools で構成されています。 基本的な構成 以下は、構成されるエージェントの最も一般的なプロパティです。

Instructions: 開発者メッセージまたはシステムプロンプトとも呼ば出る指示。
model: LLM が使用するモデル。オプションとして model_settings を使用して、temperature や top_p など、モデルのチューニングパラメーターを構成できます。
tools: タスクを達成するためにエージェントが使用できるツール。

from agents import Agent, ModelSettings, function_tool

@function_tooldefget_weather(city: str) -> str:returnf"The weather in {city} is sunny"
agent = Agent(
    name="Haiku agent",
    instructions="Always respond in haiku form",
    model="o3-mini",
    tools=[get_weather],
)

エージェントの実行

Runner クラスを使ってエージェントを実行できます。 これには 3 つのオプションがあります。

  1. Runner.run(): 非同期で実行し、RunResult を返します。
  2. Runner.run_sync(): 非同期メソッドで、内部で .run() を実行します。
  3. Runner.run_streamed(): 非同期で実行し、RunResultStreaming を返します。 ストリーミングモードで LLM を呼び出し、イベントを受け取るたびにユーザーにストリーミングします。
from agents import Agent, Runner

asyncdefmain(): agent = Agent(name="Assistant", instructions="You are a helpful assistant")

result = <span class="hljs-keyword">await</span> Runner.run(agent, <span class="hljs-string">"Write a haiku about recursion in programming."</span>)
print(result.final_output)
<span class="hljs-comment"># Code within the code,</span>
<span class="hljs-comment"># Functions calling themselves,</span>
<span class="hljs-comment"># Infinite loop's dance.</span></code></pre>


エージェントアーキテクチャ

アプリケーションは 7 つの専門化されたエージェントで構成されています。

  1. Triage エージェント 🤖
    • 機能: ユーザー入力を受け取り、ハンドオフでタスクを委任する主要ルーター
    • : 「Show production errors(プロダクションエラーを表示)」は IRIS プロダクションエージェントに転送されます。
  2. ベクトル検索エージェント 🤖
    • 機能: IRIS 2025.1 リリースノートの内容を提供します(RAG 機能)
    • : 「Provide me summary of Release Notes(リリースノートの要約を提供)」はベクトル検索エージェントに転送されます。
  3. IRIS Dashboard エージェント 🤖
    • 機能: リアルタイムの管理ポータルメトリクスを提供します: plaintext Copy
      ApplicationErrors, CSPSessions, CacheEfficiency, DatabaseSpace, DiskReads,  
      DiskWrites, ECPAppServer, ECPDataServer, GloRefs, JournalStatus,  
      LicenseCurrent, LockTable, Processes, SystemUpTime, WriteDaemon, [...]
  4. IRIS 実行プロセスエージェント 🤖
    • 機能: アクティブなプロセスを次の詳細とともに監視します。
      • Process ID | Namespace | Routine | State | PidExternal
  5. IRIS Production エージェント 🤖
    • 機能: プロダクションの開始と停止の機能とともにプロダクションの詳細を提供します。
  6. WebSearch エージェント 🤖
    • 機能: API 統合によりコンテキストウェブ検索を実行します。
  7. Order エージェント 🤖
    • 機能: 注文 ID を使用して注文のステータスを取得します。


ハンドオフ

ハンドオフによって、タスクを別のエージェントに委任することができます。 これは特に、それぞれのエージェントが異なる分野に特化している場合に役立ちます。 たとえば、カスタマーサポートアプリには、注文ステータス、返金、FAQ などのそれぞれのタスクを専門的に処理するエージェントが実装されている場合があります。

Triage エージェントはこのアプリケーションのメインエージェントで、ユーザー入力に基づいて別のエージェントにタスクを委任するエージェントです。

#TRIAGE AGENT, Main agent receives user input and delegates to other agent by using handoffs
    triage_agent = Agent(
        name="Triage agent",
        instructions=(
            "Handoff to appropriate agent based on user query.""if they ask about Release Notes, handoff to the vector_search_agent.""If they ask about production, handoff to the production agent.""If they ask about dashboard, handoff to the dashboard agent.""If they ask about process, handoff to the processes agent.""use the WebSearchAgent tool to find information related to the user's query and do not use this agent is query is about Release Notes.""If they ask about order, handoff to the order_agent."
        ),
        handoffs=[vector_search_agent,production_agent,dashboard_agent,processes_agent,order_agent,web_search_agent]
    )


トレース

Agents SDK には、トレース機能が組み込まれており、エージェントの実行中にLLM の生成、ツールの呼び出し、ハンドオフ、ガードレール、カスタムイベントの発生など、イベントの包括的な記録を収集できます。 Traces ダッシュボードを使用すると、開発中と本番稼動時にワークフローのデバッグ、可視化、監視を行えます。
https://platform.openai.com/logs

image

 


アプリケーションのインターフェース

アプリケーションのワークフロープロセス
ベクトル検索エージェント

ベクトル検索エージェントは、「New in InterSystems IRIS 2025.1」のテキスト情報のデータがまだ存在しない場合に、そのデータを一度だけ自動的に IRIS Vector Store に取り込みます。  


以下のクエリを使用してデータを検索しましょう

SELECTid, embedding, document, metadata
FROM SQLUser.AgenticAIRAG

Triage エージェントはユーザー入力を受け取って、質問をベクトル検索エージェントに転送します。

IRIS Dashboard エージェント

Triage エージェントはユーザー入力を受け取って、質問を IRIS Dashboard エージェントに転送します。

IRIS Processes エージェント

Triage エージェントはユーザー入力を受け取って、質問を IRIS Processes エージェントに転送します。

IRIS Production エージェント

Production エージェントを使用して、プロダクションの開始と停止を行います。

Production エージェントを使用して、プロダクションの詳細を取得します。

Local エージェント

Triage エLocal ージェントはユーザー入力を受け取って、質問を Local Order エージェントに転送します。

WebSearch エージェント

ここでは、Triage エージェントは 2 つの質問を受け取って、WebSearch エージェントに転送します。

MCP Server アプリケーション

MCP Server は https://localhost:8000/sse で実行しています。

image
以下のコードで MCP Server を起動しています。

import os
import shutil
import subprocess
import time
from typing import Any
from dotenv import load_dotenv

load_dotenv()

#Get OPENAI Key, if not fond in .env then get the GEIMINI API KEY#IF Both defined then take OPENAI Key openai_api_key = os.getenv("OPENAI_API_KEY") ifnot openai_api_key: raise ValueError("OPENAI_API_KEY is not set. Please ensure to defined in .env file.")

ifname == "main": # Let's make sure the user has uv installedifnot shutil.which("uv"): raise RuntimeError( "uv is not installed. Please install it: https://docs.astral.sh/uv/getting-started/installation/" )

<span class="hljs-comment"># We'll run the SSE server in a subprocess. Usually this would be a remote server, but for this</span>
<span class="hljs-comment"># demo, we'll run it locally at http://localhost:8000/sse</span>
process: subprocess.Popen[Any] | <span class="hljs-keyword">None</span> = <span class="hljs-keyword">None</span>
<span class="hljs-keyword">try</span>:
    this_dir = os.path.dirname(os.path.abspath(__file__))
    server_file = os.path.join(this_dir, <span class="hljs-string">"MCPserver.py"</span>)

    print(<span class="hljs-string">"Starting SSE server at http://localhost:8000/sse ..."</span>)

    <span class="hljs-comment"># Run `uv run server.py` to start the SSE server</span>
    process = subprocess.Popen([<span class="hljs-string">"uv"</span>, <span class="hljs-string">"run"</span>, server_file])
    <span class="hljs-comment"># Give it 3 seconds to start</span>
    time.sleep(<span class="hljs-number">3</span>)

    print(<span class="hljs-string">"SSE server started. Running example...\n\n"</span>)
<span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
    print(<span class="hljs-string">f"Error starting SSE server: <span class="hljs-subst">{e}</span>"</span>)
    exit(<span class="hljs-number">1</span>)

 

MCP Server には次のツールが備わっています。

  • IRIS 2025.1 リリースノートの詳細を提供(ベクトル検索)
  • IRIS 情報ツール
  • 天気チェックツール
  • シークレットワードの検索ツール(ローカル関数)
  • 加算ツール(ローカル関数)

MCP アプリケーションは  http://localhost:8001で実行しています。

 

MCP Server ベクトル検索(RAG)機能

MCP Server には InterSystems IRIS ベクトル検索インジェスト機能と検索拡張生成(RAG)機能が備わっています。


MCP Server の他の機能

MCP Server は、ユーザー入力に基づいて、適切なツールに動的にタスクを委任します。


詳細については、iris-AgenticAI の Open Exchange アプリケーションページをご覧ください。

以上です

0
0 26
記事 Toshihiko Minamoto · 10月 1, 2025 6m read

コミュニティの皆さん、こんにちは。
従来のキーワードベースの検索では、ニュアンスのあるドメイン固有のクエリには対応できません。 ベクトル検索であれば、セマンティック認識を利用して、キーワードだけでなくコンテキストにも基づいたレスポンスを AI エージェントで検索して生成することができます。
この記事では、エージェンティック AI RAG(検索拡張生成)アプリケーションを作成手順を紹介します。

実装手順:

  1. エージェントツールを作成する
    • インジェスト機能の追加: ドキュメント(例: InterSystems IRIS 2025.1 リリースノート)を自動的にインジェストしてインデックス作成を行います。
    • ベクトル検索機能の実装
  2. ベクトル検索エージェントを作成する
  3. Triage(メインエージェント)に渡す
  4. エージェントを実行する

1. エージェントツールを作成する
1.1 - 
ドキュメントの取り込みを実装します。ドキュメントの取り込みとインデックス作成を自動化します。

インジェストツールは以下のコードで実装します。

defingestDoc(self):#Check if document is defined, by selecting from table#If not defined then INGEST document, Otherwise back
        embeddings = OpenAIEmbeddings()	
        #Load the document based on the fle type
        loader = TextLoader("/irisdev/app/docs/IRIS2025-1-Release-Notes.txt", encoding='utf-8')      
    documents = loader.load()        
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=<span class="hljs-number">400</span>, chunk_overlap=<span class="hljs-number">0</span>)
    
    texts = text_splitter.split_documents(documents)
                   
    <span class="hljs-comment">#COLLECTION_NAME = "rag_document"</span>
    db = IRISVector.from_documents(
        embedding=embeddings,
        documents=texts,
        collection_name = self.COLLECTION_NAME,
        connection_string=self.CONNECTION_STRING,
    )

    db = IRISVector.from_documents(embedding=embeddings,documents=texts, collection_name = self.COLLECTION_NAME, connection_string=self.CONNECTION_STRING,)</code></pre>

ベクトル検索エージェントは、指定されたリポジトリフォルダから「New in InterSystems IRIS 2025.1」を IRIS Vector Store に自動的に取り込んでインデックスを作成します。この操作はそのデータがまだ存在しない場合にのみ実行されます。


以下のクエリを実行して、ベクトルストアから必要なデータを取得します。

SELECTid, embedding, document, metadata
FROM SQLUser.AgenticAIRAG


1.2 - ベクトル検索機能の実装
以下のコードはエージェントの検索機能を実装します。

defragSearch(self,prompt):#Check if collections are defined or ingested done.# if not then call ingest method
        embeddings = OpenAIEmbeddings()	
        db2 = IRISVector (
            embedding_function=embeddings,    
            collection_name=self.COLLECTION_NAME,
            connection_string=self.CONNECTION_STRING,
        )
        docs_with_score = db2.similarity_search_with_score(prompt)
        relevant_docs = ["".join(str(doc.page_content)) + " "for doc, _ in docs_with_score]
    <span class="hljs-comment">#Generate Template</span>
    template = <span class="hljs-string">f"""
    Prompt: <span class="hljs-subst">{prompt}</span>
    Relevant Docuemnts: <span class="hljs-subst">{relevant_docs}</span>
    """</span>
    <span class="hljs-keyword">return</span> template</code></pre>


Triage エージェントは、受信したユーザークエリを処理し、それを Vector Search Agent に委任します。このエージェントは、セマンティック検索を実行して、最も関連性の高い情報を取得します。


2 - ベクトルストアエージェントを作成する

以下のコードは、以下の要素を含む vector_search_agent を実装します。

  • エージェントを調整するためのカスタム handoff_descriptions
  • 明確な演算 instructions
  • iris_RAG_search ツール(ドキュメントの取り込みとベクトル検索操作に irisRAG.py を使用)
@function_tool    @cl.step(name = "Vector Search Agent (RAG)", type="tool", show_input = False)asyncdefiris_RAG_search():"""Provide IRIS Release Notes details,IRIS 2025.1 Release Notes, IRIS Latest Release Notes, Release Notes"""ifnot ragOprRef.check_VS_Table():
                 #Ingest the document first
                 msg = cl.user_session.get("ragclmsg")
                 msg.content = "Ingesting Vector Data..."await msg.update()
                 ragOprRef.ingestDoc()
        <span class="hljs-keyword">if</span> ragOprRef.check_VS_Table():
             msg = cl.user_session.get(<span class="hljs-string">"ragclmsg"</span>)
             msg.content = <span class="hljs-string">"Searching Vector Data..."</span>
             <span class="hljs-keyword">await</span> msg.update()                 
             <span class="hljs-keyword">return</span> ragOprRef.ragSearch(cl.user_session.get(<span class="hljs-string">"ragmsg"</span>))   
        <span class="hljs-keyword">else</span>:
             <span class="hljs-keyword">return</span> <span class="hljs-string">"Error while getting RAG data"</span>
vector_search_agent = Agent(
        name=<span class="hljs-string">"RAGAgent"</span>,
        handoff_description=<span class="hljs-string">"Specialist agent for Release Notes"</span>,
        instructions=<span class="hljs-string">"You provide assistance with Release Notes. Explain important events and context clearly."</span>,
        tools=[iris_RAG_search]
)</code></pre>


3 - Triage(メインエージェント)に渡す
以下のコードは、処理済みのクエリを Triage エージェント(メインコーディネーター)に渡すためのハンドオフプロトコルを実装します。

 triage_agent = Agent(
        name="Triage agent",
        instructions=(
            "Handoff to appropriate agent based on user query.""if they ask about Release Notes, handoff to the vector_search_agent.""If they ask about production, handoff to the production agent.""If they ask about dashboard, handoff to the dashboard agent.""If they ask about process, handoff to the processes agent.""use the WebSearchAgent tool to find information related to the user's query and do not use this agent is query is about Release Notes.""If they ask about order, handoff to the order_agent."
        ),
        handoffs=[vector_search_agent,production_agent,dashboard_agent,processes_agent,order_agent,web_search_agent]
    )


4 - エージェントを実行する

以下のコードは次の内容を実行します。

  1. ユーザー入力を受け取る
  2. triage_agent  を呼び出す
  3. クエリを Vector_Search_Agent に送信して処理する
@cl.on_message
async def main(message: cl.Message):
    """Process incoming messages and generate responses."""
    # Send a thinking message
    msg = cl.Message(content="Thinking...")
    await msg.send()
agent: Agent = cast(Agent, cl.user_session.get(<span class="hljs-string">"agent"</span>))
config: RunConfig = cast(RunConfig, cl.user_session.get(<span class="hljs-string">"config"</span>))

# Retrieve the chat history from the session.
history = cl.user_session.get(<span class="hljs-string">"chat_history"</span>) or []

# Append the user'<span class="hljs-keyword">s</span> message to the history.
history.append({<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: message.content})

# Used by RAG agent
cl.user_session.<span class="hljs-keyword">set</span>(<span class="hljs-string">"ragmsg"</span>, message.content)
cl.user_session.<span class="hljs-keyword">set</span>(<span class="hljs-string">"ragclmsg"</span>, msg)

<span class="hljs-keyword">try</span>:
    <span class="hljs-keyword">print</span>(<span class="hljs-string">"\n[CALLING_AGENT_WITH_CONTEXT]\n"</span>, history, <span class="hljs-string">"\n"</span>)
    result = Runner.run_sync(agent, history, run_config=config)
           
    response_content = result.final_output
    
    # Update the thinking message with the actual response
    msg.content = response_content
    await msg.update()

    # Append the assistant'<span class="hljs-keyword">s</span> response to the history.
    history.append({<span class="hljs-string">"role"</span>: <span class="hljs-string">"developer"</span>, <span class="hljs-string">"content"</span>: response_content})
    # NOTE: Here we are appending the response to the history <span class="hljs-keyword">as</span> a developer message.
    # This is a BUG in the agents library.
    # The expected behavior is to append the response to the history <span class="hljs-keyword">as</span> an assistant message.

    # Update the session with the <span class="hljs-keyword">new</span> history.
    cl.user_session.<span class="hljs-keyword">set</span>(<span class="hljs-string">"chat_history"</span>, history)
    
    # Optional: Log the interaction
    <span class="hljs-keyword">print</span>(f<span class="hljs-string">"User: {message.content}"</span>)
    <span class="hljs-keyword">print</span>(f<span class="hljs-string">"Assistant: {response_content}"</span>)
    
except Exception <span class="hljs-keyword">as</span> e:
    msg.content = f<span class="hljs-string">"Error: {str(e)}"</span>
    await msg.update()
    <span class="hljs-keyword">print</span>(f<span class="hljs-string">"Error: {str(e)}"</span>)</code></pre>


実際の動作をご覧ください

詳細については、iris-AgenticAI の Open Excahnge アプリケーションページをご覧ください。
以上です

0
0 17
記事 Toshihiko Minamoto · 5月 16, 2025 4m read
OwnObjectScriptExtensionLogo

OwnObjectScriptExtension

ObjectScript は InterSystems IRIS などの InterSystems 製品に使用されている強力な言語で、堅牢なアプリケーションの構築を可能にします。 OwnObjectScriptExtension は Visual Studio Code の拡張機能として、ObjectScript 開発エクスペリエンスを強化する広範なツールと機能を提供しています。 この記事では、OwnObjectScriptExtension によって ObjectScript 開発ワークフローがどのように改善されるかを説明します。


機能

Add Method Description

メソッドの説明を包括的に記述することは、コードを明確に維持し、コラボレーションを促進する上で欠かせません。 OwnObjectScriptExtension を使用すると、メソッドの説明を簡単に生成できます。 メソッド内にカーソルを配置し、Add Method Description コマンドを実行するだけで完了です。 拡張機能によってメソッドの説明テンプレートが自動的に生成されるため、意味のあるドキュメントを簡単に提供できます。

Make Select Statement

ObjectScript を使用する際は、データベースの操作が必要となることがよくあります。 Make Select Statement 機能を使用すると、SQL の SELECT ステートメントを生成するプロセスを単純化できます。 この拡張機能は、現在開いている ObjectScript ファイルを分析することで、クラス名に基づく SELECT ステートメントを作成します。 SQLTools 拡張機能がインストール済みである場合は、生成されたステートメントを直接 Visual Studio Code 内で実行できます。

Create New Wizard ベータ

`Create New Wizard` 機能を使用すると、新しい ObjectScript クラス、メッセージ、ビジネスサービス、またはビジネスオペレーションの作成がより便利になります。 新しいコンポーネントの生成プロセスは、使い慣れた InterSystems Studio ウィザード似たウィザード形式のインターフェースによって誘導されます。 コマンドを実行して指示に従うと、新しい ObjectScript を素早くセットアップできるため、時間と労力を節約できます。
  • この機能は現在ベータであり、期待どおりに動作しない場合があります。 生成されたコードを調整する必要がある場合があります。*

Translate Embedded Python ベータ

特定のシナリオでは、ObjectScript コード内で Python の力を利用したい場合があります。 `Translate Embedded Python` 機能を使用すると、ObejctScript メソッドを Embedded Python メソッドに変換することができます。 このコマンドを実行すると、拡張機能によって、_py_ のプレフィックスとともに同じ名前で新しいメソッドが生成されます。 このため、コードベースの構造と編成を維持したまま、Python 機能を統合することができます。
  • この機能は現在ベータであり、期待どおりに動作しない場合があります。 生成されたコードを調整する必要がある場合があります。*

インストールとセットアップ

OwnObjectScriptExtension を利用し始めるには、Visual Studio Code Marketplace から直接インストールするか、GitHub から最新リリースをダウンロードできます。 インストールが完了したら、InterSystems ObjectScript 拡張機能がインストールされていることを確認してください。


構成とカスタマイズ

この拡張機能には、ユーザーの環境に合わせて使用できる様々な構成オプションが提供されています。 また、InterSystems Real Dark の色テーマが提供されているため、Visual Studio Code の視覚的なエクスペリエンスを強化できます。


ご質問やフィードバックがございましたら、お気軽にご連絡ください。 拡張機能を活用できますように!

0
0 64
記事 Akio Hashimoto · 12月 22, 2024 2m read

​ UDL形式でのインポート・エクスポートが出来ない古いCahceバージョンのソースを保守していたり、古くからのバージョン管理下においてXMLでのバージョン管理を行っている環境であったりと、未だにXMLでのエクスポート・インポートが必要になる場面はまれにあるかと思います。 今回、そういった環境下でもわざわざ管理ポータルを開かずとも、VSCodeでXML形式でエクスポートする拡張機能をリリースしましたので、共有させて頂きます。

機能について

編集画面、あるいは、VSCodeのエクスプローラータブ内からクラスを選択し、コンテキストメニューの「XML形式でエクスポート」を実行します。

image

image

XMLファイルは所定の場所に保存されます。保存先は設定で指定が出来ます。

複数のクラスを選択した場合、初期値では1対1でXMLファイルが保存されます。

image  

設定を変更する事で、1つのXMLファイルとして保存する事も可能です。

image  

利用方法

  1. 拡張機能の検索窓から"ObjectScript To XML"を検索し、インストールします。

image

  1. READMEに記載されているソースをダウンロードし、IRISへインポートします。

  2. ウェブ・アプリケーションを作成します。

  3. 必要な場合、拡張機能の設定値を変更します。

image   

"objectscript-to-xml": {
    "applicationName": "/exml-api",
    "exportDir": "exports",
    "bundled": false
}
  • applicationNameに作成したウェブ・アプリケーションの名前を指定します。

  • exportDirにはエクスポートしたXMLファイルの配置先を指定します。

  • bundledがtrueの場合は、1つのXMLファイルとしてエクスポートされます。既定値はfalseです。

0
0 198
記事 Toshihiko Minamoto · 11月 21, 2024 6m read

image
コミュニティの皆さん、こんにちは。
この記事では、iris-RAG-Gen という私のアプリケーションをご紹介します。

iris-RAG-Gen は、IRIS Vector Search の機能を使用して、Streamlit ウェブフレームワーク、LangChain、および OpenAI で ChatGPT をパーソナライズするジェネレーティブ AI 検索拡張生成(RAG: Retrieval-Augmented Generation)アプリケーションです。 このアプリケーションは IRIS をベクトルストアとして使用します。
image

アプリケーションの機能

  • ドキュメント(PDF または TXT)を IRIS に取り込む
  • 選択されたドキュメントの取り込みを使ってチャットする
  • ドキュメントの取り込みを削除する
  • OpenAI ChatGPT

ドキュメント(PDF または TXT)を IRIS に取り込む

以下の手順に従って、ドキュメントを取り込みます。

  • OpenAI キーを入力します。
  • ドキュメント(PDF または TXT)を選択します。
  • ドキュメントの説明を入力します。
  • 「Ingest Document」ボタンをクリックします。

image
 

ドキュメントの取り込み機能は、ドキュメントの詳細を rag_documents テーブルに挿入し、ベクトルデータを保存する 'rag_document + id'(rag_documents の ID)テーブルを作成します。

image

以下の Python コードは選択されたドキュメントをベクトルに保存します。

from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.document_loaders import PyPDFLoader, TextLoader
from langchain_iris import IRISVector
from langchain_openai import OpenAIEmbeddings
from sqlalchemy import create_engine,text

classRagOpr:#Ingest document. Parametres contains file path, description and file type defingestDoc(self,filePath,fileDesc,fileType): embeddings = OpenAIEmbeddings() #Load the document based on the file typeif fileType == "text/plain": loader = TextLoader(filePath)
elif fileType == "application/pdf": loader = PyPDFLoader(filePath)

    <span class="hljs-comment">#load data into documents</span>
    documents = loader.load()        
    
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=<span class="hljs-number">400</span>, chunk_overlap=<span class="hljs-number">0</span>)
    <span class="hljs-comment">#Split text into chunks</span>
    texts = text_splitter.split_documents(documents)
    
    <span class="hljs-comment">#Get collection Name from rag_doucments table. </span>
    COLLECTION_NAME = self.get_collection_name(fileDesc,fileType)
           
    <span class="hljs-comment"># function to create collection_name table and store vector data in it.</span>
    db = IRISVector.from_documents(
        embedding=embeddings,
        documents=texts,
        collection_name = COLLECTION_NAME,
        connection_string=self.CONNECTION_STRING,
    )

<span class="hljs-comment">#Get collection name</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_collection_name</span><span class="hljs-params">(self,fileDesc,fileType)</span>:</span>
    <span class="hljs-comment"># check if rag_documents table exists, if not then create it </span>
    <span class="hljs-keyword">with</span> self.engine.connect() <span class="hljs-keyword">as</span> conn:
        <span class="hljs-keyword">with</span> conn.begin():     
            sql = text(<span class="hljs-string">"""
                SELECT *
                FROM INFORMATION_SCHEMA.TABLES
                WHERE TABLE_SCHEMA = 'SQLUser'
                AND TABLE_NAME = 'rag_documents';
                """</span>)
            result = []
            <span class="hljs-keyword">try</span>:
                result = conn.execute(sql).fetchall()
            <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> err:
                print(<span class="hljs-string">"An exception occurred:"</span>, err)               
                <span class="hljs-keyword">return</span> <span class="hljs-string">''</span>
            <span class="hljs-comment">#if table is not created, then create rag_documents table first</span>
            <span class="hljs-keyword">if</span> len(result) == <span class="hljs-number">0</span>:
                sql = text(<span class="hljs-string">"""
                    CREATE TABLE rag_documents (
                    description VARCHAR(255),
                    docType VARCHAR(50) )
                    """</span>)
                <span class="hljs-keyword">try</span>:    
                    result = conn.execute(sql) 
                <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> err:
                    print(<span class="hljs-string">"An exception occurred:"</span>, err)                
                    <span class="hljs-keyword">return</span> <span class="hljs-string">''</span>
    <span class="hljs-comment">#Insert description value </span>
    <span class="hljs-keyword">with</span> self.engine.connect() <span class="hljs-keyword">as</span> conn:
        <span class="hljs-keyword">with</span> conn.begin():     
            sql = text(<span class="hljs-string">"""
                INSERT INTO rag_documents 
                (description,docType) 
                VALUES (:desc,:ftype)
                """</span>)
            <span class="hljs-keyword">try</span>:    
                result = conn.execute(sql, {<span class="hljs-string">'desc'</span>:fileDesc,<span class="hljs-string">'ftype'</span>:fileType})
            <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> err:
                print(<span class="hljs-string">"An exception occurred:"</span>, err)                
                <span class="hljs-keyword">return</span> <span class="hljs-string">''</span>
            <span class="hljs-comment">#select ID of last inserted record</span>
            sql = text(<span class="hljs-string">"""
                SELECT LAST_IDENTITY()
            """</span>)
            <span class="hljs-keyword">try</span>:
                result = conn.execute(sql).fetchall()
            <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> err:
                print(<span class="hljs-string">"An exception occurred:"</span>, err)
                <span class="hljs-keyword">return</span> <span class="hljs-string">''</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">"rag_document"</span>+str(result[<span class="hljs-number">0</span>][<span class="hljs-number">0</span>])</code></pre>

 

管理ポータルで以下の SQL コマンドを入力し、ベクトルデータを取得します。

SELECT top 5id, embedding, document, metadata
FROM SQLUser.rag_document2

image

 

選択されたドキュメントの取り込みを使ってチャットする

チャットオプションの選択セクションから「Document」を選択して質問を入力します。アプリケーションはベクトルデータを読み取り、関連する回答を返します。
image
以下の Python コードは、選択されたドキュメントをべく鳥に保存します。

from langchain_iris import IRISVector
from langchain_openai import OpenAIEmbeddings,ChatOpenAI
from langchain.chains import ConversationChain
from langchain.chains.conversation.memory import ConversationSummaryMemory
from langchain.chat_models import ChatOpenAI

classRagOpr:defragSearch(self,prompt,id):#Concat document id with rag_doucment to get the collection name COLLECTION_NAME = "rag_document"+str(id) embeddings = OpenAIEmbeddings() #Get vector store reference db2 = IRISVector ( embedding_function=embeddings,
collection_name=COLLECTION_NAME, connection_string=self.CONNECTION_STRING, ) #Similarity search docs_with_score = db2.similarity_search_with_score(prompt) #Prepair the retrieved documents to pass to LLM relevant_docs = ["".join(str(doc.page_content)) + " "for doc, _ in docs_with_score] #init LLM llm = ChatOpenAI( temperature=0,
model_name="gpt-3.5-turbo" ) #manage and handle LangChain multi-turn conversations conversation_sum = ConversationChain( llm=llm, memory= ConversationSummaryMemory(llm=llm), verbose=False ) #Create prompt template = f""" Prompt: {prompt} Relevant Docuemnts: {relevant_docs} """#Return the answer resp = conversation_sum(template) return resp['response']

</code></pre>


詳細については、iris-RAG-Gen の Open Exchange アプリケーションページをご覧ください。

よろしくお願いします。

0
0 66
お知らせ Toshihiko Minamoto · 11月 20, 2024

ほとんどの方が @Daniel TamajonCachéQuality プロジェクトをご存知かと思います。 まだご存知でない方のために説明すると、InterSystems 製品用に記述されたコードの静的構文アナライザーです。 コード内の様々な種類の問題や潜在的なバグがお客様のプロダクション環境で見つかる前に、それらを検出して解決するのに役立てられます。 つまり、CachéQuality を使用することで、より優れた製品を提供できるようになります。 ObjectScript コードのチェックに使用されるルールの完全なリストは、こちらをご覧ください。

これは Studio ですでに提供されているものですが、 VSCode でも使用できるようになりました。

インストール

VSCode の拡張機能セクションで、「cachequality」を検索し、SonarLint for CachéQuality をインストールします。より優れたエクスペリエンスを得るには、先に VSCode for ObjectScript をインストールしてください。 いずれの拡張機能も、「objectscript」の検索で見つかります。

この拡張機能をインストールした時点から、構成を行わずに使用し始めることができ、クラスを開くと、検出されるすべての問題が下線表示されるようになります。

下線表示にマウスポインターを合わせると、詳細を表示できます。

また、直接 VSCode で問題の詳細を開くこともできます。

VSCode には問題ビューが備わっており、Cmd+Shift+M ホットキーで有効にできます。このビューには、開いているソースファイルで検出された問題のリストが表示されます。 CacheQuality が検出した問題のリストを確認し、実際の場所に移動できます。

修正された行は保存後に再チェックされます

ただし、制限があります。 ルールのリストと、ルールに関連する他のいくつかのパラメーターを制御できません。 拡張機能は、デフォルト値による事前構成済みで提供されます。 さらに制御が必要な場合は、コネクテッドモードを使用できます。

コネクテッドモード

この拡張機能には、コネクテッドというモードも備わっています。 このモードでは、SonarQube サーバーをインストール済みの CacheQuality プラグインに接続できます。

SonarQube を使って、ルールのリストをカスタマイズできます。 ルールのパラメーターを無効化または有効化し、変更できます。 たとえば、`To method has too many lines` ルールはデフォルトで 50 行以降にトリガーされますが、この数値を変更することができます。

SonarQube Server がある場合は、まず、プロジェクト全体を解析する必要があります。 これには様々な方法があり、詳細は SonarQube ドキュメントに記載されています。 また、VSCode からプロジェクトにアクセスするにはトークンが必要です。

VSCode 設定の変更

    "sonarlint.connectedMode.project": {
        "projectKey": "Samples",
        "serverId": "local"
    },
    "sonarlint.connectedMode.servers": [
        {
            "serverId": "local",
            "serverUrl": "http://localhost:9000",
            "token": "65b19eb2ef04cd81a033c89820acf65d1f349c4f"
        }
    ]

projectKey は SonarQube に定義されているもので、サーバーセクションに定義されたリストの serverId である必要があります。

設定を保存し、SonarQube 側に変更を保存したら、バインディングを更新して VSCode を最新状態にします。

設定が正しく更新されたら、以下の通知が表示されます。

プロジェクトに使用されているルールのリストをカスタマイズする場合は、まず、ビルトインの品質プロファイル Caché Quality をコピーする必要があります。

そして、プロジェクトに新しいプロファイルを有効化します。

検出された一部の問題は SonarQube で解決でき、VSCode 拡張機能はそれを認識するため、再度表示されることはありません。

たとえば、このような問題があります。

呼び出されないメソッドの問題を誤検出として解決し、変数の問題を修正しないようにしましょう。

ファイルを開き直すと、新しい情報でもう一度解析されます。 %OnNew メソッドには未解決の問題が残っていません。

問題とフィードバック

CacheQuality プロジェクト自体はオープンソースではありませんが、VSCode の拡張機能はオープンソースです。 問題やフィードバックはそちらにお送りください。

0
0 95
お知らせ Mihoko Iijima · 7月 8, 2024

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

次のInterSystems プログラミングコンテストの内容についてご案内します📣

🏆 InterSystems Python コンテスト 🏆

期間:2024年7月15日~2024年8月4日

賞金総額:$14,000


0
0 179
記事 Toshihiko Minamoto · 4月 8, 2024 10m read

 

人工知能は、命令によってテキストから画像を生成したり、単純な指示によって物語を差作成したりすることだけに限られていません。

多様な写真を作成したり、既存の写真に特殊な背景を含めたりすることもできます。

また、話者の言語や速度に関係なく、音声のトランスクリプションを取得することも可能です。

では、ファイル管理の仕組みを調べてみましょう。

問題

入力値としてファイルが必要なメソッドについて OpenAI 情報を分析する場合、multipart/form-data を使用してパラメーターを指定する必要があります。

IRIS では、JSON コンテンツを使って POST メソッドへの呼び出しを作成する方法をすでに知っていますが、 この場合、Base64 フォーマットのファイルコンテンツを持つパラメーターを使用するのは非現実的です。

multipart/form-data にファイルコンテンツを含めるには、クラス %Net.MIMEPart を使用する必要があります。

呼び出しにファイルを含めるには、クラスオブジェクト %Net.MIMEPart に関連付けられた Content-Disposition ヘッダーを作成します。

set content = ##class(%Net.MIMEPart).%New()
set contentDisposition = "form-data; name="_$CHAR(34)_"image"_$CHAR(34)
set contentDisposition = contentDisposition_"; filename="_$CHAR(34)_fileName_$CHAR(34)
do content.SetHeader("Content-Disposition",contentDisposition)

Request クラスを使用してプロセスの値を保持するため、Base64 コンテンツを、コンテンツのボディを構成するストリームに変換する必要があります。

StreamUtils ユーティリティを使用して、Base64 を Stream に変換できます。

注意: 「pImage」変数には、ファイルコンテンツの Base64 文字列が含まれます。

Do##class(HS.Util.StreamUtils).Base64Encode(pImage, .tStream)
Set content.Body = tStream

ただし、Global Summit 2023 において、幸運にも InterSystems エキスパートからもっと有用なコツを得られました。 実行は StreamUtils よりも高い効果があり、最終的には String と Stream のレコードを読み取るループがあることを教えていただきました。

これは、JSON を使用してそれを Stream に変換する Get を実行するだけの単純なソリューションです。

set contentfile = {}
set contentfile.file = pImage
set content.Body = contentfile.%Get("file",,"stream<base64")

呼び出しに必要なすべてのパラメーターを含めたら、ようやくパーツをエンクローズする新しい MIMEPart クラスを作成できます。

Set rootMIME = ##class(%Net.MIMEPart).%New()
do rootMIME.Parts.Insert(content)
set writer = ##class(%Net.MIMEWriter).%New()
set tSC = writer.OutputToStream(tHttpRequest.EntityBody)
set tSC = writer.WriteMIMEBody(rootMIME)
Set tContentType = "multipart/form-data; boundary="_rootMIME.Boundary
set tSC = ..Adapter.SendFormDataArray(.tHttpResponse, "POST", tHttpRequest,,,url)

このようにして、OpenAI で必要なメソッドにファイルコンテンツを送信します。

画像ファイル

Image メソッドでは、写真を送信してバリエーションを実行することができます。 すべてのイラストは PNG 形式である必要があるため、Base64 形式のファイルコンテンツを指定する場合、ファイル名はランダムに生成され、PNG 拡張子が付けられます。

以下は、写真の変更例です。

元の写真バリエーション

ご覧のように、プログラムは命令を独自に解釈しています。

会社ロゴは円形と判断して入れ替えています。 また、オフィスにはガラスのドアが使用されていることを認識し、別のガラスのドアに入れ替えて、この時点ではレンガの壁が適用されています。

さらに、シャツの色を変更し、男性の腕の位置も変わっています。

また、OpenAI ではプロンプトに示されたコンテンツを挿入する領域にマスクを指定することで、画像を編集できます。

同じ画像を使用して、画像の背景を取り除くマスクを適用しました。

元の写真マスク

OpenAI にジャマイカのビーチに転送してほしいと指示すると、以下のような結果になりました。

家族や友人に会うときに、自分の休暇を自慢できるようになりました 😊

Image

エンドポイント: POST https://api.openai.com/v1/images/variations

既存の画像を変更した画像を作成できます。 変更方法を指定するプロンプトは不要であるため、この画像の解釈方法については AI のセンスを信用する必要があります。 また、結果のサイズと、リンクまたは Base64 のコンテンツのどちらの戻し方を希望するかを定義できます。

入力パラメーターは以下のようになります。

  • image: 必須
  • 変換する画像ファイルを指定します。
  • n: オプション。 デフォルトは 1 です。
  • このエリアでは、生成する画像の最大数を指定します。 (1~10 の数値を使用します)。
  • size: オプション。 デフォルトは 1024x1024 です。
  • このパラメーターは生成される画像のサイズを特徴づけます。 値は “256x256”、“512x512”、または “1024x1024” です。
  • response_format: オプション。 デフォルトで “url” になります。
  • この要素は、生成された画像を戻す際の形式を指定します。 値は “url” または “b64_json” です。

エンドポイント: POST https://api.openai.com/v1/images/edits

マスク ファイルに基づいて既存の画像を変更し、プロンプトに従って画像を作成できます。 また、結果の寸法と、リンクまたは Base64 のコンテンツのどちらの戻し方を希望するかを指定できます。

入力パラメーターは以下のようになります。

  • image: 必須
  • 変更する画像ファイルを指定します。
  • mask: 必須
  • このパートでは、適用するマスク画像ファイルを指定します。
  • n: オプション。 デフォルトは 1 です。
  • このエリアでは、生成する画像の最大数を指定します。 (1~10 の数値を使用します)。
  • size: オプション。 デフォルトは 1024x1024 です。
  • このパラメーターは生成される画像のサイズを特徴づけます。 値は “256x256”、“512x512”、または “1024x1024” です。
  • response_format: オプション。 デフォルトで “url” になります。
  • この要素は、生成された画像を戻す際の形式を指定します。 値は “url” または “b64_json” です。

音声ファイル

OpenAI が管理するのは画像だけではありません。 音声ファイルを使用して、提供されたレコーディングのトランスクリプションまたは翻訳を取得することもできます。

このメソッドは、固有名詞、ブランド、およびスラングを区別して正しいトランス来居プションと翻訳を提供できる Whisper モデルを使用します。 たとえば、「micromachine」というブランドについて言及するのと、一般名詞の「micro machines」をスペイン語に翻訳するのは同じことではありません。

次の例は、80 年代の有名な広告のトランスクリプションです。

<iframe allowfullscreen="" frameborder="0" height="360" src="https://www.youtube.com/embed/zLP6oT3uqV8" width="640"></iframe>

Whisper にこの音声のトランスクリプションを作成する命令の結果は以下のようになります。

{
    "text": "This is the Micromachine Man presenting the most midget miniature motorcade of micromachines. 
Each one has dramatic details, terrific trim, precision paint jobs, plus incredible micromachine pocket playsets. 
There's a police station, fire station, restaurant, service station, and more. Perfect pocket portables to take anyplace. 
And there are many miniature playsets to play with and each one comes with its own special edition micromachine vehicle and 
fun fantastic features that miraculously move. Raise the boat lift at the airport, marina, man the gun turret at 
the army base, clean your car at the car wash, raise the toll bridge. And these playsets fit together to form a micromachine world.
Micromachine pocket playsets, so tremendously tiny, so perfectly precise, so dazzlingly detailed, you'll want to pocket them all.
Micromachines and micromachine pocket playsets sold separately from Galoob. The smaller they are, the better they are."
}

素晴らしいです! そう思いませんか?

上記の結果は、Whisper モデルが受けたトレーニングによって実現しています。 これに関する情報は、OpeanAI ページに記載されている以下のダイアグラムでご覧いただけます。

 

詳細は、https://openai.com/research/whisper をご覧ください。

サービスは処理するファイルのタイプ(WAV、MP3、OGG など)を知っておく必要があるため、ファイル名に関する情報をプログラムに提供することが重要であることに注意してください。

呼び出しには Base64 コンテンツのみを含めるため、ランダムなテキストと指定拡張子でファイル名を作成できるように、ファイル拡張子も指定する必要があります。

たとえば、St.OpenAi.Msg.Audio.AudioRequest メッセージには、音声の種類を示す MP3、OGG、WAV、FLAC などの “type” プロパティがあります。

エンドポイント: https://api.openai.com/v1/audio/transcriptions

このメソッドでは、音声のコンテンツを音声の言語に文字起こしできます。

入力パラメーターは以下のようになります。

  • file: 必須
  • 文字起こしする音声ファイル(ファイル名ではありません)を指定します。 次の形式がサポートされています: FLAC、MP3、MP4、MPEG、MPGA、M4A、OGG、WAV、または WEBM
  • model: 必須。
  • トランスクリプションを作成するのに使用するモデル。 現時点では、“whisper-1” のみを使用できます。
  • language: オプション。 デフォルトでは、音声の言語です。
  • ISO-639-1 によると、指定されている場合、精度とレイテンシーが改善されます。
  • prompt: オプション。
  • これは、モデルのスタイルをガイドするため、または前の音声セグメントを継続するためのオプションのテキストです。 このメッセージは音声の言語に一致している必要があります。
  • response_format。 オプション。 デフォルトで “json” になります。
  • このパートでは、トランスクリプション出力のフォーマットを明確にします。 “json”、“text”、“verbose_json” のいずれかのオプションを使用します。
  • temperature: オプション。 デフォルト値は 0 です。
  • サンプリング温度は 0~1 です。 0.8 のように値が高くなるほど出力がよりランダムになり、0.2 のように低くなるほど集中的で確定的になります。 0 に設定すると、モデルは対数尤度を使用して、特定のしきい値に達するまで温度を自動的に高めます。

このメソッドのドキュメントは https://platform.openai.com/docs/api-reference/audio/createTranscription<をご覧ください。

エンドポイント: https://api.openai.com/v1/audio/translations

このメソッドでは、音声のコンテンツを英語に翻訳できます。

入力パラメーターは以下のようになります。

  • file: 必須
  • 翻訳する音声ファイルです(ファイル名ではありません)。 次の形式がサポートされています: FLAC、MP3、MP4、MPEG、MPGA、M4A、OGG、WAV、または WEBM
  • model: 必須。
  • このフィールドには、トランスクリプションを作成するために使用するモデルを入力します。 現時点では、“whisper-1” のみを使用できます。
  • prompt: オプション。
  • これは、モデルのスタイルをガイドするため、または前の音声セグメントを継続するためのオプションのテキストです。 このメッセージは英語である必要があります。
  • response_format。 オプション。 デフォルトで “json” になります。
  • ここでは、トランスクリプションの出力の形式を “json”、“text”、“verbose_json” から指定します。
  • temperature: オプション。 デフォルト値は 0 です。
  • サンプリング温度は 0~1 です。 0.8 のように値が高くなるほど出力がよりランダムになり、0.2 のように低くなるほど集中的で確定的になります。 0 に設定すると、モデルは対数尤度を使用して、特定のしきい値に達するまで温度を自動的に高めます。

このメソッドのドキュメントは https://platform.openai.com/docs/api-reference/audio/createTranscriptionをご覧ください。

次の内容

OpenAI は継続的に進化しているため、次回の記事ではテキストから音声への変換方法とその他の新機能をいくつか紹介します。

記事を気に入っていただけたなら、「いいね」を押してください。

0
0 131
記事 Toshihiko Minamoto · 1月 31, 2024 3m read

コミュニティの皆さん、こんにちは!!

Open Exchange に最新の「IRIS Api Tester」アプリケーションをアップロードしました。

InterSystems IRIS と Newman を使用した Docker プロジェクトで、素早く簡単に Postman コレクションをテストできます。

リポジトリをクローンするだけで、初期状態で使用できるようになっています: https://github.com/daniel-aguilar-garcia/irisapitester

docker-compose ファイルを実行します。

この URL をブラウザで開きます。

http://localhost:52773/csp/user/index.html

テストを Postman コレクションに追加します。

この例では、テストをコレクションの Test セクションに追加することでコレクションのすべてのエントリにグローバルテストを追加していますが、個別のテストを項目ごとに追加することもできます。

ここでは、リクエストのステータスコードが 200 になることをテストしています。ステータスコードが 200 でない場合には、レポートにエラーとして表示されます。

テストを追加したら、コレクションを JSON 形式でエクスポートします。

次に、JSON ファイルを IRIS Api Tester のホームページにドラッグし、「Run Test」ボタンを押します。

数秒後、レポートページにリダイレクトされます。

ここで、レポート内を移動して、すべてのテストを詳しく調べることができます。

ユーザーインターフェースを使わずにテストを起動したい場合は、このリクエストを使用できます。

テストを実行するための POST リクエスト:

localhost:52773/run_tests

Body の例:

{

"collection" : { "info": { "_postman_id": "79cfb5de-a2ab-4548-aa54-4a1712bf67a4", "name": "TestNewman", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", "_exporter_id": "838575" }, "item": [ { "name": "test_ok", "event": [ { "listen": "test", "script": { "exec": [ "" ], "type": "text/javascript" } } ], "request": { "method": "GET", "header": [], "url": { "raw": "localhost:52773/test_ok", "host": [ "localhost" ], "port": "52773", "path": [ "test_ok" ] } }, "response": [] }, { "name": "test_ko", "request": { "method": "GET", "header": [], "url": { "raw": "localhost:52773/test_ko", "host": [ "localhost" ], "port": "52773", "path": [ "test_ko" ] } }, "response": [] } ], "event": [ { "listen": "prerequest", "script": { "type": "text/javascript", "exec": [ "" ] } }, { "listen": "test", "script": { "type": "text/javascript", "exec": [ "pm.test("Verificar código de cabecera", function () {", " pm.response.to.not.have.status(500);", "});" ] } } ] } }

次に、HTML レポートを取得します。

HTML レポートを取得するための GET リクエスト:

localhost:52773/show_report

必要であれば、エクスポートしたサンプルコレクションの JSON ファイルを残しているので、ぜひお試しください。

このアプリがお役に立てれば幸いです。

お読みいただきありがとうございました!!

以下は、デモ動画です ;-)

<iframe allowfullscreen="" frameborder="0" height="360" src="https://www.youtube.com/embed/6JJJ0a6dSmY" width="640"></iframe>

0
0 100
記事 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
記事 Toshihiko Minamoto · 11月 15, 2023 9m read

前の記事 - AI による臨床文書の保管、取得、検索の単純化

この記事では、AI を使用した文字起こしと要約によってヘルスケアに変革を起こす OpenAI の高度な言語モデルの可能性を探ります。 OpenAPI の最先端 API を活用して、録音データを文字起こしし、自然言語処理アルゴリズムを使って簡潔な要約を生成するための重要なインサイトを抽出するプロセスを掘り下げていきます。

似たような機能は Amazon Medical Transcibe や Medvoice などの既存のソリューションでも提供されていますが、この記事では、OpenAI テクノロジーを使用してこれらの強力な機能を InterSystems FHIR に実装することに焦点を当てています。

Vue.js の録音データ

Vue.js アプリのボイスレコーダーは、完全にネイティブであり、Mediarecorder インターフェースを使って JavaScript で記述されています。 これは、アプリケーションを軽量に維持しながら、録音オプションを完全に制御できるようにすることを目的としています。 以下は、録音入力の開始と停止を行うスニペットです。

// オーディオストリームをチャンクとして保存する録音開始メソッドasync startRecording() {
      try {
        const stream = await navigator.mediaDevices.getUserMedia({
          audio: true,
        });
        this.mediaRecorder = new MediaRecorder(stream);
        this.mediaRecorder.start();

        this.mediaRecorder.ondataavailable = (event) => {
          this.chunks.push(event.data);
        };
        this.isRecording = true;
      } catch (error) {
        console.error("Error starting recording:", error);
      }
}

// 停止後にブロブを作成する(そして転写メソッドを呼び出す)録画停止メソッド
stopRecording() {
      if (this.mediaRecorder) {
        this.isLoading = true;
        this.mediaRecorder.stop();
        this.mediaRecorder.onstop = async () => {
          const blob = new Blob(this.chunks, {
            type: "audio/webm;codecs=opus",
          });
          awaitthis.sendAudioToWhisper(
            new File([blob], `file${Date.now()}.m4a`)
          );

          this.getSummary(this.transcription);
        };
      }
}

文字起こしコンポーネント

OpenAI の Whisper モデルを使った音声データの文字起こしには、いくつかの基本コンポーネントが使用されます。 以下のコードスニペットは、文字起こしプロセスに関わるステップを示します。

const apiKey = process.env.OPENAI_API_KEY;

const formData = new FormData();
formData.append("file", blob);
formData.append("model", "whisper-1");
formData.append("response_format", "json");
formData.append("temperature", "0");
formData.append("language", "en");

try {
  const response = await fetch(
    "https://api.openai.com/v1/audio/transcriptions",
    {
      method: "POST",
      headers: {
        Accept: "application/json",
        Authorization: `Bearer ${apiKey}`,
      },
      body: formData,
      redirect: "follow",
    }
  );

  const data = await response.json();
  if (data.text) {
    this.transcription = data.text;
  }
} catch (error) {
  console.error("Error sending audio to Whisper API:", error);
}

returnthis.transcription;
  1. API キー - OPENAI_API_KEY は、OpenAI API にアクセスするために必要な認証トークンです。
  2. フォームデータ - 文字起こしされる音声ファイルは、FormData オブジェクトに追加されます。 選択されたモデル(whisper-1)、レスポンス形式(json)、体温(``)、および言語(en)などの追加パラメーターも含まれています。
  3. API リクエスト - OpenAI API エンドポイント https://api.openai.com/v1/audio/transcriptions への POST リクエストには、ヘッダーとフォームデータを含むボディを指定して、fetch メソッドで送信されています。
  4. レスポンス処理 - API からのレスポンスがキャプチャされ、文字起こしされたテキストが data オブジェクトから抽出されます。 文字起こしを変数 this.transcription に割り当てて、さらに処理するか使用することができます。

要約コンポーネント

以下のコードスニペットは、OpenAI の text-davinci-003 モデルを使用したテキスト要約プロセスに関わる基本コンポーネントを示しています。

response = openai.Completion.create(
    model="text-davinci-003",
    prompt="Summarize the following text and give title and summary in json format. \
            Sample output - {\"title\": \"some-title\", \"summary\": \"some-summary\"}.\
            Input - "
    + text,
    temperature=1,
    max_tokens=300,
    top_p=1,
    frequency_penalty=0,
    presence_penalty=1
)

return response["choices"][0]["text"].replace('\n', '')
  1. モデルの選択 - model パラメーターは text-davinci-003 に設定されており、OpenAI のテキスト補完モデルが要約に使用されていることを示します。
  2. プロンプト - モデルに提供されるプロンプトは、望ましい結果を指定しています。これは入力テキストを要約して JSON 形式でタイトルと要約を返します。 入力テキストは、プロンプトに連結して処理されます。 OpenAI を通じてレスポンス変換を処理できるところに興味深いポイントがあります。 受信側での検証のみで十分であり、将来的にはコンバーターがほとんど必要なくなる可能性があります。
  3. 生成パラメーター - 生成された要約の動作と品質を制御するために、temperaturemax_tokenstop_pfrequency_penaltypresence_penalty などのパラメーターが設定されます。
  4. API リクエストとレスポンスの処理 - API リクエストを行うために、openai.Completion.create() メソッドが呼び出されます。 レスポンスがキャプチャされ、生成された要約テキストがレスポンスオブジェクトから抽出されます。 要約テキストに含まれる改行文字(\n)は、最終結果を返す前に取り除かれます。

FHIR のドキュメント参照

OpenAI テクノロジーを使用して医師と患者の会話の文字起こしと要約を実装する文脈においては、FHIR 規格内での診療記録の保管を考慮することが重要です。 FHIR は、診療記録などの医療情報を様々な医療システムやアプリケーション間で交換するための構造化された標準アプローチです。 FHIR の DocumentReference リソースは、診療記録や関連文書を保管するための専用のセクションとして機能します。

文字起こしと要約機能を医師と患者の会話ワークフローに統合する場合、生成される文字起こしと要約は、FHIR Documents リソース内の診療記録として保管できます。 これにより、生成されたインサイトへのアクセス、取得、およびヘルスケアプロバイダーやその他の承認機関の間での共有を簡単に行えます。

{
    "resourceType": "Bundle",
    "id": "1a3a6eac-182e-11ee-9901-0242ac170002",
    "type": "searchset",
    "timestamp": "2023-07-01T16:34:36Z",
    "total": 1,
    "link": [
        {
            "relation": "self",
            "url": "http://localhost:52773/fhir/r4/Patient/1/DocumentReference"
        }
    ],
    "entry": [
        {
            "fullUrl": "http://localhost:52773/fhir/r4/DocumentReference/1921",
            "resource": {
                "resourceType": "DocumentReference",
                "author": [
                    {
                        "reference": "Practitioner/3"
                    }
                ],
                "subject": {
                    "reference": "Patient/1"
                },
                "status": "current",
                "content": [
                    {
                        "attachment": {
                            "contentType": "application/json",
                            "data": ""
                        }
                    }
                ],
                "id": "1921",
                "meta": {
                    "lastUpdated": "2023-07-01T16:34:33Z",
                    "versionId": "1"
                }
            },
            "search": {
                "mode": "match"
            }
        }
    ]
}

試してみましょう

  1. プロジェクトをクローン - 次の GitHub リンクからプロジェクトリポジトリをクローンします: https://github.com/ikram-shah/iris-fhir-transcribe-summarize-export
  2. ローカルでセットアップ - 提供された指示に従って、プロジェクトをローカルマシン上にセットアップします。 セットアップ中に問題が発生した場合は、お知らせください。
  3. 患者を選択 - プロジェクト内の提供されたサンプルリストから患者を選択します。 この患者は、文字起こしと要約に使用される医師と患者の会話と関連付けられます。
  4. 対話ページ - 患者が選択されたら、プロジェクト内の対話ページに移動します。 このページで、「Take Notes」オプションを見つけてクリックし、医師と患者の会話の文字起こしプロセスを開始します。
  5. 文字起こしの表示と編集 - 文字起こしプロセスが完了したら、生成された文字起こしを表示するオプションが表示されます。 さらに整理してわかりやすくするために、文字起こしに関連付けられたタイトルと要約を編集することもできます。
  6. FHIR DocumentReference に保存 - タイトルと要約の処理が完了し、変更を保存すると、FHIR DocumentReference 内に自動的に保管されます。 これにより、関連する診療記録がキャプチャされ、それぞれの患者の記録に確実に関連付けられます。 現時点では、このプロジェクトは文字起こしテキスト全体を保存しませんが、 完全な文字起こしの補完を含めるように変更することもできます。

デモ

アプリケーション全体のデモはこちらでご覧ください: https://youtu.be/3Th6bR4rw0w

今後の方向性

AI を活用した文字起こしと要約の応用を遠隔医療通信に拡大することには、計り知れない可能性が秘められています。 これらの機能を Zoom、Teams、Google Meet などの一般的な会議プラットフォームに統合することで、医師と患者のリモート対話を合理化できる可能性があります。 遠隔医療セッションの自動文字起こしと要約機能には、正確な文書作成や分析の強化といったメリットがあります。 ただし、データプライバシーが重大な課題として残されます。 これに対応するためには、外部サーバーにデータを送信する前に、個人を特定できる情報(PII)をフィルターまたは匿名化する対策を実装する必要があります。

今後の方向性としては、ローカルで処理するためのオンデバイス AI モデルの調査、多言語コミュニケーションのサポートの改善、プライバシー維持した手法の進歩が挙げられます。

有用な実装だと思われた方は、Grand Prix 2023 でこのアプリに投票してください。

0
1 337
お知らせ Mihoko Iijima · 10月 29, 2023

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

Javaとその関連技術に特化したInterSystemsの新しいオンライン・プログラミング・コンテストの開催が決定しました!

現在開催中の 第1回 InterSystems Japan 技術文書ライティングコンテストの応募締め切り後に新しく始まる、US 開発者コミュニティのプログラミングコンテストのご案内です。

🏆 InterSystems Java プログラミングコンテスト🏆

期間: 2023年11月13日~12月3日

賞品総額: $14,000


0
0 142
記事 Toshihiko Minamoto · 10月 26, 2023 4m read

問題

あわただしい臨床環境では迅速な意思決定が重要であるため、文書保管とシステムへのアクセスが合理化されていなければいくつもの障害を生み出します。 文書の保管ソリューションは存在しますが(FHIR など)、それらの文書内で特定の患者データに有意にアクセスして効果的に検索するのは、重大な課題となる可能性があります。

動機

AI により、文書の検索が非常に強力になりました。 ChromaLangchain のようなオープンソースツールを使用して、ベクトル埋め込みを保存して使用し、生成 AI API 全体でクエリを実行することで、ドキュメント上での質疑応答がかつてないほど簡単になっています。 より献身的に取り組む組織は、既存のドキュメントにインデックスを作成し、エンタープライズ用に微調整されたバージョンの GPT を構築しています。 GPT の現状に関する Andrej Karpathy の講演では、このトピックに関する素晴らしい概要が提供されています。

このプロジェクトは、医療関係者が文書を操作するあらゆるタッチポイントにおいて発生する摩擦を緩和する試みです。 医療関係者が情報を保管し、必要な情報を難なく検索できるように、入力と処理から保管と検索まで、IRIS FHIR と AI を活用しました。

ソリューション

医療関係者が音声メモを記録できるフルスタックのウェブアプリを構築しました。 これらのメモは、Open AI を使って文字起こしされ、要約されてから FHIR サーバーに保管されます。 保管されたドキュメントは、インデックス作成されてから、セマンティック検索で使用できるようになります。  

デモ動画

主な機能

  1. ウェブアプリ - 患者、観察、遭遇に関する診療情報を表示します。 これは Vue.js で構築されています。
  2. 音声データの文字起こし - Open AI Whisper API を使って、録音を正確なテキストに文字起こしします。
  3. テキストの要約 - 文字起こしされた内容を必要なフォーマットで要約してタイトルが付けられます。 症状、診断などの具体的なセクションなどです。 これは、text-da-vinci-003 を使った Open AI テキスト補完 API で行われます。
  4. ドキュメントの保管 - 要約されたドキュメントは、DocumentReference アーティファクトを使って FHIR に保管されます。
  5. セマンティックドキュメント検索 - 保管されたドキュメントはインデックス作成されて、チャンクとして Chroma に保管されます。 これは、Langchain を使用して検索スペースを制限してセマンティック検索に GPT トークンを控えめに使用するために使用されます。 現時点では、使用できるドキュメント数が少ないため、検索時にドキュメントを読み込んでいますが、 非同期的にバックグラウンドでインデックス作成するように変更することが可能です。
  6. ドキュメントのエクスポート - 最後に、ドキュメントを Google Docs に、その他のデータを Google Sheets にエクスポートするオプションがあります。 ユーザーは他の医療関係者や患者とのコラボレーションとやり取りを簡単に行えるように、OAuth を使って特定のアカウントにログインし、ドキュメントをエクスポートすることができます。

試してみましょう

次の GitHub リンクからプロジェクトリポジトリをクローンします: https://github.com/ikram-shah/iris-fhir-transcribe-summarize-export。 提供された指示に従って、プロジェクトをローカルマシン上にセットアップしてください。 期待される動作が得られない場合は、お知らせください。

ご意見とフィードバック

現在使用できる高度言語モデルと大量のデータを合わせることで、ヘルスケア分野の特に文書管理の領域に革命を起こす大きな可能性があります。 以下に、ご意見やフィードバックをお寄せください。 このプロジェクトの背後にある技術的な情報について、さらに多くの記事を投稿する予定です。

このプロジェクトに期待できると思われる場合は、Grand Prix コンテストでこのアプリに投票してください!

0
0 184
記事 Toshihiko Minamoto · 10月 18, 2023 7m read

コミュニティの皆さん、こんにちは。

パート 1 では、すべてのパッケージ、使用されているライブラリ、および REST サービスについて説明しました。

次は、コンバーターサービスとバリデーターサービスについて詳しく説明したいと思います。

OpenAPI-Suite はデフォルトで、仕様バージョンが 3.0 未満である場合に HTTP リクエストを converter.swagger.io に送信し、別の HTTP リクエストを validator.swagger.io に送信して仕様ドキュメントの構造を単純化します。  

オンラインユーティリティの使用は便利ではありますが、場合によっては独自のコンバーターとバリデーターのインスタンスを使用する方が便利な場合もあります。  たとえば、OpenAPI-Suite が ObjectScript 開発者向けに組織のサーバーに提供されている場合、外部サービスへのリクエストを回避する方が好ましいことがあります(プライバシーやリクエストレートの制限を回避するため)。 

以下を実行してください。 

docker run -d -p 8085:8080 --name swagger-converter swaggerapi/swagger-converter:latest
docker run -d -p 8086:8080 --name swagger-validator-v2 swaggerapi/swagger-validator-v2:latest
ブラウザで http://localhost:8085/ と http://localhost:8086/ を開くと、これらのサービスの UI にアクセスできます。  

ローカルサービスを使用するために OpenAPI-Suite を構成する必要があるため、IRIS ターミナルを開いて、以下のグローバルを設定します。

^swaggervalidator("ValidatorURL")="http://"^swaggervalidator("Port")=^swaggerconverter("ConverterURL")="http://"^swaggerconverter("Port")=

では、これを Docker-Compose に統合して、自動的に行う方法を見てみましょう。

まず、post-start スクリプト(init_openapisuite.sh)を準備します。

#!/bin/bash

openapi_suite() {
iris session $ISC_PACKAGE_INSTANCENAME -U IRISAPP <<- END
Set^swaggerconverter("ConverterURL") = "${CONVERTER_URL:-converter.swagger.io}"Set^swaggerconverter("Port") = "${CONVERTER_PORT:-80}"Set^swaggervalidator("ValidatorURL") = "${VALIDATOR_URL:-validator.swagger.io}"Set^swaggervalidator("Port") = "${VALIDATOR_PORT:-80}"Halt
END
}

openapi_suite

exit 0

このスクリプトは iris-main プログラムによって実行されます。  スクリプトに「execute」権限があることを確認してください(chmod +x init_openapisuite.sh)。  

次に、以下のように docker-compose ファイルを作成します。

version: '3.6'
services:
  iris:
    build: 
      context: .
      dockerfile: Dockerfile
    restart: always
    command: --check-caps false --ISCAgent false -a /home/irisowner/irisdev/init_openapisuite.sh
    environment:
      - CONVERTER_URL=http://swagger-converter
      - CONVERTER_PORT=8080
      - VALIDATOR_URL=http://swagger-validator-v2
      - VALIDATOR_PORT=8080
    ports: 
      - 1972
      - 52796:52773
      - 53773
    volumes:
      - ./:/home/irisowner/irisdev
  swagger-converter:
    image: swaggerapi/swagger-converter:latest
    restart: always
    # optional, openapi-suite don't need port exposed
    ports:
      - 8085:8080
  swagger-validator-v2:
    image: swaggerapi/swagger-validator-v2:latest
    restart: always
    # optional, openapi-suite don't need port exposed
    ports:
      - 8086:8080

すべてのリソースはこちらのリポジトリにあります。すでにクローンした場合は、「git pull」を実行して最新のアップデートを取得してください。  すると、以下のコマンドを使って、すべてのサービスとともに OpenAPI-Suite をローカルで起動できます。 

docker-compose --file docker-compose-with-swagger.yml up -d; or for compose plugin users; docker compose --file docker-compose-with-swagger.yml up -d

 

これは単なる 1 つのアイデアに過ぎませんが、OpenAPI-Suite 実装が十分に完全になれば、おそらく Swagger 3.0 のオンライン ObjectScript コード生成サービスを提供するために使用できるようになる可能性があります。  現時点では、アプリケーションは dc demo server にホストされているため、openapi-suite 用の小さなクライアントを作るアイデアを得ました(これも openapi-suite 自体で生成されたものです! ).  つまり、すべてのツールをローカルにインストールしなくても、リモートコード生成を利用することが可能です。

zpm "install openapi-suite-client"

 

; remote openapi-suite REST service url : Set server = "https://openapisuite.demo.community.intersystems.com/openapisuite"; Specification could be an URL, filepath or a stream.Set specification = "https://petstore3.swagger.io/api/v3/openapi.json"; Package name for generated classes.Set packageName = "petstoreclient"; available type : ; - "client" : to generate http client classes. ; - "production" :  to generate production client classes.; - "rest" : to generate REST server classesSet type = "client"; Request and Install the generated code.Set sc = ##class(dc.openapi.suite.client.RemoteCodeGen).Generate(specification, packageName, type, server)
 
ターミナルの出力
IRISAPP>Set sc = ##class(dc.openapi.suite.client.RemoteCodeGen).Generate(specification, packageName, type, server)

Load started on 02/06/202320:49:19 Loading file /usr/irissys/mgr/Temp/Lgm86wQGGdNSiQ.xml as xml Imported class: petstoreclient.HttpClient Imported class: petstoreclient.model.Address Imported class: petstoreclient.model.ApiResponse Imported class: petstoreclient.model.Category Imported class: petstoreclient.model.Customer Imported class: petstoreclient.model.Order Imported class: petstoreclient.model.Pet Imported class: petstoreclient.model.Tag Imported class: petstoreclient.model.User Imported class: petstoreclient.model.spec Imported class: petstoreclient.requests.addPet Imported class: petstoreclient.requests.createUser Imported class: petstoreclient.requests.createUsersWithListInput Imported class: petstoreclient.requests.deleteOrder Imported class: petstoreclient.requests.deletePet Imported class: petstoreclient.requests.deleteUser Imported class: petstoreclient.requests.findPetsByStatus Imported class: petstoreclient.requests.findPetsByTags Imported class: petstoreclient.requests.getInventory Imported class: petstoreclient.requests.getOrderById Imported class: petstoreclient.requests.getPetById Imported class: petstoreclient.requests.getUserByName Imported class: petstoreclient.requests.loginUser Imported class: petstoreclient.requests.logoutUser Imported class: petstoreclient.requests.placeOrder Imported class: petstoreclient.requests.updatePet Imported class: petstoreclient.requests.updatePetWithForm Imported class: petstoreclient.requests.updateUser Imported class: petstoreclient.requests.uploadFile Imported class: petstoreclient.responses.GenericResponse Imported class: petstoreclient.responses.addPet Imported class: petstoreclient.responses.createUser Imported class: petstoreclient.responses.createUsersWithListInput Imported class: petstoreclient.responses.deleteOrder Imported class: petstoreclient.responses.deletePet Imported class: petstoreclient.responses.deleteUser Imported class: petstoreclient.responses.findPetsByStatus Imported class: petstoreclient.responses.findPetsByTags Imported class: petstoreclient.responses.getInventory Imported class: petstoreclient.responses.getOrderById Imported class: petstoreclient.responses.getPetById Imported class: petstoreclient.responses.getUserByName Imported class: petstoreclient.responses.loginUser Imported class: petstoreclient.responses.logoutUser Imported class: petstoreclient.responses.placeOrder Imported class: petstoreclient.responses.updatePet Imported class: petstoreclient.responses.updatePetWithForm Imported class: petstoreclient.responses.updateUser Imported class: petstoreclient.responses.uploadFile Compiling 49 classes Compiling class petstoreclient.HttpClient Compiling class petstoreclient.model.Address Compiling class petstoreclient.model.Category Compiling class petstoreclient.model.ApiResponse Compiling class petstoreclient.model.Customer Compiling class petstoreclient.model.Order Compiling class petstoreclient.model.Tag Compiling class petstoreclient.model.Pet Compiling class petstoreclient.model.spec Compiling class petstoreclient.requests.addPet Compiling class petstoreclient.model.User Compiling class petstoreclient.requests.createUser Compiling class petstoreclient.requests.deleteOrder Compiling class petstoreclient.requests.createUsersWithListInput Compiling class petstoreclient.requests.deleteUser Compiling class petstoreclient.requests.deletePet Compiling class petstoreclient.requests.findPetsByStatus Compiling class petstoreclient.requests.findPetsByTags Compiling class petstoreclient.requests.getInventory Compiling class petstoreclient.requests.getOrderById Compiling class petstoreclient.requests.getPetById Compiling class petstoreclient.requests.getUserByName Compiling class petstoreclient.requests.loginUser Compiling class petstoreclient.requests.logoutUser Compiling class petstoreclient.requests.updatePet Compiling class petstoreclient.requests.placeOrder Compiling class petstoreclient.requests.updateUser Compiling class petstoreclient.requests.updatePetWithForm Compiling class petstoreclient.requests.uploadFile Compiling class petstoreclient.responses.GenericResponse Compiling class petstoreclient.responses.createUser Compiling class petstoreclient.responses.addPet Compiling class petstoreclient.responses.deleteOrder Compiling class petstoreclient.responses.createUsersWithListInput Compiling class petstoreclient.responses.deletePet Compiling class petstoreclient.responses.deleteUser Compiling class petstoreclient.responses.findPetsByTags Compiling class petstoreclient.responses.findPetsByStatus Compiling class petstoreclient.responses.getOrderById Compiling class petstoreclient.responses.getInventory Compiling class petstoreclient.responses.getPetById Compiling class petstoreclient.responses.getUserByName Compiling class petstoreclient.responses.logoutUser Compiling class petstoreclient.responses.loginUser Compiling class petstoreclient.responses.placeOrder Compiling class petstoreclient.responses.updatePet Compiling class petstoreclient.responses.updatePetWithForm Compiling class petstoreclient.responses.updateUser Compiling class petstoreclient.responses.uploadFile Compiling routine petstoreclient.HttpClient.1 Compiling routine petstoreclient.model.Address.1 Compiling routine petstoreclient.model.ApiResponse.1 Compiling routine petstoreclient.model.Category.1 Compiling routine petstoreclient.model.Customer.1 Compiling routine petstoreclient.model.Order.1 Compiling routine petstoreclient.model.Tag.1 Compiling routine petstoreclient.model.Pet.1 Compiling routine petstoreclient.requests.addPet.1 Compiling routine petstoreclient.model.User.1 Compiling routine petstoreclient.requests.createUser.1 Compiling routine petstoreclient.requests.createUsersWithListInput.1 Compiling routine petstoreclient.requests.deleteOrder.1 Compiling routine petstoreclient.requests.deletePet.1 Compiling routine petstoreclient.requests.deleteUser.1 Compiling routine petstoreclient.requests.findPetsByStatus.1 Compiling routine petstoreclient.requests.getInventory.1 Compiling routine petstoreclient.requests.findPetsByTags.1 Compiling routine petstoreclient.requests.getOrderById.1 Compiling routine petstoreclient.requests.getPetById.1 Compiling routine petstoreclient.requests.getUserByName.1 Compiling routine petstoreclient.requests.loginUser.1 Compiling routine petstoreclient.requests.logoutUser.1 Compiling routine petstoreclient.requests.placeOrder.1 Compiling routine petstoreclient.requests.updatePet.1 Compiling routine petstoreclient.requests.updatePetWithForm.1 Compiling routine petstoreclient.requests.updateUser.1 Compiling routine petstoreclient.requests.uploadFile.1 Compiling routine petstoreclient.responses.GenericResponse.1 Compiling routine petstoreclient.responses.addPet.1 Compiling routine petstoreclient.responses.createUser.1 Compiling routine petstoreclient.responses.deleteOrder.1 Compiling routine petstoreclient.responses.createUsersWithListInput.1 Compiling routine petstoreclient.responses.deletePet.1 Compiling routine petstoreclient.responses.deleteUser.1 Compiling routine petstoreclient.responses.findPetsByTags.1 Compiling routine petstoreclient.responses.findPetsByStatus.1 Compiling routine petstoreclient.responses.getInventory.1 Compiling routine petstoreclient.responses.getOrderById.1 Compiling routine petstoreclient.responses.getPetById.1 Compiling routine petstoreclient.responses.loginUser.1 Compiling routine petstoreclient.responses.getUserByName.1 Compiling routine petstoreclient.responses.logoutUser.1 Compiling routine petstoreclient.responses.updatePet.1 Compiling routine petstoreclient.responses.placeOrder.1 Compiling routine petstoreclient.responses.updatePetWithForm.1 Compiling routine petstoreclient.responses.updateUser.1 Compiling routine petstoreclient.responses.uploadFile.1 Load finished successfully.

IRISAPP>

<p>
   
</p>

お読みいただきありがとうございました!

0
0 75
記事 Toshihiko Minamoto · 9月 28, 2023 22m read

コミュニティの皆さん、こんにちは。

私が作成した OpenAPI-Suite という最新のパッケージをご紹介します。これは、OpenAPI 仕様バージョン 3.0 から ObjectScript コードを生成するツールセットです。  簡単に言うと、これらのパッケージでは以下を行うことができます。

  • サーバーサイドクラスの生成。  ^%REST による生成コードに非常に似ていますが、バージョン 3.0 がサポートされていることに付加価値があります。
  • HTTP クライアントクラスの生成。
  • クライアントプロダクション(ビジネスサービス、ビジネスオペレーション、ビジネスプロセス、Ens.Request、Ens.Response)クラスの生成。
  • コードの生成とダウンロードまたはサーバーでの直接コンパイルを行う Web インターフェース。
  • バージョン 1.x からバージョン 3.0 への仕様の変換。
  • 概要

    OpenAPI Suite は多数のパッケージに分割されており、様々な開発者コミュニティライブラリや公開 REST サービスを使用しています。  以下の図では、開発されたすべてのパッケージと、使用されているライブラリと Web サービスを示しています。

    注意: 公開 REST サービスの使用に問題がある場合は、コンバーターとバリデーターサービスの Docker インスタンスを開始することができます。

    各パッケージの機能

    OpenAPI Suite は、メンテナンス、改善、および今後の拡張を行いやすくするために、様々なパッケージで設計されています。  パッケージごとに役割がありますので、  それを確認してみましょう!

    openapi-common-lib

    これには、他のパッケージのすべての共通コードが含まれています。  たとえば、openapi-client-genopenapi-server-gen は、OpenAPI 仕様の以下の入力を受け入れます。 

  • URL
  • ファイルパス
  • %Stream.Object 
  • %DynamicObject
  • YAML 形式
  • JSON 形式
  • OpenAPI バージョン 1.x、2.x、3.0.x
  • ただし、%DynamicObject 内の仕様 3.0.x のみを処理できます。  変換のコードはこのパッケージにあります。  また様々なユーティリティも含まれています。  

    swagger-converter-cli

    openapi-common-lib の依存関係です。  これは、OpenAPI バージョン 3.0 でバージョン 1.x または 2.x を変換するために公開 REST サービスの converter.swagger.io を使用する HTTP クライアントです。

    swagger-validator-cli

    これも openapi-common-lib の依存関係です。名前は「validator」となっていますが、仕様の検証に使用されるものではありません。  converter.swagger.io は、OpenAPI 仕様の構造を単純化できるように、「parse」サービスを提供しています。  例: 「nested object definition」の定義を作成し、それを「$ref」に置換します。  これにより、コード生成アルゴリズムで処理されるケース数が軽減されます。

    openapi-client-gen

    このパッケージは、開発者が REST サービスを使用しやすくするクライアントサイドのコード生成専用です。

    単純な HTTP クライアントまたはプロダクションクライアント(ビジネスサービス、プロセス、オペレーション、プロダクションクラス)が含まれます。  元々、OpenAPI 2.x をサポートするために作成されていましたが、バージョン 3.x をサポートするように完全にリファクタリングされました。

    openapi-server-gen

    これは openapi-client-gen とは逆に、サーバーサイドのコード生成専用です。  ^%REST が存在するため、仕様バージョン 2.0 ではなく、バージョン 3.0 サポートがこのパッケージのターゲットとなっています。  

    openapi-suite

    上記すべてのパッケージをひとまとめにし、以下を行う REST API を提供します。 

  • コードを生成し、IRIS インスタンスでコードをコンパイルします。
  • コンパイルせずにダウンロードのみのコードを生成します。
  • この REST API を使用し、OpenAPI Suite の機能を使用するための Web インターフェースも提供されています。

    ライブラリ

    以下に、この開発で利用した DC 上の既存のライブラリをいくつか紹介します。

    objectscript-openapi-definition

    OpenAPI 仕様からモデルクラスを生成する便利なライブラリです。  これはこのプロジェクトで非常に重要な要素であり、私自身も貢献しているライブラリです。

    ssl-client

    SSL 構成を作成できるようにします。  主に、HTTPS リクエストの「DefaultSSL」という名前の構成の作成に使用されています。  

    yaml-utils

    YAML 形式仕様の場合に、このライブラリは JSON 形式に変換するために使用されます。  このプロジェクトでは不可欠なライブラリです。  ちなみに、最初は openapi-client-gen バージョン 1 で YAML 仕様をテストするために開発されました。

    io-redirect

    これは私のライブラリの 1 つです。「write」をストリーム、ファイル、グローバル、または文字列変数にリダイレクトできます。  ログのトレースを維持するために、REST サービスで使用されています。  このコミュニティ記事からアイデアを得ました。

    IPM によるインストール

    このスイートをインストールするには、IPM(zpm)の使用が最適です。  多数のパッケージと依存関係があるため、IPM を使用するのが確実に便利と言えます。

    zpm "install openapi-suite"; optional; zpm "install swagger-ui"

     

    Docker によるインストール

    特別なことは何もありません。このプロジェクトは intersystems-iris-dev-template を使用しています。

    git clone git@github.com:lscalese/openapi-suite.git
    cd openapi-suite
    docker-compose up -d

    Iris の起動にエラーがある場合は、おそらく iris-main.log の権限の問題と思われます。

    以下を試してみてください。

    touch iris-main.log && chmod 777 iris-main.log

    注意: irisowner ユーザーに RW 権限を追加するだけで十分なはずです。

    使用方法

    OpenAPI-Suite には、コードを「生成してダウンロード」するか「生成してインストール」するための Web インターフェースが備わっています。  

    このインターフェースは http://localhost:52796/openapisuite/ui/index.cspで使用できます(*必要に応じて、使用しているポート番号に変更してください)。  

    非常に簡単で、フォームに入力するだけです。

  • Application package name: 生成されるクラスに使用されるパッケージの名前です。  既存でないパッケージ名である必要があります。
  • What do you want to generate?: 生成するものを HTTP Client、Client Production、または REST server から選択します。
  • Namespace: コードが生成されるネームスペースを選択します。  「Install On Server」(サーバーにインストール)をクリックした場合にのみ意味があり、そうでない場合はこのフィールドは無視されます。
  • Web Application Name: Web アプリケーションはオプションであり、「REST Server」の生成を選択した場合にのみ利用できます。  生成される REST ディスパッチクラスに関連する Web アプリケーションを作成しない場合は、空のままにします。
  • OpenAPI specification field: 仕様を指している URL を入力するか、仕様自体をコピー/貼り付けします(後者の場合、仕様は JSON 形式である必要があります)。
  • 「Download Only」(ダウンロードのみ)ボタンをクリックした場合、コードは XML ファイルで生成されて返され、クラスはサーバーから削除されます。  生成されるクラスを一時的に保存するために使用するネームスペースは、OpenAPI-Suite がインストールされているネームスペースです(Docker インストールを使用した場合のデフォルトは IRISAPP です)。  

    ただし、「Install On Server」(サーバーにインストール)ボタンをクリックした場合、コードは生成・コンパイルされ、サーバーは、コード生成/コンパイルのステータス付きの JSON メッセージとログを返します。

    デフォルトではこの機能は無効化されていますが、有効にするには IRIS ターミナルを開いて以下を実行してください。

    Set^openapisuite.config("web","enable-install-onserver") = 1

    OpenAPI-Suite REST API を詳しく見る

    CSP フォームは、http://localhost:52796/openapisuite にある REST サービスを使用します。

    swagger-ui http://localhost:52796/swagger-ui/index.html を開き、http://localhost:52796/openapisuite/_spec を詳しく見てみましょう。

    これは、Angular フレームワークを使用してより高度なフロントエンドアプリケーションを作成するための第一歩です。

    コードをプログラミングで生成する

    もちろん、UI の使用は必須ではありません。このセクションでは、コードをプログラミングで生成し、生成されたサービスを使用する方法について説明します。

    すべてのスニペットは、dc.openapi.suite.samples.PetStore クラスでも使用できます。

    HTTP クライアント

    Set features("simpleHttpClientOnly") = 1Set sc = ##class(dc.openapi.client.Spec).generateApp("petstoreclient", "https://petstore3.swagger.io/api/v3/openapi.json", .features)

     

    最初の引数は、クラスが生成されるパッケージであるため、有効なパッケージ名を渡すようにしましょう。  2 つ目の引数は、仕様を指す URL、ファイル名、ストリーム、または %DynamicObject です。  「features」は配列であり、現在以下のサブスクリプトのみを使用できます。 

    simpleHttpClientOnly: 1 である場合、単純な HTTP クライアントのみが生成されます。そうでない場合、プロダクションも生成されます(デフォルトの動作)。

    compile: 0 である場合、生成されたコードはコンパイルされません。  エクスポートの目的のみでコードを生成する場合に便利です。  デフォルトは、compile = 1 です。

    以下は、生成したばかりの HTTP クライアントで「addPet」サービスを使用する例です。

    Set messageRequest = ##class(petstoreclient.requests.addPet).%New()
    Set messageRequest.%ContentType = "application/json"Do messageRequest.PetNewObject().%JSONImport({"id":456,"name":"Mittens","photoUrls":["https://static.wikia.nocookie.net/disney/images/c/cb/Profile_-_Mittens.jpg/revision/latest?cb=20200709180903"],"status":"available"})
    

    Set httpClient = ##class(petstoreclient.HttpClient).%New("https://petstore3.swagger.io/api/v3","DefaultSSL") ; MessageResponse will be an instance of petstoreclient.responses.addPetSet sc = httpClient.addPet(messageRequest, .messageResponse) If$$$ISERR(sc) Do$SYSTEM.Status.DisplayError(sc) Quit sc

    Write !,"Http Status code : ", messageResponse.httpStatusCode,! Do messageResponse.Pet.%JSONExport()

     
    クリックして生成されたクラスを表示します。
    <div class="spoiler-content" style="">
      <pre class="codeblock-container" idlang="0" lang="ObjectScript" tabsize="4"><code class="language-cls hljs cos"><span class="hljs-keyword">Class</span> petstoreclient.HttpClient <span class="hljs-keyword">Extends</span> <span class="hljs-built_in">%RegisteredObject</span> [ ProcedureBlock ]
    

    {

    Parameter SERVER = "https://petstore3.swagger.io/api/v3";Parameter SSLCONFIGURATION = "DefaultSSL";Property HttpRequest [ InitialExpression = {##class(%Net.HttpRequest).%New()} ];Property SSLConfiguration As%String [ InitialExpression = {..#SSLCONFIGURATION} ];Property Server As%String [ InitialExpression = {..#SERVER} ];Property URLComponents [ MultiDimensional ]; Method %OnNew(Server As%String, SSLConfiguration As%String) As%Status { Set:$Data(Server) ..Server = Server Set:$Data(SSLConfiguration) ..SSLConfiguration = SSLConfiguration Quit..InitializeHttpRequestObject() }

    Method InitializeHttpRequestObject() As%Status { Set..HttpRequest = ##class(%Net.HttpRequest).%New() Do##class(%Net.URLParser).Decompose(..Server, .components) Set:$Data(components("host"), host) ..HttpRequest.Server = host Set:$Data(components("port"), port) ..HttpRequest.Port = port Set:$$$LOWER($Get(components("scheme")))="https"..HttpRequest.Https = $$$YES, ..HttpRequest.SSLConfiguration = ..SSLConfigurationMerge:$Data(components) ..URLComponents = components Quit$$$OK }

    /// Implement operationId : addPet/// post /pet Method addPet(requestMessage As petstoreclient.requests.addPet, Output responseMessage As petstoreclient.responses.addPet = {##class(petstoreclient.responses.addPet).%New()}) As%Status { Set sc = $$$OK$$$QuitOnError(requestMessage.LoadHttpRequestObject(..HttpRequest)) $$$QuitOnError(..HttpRequest.Send("POST", $Get(..URLComponents("path")) _ requestMessage.%URL)) $$$QuitOnError(responseMessage.LoadFromResponse(..HttpRequest.HttpResponse, "addPet")) Quit sc } ... }

      <p>
         
      </p>
      
      <pre class="codeblock-container" idlang="0" lang="ObjectScript" tabsize="4"><code class="language-cls hljs cos"><span class="hljs-keyword">Class</span> petstoreclient.requests.addPet <span class="hljs-keyword">Extends</span> <span class="hljs-built_in">%RegisteredObject</span> [ ProcedureBlock ]
    

    {

    Parameter METHOD = "post";Parameter URL = "/pet";Property%ConsumeAs%String;Property%ContentTypeAs%String;Property%URLAs%String [ InitialExpression = {..#URL} ];/// Use this property for body content with content-type = application/json.
    /// Use this property for body content with content-type = application/xml.
    /// Use this property for body content with content-type = application/x-www-form-urlencoded.Property Pet As petstoreclient.model.Pet;/// Load %Net.HttpRequest with this property object. Method LoadHttpRequestObject(ByRef httpRequest As%Net.HttpRequest) As%Status { Set sc = $$$OKSet httpRequest.ContentType = ..%ContentTypeDo httpRequest.SetHeader("accept", ..%Consume) If$Piece($$$LOWER(..%ContentType),";",1) = "application/json"Do..Pet.%JSONExportToStream(httpRequest.EntityBody) If$Piece($$$LOWER(..%ContentType),";",1) = "application/xml"Do..Pet.XMLExportToStream(httpRequest.EntityBody) If$Piece($$$LOWER(..%ContentType),";",1) = "application/x-www-form-urlencoded" { ; To implement. この場合、コードの生成はまだありません。$$$ThrowStatus($$$ERROR($$$NotImplemented)) } Quit sc }

    }

      <p>
         
      </p>
      
      <pre class="codeblock-container" idlang="0" lang="ObjectScript" tabsize="4"><code class="language-cls hljs cos"><span class="hljs-keyword">Class</span> petstoreclient.responses.addPet <span class="hljs-keyword">Extends</span> petstoreclient.responses.GenericResponse [ ProcedureBlock ]
    

    {

    /// http status code = 200 content-type = application/xml/// http status code = 200 content-type = application/json/// Property Pet As petstoreclient.model.Pet;/// Implement operationId : addPet/// post /pet Method LoadFromResponse(httpResponse As%Net.HttpResponse, caller As%String = "") As%Status { Set sc = $$$OKDo##super(httpResponse, caller) If$$$LOWER($Piece(httpResponse.ContentType,";",1))="application/xml",httpResponse.StatusCode = "200" { $$$ThrowStatus($$$ERROR($$$NotImplemented)) } If$$$LOWER($Piece(httpResponse.ContentType,";",1))="application/json",httpResponse.StatusCode = "200" { Set..Pet = ##class(petstoreclient.model.Pet).%New() Do..Pet.%JSONImport(httpResponse.Data) Return sc } Quit sc }

    }

      <p>
         
      </p>
    </div>
    

     

    HTTP クライアントのプロダクション

    Set sc = ##class(dc.openapi.client.Spec).generateApp("petstoreproduction", "https://petstore3.swagger.io/api/v3/openapi.json")

    最初の引数は、単純な HTTP クライアントのコード生成をテストする場合のパッケージ名であるため、クライアントプロファクションの場合は必ず別のパッケージ名を使用してください。  2 つ目と 3 つ目も HTTP クライアントと同じルールが適用されます。

    テストする前に、以下のコマンドを使用して、管理ポータルからプロダクションを起動してください。

    Do##class(Ens.Director).StartProduction("petstoreproduction.Production")

    以下は、「addPet」サービスを使用する例ですが、今回は生成されたプロダクションを使用します。

    Set messageRequest = ##class(petstoreproduction.requests.addPet).%New()
    Set messageRequest.%ContentType = "application/json"Do messageRequest.PetNewObject().%JSONImport({"id":123,"name":"Kitty Galore","photoUrls":["https://www.tippett.com/wp-content/uploads/2017/01/ca2DC049.130.1264.jpg"],"status":"pending"})
    ; MessageResponse will be an instance of petstoreclient.responses.addPetSet sc = ##class(petstoreproduction.Utils).invokeHostSync("petstoreproduction.bp.SyncProcess", messageRequest, "petstoreproduction.bs.ProxyService", , .messageResponse)
    Write !, "Take a look in visual trace (management portal)"If$$$ISERR(sc) Do$SYSTEM.Status.DisplayError(sc)
    Write !,"Http Status code : ", messageResponse.httpStatusCode,!
    Do messageResponse.Pet.%JSONExport()

    次に、視覚的なトレースを開いて詳細を確認します。 

    packages モデル、リクエスト、およびレスポンスに生成されたクラスは、単純な HTTP クライアント用に生成されるコードと非常によく似ています。  パッケージリクエストのクラスは Ens.Request を継承し、パッケージレスポンスのクラスは Ens.Response を継承します。  ビジネスオペレーションのデフォルトの実装は非常に単純です。以下のスニペットをご覧ください。 

    Class petstoreproduction.bo.Operation Extends Ens.BusinessOperation [ ProcedureBlock ]
    {
    
    Parameter ADAPTER = "EnsLib.HTTP.OutboundAdapter";Property Adapter As EnsLib.HTTP.OutboundAdapter;/// Implement operationId : addPet/// post /pet
    Method addPet(requestMessage As petstoreproduction.requests.addPet, Output responseMessage As petstoreproduction.responses.addPet) As%Status
    {
        Set sc = $$$OK, pHttpRequestIn = ##class(%Net.HttpRequest).%New(), responseMessage = ##class(petstoreproduction.responses.addPet).%New()
        $$$QuitOnError(requestMessage.LoadHttpRequestObject(pHttpRequestIn))
        $$$QuitOnError(..Adapter.SendFormDataArray(.pHttpResponse, "post", pHttpRequestIn, , , ..Adapter.URL_requestMessage.%URL))
        $$$QuitOnError(responseMessage.LoadFromResponse(pHttpResponse, "addPet"))
        Quit sc
    }
    ...
    }
    }

     

    HTTP サーバーサイド REST アプリケーション

    Set sc = ##class(dc.openapi.server.ServerAppGenerator).Generate("petstoreserver", "https://petstore3.swagger.io/api/v3/openapi.json", "/petstore/api")

    最初の引数は、クラスを生成するパッケージ名です。  2 つ目は HTTP クライアントと同じルールが適用されます。  3 つ目の引数は必須ではありませんが、使用されている場合、Web アプリケーションが指定された名前で作成されます(有効な Web アプリケーション名を指定することに注意してください)。

    クラス petstoreserver.disp(ディスパッチ %CSP.REST クラス)は、^%REST が生成するコードに似ており、リクエストを受け入れるか拒否する多数のチェックを実行し、petstoreserver.impl で関連するサービス ClassMethod 実装を呼び出します。  主な違いは、実装メソッドに渡される引数で、これは petstoreserver.requests オブジェクトです。 例:

    Class petstoreserver.disp Extends%CSP.REST [ ProcedureBlock ]
    {
    

    Parameter CHARSET = "utf-8";Parameter CONVERTINPUTSTREAM = 1;Parameter IgnoreWrites = 1;Parameter SpecificationClass = "petstoreserver.Spec";/// Process request post /petClassMethod addPet() As%Status { Set sc = $$$OKTry{ Set acceptedMedia = $ListFromString("application/json,application/xml,application/x-www-form-urlencoded") If '$ListFind(acceptedMedia,$$$LOWER(%request.ContentType)) { Do##class(%REST.Impl).%ReportRESTError(..#HTTP415UNSUPPORTEDMEDIATYPE,$$$ERROR($$$RESTContentType,%request.ContentType)) Quit } Do##class(%REST.Impl).%SetContentType($Get(%request.CgiEnvs("HTTP_ACCEPT"))) If '##class(%REST.Impl).%CheckAccepts("application/xml,application/json") Do##class(%REST.Impl).%ReportRESTError(..#HTTP406NOTACCEPTABLE,$$$ERROR($$$RESTBadAccepts)) QuitIf '$isobject(%request.Content) Do##class(%REST.Impl).%ReportRESTError(..#HTTP400BADREQUEST,$$$ERROR($$$RESTRequired,"body")) QuitSet requestMessage = ##class(petstoreserver.requests.addPet).%New() Do requestMessage.LoadFromRequest(%request) Set scValidateRequest = requestMessage.RequestValidate() If$$$ISERR(scValidateRequest) Do##class(%REST.Impl).%ReportRESTError(..#HTTP400BADREQUEST,$$$ERROR(5001,"Invalid requestMessage object.")) QuitSet response = ##class(petstoreserver.impl).addPet(requestMessage) Do##class(petstoreserver.impl).%WriteResponse(response) } Catch(ex) { Do##class(%REST.Impl).%ReportRESTError(..#HTTP500INTERNALSERVERERROR,ex.AsStatus(),$parameter("petstoreserver.impl","ExposeServerExceptions")) } Quit sc } ... }

    ご覧のとおり、dispatch クラスは実装メソッドを呼び出す前に「LoadFromRequest」と「RequestValidate」を呼び出しています。  これらのメソッドにはデフォルトの実装がありますが、コードジェネレーターはすべてのケースに対応できません。  現時点では、「query」、「headers」、「path」、およびコンテンツタイプが「application/json」、「application/octet-stream」、または「multipart/form-data」である body で最も一般的なケースがパラメーターとして自動的に処理されます。  開発者は、必要に応じて実装をチェック/完了する必要があります(未対応のケースについては、デフォルトでは、コードジェネレーターは $$$ThrowStatus($$$ERROR($$$NotImplemented)) を設定します)。

     
    リクエストクラスの例:
    Class petstoreserver.requests.addPet Extends%RegisteredObject [ ProcedureBlock ]
    {
    

    Parameter METHOD = "post";Parameter URL = "/pet";Property%ConsumeAs%String;Property%ContentTypeAs%String;Property%URLAs%String [ InitialExpression = {..#URL} ];/// Use this property for body content with content-type = application/json.
    /// Use this property for body content with content-type = application/xml.
    /// Use this property for body content with content-type = application/x-www-form-urlencoded.Property Pet As petstoreserver.model.Pet;/// Load object properties from %CSP.Request object. Method LoadFromRequest(request As%CSP.Request = {%request}) As%Status { Set sc = $$$OKSet ..%ContentType = $Piece(request.ContentType, ";", 1) If ..%ContentType = "application/json"{ Do..PetNewObject().%JSONImport(request.Content) } If ..%ContentType = "application/xml" { ; To implement. There is no code generation yet for this case.$$$ThrowStatus($$$ERROR($$$NotImplemented)) } If ..%ContentType = "application/x-www-form-urlencoded" { ; To implement. There is no code generation yet for this case.$$$ThrowStatus($$$ERROR($$$NotImplemented)) } Quit sc }

    /// Load object properties from %CSP.Request object. Method RequestValidate() As%Status { Set sc = $$$OK$$$QuitOnError(..%ValidateObject()) If ''$ListFind($ListFromString("application/json,application/xml,application/x-www-form-urlencoded"), ..%ContentType) { Quit:..Pet=""$$$ERROR(5659, "Pet") } If$IsObject(..Pet) $$$QuitOnError(..Pet.%ValidateObject()) Quit sc }

    }

    <p>
       
    </p>
    

     

    ^%REST の使用方法と同じように、「petstoreserver.impl」クラスには、サービスに関連したすべてのメソッドが含まれており、開発者が実装する必要があります。 

    Class petstoreserver.impl Extends%REST.Impl [ ProcedureBlock ]
    {
    
    Parameter ExposeServerExceptions = 1;/// Service implemntation for post /petClassMethod addPet(messageRequest As petstoreserver.requests.addPet) As%Status
    {
        ; Implement your service here.; Return {}$$$ThrowStatus($$$ERROR($$$NotImplemented))
    }
    
    ...
    }

     

    生成されたパッケージの短い説明

      <td>
        タイプ
      </td>
      
      <td>
        説明
      </td>
    </tr>
    
    <tr>
      <td>
        petstoreclient.model petstoreproduction.model
      </td>
      
      <td>
        クライアントサイドとサーバーサイド
      </td>
      
      <td>
        すべてのモデルが含まれます。  これらのクラスは、JSON から簡単にオブジェクトを読み込めるように %JSON.Adaptor を拡張します。   プロダクションが生成されると、これらのクラスは %Persistent も拡張します。
      </td>
    </tr>
    
    <tr>
      <td>
        petstoreclient.requests   petstoreproduction.requests
      </td>
      
      <td>
        クライアントサイドとサーバーサイド
      </td>
      
      <td>
        %Net.HttpRequest を簡単に初期化するために使用されるオブジェクト。  仕様にはオペレーションごとのクラスが定義されています。プロダクションが生成される場合、これらのクラスは Ens.Request を拡張します。 注意: このクラスの実装は、生成対象がサーバーサイドであるかクライアントサービスであるかによって異なります。  クライアントサイドの場合、すべてのクラスには「LoadHttpRequestObject」メソッドが含まれるため、このクラスプロパティから「%Net.HttpRequest」を読み込むことができます。 クラスがサーバーサイドを対象に生成される場合、「%request」オブジェクトからインスタンスを読み込むために、各クラスに「LoadFromRequest」メソッドが含まれています。
      </td>
    </tr>
    
    <tr>
      <td>
        petstoreclient.responses petstoreproduction.responses
      </td>
      
      <td>
        クライアントサイドとサーバーサイド
      </td>
      
      <td>
        petstoreclient.requests の 逆です。  %Net.HttpRequest のレスポンスを処理できます。プロダクションが生成される場合、これらのクラスは Ens.Response を拡張します。
      </td>
    </tr>
    
    <tr>
      <td>
        petstoreclient.HttpClient
      </td>
      
      <td>
        クライアントサイド
      </td>
      
      <td>
        HTTP リクエストを実行するためのすべてのメソッドが含まれます。OpenAPI 仕様で定義されるオペレーションごとに 1 つのメソッドがあります。
      </td>
    </tr>
    
    <tr>
      <td>
        petstoreproduction. bo.Operation
      </td>
      
      <td>
        クライアントサイド
      </td>
      
      <td>
        オペレーションクラスには、OpenAPI 仕様で定義されたオペレーションごとに 1 つのメソッドがあります。
      </td>
    </tr>
    
    <tr>
      <td>
        petstoreproduction.bp
      </td>
      
      <td>
        クライアントサイド
      </td>
      
      <td>
        同期と非同期の 2 つのデフォルトのビジネスプロセスが定義されています。
      </td>
    </tr>
    
    <tr>
      <td>
        petstoreproduction.bs
      </td>
      
      <td>
        クライアントサイド
      </td>
      
      <td>
        実装するすべての空のビジネスサービスが含まれます。
      </td>
    </tr>
    
    <tr>
      <td>
        petstoreproduction.Production
      </td>
      
      <td>
        クライアントサイド
      </td>
      
      <td>
        プロダクション構成の設定。
      </td>
    </tr>
    
    <tr>
      <td>
        petstoreserver.disp
      </td>
      
      <td>
        サーバーサイド
      </td>
      
      <td>
        クラス dispatch %CSP.REST
      </td>
    </tr>
    
    <tr>
      <td>
        petstoreserver.Spec
      </td>
      
      <td>
        サーバーサイド
      </td>
      
      <td>
        このクラスには、XData ブロックに OpenAPI 仕様が含まれています。
      </td>
    </tr>
    
    <tr>
      <td>
        petstoreserver.impl
      </td>
      
      <td>
        サーバーサイド
      </td>
      
      <td>
        これには、OpenAPI 仕様で定義されたオペレーションに関連するすべての空のメソッドが含まれています。  これが、開発者がサービスを実装する必要のあるクラス(%REST.Impl を拡張)です。
      </td>
    </tr>
    
    パケージ名 / クラス名

    開発ステータス

    OpenAPI-Suite はまだ非常に未熟な製品であり、さらに多くのテストを実施した上での改善が必要です。  OpenAPI 3 のサポートは部分的であり、さらに多くの機能がサポートされる可能性があります。 

    テストは公開されている仕様 https://petstore3.swagger.io/api/v3/openapi.json と比較的に単純な 2 つの仕様を使って実施されました。  もうちろん、すべてのケースに対応するには不十分です。  仕様を共有していただければ、喜んでテストに使用させていただきます。

    このプロジェクトの基盤は十分であり、AsyncAPI をサポートするように拡張するなど、簡単に進化させることができると考えています。

    お気軽にフィードバックをお寄せください。

    このアプリケーションをご利用いただき、開発者ツールコンテストで支援していただければ幸いです。

    お読みいただきありがとうございました。

    0
    0 132
    記事 Mihoko Iijima · 9月 26, 2023 4m read

    この記事では、2023年3月1日~31日の期間に開催された「技術文書ライティングコンテスト:InterSystems IRISチュートリアル」に応募された24作品の中から、Open Exchangeに公開されている sqlalchemy-iris を利用してPythonとSQLでIRISのデータを操作する方法を投稿された Heloisa Paivaさんの記事をご紹介します。

    Open Exchangeは、世界各地にいる開発者コミュニティメンバーが開発したインターシステムズ製品で利用できるサンプルアプリが登録されているページで、自由にダウンロードしてご利用いただけます。

    Heloisaさんの記事のように公開されている Open Exchange の利用例があると、「ちょっと使ってみたいな・・」と思われているメンバーの方への情報共有ができてとても有用な記事になると思います!丁度日本で初開催の「技術文書ライティングコンテスト」開催中ですので、ぜひ使用例や感想など、投稿してみてください!💪

    0
    0 787
    お知らせ Mihoko Iijima · 8月 8, 2023

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

    次の InterSystems オンラインプログラミングコンテストは、Pythonに特化した内容を予定しています!

    🏆 InterSystems Python プログラミングコンテスト 🏆

    期間: 2023年9月4日~24日

    賞金総額: $13,500


    0
    0 402
    お知らせ Mihoko Iijima · 5月 30, 2023

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

    毎年恒例の InterSystems IRIS開発者向け「グランプリ・コンテスト」の開催が決定しました!

    今年のお題は「InterSystems IRIS data platformを利用してオープンソースを作成する」です。

    🏆 InterSystemsグランプリ・コンテスト2023 🏆

    期間: 2023年6月12日~7月2日

    賞金総額: $26,000


    0
    0 192
    記事 Toshihiko Minamoto · 4月 28, 2023 2m read

    本番環境でのopenhl pythonモジュールの使用に関する作業の説明の続きです。

    Embedded Pythonを搭載しているirisは、まだ最終リリースがされていません(原文投稿当時)が、現時点で本番で使用する必要があります。 そこで、リクエストをxlsxファイルにエクスポートするサービスは別サーバーにバックアップし、クエリ結果は別データベースのグローバルに保存することにしました。

    このデータベースは、ネットワーク化され、サービスサーバーはローカル、本番サーバーはリモートとしています。本番サーバー、サービスサーバ間のコミュニケーションは、REST サービスを使って実装しています。

    つまり、クライアントアプリケーションのサーバー上では、ユーザーは大きなレポートを発行します。レポートはバックグラウンドで作成され、グローバルに保存されています。 リモートデータベース上では、グローバルへの完全な参照をパラメータとしてRESTサービスが呼び出されます。 このサービスはバックグラウンドで起動し、Excelファイルに内容をエクスポートし、その後、合図として生成されたファイルへのリンクでRESTサービスを呼び出します。 メッセージを受け取った本番サーバーのサービスは、Excelファイルをアーカイブして、クライアントにメールで送信します。 そして、ここで忘れてはならないのは、リモートとローカルのデータベースは単一のリソースで保護されなければならず、その特権はファイルを生成するユーザーに割り当てられなければならないことです。

    これにより、プロダクトサーバーで%SYS.ZENReportExcelExporterを置き換えています。 将来的には、このソリューションの発展形として、メールによるファイル送信を、準備完了の通知によりユーザが独自にダウンロードできる生成ファイルのリンクパネルに置き換えることを計画しています。

    0
    0 387
    記事 Toshihiko Minamoto · 4月 5, 2023 3m read

    テクノロジー分野で 19 年間働いてきた中、様々な分野でいくつかのプロジェクトに参加することができましたが、健康分野は私が一番惹かれている分野の 1 つです。

    健康に焦点があてられたものを作成するチャンスを得るたびに、FHIR プロトコルを使用することにワクワクしています。

    とは言え、テック系の 3 人の IT 男子で構成されるチームでは、本当に利用価値のあるものを作り出すのは困難であるため、女性の健康のように重要なトピックにおいては、この主題を非常によく理解している人をチームに招きました。

    15 年以上の経験があるだけでなく、医師として 1,000 回以上の出産を担当した経験も持ち合わせた産婦人科医の Talita Yurie Nakata 医師です。 彼女のビジョンとガイダンスにより、私たちはこのアイデアの重要性と、それが医師と患者にどれだけ役立つかを理解しました。

    このアプリケーションの背後には、患者(妊娠者)の情報を患者自身に提供し、そのデータを更新できるようにすれば、妊娠経過を管理している医師は常に状況を認識し、異常が発生した場合にアラートを受け取れるようになるという 構想があります。

    患者の 2 つの指標(体重と血圧)データを使って、妊娠状況を監視し、望ましくない合併症を予防することができました。 (もちろん、より正確なビューを得るには、情報が多いほど良いのですが、この MVP ではこれらの 2 つのデータを使用します)

    太りすぎには妊娠糖尿病のリスクが伴い、高血圧は子癇(しかん)を引き起こす可能性があります。

    また、以下の記事で研究されているとおり、いずれの状態も、母体と胎児に多くの問題をもたらしてしまいます。

    Maternal Obesity and Risk of Gestational Diabetes Mellitus(母体の肥満と妊娠糖尿病のリスク)
    https://diabetesjournals.org/care/article/30/8/2070/28574/Maternal-Obesity-and-Risk-of-Gestational-Diabetes

    Pre-Pregnancy Obesity, Excessive Gestational Weight Gain, and the Risk of Pregnancy-Induced Hypertension and Gestational Diabetes Mellitus(妊娠前の肥満、妊娠による過度の体重増加、および妊娠による高血圧と妊娠糖尿病のリスク)
    https://www.mdpi.com/2077-0383/9/6/1980
     
    Influence of maternal obesity on the association between common pregnancy complications and risk of childhood obesity: an individual participant data meta-analysis(一般的な妊娠合併症と小児肥満のリスクの関係に対する母体の肥満の影響: 各参加者データのメタ分析)
    https://www.sciencedirect.com/science/article/abs/pii/S2352464218302736

    FioCruz: Oswaldo Cruz Foundation
    Gestational obesity: an alert situation(妊娠性肥満: 警戒すべき状況)
    https://portal.fiocruz.br/noticia/obesidade-gestacional-uma-situacao-de-alerta

    以下は、Febrasgo( ブラジル産婦人科連合会)からの引用です。

    1 型糖尿病、2 型糖尿病、または妊娠糖尿病の女性は、子癇前症を発症するリスクが高くなります。 最初の 2 つの状況は慢性の軽度の炎症に関連しており(Nunemaker, 2016)、子癇前症の妊婦は妊娠前にインスリン抵抗性になりやすいという事実に加えて、これが糖尿病の女性が子癇前症を発症する可能性が高い理由の 1 つである可能性があります(Scioscia et al., 2009)。 妊娠糖尿病を患う妊婦には、内皮機能不全の証拠から、子癇前症の妊婦と同様の免疫プロファイルがあると言えます。

    謝辞

    繰り返しになりますが、作成する各アプリケーションへのすべてのコミュニティサポートに感謝の意を表したいと思います。

    このアプリが興味深いと思われた方、インサイトに貢献していると感じた方は、ぜひこのアプリに投票してください。笑い

    アプリを気に入っていただけた方、私たちのコミュニティへの貢献を楽しみとされている方は、Pregnancy Symptoms Tracker に投票し、この制作活動をご支援ください!

    1
    0 127
    お知らせ Mihoko Iijima · 3月 27, 2023

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

    次のプログラミングコンテストの詳細が決定し「IRIS Cloud SQLのデータを利用してAI/MLソリューションを作成する」がテーマとなりました。

    🏆 InterSystems IRIS Cloud SQL and IntegratedML コンテスト 🏆

    期間: 2023年4月3日~23日

    賞金総額: $13,500

     

    0
    0 109
    お知らせ Mihoko Iijima · 2月 13, 2023

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

    InterSystems デベロッパーツールコンテストの勝者が発表されました!

    この記事では、コンテスト受賞者を発表します📣

    その前に...

    今回のコンテストですが、なんと 21 の応募 がありました!🔥  多数のご応募、ありがとうございました!

    1
    0 157
    お知らせ Mihoko Iijima · 2月 10, 2023

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

    【InterSystems デベロッパーツールコンテスト】の投票が開始されました!

    🔥 ベストアプリケーションはこれだ!! 🔥 と思う作品にぜひ投票をお願いします!

    (今回は21作品がエントリーされています!)

    投票方法は以下ご参照ください。

    0
    0 127
    お知らせ Mihoko Iijima · 1月 15, 2023

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

    2023年最初のコンテストの開催が決定しました!今回は、開発者の皆さんの開発が快適になるような便利ツールをご応募いただくコンテストです!

    🏆 InterSystems デベロッパーツールコンテスト🏆

    InterSystems IRISを使用して、開発のスピードアップ、より定性的なコードの貢献、テスト、デプロイ、サポート、ソリューションのモニタリングを支援するアプリケーションを提出してください。

    期間: 2023年1月23日~2月12日

    賞金: $13,500

     

    0
    0 145
    お知らせ Mihoko Iijima · 11月 30, 2022

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

    【InterSystems IRIS for Health コンテスト: FHIR ソリューション for Women's Health】の投票が開始されました!

    🔥 ベストソリューションはこれだ!! 🔥と思う作品にぜひ投票お願いします!

     

    投票方法は以下ご参照ください。

    0
    0 100
    お知らせ Mihoko Iijima · 10月 11, 2022

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

    次のコンテストの詳細が決定しましたのでお知らせします📣

    今回は、FHIRの知識を共有するためのコンテストを企画しています。

    🏆 InterSystems IRIS for Health コンテスト: FHIR for Women's Health 🏆

    InterSystems FHIR または、InterSystems Healthcare Interoperability を使用したアプリケーションを作成してご応募ください。

    期間: 2022年11月14日~12月4日

    賞金: $13,500!

    >> 応募はこちらから! <<

    0
    0 181
    お知らせ Mihoko Iijima · 9月 15, 2022

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

    サステナブルなソリューションの構築をテーマとした Interoperability プログラミングコンテストの投票が開始されました!

    🔥 ベストアプリケーションはこれだ! 🔥 と思う作品にぜひ投票お願いします!

    投票方法は以下ご参照ください。

    0
    0 86