ブラウザ上でローカルLLMと対話したい#3|HTTPリクエスト

0 アクセス

はじめに

この記事はブラウザ上でローカルLLMと対話したい#2|ローカルHTTPサーバーの続き

今回はローカルのOllamaサーバーにAPIリクエストを送り、その結果を表示する部分を実装する

javascriptを別ファイルに書き出す

#1の時点では、1個のhtmlファイルにjavascriptも書いていたが、ここからは別でtest.jsというファイルをjsディレクトリ配下に作成し、作業していく

そこで、htmlファイルは以下のように書く

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>LLM Chat</title>
</head>
<body>
    <input type="text" id="inputmsg"> <!--入力ボックス-->
    <button type="button" id="send">送信</button><!--送信ボタン-->

    <div id="messages"><!--メッセージ領域-->
    </div>

    <script src="js/test.js" charset="utf-8"></script>
</body>
</html>

<script src=”js/test.js” charset=”utf-8″></script>の部分がjavascriptを呼び出す部分
jsファイルを相対パスで指定している

ソースコード

全体像
今回はchat関数の追加が主な変更点

async function chat(message) {
    const url = 'http://127.0.0.1:11434/api/chat';

    const data = {
        model: "Llama-3.1-Swallow-8B-Instruct-v0.1_Q4_K_M",
        messages: [{ role: "user", content: message }],
        stream: false
    };

    // 非同期なHTTPリクエストを送信
    const response = await fetch(url, {
        method: "POST",
        headers: {
            "Content-Type": "application/json"
        },
        body: JSON.stringify(data)
    });

    const result = await response.json();
    return result.message;

}

const inputMsg = document.getElementById('inputmsg');
const sendBtn = document.getElementById('send');
const messagesDiv = document.getElementById('messages');

sendBtn.addEventListener('click', async () => {
    const message = inputMsg.value.trim();
    
    // messagesに送信メッセージを追加
    const userMessageEl = document.createElement('div');
    userMessageEl.textContent = message;
    messagesDiv.appendChild(userMessageEl);

    // 入力をクリア
    inputMsg.value = '';

    // messagesに返信メッセージを追加
    // chat関数が完了するまで待つ
    const result = await chat(message);
    
    const systemMessageEl = document.createElement('div');
    systemMessageEl.textContent = result.content;
    messagesDiv.appendChild(systemMessageEl);

});

chat関数

入力メッセージを受け取り、返信メッセージを返す非同期関数

async function chat(message) {
    const url = 'http://127.0.0.1:11434/api/chat';

    const data = {
        model: "Llama-3.1-Swallow-8B-Instruct-v0.2_Q4_K_M",
        messages: [{ role: "user", content: message }],
        stream: false
    };

    // 非同期なHTTPリクエストを送信
    const response = await fetch(url, {
        method: "POST",
        headers: {
            "Content-Type": "application/json"
        },
        body: JSON.stringify(data)
    });

    const result = await response.json();
    return result.message;

}

dataは辞書型の変数、modelでLLMのモデルを指定する
指定したモデルはLlama 3.1 SwallowをOllamaで使えるようにする|ローカルLLMで追加したモデルの現時点での最新バージョン
ここはOllamaに入っている各自のモデルを指定すればよい

fetchで非同期なHTTPメソッドを送信する
これの前にawaitをつけることで、処理が完了するまで先へ進まないようにしている

responseはサーバーからの応答をjson形式で受け取る
これも非同期処理なので、awaitで応答を待つ(処理が完了するまでは、reultにはPromiseが格納される)
もし待たなければ、最後のresult.messageでエラーが起こる

実行画面

ローカルサーバーを立ててブラウザでファイルを開く方法については前回の記事を参照

Ollamaのサーバーも別のターミナルを開いて立てる

(参考)OllamaのPythonライブラリを使ってローカルLLMを利用する

ローカルホストのページをブラウザで開いて、メッセージを送信する

これで、超簡易的ではあるが、ローカルLLMとメッセージのやりとりがブラウザ上でできるようになった
なお、会話履歴はLLMに送っていないので、応答は前のメッセージの内容を反映していない

今後の予定

さらに改善するための例を一部挙げる

  • 会話履歴を反映した会話
  • 表示画面などのUI改善
  • Enterキーで送信する機能の追加