概要
色々なソースから、RAG用のベクトルストアを作成する方法を書きます。
- テキストファイル
- Webページ
基本的な流れ
ファイルからテキストを読み込む。
↓
テキストをチャンクに分ける。
↓
ベクトルストアを作成する。
埋め込みモデル
埋め込みモデルには、multilingual-e5-large
を使います。
Webページからベクトルストアを作成するときだけ、multilingual-e5-large
だと上手くいかなかったのでOpenAIのtext-embedding-3-small
を使います。(お金がかかる)
トークンが多すぎてmultilingual-e5-large
だと使えないのかもしれないです。
LangChain.jsでは埋め込みモデルは以下のようにインスタンスします。
apikeyは.envファイルに書き込んでおきます。
// embeddings =========================================================================
const emb_e5 = new HuggingFaceInferenceEmbeddings({
apiKey: process.env.HUGGINGFACEHUB_API_KEY,
model: "intfloat/multilingual-e5-large"
});
const emb_openai = new OpenAIEmbeddings({
openAIApiKey: process.env.OPEN_AI_API_KEY,
});
近似最近傍探索ライブラリ
近似最近傍探索ライブラリにはFaissを使います。
1. テキストファイルからベクトルストアを作成する
テキストファイルはファイルを読み込むだけです。
// make index =========================================================================
const make_index_text = async () => {
// textファイルを読み込み
const text = fs.readFileSync("data.txt", "utf8");
// textをチャンクに分ける
const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 400, chunkOverlap: 50 });
const docs = await textSplitter.createDocuments([text]);
// ベクトルストアを作成
const vectorStore = await FaissStore.fromDocuments(
docs,
emb_e5 // or emb_openai
);
// indexTEXTというフォルダに保存
await vectorStore.save("indexTEXT");
};
全体
// import ============================================================================
import * as fs from "fs";
import { OpenAIEmbeddings } from "@langchain/openai";
import { HuggingFaceInferenceEmbeddings } from "@langchain/community/embeddings/hf";
import { RecursiveCharacterTextSplitter } from "langchain/text_splitter";
import { FaissStore } from "@langchain/community/vectorstores/faiss";
// embeddings =========================================================================
const emb_e5 = new HuggingFaceInferenceEmbeddings({
apiKey: process.env.HUGGINGFACEHUB_API_KEY,
model: "intfloat/multilingual-e5-large"
});
const emb_openai = new OpenAIEmbeddings({
openAIApiKey: process.env.OPEN_AI_API_KEY,
});
// make index =========================================================================
const make_index_text = async () => {
const text = fs.readFileSync("data.txt", "utf8");
const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 400, chunkOverlap: 50 });
const docs = await textSplitter.createDocuments([text]);
const vectorStore = await FaissStore.fromDocuments(
docs,
emb_e5 // or emb_openai
);
await vectorStore.save("indexTEXT"); // indexフォルダ
};
// do function =====================================================================
make_index_text();
2. PDFからベクトルストアを作成する
PDFはPDFLoader
を使ってテキストを読み込みます。
// make index =========================================================================
const make_index_pdf = async () => {
// PDFを読み込み&チャンクに分ける
const loader = new PDFLoader("data.pdf");
const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 400, chunkOverlap: 50 });
const docs = await loader.loadAndSplit(textSplitter);
// ベクトルストアを作成
const vectorStore = await FaissStore.fromDocuments(
docs,
emb_e5 // or emb_openai
);
// indexPDFに保存
await vectorStore.save("indexPDF"); // indexフォルダ
};
全体
// import ============================================================================
import { PDFLoader } from "langchain/document_loaders/fs/pdf";
import { RecursiveCharacterTextSplitter } from "langchain/text_splitter";
import { FaissStore } from "@langchain/community/vectorstores/faiss";
import { HuggingFaceInferenceEmbeddings } from "@langchain/community/embeddings/hf";
import { OpenAIEmbeddings } from "@langchain/openai";
// embeddings =========================================================================
const emb_e5 = new HuggingFaceInferenceEmbeddings({
apiKey: process.env.HUGGINGFACEHUB_API_KEY,
model: "intfloat/multilingual-e5-large"
});
const emb_openai = new OpenAIEmbeddings({
openAIApiKey: process.env.OPEN_AI_API_KEY,
});
// make index =========================================================================
const make_index_pdf = async () => {
// PDFを読み込み&チャンクに分ける
const loader = new PDFLoader("data.pdf");
const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 400, chunkOverlap: 50 });
const docs = await loader.loadAndSplit(textSplitter);
// ベクトルストアを作成
const vectorStore = await FaissStore.fromDocuments(
docs,
emb_e5 // or emb_openai
);
// indexPDFに保存
await vectorStore.save("indexPDF"); // indexフォルダ
};
// do function =====================================================================
make_index_pdf();
3. Webページからベクトルストアを作成する
WebページはRecursiveUrlLoader
を使って読み込みます。
設定したURLの子ディレクトリも全部読み込まれます。
埋め込みモデルにはmultilingual-e5-large
が使えなかったので、OpenAIのモデルを使ってます。
// make index =========================================================================
const make_index_web = async () => {
// Webページからテキスト読み込み&チャンクに分ける
const url = "https://www.toraichi.com/"
const compiledConvert = compile({ wordwrap: 130 });
const loader = new RecursiveUrlLoader(url, {
extractor: compiledConvert,
maxDepth: 1,
});
const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 500, chunkOverlap: 100 });
const docs = await loader.loadAndSplit(textSplitter);
// ベクトルストアを作成
const vectorStore = await FaissStore.fromDocuments(
docs,
emb_openai
);
// indexWEBフォルダに保存
await vectorStore.save("indexWEB");
};
全体
// import ============================================================================
import { compile } from "html-to-text";
import { RecursiveUrlLoader } from "langchain/document_loaders/web/recursive_url";
import { RecursiveCharacterTextSplitter } from "langchain/text_splitter";
import { OpenAIEmbeddings } from "@langchain/openai";
import { FaissStore } from "@langchain/community/vectorstores/faiss";
// embeddings =========================================================================
const emb_openai = new OpenAIEmbeddings({
openAIApiKey: process.env.OPEN_AI_API_KEY,
});
// make index =========================================================================
const make_index_web = async () => {
// Webページからテキスト読み込み&チャンクに分ける
const url = "https://www.なんかのサイト.com/"
const compiledConvert = compile({ wordwrap: 130 });
const loader = new RecursiveUrlLoader(url, {
extractor: compiledConvert,
maxDepth: 1,
});
const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 500, chunkOverlap: 100 });
const docs = await loader.loadAndSplit(textSplitter);
// ベクトルストアを作成
const vectorStore = await FaissStore.fromDocuments(
docs,
emb_openai
);
// indexWEBフォルダに保存
await vectorStore.save("indexWEB");
};
// do function =====================================================================
make_index_web();
おわり