第3回:ChatGPTを使った社内FAQボットの作り方(RAG入門)
~業務ドキュメントを“使えるAI知識”に変える方法~
はじめに
社内では「マニュアルはあるけど誰も見ていない」「同じ質問が何度も飛び交う」……そんな悩みが絶えません。
この課題に対して、ChatGPT × 業務文書による「社内FAQボット」が注目されています。
本記事では、そのコア技術である RAG(検索拡張生成:Retrieval-Augmented Generation の基本と、Pythonで作るPoC例を紹介します。
RAGとは?
RAGのざっくり概要
通常のLLM(ChatGPTなど)は、訓練時点の情報しか知らず、社内独自の知識や最新情報には対応できません。
RAGはそれを補う仕組みで、検索と生成のハイブリッド手法です。
RAGの流れ
- ユーザーの質問を受け取る
- ドキュメントベースから類似情報を検索(Retriever)
- 抽出した情報をLLMに渡して回答を生成(Generator)
→ ChatGPTに“参照資料”を渡すことで、社内専用AIボットが実現します。
必要な構成要素(ざっくり)
| 要素 | 説明 | 代表ツール例 |
|---|---|---|
| ① 文書ベクトル化 | ドキュメントを数値化する |
OpenAIEmbedding, e5-base-v2
|
| ② ベクトルDB | 検索用インデックスの保存先 |
Chroma, FAISS
|
| ③ フレームワーク | 構築支援ライブラリ |
LangChain, LlamaIndex
|
| ④ LLM | 回答を生成するAI本体 |
OpenAI GPT, Azure OpenAI
|
🛠 PoCレベルのFAQボットを作る(LangChain + Chroma)
フォルダ構成
rag-faq-bot/
├── manual.txt # 質問元になる業務マニュアル(テキスト形式)
├── chroma_db/ # ChromaのベクトルDB保存フォルダ(自動生成)
└── faq_bot.py # 実行スクリプト(RAGの質問ループ)
manual.txt
【VPNの設定方法】
1. 社員ポータルからVPNクライアントをダウンロードしてください。
2. 接続には社員番号とパスワードが必要です。
3. WindowsではOpenVPN、MacではTunnelblickを使用します。
【メール設定】
1. OutlookではIMAPを使います。
- 受信: imap.company.co.jp
- 送信: smtp.company.co.jp
2. 初期パスワードは「Welcome123!」です。
【PCの初期セットアップ】
1. 起動後はWindows初期設定に従ってください。
2. 社内LAN接続でウイルス対策ソフトが自動導入されます。
ライブラリのインストール
pip install openai langchain langchain-community langchain-huggingface chromadb tiktoken
pip install langchain langchain-community # 基本ライブラリ+Community対応
pip install langchain-openai # 4o-miniなどOpenAI系を使う場合
pip install langchain-huggingface sentence-transformers huggingface-hub # 埋め込み用(HuggingFace系)
pip install chromadb # ベクトルDB(Chroma)
pip install openai
ステップ①:業務マニュアルを読み込み
from langchain_community.document_loaders import TextLoader
loader = TextLoader("manual.txt", encoding="utf-8")
documents = loader.load()
ステップ②:文書を分割し、埋め込みベクトルを生成
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_huggingface import HuggingFaceEmbeddings
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
docs = splitter.split_documents(documents)
embeddings = HuggingFaceEmbeddings(
model_name="intfloat/e5-base-v2",
encode_kwargs={"normalize_embeddings": True}
)
ステップ③:ChromaベクトルDBへ登録
from langchain_community.vectorstores import Chroma
vectordb = Chroma.from_documents(docs, embeddings, persist_directory="./chroma_db")
ステップ④:ChatGPTに質問して回答生成
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
llm = ChatOpenAI(
model="gpt-4o-mini", # 今回はgpt-4o-miniを使用
api_key="sk-xxxx..." # 自分のAPIキー(下方にあるリンクを参照のこと)
)
prompt_template = PromptTemplate.from_template("""
以下の情報をもとに質問に答えてください。
{context}
質問: {question}
答え:
""")
THRESHOLD = 0.5
TOP_K = 8
while True:
query = input("質問を入力してください(終了するには 'exit'):")
if query.lower() == "exit":
break
docs_with_score = vectordb.similarity_search_with_score(query, k=TOP_K)
# 閾値でフィルタ(スコアが低いほど類似度が高い)
relevant_docs = [doc for doc, score in docs_with_score if score <= THRESHOLD]
if not relevant_docs:
print(f"\n【回答】\n申し訳ありませんが、『{query}』に関する情報は manual.txt に記載がありません。\n")
continue
context = "\n\n".join(doc.page_content for doc in relevant_docs)
prompt = prompt_template.format(context=context, question=query)
answer = llm.invoke(prompt).content.strip()
print("\n【回答】\n" + answer + "\n")
※APIキーの取得方法は下記を参照
スクリプト全文(faq_bot.py)
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
# ------------------ パラメータ ------------------
THRESHOLD: float = 0.5 # 類似度スコアの下限
TOP_K: int = 8 # 取得する上位ドキュメント数
# ① 文書を読み込む
loader = TextLoader("manual.txt", encoding="utf-8")
documents = loader.load()
# ② 分割
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
docs = splitter.split_documents(documents)
# ③ 埋め込みベクトル生成
embeddings = HuggingFaceEmbeddings(
model_name="intfloat/e5-base-v2",
encode_kwargs={"normalize_embeddings": True}
)
# ④ ChromaベクタDBに登録
vectordb = Chroma.from_documents(docs, embeddings, persist_directory="./chroma_db")
llm = ChatOpenAI(
model="gpt-4o-mini",
api_key="sk-proj-xxxxx"
)
# ⑤ プロンプトテンプレート
prompt_template = PromptTemplate.from_template("""
以下の情報をもとに質問に答えてください。
{context}
質問: {question}
答え:
""")
# ⑥ 質問ループ
while True:
query = input("質問を入力してください(終了するには 'exit'):")
if query.lower() == "exit":
break
# ⑦-1 類似検索(スコア付き)
docs_with_score = vectordb.similarity_search_with_score(query, k=TOP_K)
# ⑦-2 閾値でフィルタ
relevant_docs = [doc for doc, score in docs_with_score if score <= THRESHOLD]
if not relevant_docs:
print(f"\n【回答】\n申し訳ありませんが、『{query}』に関する情報は manual.txt に記載がありません。\n")
continue
# ⑦-3 LLM へ渡すコンテキスト生成
context = "\n\n".join(doc.page_content for doc in relevant_docs)
prompt = prompt_template.format(context=context, question=query)
# ⑦-4 回答生成
answer = llm.invoke(prompt).content.strip()
print("\n【回答】\n" + answer + "\n")
RAG運用時の注意点
| 観点 | 説明 |
|---|---|
| 文書の粒度 | 小さく区切らないと検索精度が低下します(節ごとが理想) |
| 情報の更新 | 文書更新時はベクトルDBの再生成が必要です |
| 出力の信頼性 | ChatGPTが“それっぽい誤答”をする可能性あり。参照元の表示などを工夫しましょう。 例えば、manual.txtにない問い合わせをしても下記ロジックが動作しない。 print(f"\n【回答】\n申し訳ありませんが、『{query}』に関する情報は manual.txt に記載がありません。\n") |
まとめ
ChatGPT+RAG構成によって、社内ナレッジを“使えるAI知識”として再活用することが可能です。
まずは小さなPoCから始め、
FAQ → マニュアル → 社内ナレッジ共有基盤へと拡張していきましょう。