はじめに

仕事の中で、こんな「知識の断絶(ナレッジギャップ)」を感じたことはありませんか?

  • 新入社員:「有休に関する情報」を探そうとしても、社内規定集がどこにあるかわかりません。
  • 熟練エンジニア:当社の製品でよくあるエラーに直面し、毎回調べている気がするが、今回はチャット履歴やドキュメントを探しても見つからない。
  • 営業・カスタマーサポートチーム:顧客から製品に関する非常に具体的で、少し突っ込んだ技術仕様の質問を受けたが、その答えは、製品マニュアルのどこかで見た記憶がある。しかし、いざ探してみると見つからない。

生成AIのチャットに聞いてみても、「わかりません」と返されたり、一般的で的外れな答えしか返ってこないことも多いでしょう。

なぜ、あれほど「賢い」AIたちが、私たち自身の「社内の知恵」を理解できないのでしょうか? それはAIが「十分に賢くない」からではなく、従来の言語モデル(LLM)自体の設計に根本的な制約があるからです。 LLMは、学習データの外にある私的でリアルタイムな情報にはアクセスできません。 言ってみれば、記憶力と知識は抜群だけれど、あなたの会社の内部事情をまったく知らない「外部の専門家」のような存在なのです。

社内文書などから質問に関連する情報を検索し、その内容をLLMに参照させて回答を生成する仕組みが、RAG(Retrieval-Augmented Generation/検索拡張生成)です。RAGは回答の根拠となる情報を与える方法ですが、正確性を保証するものではないため、検索結果と回答品質の評価が必要です。

通常は品質や運用負担の面からクラウドAPIが第一候補になります。一方、機密データを外部へ送信できない、外部APIへ接続できないといった制約がある場合は、ローカルLLMとRAGを組み合わせることで生成AIを活用できる可能性があります。

なぜあなたのAIは新しい知識を「学べない」のか?──LLMの限界とRAGの誕生

RAGがなぜこれほど重要なのかを理解するためには、まずLLM(大規模言語モデル)の「弱点」を知る必要があります。

一般的なLLMは、その知識を膨大な学習データから得ています。この学習プロセスには莫大なコストがかかり、数か月、場合によってはそれ以上の時間を要します。そのため、新しい情報が出るたびにモデルを再学習させることは現実的ではありません。

この構造的な制約により、LLMには次の2つの大きな限界があります:

  1. 知識が静的であること

    学習データの最終更新日以降に起きた出来事を知ることはできません。

  2. 情報が隔離されていること

    個人ファイル、社内ナレッジベース、非公開データベースなどにはアクセスできません。

このような状況で、AIが知らない情報を尋ねると、LLMはしばしば「ハルシネーション(幻覚)」と呼ばれる、もっともらしい嘘を生成する現象を引き起こします。 ハルシネーションは、正確な情報が求められるビジネスの現場では非常に問題です。

この問題を解決するために登場したのが、RAG技術です。 その核心的な発想はとてもシンプルです: モデルが知らないなら、外部の情報を調べてから答えさせればいい。

RAGは、賢いLLMに「外付けのハードディスク」と「検索エンジン」を持たせるようなものです。 つまり、必要に応じてインターネットや社内文書を検索し、その情報を参照して答えを導き出せるようにするのです。

3ステップで理解するRAG──AIはどのように「調べてから答える」のか?

RAGのワークフローは、次の3つの主要なステップに分解して理解することができます: すなわち、それぞれの頭文字である、検索(Retrieval)拡張(Augmentation)生成(Generation)です。

それでは、このプロセスを図でわかりやすく見てみましょう。

  1. 検索(Retrieval): ユーザーが質問を入力すると、システムはまず指定されたナレッジベース(PDFやドキュメントライブラリなど)の中から、その質問に最も関連性の高い情報の断片を検索します。
  2. 拡張(Augmentation): ここがRAGの“核心”です。 システムはユーザーの元の質問と、先ほど検索で得られた情報断片をひとつにまとめ、より内容が具体的で文脈が明確な「拡張プロンプト(Augmented Prompt)」(※検索結果を付与した、より具体的な指示書)を作成します。
  3. 生成(Generation): 最後に、システムはこの「拡張プロンプト」を大規模言語モデル(LLM)に送信します。 このときのLLMは、記憶だけに頼らず、検索で取得した参照資料に基づいて回答を生成します。

これにより、LLMは「記憶だけ」で答えるのではなく、検索で得た具体的な情報を参照して回答できるようになります。回答品質は、元データ、文書の分割方法、検索精度、モデルなどに左右されます。

LLMが知らないことにはプロンプトを通じて情報を伝える。これがRAGの技術的な仕組みです。

性能デモ:RAGと実際のAIモデルを組み合わせたとき

ここまでRAGの仕組みを紹介しました。 RAGを実際に体感していただくために、非常に簡単なプログラムを使って、試してみましょう。

デモ環境構成:

  • 大規模言語モデル(LLM):

    qwen3:8b モデルを Ollama を使って接続します。質問の理解と最終的な回答生成を行います。

  • 埋め込みモデル(Embeddingモデル): intfloat/multilingual-e5-base。 テキストをベクトル(数値表現)へ変換する多言語対応のモデル。 (LLMの学習データに含まれていない)情報をナレッジベースから検索するために使用します。

今回用意する「ナレッジベース」:

LLMが知りえない、プロジェクト・ノヴァという架空のプロジェクトの情報としてテキストファイル my_knowledge.txt を用意しました。

1「プロジェクト・ノヴァ」は、次世代の再生可能エネルギー源として、深海熱水噴出孔の地熱を利用する画期的な研究開発プロジェクトです。
2このプロジェクトの責任者は、海洋物理学の権威である佐藤博士です。
3プロジェクトは2023年第4四半期に正式に開始され、初期段階の予算は5億円です。
4主な研究施設は沖縄県の沖合に設置されています。
5目標は、5年以内に商業利用可能なプロトタイプを完成させることです。

サンプルプログラム:

ここではRAGの基本的な流れを確認するため、LangChainを使った最小限のサンプルを示します。実際の業務利用では、データ整備、検索方法、権限管理、評価方法などを別途設計する必要があります。

1import re
2from langchain_community.document_loaders import TextLoader
3from langchain.text_splitter import CharacterTextSplitter
4from langchain_community.vectorstores import FAISS
5from langchain_huggingface import HuggingFaceEmbeddings
6from langchain_ollama import OllamaLLM
7from langchain_core.embeddings import Embeddings
8from langchain_core.prompts import ChatPromptTemplate
9from langchain_core.runnables import RunnablePassthrough, RunnableParallel
10from langchain_core.output_parsers import StrOutputParser
11 
12# E5モデルは入力テキストの前にquery: passage: を付ける必要があるため、カスタムEmbeddingsクラスを作成
13class E5Embeddings(Embeddings):
14    def __init__(self, model_name="intfloat/multilingual-e5-base"):
15        self.embedder = HuggingFaceEmbeddings(
16            model_name=model_name,
17            encode_kwargs={"normalize_embeddings": True}
18        )
19    def embed_documents(self, texts):
20        return self.embedder.embed_documents([f"passage: {t}" for t in texts])
21    def embed_query(self, text):
22        return self.embedder.embed_query(f"query: {text}")
23 
24def setup_rag_chain():
25    loader = TextLoader("my_knowledge.txt", encoding="utf-8")
26    docs = loader.load()
27    text_splitter = CharacterTextSplitter(chunk_size=400, chunk_overlap=50)
28    split_docs = text_splitter.split_documents(docs)
29 
30    embeddings = E5Embeddings()
31    vectorstore = FAISS.from_documents(split_docs, embeddings)
32    retriever = vectorstore.as_retriever(search_kwargs={"k": 1})
33 
34    llm = OllamaLLM(model="qwen3:8b")
35    prompt = ChatPromptTemplate.from_template(
36        "以下の情報のみに基づいて、質問に答えてください。\n\n{context}\n\n質問:{question}"
37    )
38 
39    rag_chain = (
40        RunnableParallel(
41            {"context": retriever, "question": RunnablePassthrough()}
42        )
43        | prompt
44        | llm
45        | StrOutputParser()
46    )
47    return rag_chain
48 
49def main():
50    rag_chain = setup_rag_chain()
51    question = "「プロジェクト・ノヴァ」の責任者は誰ですか?"
52    answer = rag_chain.invoke(question)
53    cleaned_answer = re.sub(r"<think>.*?</think>", "", answer, flags=re.DOTALL).strip()
54 
55    print("質問:", question)
56    print("回答:", cleaned_answer)
57 
58if __name__ == "__main__":
59    main()

このコードでは、専用の埋め込みモデル(Embeddingモデル)を定義し、さらに OllamaでQwen3:8b を頭脳(LLM)として指定し、 それらを組み合わせてひとつの RAGアプリケーション を構築しています。

実行と結果:

この例では、RAGシステムが用意した文書を参照し、「プロジェクト・ノヴァ(Project Nova)」に関する質問へ回答します。

1質問: 「プロジェクト・ノヴァ」の責任者は誰ですか?
2回答: 「プロジェクト・ノヴァ」の責任者は、海洋物理学の権威である**佐藤博士**です。

このデモはRAGの基本的な仕組みを示したものです。実際の業務で活用するには、多様なファイル形式(PDF、Word、PowerPoint等)への対応、検索精度の調整、ユーザーごとのアクセス権限管理など、利用環境に応じた設計と検証が必要です。当社では、業務データを用いて必要な回答品質を満たせるかを確認し、RAGを適用する場合の課題を整理します。

まとめと展望:RAGが切り拓く、企業AI活用の新たな章

今回のコラムを通して、RAGは決して難解な技術ではなく、「検索」と「生成」を巧みに組み合わせた実践的なフレームワークであることを紹介しました。 RAGは、LLMが学習時に持っていない情報を外部の文書から補うための方法の一つです。

この技術を使うことで、次のような利用用途が可能となります。

  • 社内ナレッジベース: 社員が自然言語で会社の規程、技術ドキュメント、プロジェクト履歴を検索できる。
  • インテリジェントカスタマーサポート: AIが製品マニュアルやヘルプドキュメントを参照し、問い合わせへの回答案を作成する。
  • パーソナルナレッジアシスタント: 自分のノートやファイルを検索し、情報整理や文章作成を支援する。

企業でRAGを導入・運用するには、対象文書の整備、検索精度、回答品質、権限管理などを確認する必要があります。当社では、実際の業務データを用いたPoCから、Local LLMを含む構成の適用可否の評価まで、検討状況に合わせて支援します。