0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LangChain.jsでベクトルストアを作成する。

Last updated at Posted at 2024-04-11

概要

色々なソースから、RAG用のベクトルストアを作成する方法を書きます。

  1. テキストファイル
  2. PDF
  3. 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();

おわり

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?