gpt-oss:20bでRAGを試してみた

お疲れ様です。

前回Ollamaを使用してgpt-oss:20bを動かしてみたのですが、ここまでできたらRAGも試してみたいということで実装してみました。

  • 前回の記事

fallpoke-tech.hatenadiary.jp

RAGの実装については以前GeminiAPIを使って実装したコードをベースに作成しています。 使用したベクトルDBも同様です。(データ自体は増えていますが。)
その時の記事と実装も併せてどうぞ。

fallpoke-tech.hatenadiary.jp

コード

早速にはなりますが、実際のRAGのコードを下記に記載します。

ソースコード全体はこちらにあります。 github.com

def response_generator_langchain_ollama_rag() -> str:
    """langchain_ollamaを使用+RAG
    """
    llm = OllamaLLM(model='gpt-oss:20b')
    
    # 直前のユーザの入力を取得
    user_input = st.session_state.messages[-1]["content"]
    
    # ベクトル化する準備
    model_kwargs = {
        "device": "cuda" if torch.cuda.is_available() else "cpu", 
        "trust_remote_code": True
    }
    embedding = HuggingFaceEmbeddings(
        model_name="pfnet/plamo-embedding-1b",
        model_kwargs=model_kwargs
    )
    
    # DBを読み込んで知識データ取得
    vectorstore = Chroma(collection_name="elephants", 
                         persist_directory="chat/chroma", 
                         embedding_function=embedding)
    docs = vectorstore.similarity_search(query=user_input, k=10)
    context = "\n".join([f"Content:\n{doc.page_content}" for doc in docs])
    
    messages = [
        ROLES[msg["role"]](content=msg["content"]) 
        for msg in st.session_state.messages[:-1]
    ] + [HumanMessage(content=RAG_PROMPT.format(question=user_input, context=context))]
    
    response = llm.invoke(messages)
    
    response_html = Markdown().convert(response)
    
    return response_html

下記、以前作成のGeminiAPI版との違いを中心に説明します。

  • モデルについて

モデルはOllamaを使用しているのでlangchain_ollamaOllamaLLMを使用します。 こちらは個別にpip installが必要です。

pip install langchain_ollama

参考: https://python.langchain.com/docs/integrations/llms/ollama/

実際の実行時にはollama serveでOllamaのサーバを立ち上げておきます。
今回はgpt-oss:20bを使用するので引数modelに指定します。

  • データについて

StreamlitでUIを簡易的に作成して表示しているので、チャット履歴のデータはst.session_state.messagesに格納されています。 データの形式は以下。

st.session_state.messages = [
  {"role": "user", "content": "..."},
  {"role": "assistant", "content": "..."},
]

このデータの形式をLangChainのモデル入力形式に変換して入力します。 直前のユーザの入力はベクトルDBの検索結果も含めてRAG用のプロンプトに埋め込み入力としています。

出力結果

出力結果としては以下になります。
表示が崩れているのはStreamlitの問題だと思います。(そろそろfrontendはReactでちゃんと作ろうかな…。)

output_gpt-oss

GeminiAPIとの比較

以前からベクトルDBのデータが増えているので比較用に同条件でGeminiAPI版も試してみました。 2025/8/10現在は無料版のAPIなのでモデルをgemini-2.5-flashに設定しています。

output_gemini

データが同じなので内容に大差はありませんが、gpt-ossの方が出力の情報を綺麗にまとめようとしているイメージです。 モデルごとの特性がでているようで面白いですね。