Next.jsのプロジェクトでサーバーサイドでLlamaIndexTSを使用しようとしたところ
⨯ ./node_modules/onnxruntime-node/bin/napi-v3/darwin/arm64/onnxruntime_binding.node
Module parse failed: Unexpected character '�' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
のようなエラーが発生して、対処方法を調べたので残しておきます。
結論だけいうとnext.config.mjs
に以下のような設定を追加すれば良いです。
experimental: {
serverComponentsExternalPackages: ["sharp", "onnxruntime-node"],
},
サンプルプロジェクトを作ります。
$ npx create-next-app@latest
Need to install the following packages:
[email protected]
Ok to proceed? (y)
✔ What is your project named? … nextjs-llamaindex-test
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like to use `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to customize the default import alias (@/*)? … No / Yes
Llamaindexを追加します。
$ cd nextjs-llamaindex-test/
$ npm i llamaindex
このときpackage.json
の内容は以下のようになっています。
$ cat package.json
{
"name": "nextjs-llamaindex-test",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"llamaindex": "^0.5.24",
"next": "14.2.9",
"react": "^18",
"react-dom": "^18"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"eslint": "^8",
"eslint-config-next": "14.2.9",
"postcss": "^8",
"tailwindcss": "^3.4.1",
"typescript": "^5"
}
}
Test用のAPIを追加します。
$ mkdir -p app/api/complete
$ touch app/api/complete/route.ts
route.ts
の中身はシンプルにリクエストのBodyから読み取った内容をLLMに渡して結果を返すだけにします。
import { NextResponse, NextRequest } from "next/server";
import { Groq } from "llamaindex";
export async function POST(request: NextRequest) {
const { prompt } = await request.json();
try {
const llm = new Groq();
const result = await llm.complete({ prompt });
return NextResponse.json({ result: result.text });
} catch (error) {
return NextResponse.json({ error });
}
}
今回はLLMにGroqを使用していますが何でもいいです。
Groqを使っている場合は環境変数GROQ_API_KEY
にAPIキーを設定しておいてください。
開発サーバーを立ち上げます。
$ npm run dev
localhost:3000
にサーバーが立ち上がるので、リクエストを送ってみます。
$ curl -X POST -H "Content-Type: application/json" -d '{"prompt":"エラーが発生しますか?"}' localhost:3000/api/complete
すると、開発サーバーを立ち上げたターミナルに以下のようなエラーが出ていることが分かります。
⨯ ./node_modules/onnxruntime-node/bin/napi-v3/darwin/arm64/onnxruntime_binding.node
Module parse failed: Unexpected character '�' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
(Source code omitted for this binary file)
Import trace for requested module:
./node_modules/onnxruntime-node/bin/napi-v3/darwin/arm64/onnxruntime_binding.node
./node_modules/onnxruntime-node/bin/napi-v3/ sync ^\.\/.*\/.*\/onnxruntime_binding\.node$
./node_modules/onnxruntime-node/dist/binding.js
./node_modules/onnxruntime-node/dist/backend.js
./node_modules/onnxruntime-node/dist/index.js
./node_modules/@xenova/transformers/src/backends/onnx.js
./node_modules/@xenova/transformers/src/env.js
./node_modules/@xenova/transformers/src/transformers.js
./node_modules/llamaindex/dist/internal/deps/transformers.js
./node_modules/llamaindex/dist/embeddings/HuggingFaceEmbedding.js
./node_modules/llamaindex/dist/embeddings/index.js
./node_modules/llamaindex/dist/index.edge.js
./node_modules/llamaindex/dist/index.react-server.js
./app/api/complete/route.ts
エラー内容を見る限りllamaindex
, transformers
, onnxruntime-node
のどこかで何か問題が起きてそうです。
エラーメッセージで検索してみると、このIssueがみつかりました。
Issueによるとnext.config.mjs
に設定を追加すれば解決するとのことなので以下のように設定します。
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
serverComponentsExternalPackages: ["sharp", "onnxruntime-node"],
},
};
export default nextConfig;
開発サーバーを再度立ち上げてリクエストを送ると正常に動いていることが確認できます。
$ curl -X POST -H "Content-Type: application/json" -d '{"prompt":"エラーが発生しますか?"}' localhost:3000/api/complete
{"result":"あなたが私にエラーを示すコードや文脈を提供しない限り、私は判断することができません。エラーメッセージと共に問題のコードを提供することで、私はエラーを修正するためのアドバイスを提供することができます。"}