LLMをアプリケーションに組み込む際に欠かせないのがRAGです。独自の情報を付与することで、アプリケーションを差別化し、魅力的なものにします。

Python向けのソフトウェアは多いですが、今回はTypeScriptで使えるLlamaIndexTSを紹介します。ブラウザのJavaScriptとも親和性が高いので、フロントエンドエンジニアでも利用できるでしょう。

LlamaIndexTSについて

LlamaIndexTSはPythonで作られているLlamaIndexのTypeScript版です。LLMアプリケーションを開発したり、RAG機能を追加するのを手軽にするフレームワークになります。

使い方

一番簡単な使い方として、 npx を使ったベースのインストール方法があります。

% npx create-llama@latest

そうすると、ウィザードに沿ってベースを生成できます。生成できるのは、以下の6種類となっています。

  • Agentic RAG
  • Financial Report
  • Deep Research
  • Code Generator
  • Document Generator
  • Human in the Loop

そして、言語も選択します。TypeScriptの場合はNextJSベースになります。

? What language do you want to use? › - Use arrow-keys. Return to submit.
    Python (FastAPI)
❯   Typescript (NextJS)

アプリの使い方

アプリのUIは基本的にチャット形式になります。

ただし、APIも利用できます。アプリから利用する際には、こちらが参考になるでしょう。

curl --location 'localhost:3000/api/chat' \
--header 'Content-Type: application/json' \
--data '{ "messages": [{ "role": "user", "content": "Compare the financial performance of Apple and Tesla" }] }'

モデルの選択

デフォルトではOpenAIを利用します。OpenAIのAPIキーを取得して、 .env ファイルの OPENAI_API_KEY に適用します。対応しているモデルについてはLLM modelにあり、一緒に利用できるembedding modelも選定してください。

データの生成

生成されたアプリでは、 data ディレクトリが存在します。選択したベースによりますが、 Code Generator の場合は空でした。 Agentic RAG の場合はPDFファイルがありました。

ここにあるファイルを読み込んで、検索のインデックスを生成します。インデックスの生成は pnpm コマンドが推奨されています。

npx pnpm run generate

検索インデックスは、 storage フォルダの中に生成されます。このインデックスが生成されることで、その内容に沿った質問や回答ができるようになります。

外部ベクトルデータベース連携

LlamaIndexTSは多くの外部ベクトルデータベースと連携できます。例えば、以下のようなものがあります。

  • インメモリ
    またはディスクに保存可能なシンプルなベクトルストア
  • AstraDB
    Apache Cassandraをベースにした、スケーラブルなクラウドネイティブなデータベース
  • Chroma
    Chromaは、使いやすさとパフォーマンスを重視したオープンソースのベクトルデータベースです
  • Milvus
    スケーラブル、かつハイパフォーマンスなオープンソースのベクトルデータベース
  • MongoDB Atlas
    ドキュメント指向のデータベースであるMongoDB Atlasのベクトル検索機能
  • PGVector
    PostgreSQLをベースにしたオープンソースのベクトルストア
  • Pinecone
    スケーラブルで高性能なベクトルデータベースを提供するマネージドサービス
  • Weaviate
    AIネイティブなオープンソースのベクトルデータベース
  • Qdrant
    高性能なベクトル検索エンジンで、リアルタイムのデータ処理に対応

例えばQdrantの場合は、以下のようなコードで利用します。

import fs from "node:fs/promises";
import { Document, VectorStoreIndex } from "llamaindex";
import { QdrantVectorStore } from "@llamaindex/qdrant";
async function main() {
  // ファイルを読み込み
  const path = "node_modules/llamaindex/examples/abramov.txt";
  const essay = await fs.readFile(path, "utf-8");
  // Qdrantのベクトルストアを初期化
  // localhost:6333でQdrantが動作している前提です
  const vectorStore = new QdrantVectorStore({
    url: "http://localhost:6333",
  });
  // ドキュメントを作成し、インデックスを生成
  const document = new Document({ text: essay, id_: path });
  // ストレージコンテキストを作成
  const storageContext = await storageContextFromDefaults({ vectorStore });
  // インデックスを生成
  const index = await VectorStoreIndex.fromDocuments([document], {
    storageContext,
  });
  // クエリエンジンを取得し、質問を実行
  const queryEngine = index.asQueryEngine();
  // 質問を実行
  const response = await queryEngine.query({
    query: "What did the author do in college?",
  });
  // 結果を出力
  console.log(response.toString());
}
main().catch(console.error);

サーバーレス環境へのデプロイ

LlamaIndexTSは、サーバーレス環境へのデプロイをサポートしています。例えば以下のようなサービスが利用可能です。

  • Cloudflare Workers
  • Vercel Functions
  • AWS Lambda
  • Netlify Functions

Cloudflare Workersを利用する場合は、以下のようなコードで利用できます。LLMとして、ChatGPTを利用しています。

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const { setEnvs } = await import("@llamaindex/env");
    setEnvs(env);

    const { agent } = await import("@llamaindex/workflow");
    const { openai } = await import("@llamaindex/openai");
    const { tool } = await import("llamaindex");
    const { z } = await import("zod");

    const timeTool = tool({
      name: "getCurrentTime",
      description: "Gets the current time",
      parameters: z.object({}),
      execute: () => new Date().toISOString(),
    });

    const myAgent = agent({
      tools: [timeTool],
      llm: openai({ model: "gpt-4o-mini" }),
    });

    try {
      const { message } = await request.json();
      const result = await myAgent.run(message);

      return new Response(JSON.stringify({ response: result.result }), {
        headers: { "Content-Type": "application/json" },
      });
    } catch (error) {
      return new Response(JSON.stringify({ error: error.message }), {
        status: 500,
        headers: { "Content-Type": "application/json" },
      });
    }
  },
};

まとめ

LlamaIndexTSを使えば、独自のデータを追加したLLM機能を素早く実装できます。デプロイ先はさまざまに、ベクトルデータベースも多数の選択肢があります。ぜひ、RAG機能を組み込んだアプリケーションを開発してください。

LlamaIndex.TS - Build LLM-powered document agents and workflows