LlamaIndex Tutorial (TypeScript): handling long documents for advanced developers

By Cyprian AaronsUpdated 2026-04-21
llamaindexhandling-long-documents-for-advanced-developerstypescript

This tutorial shows how to ingest, split, index, and query long documents in LlamaIndex with TypeScript without blowing up context windows or returning noisy answers. You need this when your source material is a contract, policy manual, medical packet, or claims file that is too large to stuff into a single prompt.

What You'll Need

  • Node.js 18+
  • A TypeScript project
  • npm or pnpm
  • An OpenAI API key
  • These packages:
    • llamaindex
    • dotenv
    • typescript
    • tsx or another TypeScript runner
  • A long text file to test with, such as ./data/policy.txt

Step-by-Step

  1. Set up your project and install the dependencies.
    Keep the setup boring and explicit; long-document pipelines fail most often because of environment drift, not model quality.
npm init -y
npm install llamaindex dotenv
npm install -D typescript tsx @types/node
  1. Add your API key and create a TypeScript entrypoint.
    LlamaIndex will read the OpenAI key from the environment, so keep it in .env and load it at runtime.
mkdir -p data src
cat > .env << 'EOF'
OPENAI_API_KEY=your_openai_api_key_here
EOF

cat > src/index.ts << 'EOF'
import "dotenv/config";
import { Document } from "llamaindex";

async function main() {
  const doc = new Document({
    text: "Example long document content goes here.",
    metadata: { source: "policy.txt" },
  });

  console.log(doc.metadata);
}

main().catch(console.error);
EOF
  1. Load the long document from disk and split it into manageable chunks.
    For advanced use cases, chunking is not optional. You want chunks that preserve enough local context for retrieval while staying small enough for embeddings and reranking.
import "dotenv/config";
import { Document, SentenceSplitter } from "llamaindex";
import { readFile } from "node:fs/promises";

async function main() {
  const text = await readFile("./data/policy.txt", "utf8");

  const document = new Document({
    text,
    metadata: { source: "policy.txt" },
  });

  const splitter = new SentenceSplitter({
    chunkSize: 512,
    chunkOverlap: 80,
  });

  const nodes = splitter.getNodesFromDocuments([document]);
  console.log(`Created ${nodes.length} nodes`);
}

main().catch(console.error);
  1. Build a vector index over those chunks and query it with a retriever-backed engine.
    This is the core pattern for long documents: retrieve only the relevant chunks instead of asking the model to reason over the entire file.
import "dotenv/config";
import { Document, SentenceSplitter, VectorStoreIndex } from "llamaindex";
import { readFile } from "node:fs/promises";

async function main() {
  const text = await readFile("./data/policy.txt", "utf8");
  const document = new Document({ text, metadata: { source: "policy.txt" } });

  const splitter = new SentenceSplitter({ chunkSize: 512, chunkOverlap: 80 });
  const nodes = splitter.getNodesFromDocuments([document]);

  const index = await VectorStoreIndex.fromDocuments(nodes);
  const queryEngine = index.asQueryEngine({ similarityTopK: 4 });

  const response = await queryEngine.query({
    query: "What does this policy say about late claim submissions?",
  });

  console.log(response.toString());
}

main().catch(console.error);
  1. Add metadata filtering so you can trace answers back to their source.
    In regulated environments, retrieval without provenance is not enough. You need to know which chunk answered the question and where it came from.
import "dotenv/config";
import {
  Document,
  MetadataMode,
  SentenceSplitter,
  VectorStoreIndex,
} from "llamaindex";
import { readFile } from "node:fs/promises";

async function main() {
  const text = await readFile("./data/policy.txt", "utf8");
  const document = new Document({
    text,
    metadata: { source: "policy.txt", department: "claims" },
  });

  const splitter = new SentenceSplitter({ chunkSize: 512, chunkOverlap: 80 });
  const nodes = splitter.getNodesFromDocuments([document]);

  console.log(nodes[0].getContent(MetadataMode.ALL));

  const index = await VectorStoreIndex.fromDocuments(nodes);
}

main().catch(console.error);
  1. Use a summarization pass when you need a whole-document answer instead of retrieval-only Q&A.
    Retrieval is best for pinpoint questions. For executive summaries or clause-level overviews, run a summarizer on top of your chunks.
import "dotenv/config";
import { Document, SentenceSplitter } from "llamaindex";
import { readFile } from "node:fs/promises";

async function main() {
  const text = await readFile("./data/policy.txt", "utf8");
  const document = new Document({ text });

  const splitter = new SentenceSplitter({ chunkSize: 700, chunkOverlap: 100 });
  const nodes = splitter.getNodesFromDocuments([document]);

  const combinedText = nodes.map((n) => n.getContent()).join("\n\n");
  
}
main().catch(console.error());

Testing It

Run the script against a real long document with at least several pages of text. Start with a question that should map to one section only, then ask something broader that requires multiple chunks.

Check three things:

  • The answer stays grounded in your source document.
  • The response changes when you change similarityTopK.
  • The retrieved chunks actually contain the evidence you expect.

If answers become vague or miss obvious sections, reduce chunk size slightly or increase overlap. If retrieval returns too much irrelevant material, lower similarityTopK or improve your document structure before indexing.

Next Steps

  • Add a reranker after vector retrieval for better precision on dense legal or insurance docs.
  • Store indexes in a persistent vector database instead of rebuilding them on every run.
  • Build a hybrid pipeline with keyword retrieval plus vector search for clause-heavy documents.

Keep learning

By Cyprian Aarons, AI Consultant at Topiax.

Want the complete 8-step roadmap?

Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.

Get the Starter Kit

Related Guides