0
0

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 の RAG で回答精度を上げるチャンク分割テクニック 3 選

0
Last updated at Posted at 2026-03-20

LangChain.js の RAG で回答精度を上げるチャンク分割テクニック 3 選

TL;DR

  • RAG の回答精度はチャンク分割の品質に大きく左右される
  • LangChain.js の RecursiveCharacterTextSplitter で区切り文字を調整するだけで精度が変わる
  • Overlap・メタデータ付与・親子チャンクの 3 テクニックを紹介

動作確認環境

  • Node.js 22.x
  • langchain 0.3.x / @langchain/openai 0.3.x / @langchain/community 0.3.x
  • TypeScript 5.x
npm install langchain @langchain/openai @langchain/community hnswlib-node

問題: RAG が的外れな回答を返す

LangChain.js で RAG を組んだものの、関連するドキュメントを取得しているはずなのに回答が的外れ。原因の多くはチャンクの切り方にある。

// ❌ よくあるNG例: 固定長で機械的に分割
const splitter = new CharacterTextSplitter({
  chunkSize: 500,
  chunkOverlap: 0, // オーバーラップなし
  separator: "\n",
});

文の途中でぶった切られたチャンクでは、ベクトル検索のマッチ精度が落ちる。

テクニック 1: RecursiveCharacterTextSplitter の区切り文字を調整

RecursiveCharacterTextSplitter は複数の区切り文字を優先度付きで試す。日本語ドキュメントの場合、デフォルトの区切り文字だとうまく分割できないことがある。

import { RecursiveCharacterTextSplitter } from "langchain/text_splitter";

const splitter = new RecursiveCharacterTextSplitter({
  chunkSize: 800,
  chunkOverlap: 200,
  separators: [
    "\n## ",    // H2見出し(最優先)
    "\n### ",   // H3見出し
    "\n\n",     // 段落区切り
    "\n",       // 改行
    "",       // 日本語の句点
    ".",        // 英語のピリオド
    " ",        // スペース
    "",         // 最終手段:1文字ずつ
  ],
});

const docs = await splitter.createDocuments([markdownText]);

ポイント: Markdown の見出し(## ### )を最優先にすることで、意味的にまとまったチャンクを作る。見出し単位で分割されるため、ベクトル検索で「○○について」と聞いたときに、該当セクション全体が取得される。

テクニック 2: チャンクにメタデータを付与

チャンクにメタデータ(ソースファイル名、セクション見出し、ページ番号など)を付与すると、リトリーバル後のフィルタリングやソース表示が可能になる。

import { Document } from "langchain/document";

// Markdown からセクション単位でチャンクを作成
function splitMarkdownWithMetadata(
  markdown: string,
  source: string
): Document[] {
  const sections = markdown.split(/(?=^## )/gm);

  return sections.map((section, index) => {
    // セクション見出しを抽出
    const headingMatch = section.match(/^## (.+)/);
    const heading = headingMatch ? headingMatch[1].trim() : `section-${index}`;

    return new Document({
      pageContent: section.trim(),
      metadata: {
        source,
        section: heading,
        index,
        charCount: section.length,
      },
    });
  });
}

const docs = splitMarkdownWithMetadata(content, "api-reference.md");

メタデータがあると、検索結果を「このドキュメントの○○セクションより」と表示でき、ユーザーが原文を確認しやすくなる。

テクニック 3: 親子チャンク(Parent-Child Chunking)

小さなチャンクで精度よく検索し、回答生成時には大きなチャンクのコンテキストを使う。LangChain.js の ParentDocumentRetriever で実現できる。

import { ParentDocumentRetriever } from "langchain/retrievers/parent_document";
import { HNSWLib } from "@langchain/community/vectorstores/hnswlib";
import { OpenAIEmbeddings } from "@langchain/openai";
import { InMemoryStore } from "langchain/storage/in_memory";
import { RecursiveCharacterTextSplitter } from "langchain/text_splitter";

// 子チャンク(検索用): 小さめ
const childSplitter = new RecursiveCharacterTextSplitter({
  chunkSize: 200,
  chunkOverlap: 50,
});

// 親チャンク(生成用): 大きめ
const parentSplitter = new RecursiveCharacterTextSplitter({
  chunkSize: 1000,
  chunkOverlap: 200,
});

const vectorstore = await HNSWLib.fromDocuments([], new OpenAIEmbeddings());
const docstore = new InMemoryStore();

const retriever = new ParentDocumentRetriever({
  vectorstore,
  docstore,
  childSplitter,
  parentSplitter,
});

// ドキュメントを追加(自動的に親子チャンクが作成される)
await retriever.addDocuments(documents);

// 検索時は子チャンクでマッチ → 親チャンクを返す
const results = await retriever.invoke("認証の実装方法は?");
// results: 親チャンク(1000文字)が返る

なぜ効果的か: 小さなチャンク(200文字)はピンポイントでマッチしやすい。でも 200 文字だけでは LLM が回答を生成するのに文脈が足りない。親チャンク(1000文字)を返すことで、検索精度と文脈の両方を確保できる。

まとめ

テクニック 効果 実装コスト
区切り文字調整 意味的にまとまったチャンク 低(設定変更のみ)
メタデータ付与 フィルタリング+ソース表示 中(カスタム分割関数)
親子チャンク 検索精度+文脈保持の両立 中(ParentDocumentRetriever)

RAG の回答品質に悩んでいるなら、まずチャンク分割を見直すのが最もコスパが良い。

ベクトルストアの選定やリトリーバル戦略、本番運用時のパフォーマンス最適化など、LangChain.js RAG の全体像は LangChain.js RAG実装ガイド — ベクトル検索から本番運用まで でまとめています。

0
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?