以前のエントリでは、Ollama
を使ってローカル環境でLLM
を構築する手順を説明しました。それだけでも十分に活用できるのですが、さらに一歩進めて、Ollama
をより深く活用する方法について考えてみました。Ollama
をセットアップすると、REST APIを介してシステムからアクセスできるようになります。このREST API経由でシステムと連携することで、より柔軟にOllama
の活用の可能性が広がります。今回は、REST APIを通じてOllama
の機能を使う手法についてしらべてみたいと思います。
今回はLLM
のモデルとしてMeta社のLllama3.1:8B
を使用しています。これ以上のサイズだとメモリが足りないというエラーが発生しました😢AIを使うのであればメモリ32GBあたりはもう必須な領域のようです。
また、使用環境についてはUbuntu22.04 LTS
上のDockerコンテナ
でOllama
を使用しています。
環境構築の参考
Ollamaのドキュメント関連参考
以下がOllama
のGitHub
で詳細はこちらに書いてあります。
APIの詳細 github.com
APIをCurlから使用してみる
LLM
とのやり取りは応答とチャット(やり取り)の2つがあり、それぞれにEndpoint
があります。
- Generate a completion(応答 Endpoint…
/api/generate
) - Generate a chat completion(チャット Endpoint…
/api/chat
)
複数のやり取りが必要あれば、チャットを使用することになります。ドキュメントにはcurlコマンド
での実行例が記載されているので試してみます。
Generate a completionの例(プロンプトだけ変えています)
【リクエスト】
$ curl http://localhost:11434/api/generate -d '{ "model": "llama3.1", "prompt": "ウミガメのスープという水平思考クイズを知っていますか?", "stream": false }'
【レスポンス】
{ "model":"llama3.1", "created_at":"2024-08-09T06:34:20.433953084Z", "response":"、、\n\nウミガメ = ガメ = ケツ = 瓶 = ウサギ = 肩 = チョコ = 甘いです。", "done":true, "done_reason":"stop", "context":[128009,128006,882,128007,271,65299,101198,102472,39850,16144,22398,107610,102677,116840,125456,29220,122624,30512,53283,76947,61689,32149,11571,128009,128006,78191,128007,271,5486,28918,65299,101198,102472,39850,284,124109,39850,284,125867,103223,284,10447,241,114,284,111707,60868,104603,284,107399,102,284,113442,78205,47260,284,220,110631,16995,38641,1811], "total_duration":14813701568, "load_duration":42110686, "prompt_eval_count":29, "prompt_eval_duration":432507000, "eval_count":34, "eval_duration":14297268000 }(ollama_api)
謎の回答が帰ってきました。連想ゲームと認識されているようです。
"response":"、、\n\nウミガメ = ガメ = ケツ = 瓶 = ウサギ = 肩 = チョコ = 甘いです。"
このレスポンスに関しては毎回テキストの内容は異なるのでその点には注意してください。
基本的には継続したやり取りを行わないのであればどちらでもいいのですが、より汎用的なものはチャットの方ですので以降はこちらを考えていくようにします。
Pythonを使用してみる
Pythonの一般的なライブラリを使用する
Curlコマンド
は便利なのですが、Pythonからアクセスしてみます。REST APIへのアクセスにはrequestsライブラリが必要なので、事前にインストールを行います。
ライブラリのインストール
$ pip3 install requests
先ほどのCurlコマンド
をPythonのコードに修正してみました。また、今回はStream型でデータを受信し、受信後にレスポンス文として変換しています。実行するとChatGPT
ではお馴染みのタイピングが徐々に行われるような形で表示されると思います。注意Stream型の場合には文字が取り込まれる毎にJSON形式のデータが受信されます。受信のオーバーヘッドが大きいので、返答のデータが小さい場合にはSteamはFalseにしても良いでしょう。(省略時はStreamはTrueとなります。)
import requests import json url = "http://localhost:11434/api/chat" headers = { "Content-Type": "application/json" } data = { "model": "llama3.1", "messages": [ { "role": "user", "content": "ウミガメのスープという水平思考クイズを知っていますか?" } ] } response = requests.post(url, headers=headers, json=data, stream=True) for chunk in response.iter_lines(): if chunk: chunk_data = json.loads(chunk.decode('utf-8')) # バイト列をデコードしてJSONに変換 if 'message' in chunk_data and 'content' in chunk_data['message']: print(chunk_data['message']['content'], end='', flush=True)
こんな形でPythonの実装ができます。
実行例
$ python ollama_api_sample.py はい、ウミガメのスープという題名で、回答する必要がある、答えが複数種類存在し、それぞれ異なる条件や性質を持つ問題です。
それらしい回答が帰ってきていますが、ハルシネーションは起こっています。
Ollamaライブラリがありました!
簡単にできる状態ですが、Ollama
のGithub
のサイトに専用のライブラリが準備されていました。それを使用すると以下のように記述できます。
ライブラリのインストール
$ pip install ollama
先ほどのコードをライブラリにすると以下のようになります。かなり短くできるようです。
import ollama stream = ollama.chat( model='llama3.1', messages=[{'role': 'user', 'content': 'ウミガメのスープという水平思考クイズを知っていますか?'}], stream=True, ) for chunk in stream: print(chunk['message']['content'], end='', flush=True)
実行例
$ python ollama_lib_stream.py 水平思考問題とは、与えられた情報に基づいて、その内容と逆のイメージを持つことを課題として提示するものです。具体的には、一方が「○」で、それに対して一方が「×」と考えさせるタイプの質問です。 例えば、「ウミガメのスープ」の場合、まずは「うみがめ」を思い出します。その後、「スープが存在した場合に何かあるはずがない」ようなものを考えてみるといいと思います。そうすると、思いつくのが「陸に上がった海水」という答えです。この例では、一方が「海の生物であるウミガメの食べ物」で、もう一方は「陸の上のスープ」を想像することで、逆のイメージを得ることができます。
こちらは長い回答例ですが、これもハルシネーションは発生しています。
おわりに
今回の記事では、Ollama
のローカルLLM環境
を活用し、REST API
を通じてPython
から直接アクセスする方法を紹介しました。これにより、Ollama
のLLM
を他のシステムと柔軟に統合できるようになります。例えば、チャットボットやカスタムAIアシスタントの構築、データ分析ツールへのAI機能の組み込みなども可能でしょう。
APIを利用することで、システム全体の連携が向上し、手作業で行っていたプロセスを自動化することも容易になります。特に、プログラミングとの親和性が高く、簡単に組み込める点は非常に魅力的だと思います。今回紹介した方法をぜひ試してみてください。