RAGの作り方|Python実装サンプル付き・社内ナレッジ検索の構築手順【2026年版】
目次 [非表示]
この記事でわかること
- Python50行で動く最小構成RAGの実装サンプル(コピペで動作)
- 2026年4月時点の技術スタック主流構成(embedding / ベクトルDB / LLM の3社並列)
- 自社SaaS『PigeonCloud』で本番運用中の3ヶ月段階的拡張ログと設計判断4つ
社内の議事録・マニュアル・仕様書が増えすぎて、どこに何が書いてあるか誰も把握できない。Q&Aチャットボットを作ってみたがハルシネーション(もっともらしい嘘)が多くて使い物にならない。こうした課題を解く現実解が RAG(Retrieval-Augmented Generation、検索拡張生成) です。本記事ではPython50行の動くサンプルを出発点に、チャンク分割・embedding・ベクトルDB・LLM呼び出しまでの実装手順を、自社SaaS『PigeonCloud』の本番運用ログ付きで解説します。
費用相場やベンダー選定基準は AI受託開発の費用相場2026年版 で詳説しています。外注のメリット・進行フローは AI開発外注ガイド をあわせてご覧ください。本記事はエンジニア向けの技術how-toに振り切って解説します。
RAG(検索拡張生成)とは?社内ナレッジ検索の仕組み
RAGは 「検索」と「生成」を組み合わせた仕組み です。3行で言えば次の通り。
- ユーザーの質問文を embedding(ベクトル) に変換する
- ベクトルDBで 類似度の高い社内文書を検索 する(top-k件)
- 検索結果を LLMのプロンプトに埋め込み、その文脈の範囲内で回答を生成させる
LLM単体との違い3点
- ハルシネーション抑制 — 回答根拠を検索結果に限定するため、LLMが勝手に創作する余地が減る
- 最新情報への追従 — ベクトルDBを更新するだけで反映。LLM再学習が不要
- ドメイン特化 — 自社の議事録・契約書・製品マニュアル等を外部漏洩させずに扱える
要件定義・見積もりのご相談は RAG受託開発サービス → からどうぞ。
最小構成で動くRAGを作る|Python 50行サンプル
まずは コピペで動く最小RAG を載せます。PostgreSQLにpgvector拡張を入れた前提で、ドキュメント読み込み→チャンク分割→embedding生成→ベクトル検索→LLM呼び出しまで50行前後で書き切ります。2026年4月時点のOpenAI SDKとAnthropic SDKを使用。
必要ライブラリ
pip install openai anthropic psycopg2-binary pgvector tiktoken
事前準備として、PostgreSQLにCREATE EXTENSION vector;を実行し、以下のテーブルを作っておきます。
CREATE TABLE docs (
id SERIAL PRIMARY KEY,
content TEXT NOT NULL,
embedding VECTOR(1536)
);
CREATE INDEX ON docs USING ivfflat (embedding vector_cosine_ops) WITH (lists=100);
実装コード(50行)
import os
import psycopg2
from openai import OpenAI
from anthropic import Anthropic
oai = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
claude = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
conn = psycopg2.connect(os.environ["DATABASE_URL"])
def chunk_text(text: str, size: int = 500) -> list[str]:
"""固定長チャンク分割(500字)。本番ではセマンティック分割も検討"""
return [text[i:i+size] for i in range(0, len(text), size)]
def embed(text: str) -> list[float]:
"""text-embedding-3-small で1536次元ベクトルに変換"""
resp = oai.embeddings.create(model="text-embedding-3-small", input=text)
return resp.data[0].embedding
def ingest(docs_dir: str):
"""ディレクトリ内の.txtを読み込んでベクトルDBに格納"""
cur = conn.cursor()
for fname in os.listdir(docs_dir):
if not fname.endswith(".txt"): continue
with open(f"{docs_dir}/{fname}") as f:
for chunk in chunk_text(f.read()):
vec = embed(chunk)
cur.execute(
"INSERT INTO docs (content, embedding) VALUES (%s, %s)",
(chunk, vec)
)
conn.commit()
def retrieve(query: str, k: int = 5) -> list[str]:
"""cos類似度 top-k件を取得"""
qvec = embed(query)
cur = conn.cursor()
cur.execute(
"SELECT content FROM docs ORDER BY embedding <=> %s::vector LIMIT %s",
(qvec, k)
)
return [row[0] for row in cur.fetchall()]
def answer(query: str) -> str:
"""検索結果を文脈としてClaudeに回答させる"""
context = "\n---\n".join(retrieve(query))
prompt = f"以下の社内文書のみを根拠に回答してください。\n\n{context}\n\n質問: {query}"
resp = claude.messages.create(
model="claude-haiku-4-5",
max_tokens=1024,
messages=[{"role": "user", "content": prompt}]
)
return resp.content[0].text
if __name__ == "__main__":
ingest("./docs")
print(answer("有給休暇の申請方法は?"))
コードの要点
- embedding モデル:
text-embedding-3-small(1536次元)を採用。精度とコストのバランス型で、日本語社内文書の検索では実用水準 - 類似度演算子: pgvectorの
<=>はcos距離。距離が小さいほど類似度が高く、ORDER BY ASC で top-k が取れる - ivfflat インデックス: 1万件超のドキュメントでは必須。
listsはデータ件数の平方根が目安 - LLMは文脈内限定回答: プロンプトで「社内文書のみを根拠に」と明示し、LLMの外部知識による創作を抑制する
このサンプルはあくまで出発点です。実運用では次章の「8ステップ」で評価パイプラインと運用監視を足していきます。
RAG実装の技術ステップ8つ(エンジニア向け)
最小構成から本番運用レベルまでの流れを、エンジニアが手を動かす順番で並べます。
ドキュメント収集
pypdf、Wordはpython-docxが定番。ファイル単位にメタデータ(部署・作成日・権限)を付けるチャンク分割
embedding生成
text-embedding-3-small(1536次元)、Cohere Embed v4、Google gemini-embedding-001から選定。日本語なら3社とも実用水準。バッチAPIでコスト圧縮可能ベクトルDB格納
類似検索処理
LLM呼び出し
評価パイプライン
運用監視
RAG設計で最初に決める4つの判断
RAGの精度は コードの巧拙よりも設計判断 で8割決まります。2026年4月時点でプロジェクト着手前に決めておく4点を整理しました。
チャンク分割戦略
固定長 vs セマンティックの判断。議事録・Slackログのように文脈が短い文書は固定長500字で十分、契約書・仕様書のように論理構造がある文書はセマンティック分割(句点・章見出し基準)が向く。
オーバーラップ50〜100字を入れると文脈の分断が減り、ヒット率が3〜5%改善する
embedding モデル選定
OpenAI text-embedding-3-small(1536次元)、Cohere Embed v4、Google gemini-embedding-001が候補。3モデルとも日本語対応しており実用水準。切り替えはAPI差し替えのみで可能。
ベクトル次元数が変わると既存データを全て再生成する必要があるため、初期選定が効く
ベクトルDB選定
下記比較表を参考に、既存インフラとスケール要件で決める。弊社では pgvector を採用。既存PostgreSQL基盤に追加できた点が決め手で、権限・バックアップ・監視が既存の仕組みで完結する。
検索スコア閾値
top-k=5・cos類似度 0.7 以上を基準に。閾値未満はLLMに渡さず「関連文書なし」と返す設計にすると、無関係文書を根拠にした誤回答を防げる。
kとthresholdは評価パイプラインで月次調整する前提で決める
ベクトルDB比較表
| 製品 | 形態 | 適した規模 | 特徴 |
|---|---|---|---|
| pgvector | PostgreSQL拡張 | 〜1000万件 | 既存PostgreSQL資産を活用可。運用ノウハウ流用 |
| Pinecone | マネージドSaaS | 1000万〜10億件 | フルマネージド・スケール自動・運用負荷最小 |
| Qdrant | OSS / Cloud両対応 | 〜1億件 | Rust製で高速。セルフホスト可 |
| Weaviate | OSS / Cloud両対応 | 〜1億件 | GraphQL対応・ハイブリッド検索が標準実装 |
▶ ポイント:どのDBを選んでも2026年時点でcos類似度+メタデータフィルタは全製品が対応。差がつくのは運用コスト・既存基盤との統合性・チームのスキルセットです。
実装に使う技術スタック(2026年4月時点の主流構成)
RAG実装で採用されている技術スタックを、LLM・embedding・フレームワークの3軸で整理します。2026年4月時点の情報で、半年単位で主要モデルは刷新されます。
LLMの選び方(3社×3軸)
回答生成に使うLLMは Claude・OpenAI・Google の3社を要件で使い分け るのが2026年時点の主流です。費用相場や総合比較は AI受託開発の費用相場2026年版 を参照してください。
- Claude Opus 4.7 (Anthropic)
- GPT-4.1 (OpenAI)
- Gemini 2.5 Pro (Google)
契約書の論点抽出・多段推論・長文要約に強い
- Claude Sonnet 4.6
- GPT-4.1 mini
- Gemini 2.5 Flash
RAGの主力帯。日次数万クエリまで経済的に回せる
- Claude Haiku 4.5
- GPT-4.1 nano
- Gemini 2.5 Flash-Lite
クエリ書換え・軽量ルーティング・ラベリング向き
embeddingモデル
検索精度の土台になるembeddingモデルは、2026年時点で以下3つが実用水準です。
| モデル | 次元数 | 特徴 |
|---|---|---|
| OpenAI text-embedding-3-small | 1536 | コストと精度のバランス型。RAGのデフォルト選択肢 |
| OpenAI text-embedding-3-large | 3072 | 精度優先。日本語の複雑な文書に強い |
| Cohere Embed v4 | 256〜1536可変 | Matryoshka構造で次元数を可変調整可能 |
| Google gemini-embedding-001 | 最大3072 | Google Cloud基盤との親和性が高い |
フレームワーク選び(LangChain / LlamaIndex / 自前実装)
実装フレームワークは3択です。
- LangChain — エコシステム最大。他サービス連携(検索API・メモリ・Agent)を足していく前提のプロジェクト向き
- LlamaIndex — RAGとドキュメントインデックスに特化。社内ナレッジ検索用途では学習コストが最も低い
- 自前実装 — 上記のPython50行サンプルのような薄いコード。ブラックボックスを避けたい・チューニング余地を最大化したい場合に有効
弊社では 自前実装 で回しています。フレームワークの抽象化が新モデル対応で足枷になるケースが増え、薄いコードのほうが3社LLM切り替えや評価パイプライン追加が速いと判断したためです。
自社SaaS PigeonCloud の RAG 運用ログ|3ヶ月で辿った段階的拡張
自社SaaS『PigeonCloud』(ロフタル運営・300社導入)にはAIファイル検索機能がRAGで組まれており、本番トラフィックで運用中です。着手から3ヶ月でどう拡張したか、時系列で残します。いわゆる完成形を一発で作ったわけではなく、評価パイプラインの数値を見て次の打ち手を決めていった記録です。
Month 1 — PoC段階(社内10名評価)
- チャンクサイズ: 固定長800字・オーバーラップなし
- embedding:
text-embedding-3-small - ベクトルDB: pgvector(既存PostgreSQL基盤に相乗り)
- LLM: Claude Sonnet 4.6 単独
- 評価: 社内10名に質問30件を投げてもらい、正答率を目視判定
得られた知見は2つ。固定長800字だと社内議事録のように短文の集まりではチャンク境界が悪く、質問と関連する文が半分に割れるケースが散見された。もうひとつは「わかりません」の返し方で、閾値設定せずに top-5 を必ず渡す実装にしていたため、関係ない文書でも無理やり回答を作ってしまう挙動が出た。
Month 2 — 本番展開(対外公開)
- チャンクサイズ: 文書種別ごとに500〜800字の可変に変更(議事録500字 / マニュアル800字)
- オーバーラップ: 50字を追加
- 検索閾値: cos類似度0.7未満は「関連文書なし」としてLLMに渡さない設計に
- 評価パイプライン: 質問100件×正解文書のペアを整備しRecall@5を週次計測
top-5ヒット率が Month 1末の72%から85%へ改善。閾値を入れたことで「わかりません」回答が全体の約8%発生するようになったが、ユーザー評価では 嘘の回答より"わからない"のほうが信頼できる というフィードバックが多数で、採用を維持している。
Month 3 — 継続改善(3社LLM動的ルーティング)
- LLM動的ルーティング: 質問の難易度で Haiku 4.5 / Sonnet 4.6 / Opus 4.7 を切り替え
- 分類器: GPT-4.1 nano に「単純検索 / 複雑推論 / 要約」の3分類を判定させる軽量前処理
- メタデータフィルタ: 部署・権限による検索範囲制御を実装
- 監視: 応答時間・API失敗率・ヒット率・わかりません率 の4指標をGrafanaに集約
単純検索の7割がHaiku 4.5で捌けるようになり、応答時間の中央値が3.2秒から2.1秒に短縮。筆者の経験では、3社LLMルーティングは 運用初月に入れるより、評価パイプラインが整ってから入れる ほうが判断根拠が明確になります。ここまでの改善はすべてPython薄い実装で通しています。
RAGの精度を上げる実践テクニック5選
最小構成で動いたあと、精度を継続的に上げる打ち手を5つ紹介します。どれも 評価パイプラインの数値で効果を測れる範囲 で導入するのが筆者の立場です。
- ハイブリッド検索 — ベクトル検索にBM25(キーワード検索)を足す。固有名詞・型番・コード片のように「文字列そのもの」を検索したい場面で強い。RRF(Reciprocal Rank Fusion)で結果をマージする手法が2026年時点では定番
- リランキング — top-20を取って Cohere Rerank API で再スコアリングし top-5に絞る。embeddingだけの検索より精度が5〜15%改善するケースが多い
- クエリ書き換え(HyDE) — 質問文から 仮想的な回答 をLLMに先に作らせて、その仮想回答でベクトル検索する手法。質問文が短すぎる場合に特に効果がある
- メタデータフィルタリング — 部署・権限・作成日でスコープを絞る。検索結果に「他部署の文書」が混入する事故を防ぐ意味でも必須
- フィードバックループ — 回答採用率(ユーザーがコピペしたか)・クリック率・low quality報告を蓄積し、ダメな回答パターンからプロンプト・チャンク・embeddingの見直しにつなげる
よくある質問(FAQ)
まとめ|RAG構築は最小構成から始めて段階的に拡張する
RAGはPython50行の最小構成で動作確認し、評価パイプラインの数値を見ながらチャンク・embedding・LLMを順に触って精度を上げる流れが現実解です。いきなり完成形を目指すとチューニングすべき変数が多すぎて収束しません。
本記事で扱った設計判断4つ(チャンク分割戦略・embeddingモデル・ベクトルDB・検索閾値)を先に決め、3社LLMのどれを主力にするかは評価パイプラインの数値が出てから選ぶ。この順序だけ守れば、PoCから本番運用までの道筋が見えます。
次に読む
PigeonCloud / SASENAI / dotomachi を自社開発・運用中。自社SaaSで本番運用しているRAG・AIエージェントのノウハウをそのまま受託開発として提供しています。
最終更新: 2026年4月22日
データ管理、もっと簡単に。
Excel・Access・スプレッドシートの課題を、ノーコードのWebデータベース「PigeonCloud」が解決します。
月額5,500円〜(5ユーザー)、30日間無料でお試しいただけます。