LLMのための前処理（ベクトル化）

## はじめに
LLMの理解を進めるために前回、生成AIの回答を表示する流れを簡易に確認しました。

https://qiita.com/kenji123/items/b7ac58adfdcb65db8525

その過程で、**LLMが理解しやすい形式にデータを加工する必要がある**ことがわかりました。
今回はその「データを加工する」部分、つまり**テキストをベクトル化して保存する流れ**を記載します。

## ファイルをベクトル化し保存する
LLMは、与えられたテキストに対して自然言語で回答を生成するAIですが、
そのままの文章を扱うのは苦手で、検索や知識照合には向いていません。
そのため、あらかじめ対象のテキストを **「意味ベースの数値（ベクトル）」に変換（ベクトル化）** し、
似た意味の文書を高速に検索できるようにするのがベクトル検索の考え方です。

このスクリプト（最後に記載）は、以下の処理を行っています。

* テキストを分割し、
* ベクトルに変換し、
* FAISS（Facebook製の高速検索エンジン）に登録します。

---

### なぜベクトル化するのか？

* 意味の近い文章を数値として比較できるようにするため
* 長文をそのまま比較するよりも高速かつ高精度に検索可能
* 主に「ドキュメント検索」や「質問応答システム（QA）」で使われる基盤技術

---
### 補足：このベクトルは誰が使うのか？

今回作成するベクトルデータは、それだけでは使えません。
**このベクトルをもとに「質問に答える」のはLLMの役割**になります。

例えば：

* OpenAIのGPTシリーズを使えば、クラウド経由で回答を生成できます（APIキーと課金が必要）
* 一方、ローカルに小型のLLMを構築する方法もあります（無料・環境構築が必要）

これらは「**ベクトルを使ってどう答えるか**」という話であり、今回のテーマである「ベクトル化と保存」とは別の段階です。
今回のスクリプトは、**その前処理（ベクトルデータ作成）の部分のみを扱っています。**



### OpenAIとローカルLLMの違い

**ベクトルを使ってどう答えるか**は、以下を使用することになります。

| 項目   | OpenAI API               | ローカルLLM（今回の例）       |
| ---- | ------------------------ | ------------------- |
| 特徴   | クラウド上で高性能なモデル（例：GPT）を使える | 自前のPC環境で簡易モデルを動かせる  |
| 利用条件 | APIキー必須（課金制）             | インターネット接続不要（ローカル完結） |
| メリット | 高精度・多機能                  | 手軽・無料・検証に最適         |



---

## ベクトル化手順例

### 使用ライブラリ

```python
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.schema import Document
from langchain.text_splitter import CharacterTextSplitter
```

* `HuggingFaceEmbeddings`: テキストをベクトル化（埋め込み）するためのツール。`all-MiniLM-L6-v2` モデルを使用。
* `FAISS`: Facebook製のベクトル検索ライブラリ。
* `Document`: LangChainのテキストラップ用クラス。
* `CharacterTextSplitter`: テキストを分割するためのユーティリティ。

---

### 1. テスト用テキストの定義

```python
text = """
これはテスト用の文章です。
LangChainとFAISSを使って、検索可能なベクトルデータベースを構築します。
"""

documents = [Document(page_content=text)]
```

* 解析対象のテキストを1つのDocumentとしてリスト化します。

---

### 2. テキスト分割（チャンク化）

```python
text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=50)
split_docs = text_splitter.split_documents(documents)
```

* 長文のままだと埋め込みに適さないため、**500文字ごとに分割**し、50文字は重複させて文脈を維持。
* `split_docs` には複数の小さなチャンクに分割された `Document` が入ります。

---

### 3. ベクトル変換（埋め込み）

```python
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
```

* HuggingFaceの小型モデルを利用（インターネット接続が必要な場合あり）。
* モデルがローカルにダウンロードされれば、以降の再利用は速くなります。

---

### 4. FAISS によるインデックス作成

```python
db = FAISS.from_documents(split_docs, embeddings)
```

* 分割された各テキストチャンクをベクトル化し、FAISSインデックスに格納します。

---

### 5. ローカルに保存

```python
db.save_local("faiss_index")
```

* 作成したベクトルデータベースを `"faiss_index"` フォルダとして保存。
* あとで検索に使うときは `FAISS.load_local(...)` を使えばOK。



## 今回のソース例
```create_faiss_index.py
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.schema import Document
from langchain.text_splitter import CharacterTextSplitter

# テキスト（ローカル処理・API不要）
text = """
これはテスト用の文章です。
LangChainとFAISSを使って、検索可能なベクトルデータベースを構築します。
"""

documents = [Document(page_content=text)]

# テキスト分割
text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=50)
split_docs = text_splitter.split_documents(documents)

# ✅ HuggingFace Embeddings を使用（OpenAIではありません）
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")

# FAISSインデックス作成
db = FAISS.from_documents(split_docs, embeddings)

# 保存
db.save_local("faiss_index")

```

## おわりに
これでLLMを理解し、情報についていけｔ、応用していけるはず。