はじめに
この記事はブラウザ上でローカルLLMと対話したい#4|対話履歴の追加のつづき
前回でテキスト対話システム部分はたぶんほぼ完成なので、今回から見た目を整えていく
class属性とは
class属性とは、HTMLタグに追加できる属性の1種
- cssやjavascriptの要素選択に使用
- 1つの要素に複数のクラスを割り当てられる
- 1つのクラスを複数の要素で共有できる
今回は、メッセージがユーザから発せられたのか、システム側から発せられたのかを区別するために使用する
class属性を追加
下記は、ユーザの入力メッセージを処理する部分の一部
(全体のソースコードはこの記事の最後に記載)
const message = inputMsg.value.trim();
// messagesに送信メッセージを追加
const userMessageEl = document.createElement('div');
// 送信メッセージにuser-messageクラス属性を追加
userMessageEl.classList.add('user-message');
userMessageEl.textContent = message;
messagesDiv.appendChild(userMessageEl);
// dialogueに送信メッセージを追加
dialogue.push({ role: "user", content: message});
今回追加したのは5,6行目の部分
要素にclass属性を追加するには、classList.add(クラス名)とする
今回はクラス名を’user-message’とした
システム側のメッセージにも同様に、’system-message’ class属性を追加しておく
cssでレイアウト
cssの書き方についてはこれから勉強が必要なので今回は簡単に、ユーザメッセージを右、システムメッセージを左にするように配置を指定するのみにした
jsファイル同様に、cssファイルを別で書くこともできるが、今回はhtmlのhead部分に追加した
記述するには<style>タグで囲った部分
クラス属性から要素を指定するには、.(ドット)クラス名とする
(例).user-message
サンプルコード
.user-message {
text-align: right;
margin-bottom: 10px;
}
.system-message {
text-align: left;
margin-bottom: 10px;
}
text-alignでテキストを右詰めか左詰めかを指定している
margin-bottomは余白の調整用
実行例

ユーザの入力が右、システムの返信が左に表示されていることがわかる
(LLMの発言内容はとんでもない間違いだが、正しい知識がなければ信じそうになるのが怖い)
おわりに
もっとcssデザインにこだわるポイントはありそう
ソースコード
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>LLM Chat</title>
<style>
.user-message {
text-align: right;
margin-bottom: 10px;
}
.system-message {
text-align: left;
margin-bottom: 10px;
}
</style>
</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>
// npx http-server
// ollama serve
// をあらかじめ実行
async function chat(dialogue) {
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: dialogue,
stream: false
};
console.log(data)
// 非同期な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');
// 対話履歴を保持する配列
const dialogue = [];
sendBtn.addEventListener('click', async () => {
const message = inputMsg.value.trim();
// messagesに送信メッセージを追加
const userMessageEl = document.createElement('div');
// 送信メッセージにuser-messageクラス属性を追加
userMessageEl.classList.add('user-message');
userMessageEl.textContent = message;
messagesDiv.appendChild(userMessageEl);
// dialogueに送信メッセージを追加
dialogue.push({ role: "user", content: message});
// 入力をクリア
inputMsg.value = '';
// messagesに返信メッセージを追加
// chat関数が完了するまで待つ
const result = await chat(dialogue);
const systemMessageEl = document.createElement('div');
// 受信メッセージにsystem-messageクラス属性を追加
systemMessageEl.classList.add('system-message');
systemMessageEl.textContent = result.content;
messagesDiv.appendChild(systemMessageEl);
// dialogueに返信メッセージを追加
dialogue.push({ role: "assistant", content: message});
});
コメントを残す