前回は、「会話履歴つきChatbot」を実装しました。
今回はこのチャットボットを改善していきます。
何を改善する?
botの性格や役割を追加しよう
前回の記事では、以下のように記載していました。
一般的には、会話履歴を
messagesという配列で持ちます。
役割は主に 3 つです。
- assistant:chatbot の返答
- system:chatbot の振る舞い
- user:ユーザーの発言
この「system」について触れていなかったので、こちらを追加していこうと思います。
履歴が長くなりすぎないようにする
会話が長くなると、ローカルモデルでは重くなりやすいという問題があります。
そのため、会話をリセットする、直近の履歴だけ送る ことで履歴を長くなりすぎないように対策することができます。
前回までのおさらい
コード
from ollama import chat
MODEL_NAME = "gemma3"
def main():
messages = []
while True:
user_input = input("You: ").strip()
if user_input in ["exit", "quit", "終了"]:
print("Bot: 終了します。")
break
messages.append({"role": "user", "content": user_input})
response = chat(
model=MODEL_NAME,
messages=messages
)
answer = response["message"]["content"]
print(f"Bot: {answer}")
messages.append({"role": "assistant", "content": answer})
if __name__ == "__main__":
main()botの性格や役割を追加しよう
会話履歴を管理している配列 messages に、system メッセージを追加することで、
bot の性格や役割を固定することができます。
今回は「日本の観光ガイド」という役割を振ってみます。
from ollama import chat
MODEL_NAME = "gemma3"
SYSTEM_PROMPT = "あなたは丁寧でわかりやすい日本の観光ガイドです。" # → 差分
def main():
messages = [ # → 差分
{"role": "system", "content": SYSTEM_PROMPT} # → 差分
] # → 差分
while True:
user_input = input("You: ").strip()
if user_input in ["exit", "quit", "終了"]:
print("Bot: 終了します。")
break
messages.append({"role": "user", "content": user_input})
response = chat(
model=MODEL_NAME,
messages=messages
)
answer = response["message"]["content"]
print(f"Bot: {answer}")
messages.append({"role": "assistant", "content": answer})
if __name__ == "__main__":
main()早速、「これから東京に行きます」とだけ伝えたらどのような回答が来るでしょうか…?

観光ガイドとして、「目的」「旅行期間」「誰と」など、旅行計画を明確にするための質問をしてくれるようになりました!
履歴が長くなりすぎないようにする
会話をリセット
現状の会話履歴つきChatbotは、前の文脈をずっと引き継いで回答してくれます。
話を変えたい時など、途中でリセットしたくなることもあると思います。
そのため、コマンド「/reset」を1つ追加します。
from ollama import chat
MODEL_NAME = "gemma3"
SYSTEM_PROMPT = "あなたは丁寧でわかりやすい日本の観光ガイドです。"
def main():
messages = [
{"role": "system", "content": SYSTEM_PROMPT}
]
while True:
user_input = input("You: ").strip()
if user_input in ["exit", "quit", "終了"]:
print("Bot: 終了します。")
break
if user_input == "/reset": # → 差分
messages = [ # → 差分
{"role": "system", "content": SYSTEM_PROMPT} # → 差分
] # → 差分
print("Bot: 会話履歴をリセットしました。") # → 差分
continue # → 差分
messages.append({"role": "user", "content": user_input})
response = chat(
model=MODEL_NAME,
messages=messages
)
answer = response["message"]["content"]
print(f"Bot: {answer}")
messages.append({"role": "assistant", "content": answer})
if __name__ == "__main__":
main()会話履歴のリセットをすることで、会話が変わるかを確認してみます。

質問:東京に行きます
→
回答:渋谷、浅草〜
→
質問:紹介してくれたのはどこ?
→
回答:東京だよ!
→
(会話履歴リセット)
→
質問:紹介してくれたのはどこ?
→
回答:何も紹介してないよ!?
となっているので、ちゃんとリセットできていそうですね…!
直近の履歴だけ送る
会話が長くなりすぎてローカルモデルでは重くならないように、直近の履歴だけモデルに送るように改善していきます。
以下の流れで改善していきます。
- どれくらいの会話を保存するのか「最大の履歴数」を決める
- 最大の履歴数を超えた古い会話がモデルに送られないようにする
from ollama import chat
MODEL_NAME = "gemma3"
SYSTEM_PROMPT = "あなたは丁寧でわかりやすい日本の観光ガイドです。"
MAX_HISTORY = 10 # → 差分
def trim_messages(messages): # → 差分
system_message = messages[0] # → 差分
conversation = messages[1:] # → 差分
trimmed_conversation = conversation[-MAX_HISTORY:] # → 差分
return [system_message] + trimmed_conversation # → 差分
def main():
messages = [
{"role": "system", "content": SYSTEM_PROMPT}
]
while True:
user_input = input("You: ").strip()
if user_input in ["exit", "quit", "終了"]:
print("Bot: 終了します。")
break
if user_input == "/reset":
messages = [
{"role": "system", "content": SYSTEM_PROMPT}
]
print("Bot: 会話履歴をリセットしました。")
continue
messages.append({"role": "user", "content": user_input})
response = chat(
model=MODEL_NAME,
messages=trim_messages(messages) # → 差分
)
answer = response["message"]["content"]
print(f"Bot: {answer}")
messages.append({"role": "assistant", "content": answer})
if __name__ == "__main__":
main()サンプルとして最大履歴数を2にして(MAX_HISTORY = 2)試してみると、、、

しっかり忘れてくれていますね…!
会話履歴の変化は以下のとおりです。
質問1:私は男性です
→
回答1:わかりました(会話履歴:質問1)
→
質問2:私の性別は?(会話履歴:質問1、回答1)
→
回答2:わかりません(会話履歴:回答1、質問2)
このように、回答2では「質問1」は会話履歴から取り除かれているため、性別を覚えていません。
おわり
いかがだったでしょうか。
今回は botの性格や役割を与える、履歴を調整する 改善を行いました。
動くchatbotを作ることで、なんとなく雰囲気が掴めてきたのではないでしょうか…?
次回は「chatbotの仕組みの理解を深めよう」をやっていきます。
お楽しみに〜