😇

Re; ollama+langchainでローカルLLMを動かす

に公開

昨日、OllamaとlangchainでローカルLLM: Gemma3: 12bを動かしました。
一方で、画像を渡せなーい・・・と悩んでいたところ、どうも、Langchain_Ollamaのtext completion を使っていたようで、chat completionを使わないといけなかったようです。

langchainのchatを使ってたのに・・・というのは自己責任で、そのあとドキュメント読んでたら普通に書いてあることでした。という訳で、今日はうまく動いたことを書いていきます。

昨日の記事は次のリンク先にございます。
https://zenn.dev/hi/articles/b85edebde2caa1

今日やりたいこと

Streamlit でローカルLLMチャットアプリを作りたい!
という訳で、今日はGemma3: 4bモデルを使ってやっていきます。なぜモデルを変えたかというのは、ただの気まぐれです。

インストールの方は次のような感じ。

$ uv pip install langchain_ollama streamlit jupyterlab

ちょっと動かすときは jupyterlab で動かします。最近もっと新しいツールが出てきているとかちらっと見ましたが・・・

まずは普通に話す

という訳で、話していきます。

from langchain_ollama import ChatOllama
from langchain_core.messages import HumanMessage

llm = ChatOllama(
      model = 'gemma3',
      temperature = 0
    )
res = llm.invoke('こんにちは。私はhです。あなたは?')
print(res)

返信は

content='こんにちは、hさん。私はGemmaです。Google DeepMindによってトレーニングされた大規模言語モデルです。あなたとお話しできて嬉しいです。何かお手伝いできることはありますか?' additional_kwargs={} response_metadata={'model': 'gemma3', (後略

ハイ帰ってきました。

問題の画像

画像を渡してみましょう。

messages = HumanMessage(
    content=[
        {'type': 'text', 'text': 'explain the image'},
        {'type': 'image_url', 'image_url': {'url': 'dog-sun.png'}}
    ]
)

res = llm([messages])
print(res)

次のようになりました。まぁ見えてそうですね。

content="Here's a breakdown of the image:\n\n**Overall Impression:**\n\nThe image is a beautiful, warm-toned portrait of a Blue Heeler (Australian Cattle Dog) enjoying a sunny day. It has a relaxed and happy feel.\n\n**Detailed Description:**\n\n*   **Subject:** The main subject is a Blue Heeler, a medium-sized herding breed known for its distinctive mottled blue-grey coat and intelligent expression. The dog is lying down in a field.\n*  (長いので略)

ちなみに日本語でもやってみたのですが、そこまで長く詳しい回答でなく、どちらかというとちょっと間違ってるかもなぁくらいでした。もしかして、英語の優位性が強い???

Function calling は失敗

Gemma3はFunction callingできると書いていたのでやってみたけど、gemma3はtoolsをサポートしていないと出てきた。ここはちょっと調べたいところ。

def add(a: int, b: int) -> int:
    """
    Add two intergers.

    Args:
        a: First Integer
        b: Second Integer
    """
    return a + b

def multiply(a: int, b: int) -> int:
    """
    Multiply two integers.

    Args:
        a: first integer
        b: second integer
    
    """ 
    return a * b


tools = [add, multiply]

llm_with_tools = llm.bind_tools(tools)
query = 'What is 3 * 12'
res4 = llm_with_tools.invoke(query).tool_calls
print(res4)

もしかしたらlangchainの方法に対応していないのか・・・。分かりません。

ResponseError: registry.ollama.ai/library/gemma3:latest does not support tools (status code: 400)

Chatアプリを作る

最後にStreamlitを使って、Chatアプリを作りました。何の工夫もないものです。これに、ファイルを渡したりする機能を付けたいところ。あと、モデル同士に対話させても面白いかもな。

このコードはほぼ、streamlitのドキュメントの内容で、OpenAI用からちょっとだけコードを変えているという感じです。

https://docs.streamlit.io/develop/tutorials/chat-and-llm-apps/build-conversational-apps#build-a-chatgpt-like-app

import streamlit as st
from langchain_ollama import ChatOllama

st.title('Chat App')

llm = ChatOllama(model='gemma3', temperature=1.0)

if 'messages' not in st.session_state:
    st.session_state.messages = []

for message in st.session_state.messages:
    with st.chat_message(message['role']):
        st.markdown(message['content'])

if prompt := st.chat_input('どうしました?'):
    st.session_state.messages.append({'role': 'user', 'content': prompt})
    with st.chat_message('user'):
        st.markdown(prompt)

    with st.chat_message('assistant'):
        res = llm.invoke(prompt)
        st.markdown(res.content)
    st.session_state.messages.append({'role': 'assistant', 'content': res.content})

アプリを実行すると、動きました。

$ streamlit run app.py

まとめ

とりあえず、やりたいことはできました。
ローカルLLMはAPIのように都度都度お金が削られないので、精神に優しい。
一方で、電気代もかかるし、部屋も暑い気がする。長文を一気に吐き出すときは、ウイーンってなってるし、これが鳴ると精神への優しさはなくなり、心配になる。

あと、かなり日本語と英語へのレスポンスが違うような気もしている。Duolingoしている私としては、英語の練習になってよい。

次は何をやるか・・RAGとかですかねぇ~

Discussion