RAG 基礎
〜 手動 RAG で無料の実行 〜
2026-02-22 作成 福島
TOP > llm > rag
[ TIPS | TOYS | OTAKU | LINK | MOVIE | CGI | AvTitle | ConfuTerm | HIST | AnSt | Asob | Shell | GBC | LLM ]

0. 前置き

0-1. ローカルルールを扱う
LLM は主に一般的な知識やルールを取り扱いますが、ローカルルールを取り扱うこともできます。
組織のガイドラインや、小売店の販売情報等が該当します。
一般的ではないけれど、取り出すことに意義のある情報です。
これらを解決・補助する仕組みに RAG(ラグ) があります。
0-2. RAG とは
RAG とは、以下の頭文字を並べたもので、LLM の学習モデルに存在しない知識を検索によって取り込み、
回答の正確性と最新性を高める流れの名前です。
Retrieval-Augmented Generation = 検索拡張生成
• Retrieval -- 検索で
• Augmented -- 追加された
• Generation -- 生成

… なんのこっちゃ?
Web で会話する ChatGPT、あるいは API を利用する OpenAI API では、
プロンプト (質疑の自然文) を送信することにより処理を開始します。

この、プロンプトを強化する仕組みが RAG です。
ただし、以下の条件を満たさなければなりません。
検索せずに適当に作成した文や、固定の文は RAG のプロンプトではありません。
そして、プロンプトを作成して終わり。… でもありません。

「プロンプトをどう作成しようが勝手だろ?」
その通りです。
しかし、IT 業界では RAG を使わないと会話が通らないので、我慢しましょう。
下記 1~3 の連続を定義したのが RAG です。

 1.検索 (入力から)
  ↓
 2.拡張 (プロンプトを補強)
  ↓
 3.生成 (LLM の結果を出力)

本稿では、検索によって強化されたプロンプトを作成します。(1, 2 に該当)
このプロンプトを ChatGPT の入力とすることにより RAG を形成します。(3 に該当)
(通常は有料の API や高価なローカル LLM を利用する自動 RAG ですが、ここでは手動 RAG として ChatGPT を使用します。これなら無料で実行できます)
0-3. コーパス
自然言語のテキストの集合をコーパスと呼びます。
どんなに乱雑なデータであっても、自然言語として集められたデータなら、それはコーパスです。
言語の種類は問いません。石板に刻まれている象形文字も、全く未知の言語でもコーパスになります。

コーパスの用途は RAG に限定しません。学習・評価・検索・参照のすべてに使用します。
LLM を学習させるときにもコーパスが使用されています。


1. コーパスの用意

ここでは、料理に関するコーパスを作成する。
サンプルは、Wikipedia に掲載されている料理の説明。

$ pip install html2text
$ wget -q -O- https://ja.wikipedia.org/wiki/料理 | html2text > corpus.txt


2. 拡張プロンプトの作成と実行

コーパスを検索して取得した文字列をプロンプトに追加しても、名称は変化せずプロンプトと呼ぶ。
あえて元のプロンプトと区別するには「拡張プロンプト」と呼ぶ。

ChatGPT のプロンプトには長さの制限があり、文字数やバイト数ではなく、トークン数が対象。
このため、本プログラムはトークン数がオーバーしないように細工してある。
(ここで使用しているトークンカウンタを動作させても課金されない。OPENAI_API_KEY を必要としないし、そもそも通信していない)

2-1. プログラムを作成する。
< retreval_augmented_prompt1.py >
#!/usr/bin/python3

import tiktoken

question = "日本の料理とは?"

# トークンカウンタを用意
tik_enc = tiktoken.encoding_for_model('gpt-4o-mini')


def get_retrieved_doc(corpus, max_tokens, word='日本'): """検索結果を取得する - 簡易版""" detected = [] total_token_count = 0 for line in corpus: if word in line: # 指定語が line に含まれている line = line.rstrip() line_token_count = len(tik_enc.encode(line)) if total_token_count + line_token_count >= max_tokens: break detected.append(line) total_token_count += line_token_count return '\n'.join(detected)
if __name__ == '__main__': # コーパスを読み込む file = open('./corpus.txt', 'r') corpus = file.readlines() file.close() MAX_TOKENS = 50000 # ChatGPT の受け入れ可能トークン数 retrieved_doc = get_retrieved_doc(corpus, MAX_TOKENS) # 拡張プロンプトを作成する augmented_prompt = f'質問: {question}\n' \ f'参考資料は以下:\n' \ f'{retrieved_doc}' print(augmented_prompt) print('-----') print(f'トークン数: {len(tik_enc.encode(augmented_prompt))}')
2-2. プログラムを実行する。
$ ./retreval_augmented_prompt1.py | fold

質問: 日本の料理とは?
参考資料は以下:
    * 4.2 日本料理
日本語
ただし、いずれの調理過程を経ているとしても、「茹で卵」「目玉焼き」などの簡単に作
れる物、「即席麺(インスタント麺、乾麺、カップ麺)」「冷凍食品」などの類は料理に
含まれないことが多い。また、住んでいる地域によっても考え方が変わる。具体的には「
刺身は日本では料理として認知されているものの、刺身を食べない国では料理として認知
されていない」などである。
    骨・内臓などを取り除き、身(肉)の部分を切り分ける。[日本料理](/wiki/%E6%97%
A5%E6%9C%AC%E6%96%99%E7%90%86 "日本料理")では[三枚おろし](/wiki/%E4%B8%89%E6%9E%
9A%E3%81%8A%E3%82%8D%E3%81%97 "三枚おろし")が一般的である。魚ごとの性質や、次に
焼くのか煮るのか、といったことに応じて、それに適した形に切っていく。[刺身](/wiki
/%E5%88%BA%E8%BA%AB "刺身")は、包丁だけで料理が完結し、包丁の切れ具合や「包丁さ
ばき」によって食感、味が大きく異なるとされる。
### [日本料理](/wiki/%E6%97%A5%E6%9C%AC%E6%96%99%E7%90%86 "日本料理")
  3. **^** 『四季日本の料理 秋』講談社 [ISBN 4-06-267453-X](/wiki/%E7%89%B9%E5%8
8%A5:%E6%96%87%E7%8C%AE%E8%B3%87%E6%96%99/406267453X)
  5. **^** 『四季日本の料理 冬』講談社 [ISBN 4-06-267454-8](/wiki/%E7%89%B9%E5%8
8%A5:%E6%96%87%E7%8C%AE%E8%B3%87%E6%96%99/4062674548)
  * 『四季日本の料理 秋』講談社 [ISBN 4-06-267453-X](/wiki/%E7%89%B9%E5%88%A5:%E
6%96%87%E7%8C%AE%E8%B3%87%E6%96%99/406267453X)
  * 『四季日本の料理 冬』講談社 [ISBN 4-06-267454-8](/wiki/%E7%89%B9%E5%88%A5:%E
6%96%87%E7%8C%AE%E8%B3%87%E6%96%99/4062674548)
  * [日本](/wiki/%E6%97%A5%E6%9C%AC%E6%96%99%E7%90%86 "日本料理")
  * [日本](https://id.ndl.go.jp/auth/ndlna/00569854)
-----
トークン数: 773
2-3. ChatGPT に質疑する。
ChatGPT を Web ブラウザで開き、上記 2-2 のテキストをプロンプトとして送信すると、以下の回答を得られる。

参考資料に基づくと、日本の料理とは次のように整理できます:
  1. 調理過程を経て完成するもの
    • ただし「茹で卵」「目玉焼き」など簡単すぎるものや、「即席麺」「冷凍食品」などは、料理として含まれないことが多い。
  2. 地域や文化による認識の差
    • 例えば、刺身は日本では料理として認知されるが、刺身を食べない国では料理として認知されない場合がある。
  3. 具体的な調理技法
    • 魚の場合、骨・内臓を取り除き身を切り分ける三枚おろしが一般的。
    • 魚の性質や調理法(焼く・煮るなど)に応じて適した形に切り分ける。
    • 刺身は包丁だけで完成し、包丁の切れ味や技術によって食感や味が変わる。
つまり、日本の料理とは、単なる食材ではなく、技術や手間をかけて完成させ、文化的に料理として認知されるものを指す、と言えます。


3. Sudachi を使う

コーパスを検索・選別するために Sudachi を利用してみる。

Sudachi はオープンソースの日本語解析器 (日本語形態素解析器) で、辞書に従って文章を単語に切り分ける。
ありがたいことにライセンスが Apache 2.0 となっている。

README によると、A,B,C の 3 種類の分割モードがある。(辞書による)
3-1. Sudachi と基本辞書をインストールする。(Python 版)
$ pip install sudachipy sudachidict_core
3-2. プログラムを作成する。
< retreval_augmented_prompt2.py >
#!/usr/bin/python3

import tiktoken
from sudachipy import dictionary, tokenizer

question = "日本の料理とは?"

# トークンカウンタを用意
tik_enc = tiktoken.encoding_for_model('gpt-4o-mini')


def get_retrieved_doc(corpus, max_tokens, wordlist): """検索結果を取得する - 単語指定版""" detected = [] total_token_count = 0 for line in corpus: if any(word in line for word in wordlist): # 指定語のどれかが line に含まれている line = line.rstrip() line_token_count = len(tik_enc.encode(line)) if total_token_count + line_token_count >= max_tokens: break detected.append(line) total_token_count += line_token_count return '\n'.join(detected)
if __name__ == '__main__':
# SplitMode: 分割する単語長を指定する # .A 最短 # .B 中間 # .C 最長 -- デフォルト split_mode = tokenizer.Tokenizer.SplitMode.C # Sudachi で単語を取り出す tokenizer_dic = dictionary.Dictionary().create() tokens = tokenizer_dic.tokenize('世界の料理', mode = split_mode) # 検索語 ['世界','料理'] を抽出する wordlist = [] for token in tokens: if token.part_of_speech()[0] in ['名詞','動詞']: wordlist.append(token.surface()) # コーパスを読み込む file = open('./corpus.txt', 'r') corpus = file.readlines() file.close() # 抽出した検索語でコーパスを検索する MAX_TOKENS = 50000 # ChatGPT の受け入れ可能トークン数 retrieved_doc = get_retrieved_doc(corpus, MAX_TOKENS, wordlist) # 拡張プロンプトを作成する augmented_prompt = f'質問: {question}\n' \ f'参考資料は以下:\n' \ f'{retrieved_doc}' print(augmented_prompt) print('-----') print(f'トークン数: {len(tik_enc.encode(augmented_prompt))}')
3-3. プログラムを実行する。
$ ./retreval_augmented_prompt2.py | fold

質問: 日本の料理とは?
参考資料は以下:
  * 2 料理の方法 料理の方法サブセクションを切り替えます
  * 3 料理の提供形態
  * 4 地域別料理一覧 地域別料理一覧サブセクションを切り替えます
    * 4.2 日本料理
  * 5 料理(調理)の競技
# 料理
**料理** (りょうり)は、食物をこしらえることで同時にこしらえた結果である[食品](
/wiki/%E9%A3%9F%E5%93%81

… 長いので省略 …
* [料理](/wiki/Category:%E6%96%99%E7%90%86 "Category:料理") * 最終更新 2025年11月28日 (金) 23:41 (日時は[個人設定](/wiki/%E7%89%B9%E5%88% A5:%E5%80%8B%E4%BA%BA%E8%A8%AD%E5%AE%9A#mw-prefsection-rendering "特別:個人設定" )で未設定ならば[UTC](/wiki/%E5%8D%94%E5%AE%9A%E4%B8%96%E7%95%8C%E6%99%82 "協定世 界時"))。 料理 ----- トークン数: 22392
3-4. ChatGPT に質疑する。
ChatGPT を Web ブラウザで開き、上記 3-3 のテキストをプロンプトとして送信すると、以下の回答を得られる。

質問は「日本の料理とは?」である。

提示資料の構造上、地域別料理一覧の中に 「日本料理」 が位置づけられている。
したがって、定義としては以下になる。

日本の料理とは
日本の料理とは、
日本という地域・民族・文化圏において発展してきた料理体系であり、
一般に 日本料理 を指す。

概念整理
  • 「料理」は民族・地域・時代により異なる。
  • その地域別分類の一つが「日本料理」。
  • 日本料理の内部には以下の体系が含まれる。
例:
  • 御節料理
  • 精進料理
  • 本膳料理
  • 懐石料理
  • 会席料理
  • 郷土料理

まとめ(最短定義) 日本の料理とは、日本で成立・発展した料理文化の総称である。
以上。