LocalLens
アーキテクチャ

なぜ QVAC か

ほとんどの仕事をこなしている 5 つの SDK 呼び出しと、それが 1 つのパッケージにまとまっている理由。

QVAC は LocalLens のローカル AI ループを 動かしている SDK です。この規模のプロジェクトで興味深いのは、本来なら 5 つの別ライブラリを引っ張ってくることになる 5 つの仕事を、1 パッケージで 扱える点です。

使っている 5 つの SDK 呼び出し

import {
  loadModel,
  ragChunk,
  ragIngest,
  ragSearch,
  completion,
  // and the lifecycle helpers:
  ragCloseWorkspace,
  ragDeleteWorkspace,
  close,
} from "@qvac/sdk";
呼び出し使用箇所役割
loadModelsrc/qvac.ts → ensureReady埋め込みモデル(GTE_LARGE_FP16)とチャットモデル(QWEN3_1_7B_INST_Q4、600M フォールバックあり)を読み込む。
ragChunksrc/rag.ts → chunkDocumentドキュメントテキストを約 220 トークン幅、40 トークンのオーバーラップで分割する。
ragIngestsrc/qvac.ts → ingestChunksチャンクを embedding にし、名前付きワークスペースに保存する。
ragSearchsrc/qvac.ts → searchクエリを embedding にし、上位 K 件のチャンクを返す。
completionsrc/qvac.ts → answer読み込み済みモデルからチャット出力をストリーミングする。
ragCloseWorkspacesrc/qvac.ts → closeWorkspaceディスク上のワークスペースを閉じる(必要なら削除する)。
closesrc/qvac.ts → closeアプリ終了時に QVAC ランタイムを片付ける。

LocalLens が使っているのはこれで全部です。手動の embedding ループも、 別建てのベクトルデータベースも、独自のトークン分割器もありません。

モデルのライフサイクル

QVAC のモデルは遅延的に、最初に使われたタイミングで読み込まれます。

private async ensureReady(): Promise<void> {
  if (this.chatModelId && this.embeddingModelId) return;
  this.readyPromise ??= this.loadModels().finally(() => {
    this.readyPromise = undefined;
  });
  await this.readyPromise;
}

知っておくと役立つ帰結が 2 つあります。

  1. コールドスタートのコストは最初の質問にかかり、起動時にはかかりません。 これで bun run dev の起動が速く保たれ、UI 側で「モデルを読み込み中…」の 表示をかけるきっかけが明確になります。
  2. 同時呼び出しは 1 つの読み込みを共有します。 全ての呼び出し元は同じ readyPromise を await します。同じティックに 2 つのリクエストが 届いても、同じソースに対して loadModel が二重に走ることはありません。

フォールバックモデルがある理由

デフォルトのチャットモデルは QWEN3_1_7B_INST_Q4 です。古いマシンや 小さいマシンでは読み込みに失敗することがあります。ゲートウェイは それを捕捉して QWEN3_600M_INST_Q4 にフォールバックします。

try {
  this.chatModelId = await loadModel({ modelSrc: QWEN3_1_7B_INST_Q4, modelConfig });
} catch {
  this.chatModelId = await loadModel({ modelSrc: QWEN3_600M_INST_Q4, modelConfig });
}

フォールバックは呼び出し元からは見えません。QvacGateway.answer は どちらの場合でも同じストリーミングシグネチャを返します。

なぜ 1 つの SDK に集約するのか?

LocalLens は embedding に @xenova/transformers、ベクトルに chromadbqdrant、テキスト生成に llama.cpp を使うこともできました。それぞれ 単独では良い選択肢です。3 つ全部を使う場合のコストは、それらを統合する グルーコード、つまりモデルのライフサイクル、ワークスペースの ライフサイクル、エラーマッピング、非同期イテレーションを自分で書くこと です。QVAC はそれらを最初から提供します。このアプリが 8 ファイルに 収まっている理由の大半はそこにあります。

関連する上流のページ

On this page