2024年12月9日月曜日

OllamaのStructured outputsの動作を確認する

OllamaがStructured Outputsをサポートしました。2024年12月6日付のブログ記事Structured outputsに紹介されています。

上記の記事の最後の方に、OpenAI compatibilityのセクションがあります。OpenAI互換のChat Completions APIでもStructured outputsをサポートしているとのことなので、以前に作成したOpenAIのChat Completions APIを呼び出すアプリを使って動作を確認してみます。

作業環境はApple Macbook ProのM4 Max/128GBです。大きなモデルを動かした方が良い結果が得られるとは思いますが、llama3.1:8bのモデルでも指定したJSONスキーマに従った回答が得られました。

日本語能力が高くないllama3.1に、日本語で「日本について教えて。」と聞いたせいか、languages日本語英語中国語が返されています。また、同じ質問でも回答がブレます。英語で「Tell me about Japan.」と聞くと、ほとんどは以下の回答になります。
{
  "capital" : "Tokyo",
  "languages" :
  [
    "Japanese"
  ],
  "name" : "Japan"
}
どちらでも指定したJSONスキーマに従ったレスポンスにはなっています。


OpenAIのChat Completions APIを呼び出すAPEXアプリケーションは、今までTool CallingやStructured Outputsの対応を後付けしてきたため、アプリケーションを動くようにするために、あちこちの記事を参照する必要があります。

以下にインストールまでの手順をまとめます。

1. ローカルPCへのAPEX環境作成


手元のPCにAPEX環境を作成する手順は以下の記事を参照します。Oracle Database 23ai FreeとOracle REST Data Servicesそれぞれのコンテナを作成して、APEX環境を作成しています。

podmanを使ってOracle Database FreeとOracle REST Data Servicesをコンテナとして実行する

Oracle Database 23ai FreeのコンテナにOracle REST Data Servicesをインストールする手順も紹介していますが(こちらの記事)、せっかくOracle社がソフトウェアをインストール済みのコンテナ・イメージを提供してくれているので、そちらを使用する方が作業は容易です。

2. 表OPENAI_TOOLSの作成


以下のDDLを実行して表OPENAI_TOOLSを作成します。この表はTool Callingの設定を保持します。


表OPENAI_TOOLSのDDLが掲載されている記事は以下です。
OpenAIのChat Completions APIを呼び出すAPEXアプリを作成する

APEXアプリケーションへのToll Callingの組み込みを紹介している記事は以下です。


3. 表OPENAI_RESPONSE_FORMATSの作成


以下のDDLを実行して表OPENAI_RESPONSE_FORMATSを作成します。この表はStructured Outputsの指定に必要なJSONスキーマを保持します。


表OPENAI_RESPOSE_FORMATSが掲載されている記事は以下です。
OpenAIのChat Completions APIでStructured Outputsを指定する


4. パッケージUTL_OPENAI_CHAT_APIの作成



記事の末尾に添付されているパッケージ定義部とパッケージ本体のコードを実行し、パッケージUTL_OPENAI_CHAT_APIを作成します。


5. APEXアプリケーションのインポート



以下のAPEXアプリケーションをワークスペースにインポートします。
https://github.com/ujnak/apexapps/blob/master/exports/chat-with-generative-ai-so.zip

APEXアプリケーションへのStructured Outputsの対応を紹介した記事は以下です。
OpenAIのChat Completions APIでStructured Outputsを指定する

以上で、ローカルのOllamaを呼び出してStructured Outputsの確認をするAPEXアプリケーションの準備ができました。

今回の作業で使用したOllamaのバージョンは0.5.1です。バージョンが古い場合は、アップデートしておきます。

ollama --version

% ollama --version

ollama version is 0.5.1

%



動作確認



本記事の本題の動作確認をします。

最初にOllamaのブログ記事にある例を動かしてみます。国の情報をJSONで返してもらいます。

Response Formatsのページを開きます。Format NamecountryFormat Typejson_schema、JSON Schemaは以下を登録します。
{
  "type" : "object",
  "properties" :
  {
    "name" :
    {
      "type" : "string"
    },
    "capital" :
    {
      "type" : "string"
    },
    "languages" :
    {
      "type" : "array",
      "items" :
      {
        "type" : "string"
      }
    }
  },
  "required" :
  [
    "name",
    "capital",
    "languages"
  ]
}

Ollamaでllama3.1:8bをpullします。

ollama pull llama3.1:8b

% ollama pull llama3.1:8b

pulling manifest 

pulling 667b0c1932bc... 100% ▕███████████████████████████████████████████████████████████████████████▏ 4.9 GB                         

pulling 948af2743fc7... 100% ▕███████████████████████████████████████████████████████████████████████▏ 1.5 KB                         

pulling 0ba8f0e314b4... 100% ▕███████████████████████████████████████████████████████████████████████▏  12 KB                         

pulling 56bb8bd477a5... 100% ▕███████████████████████████████████████████████████████████████████████▏   96 B                         

pulling 455f34728c9b... 100% ▕███████████████████████████████████████████████████████████████████████▏  487 B                         

verifying sha256 digest 

writing manifest 

success 

% 


APEXアプリケーションのホーム・ページを開きます。以下の操作を行い、LLMの出力を確認します。
  1. ボタンStart New Conversationをクリックする。
  2. Response Formatcountryを選択する。
  3. API Endpointhttp://host.containers.internal:11434/v1/chat/completionsを入力する。
  4. Model Namellama3.1:8bを入力する。
  5. MessageTell me about Japanを入力する。
  6. ボタンSend Messageをクリックする。
以上で、assistantから以下のメッセージが返されます。
{
  "capital" : "Tokyo",
  "languages" :
  [
    "Japanese"
  ],
  "name" : "Japan"
}

もう一つ、JSON Schemaを登録します。物語の登場人物と関係をJSONで表現します(Batch APIの記事で使っています)。

Format NamestoryFormat Typejson_schemaJSON Schemaとして以下を登録します。



Response Formatstoryを選択し、Messageとして以下を入力します。白雪姫の物語をChatGPTに1000語で出力してもらいました。
Please represent the characters and their relationships in the following story in JSON format.
--------
[ChatGPTが出力した白雪姫の物語を添付]


assistantからのレスポンスは以下です。
{
  "characters" :
  [
    {
      "name" : "Queen",
      "role" : "Main Character",
      "relations" :
      {
        "spouse" : "",
        "children" : "Snow White"
      }
    },
    {
      "name" : "King (initial husband of Queen)",
      "role" : "Background/Dead",
      "relations" :
      {
        "wife" : "Queen"
      }
    },
    {
      "name" : "New queen (second wife of King)",
      "role" : "Antagonist",
      "relations" :
      {
        "husband" : "King"
      }
    },
    {
      "name" : "Snow White",
      "role" : "Protagonist/Princess",
      "relations" :
      {
        "mother" : "Queen (initial husband's wife)",
        "father" : "King (initial)"
      }
    },
    {
      "name" : "Huntsman",
      "role" : "Support Character",
      "relations" :
      {
      }
    },
    {
      "name" : "Mirror",
      "role" : "Plot Device",
      "relations" :
      {
      }
    },
    {
      "name" : "Seven Dwarfs (miner group)",
      "role" : "Support Characters/Homeowners",
      "relations" :
      {
      }
    },
    {
      "name" : "Prince",
      "role" : "Love Interest/Hero",
      "relations" :
      {
        "partner/wife" : "Snow White"
      }
    }
  ]
}
指定したJSONスキーマに規定されたレスポンスが返されていることが確認できます。

もう少し頑張ってプロンプトを書くと、レスポンスに含まれるroleやrelationsの精度は上がるように思います。日本語についてはモデル次第だろうとは思いますが、いくつか試したモデルでは、意味のある回答は得られませんでした。

今回の記事は以上になります。