お疲れ様です。
前回Ollamaを使用してgpt-oss:20bを動かしてみたのですが、ここまでできたらRAGも試してみたいということで実装してみました。
- 前回の記事
RAGの実装については以前GeminiAPIを使って実装したコードをベースに作成しています。
使用したベクトルDBも同様です。(データ自体は増えていますが。)
その時の記事と実装も併せてどうぞ。
コード
早速にはなりますが、実際の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_ollamaのOllamaLLMを使用します。
こちらは個別に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でちゃんと作ろうかな…。)

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

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