🎃

LangChain で Fallbacks(Node.js)

2024/06/02に公開

はじめに

LLM を利用する場合、レートリミット、API のダウンタイムなど API の利用にまつわる問題が発生します。この記事では、問題が発生した際に対処する方法を記述します。具体的には以下の記事を参考に記述します。

https://js.langchain.com/v0.2/docs/how_to/fallbacks/

TypeScript / JavaScript での GitHub リポジトリーを公開している実装例はすくないので記事化しました。作業リポジトリはこちらです。
 
https://github.com/hayato94087/langchain-fallbacks-sample

LangChain での実装例を以下の記事で紹介しています。

LangChain とは

LangChain は、大規模言語モデル(LLM)を活用したアプリケーションの開発を支援するフレームワークです。

https://js.langchain.com/v0.2/docs/introduction/

コンセプト

この記事では以下の概要について理解します。

runnable.withFallbacks()

.withFallbacks() を指定して、フォールバックする場合の処理を設定します。

import { ChatOpenAI } from "@langchain/openai";

// モデル名が誤っている対話モデル
const modelWithBadModelName = new ChatOpenAI({
  model: "bad-model",
});

// モデル名が正しい対話モデル
const modelWithCorrectModelName = new ChatOpenAI({
  model: "gpt-3.5-turbo",
});

// フォールバックを追加
const modelWithFallback = modelWithBadModelName.withFallbacks({
  fallbacks: [modelWithCorrectModelName],
});

// モデルを呼び出す
const result = await modelWithFallback.invoke("あなたの名前は?");
console.log(result);
AIMessage {
  lc_serializable: true,
  lc_kwargs: {
    content: '私はボブです。あなたの名前は何ですか?',
    tool_calls: [],
    invalid_tool_calls: [],
    additional_kwargs: { function_call: undefined, tool_calls: undefined },
    response_metadata: {}
  },
  lc_namespace: [ 'langchain_core', 'messages' ],
  content: '私はボブです。あなたの名前は何ですか?',
  name: undefined,
  additional_kwargs: { function_call: undefined, tool_calls: undefined },
  response_metadata: {
    tokenUsage: { completionTokens: 18, promptTokens: 15, totalTokens: 33 },
    finish_reason: 'stop'
  },
  tool_calls: [],
  invalid_tool_calls: [],
  usage_metadata: { input_tokens: 15, output_tokens: 18, total_tokens: 33 }
}

作業プロジェクトの準備

TypeScript の簡易プロジェクトを作成します。

長いので折りたたんでおきます。

package.json を作成

package.json を作成します。

$ mkdir -p langchain-fallbacks-sample
$ cd langchain-fallbacks-sample
$ pnpm init

下記で package.json を上書きします。

package.json
{
  "name": "langchain-fallbacks-sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.ts",
  "scripts": {
    "typecheck": "tsc --noEmit",
    "dev": "vite-node index.ts",
    "build": "tsc"
  },
  "keywords": [],
  "author": "",
}

TypeScript & vite-node をインストール

TypeScript と vite-node をインストールします。補足としてこちらの理由のため ts-node ではなく vite-node を利用します。

$ pnpm install -D typescript vite-node @types/node

TypeScriptの設定ファイルを作成

tsconfig.json を作成します。

$ npx tsc --init

tsconfig.json を上書きします。

tsconfig.json
{
  "compilerOptions": {
    /* Base Options: */
    "esModuleInterop": true,
    "skipLibCheck": true,
    "target": "ES2022",
    "allowJs": true,
    "resolveJsonModule": true,
    "moduleDetection": "force",
    "isolatedModules": true,

    /* Strictness */
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "checkJs": true,

    /* Bundled projects */
    "noEmit": true,
    "outDir": "dist",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "jsx": "preserve",
    "incremental": true,
    "sourceMap": true,
  },
  "include": ["**/*.ts", "**/*.js"],
  "exclude": ["node_modules", "dist"]
}

git を初期化します。

$ git init

.gitignore を作成します。

$ touch .gitignore
.gitignore
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz

# testing
/coverage

# next.js
/.next/
/out/

# production
/build
dist/

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local
.env

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts

動作確認コードを作成

動作を確認するためのコードを作成します。

$ touch index.ts
index.ts
console.log('Hello, World');

型チェック

型チェックします。

$ pnpm run typecheck

動作確認

動作確認を実施します。

$ pnpm run dev

Hello, World

コミットします。

$ git add .
$ git commit -m "初回コミット"

LangChain をインストール

LangChain をインストールします。

$ pnpm add langchain @langchain/core

コミットします。

$ git add .
$ git commit -m "LangChainをインストール"

言語モデルの選択

LangChain は、多くの異なる言語モデルをサポートしており、それらを自由に選んで使用できます。

例えば、以下のような言語モデルを選択できます。

  • OpenAI
  • Anthropic
  • FireworksAI
  • MistralAI
  • Groq
  • VertexAI

ここでは OpenAI を利用します。OpenAI を LangChain で利用するためのパッケージをインストールします。

$ pnpm add @langchain/openai

コミットします。

$ git add .
$ git commit -m "LangChainでOpenAIを利用するためのパッケージをインストール"

OpenAI API キーを取得

OpenAI API キーの取得方法はこちらを参照してください。

https://zenn.dev/hayato94087/articles/85378e1f7bc0e5#openai-の-apiキーの取得

環境変数の設定

環境変数に OpenAI キーを追加します。<your-api-key> に自身の API キーを設定してください。

$ touch .env
.env
# OPENAI_API_KEY は OpenAI の API キーです。
OPENAI_API_KEY='<your-api-key>'

Node.js で環境変数を利用するために dotenv をインストールします。

$ pnpm i -D dotenv

コミットします。

$ touch .env.example
.env
# OPENAI_API_KEY は OpenAI の API キーです。
OPENAI_API_KEY='<your-api-key>'
$ git add .
$ git commit -m "環境変数を設定"

OpenAIを利用

まず、シンプルに OpenAI の LLM を使ってみます。

コードを作成

コードを作成します。

$ touch demo01.ts
demo01.ts
import { ChatOpenAI } from "@langchain/openai";
import 'dotenv/config'

const model = new ChatOpenAI({
  model: "gpt-3.5-turbo",
  temperature: 0
});

const result = await model.invoke("猫についてジョークを言ってください");
console.log(result)

ローカルで実行します。

$ pnpm vite-node demo01.ts

コミットします。

$ git add .
$ git commit -m "OpenAIを使ってみる"

コードの解説

OpenAI を利用します。

import { ChatOpenAI } from "@langchain/openai";

gpt-3.5-turbo のモデルを選択します。temperature は 0 に設定します。temperature が低いほど、モデルの出力はより予測可能になります。

const model = new ChatOpenAI({
  model: "gpt-3.5-turbo",
  temperature: 0
});

.invoke() を利用して、モデルにテキストを送信します。

const result = await model.invoke("猫についてジョークを言ってください");
console.log(result)
AIMessage {
  lc_serializable: true,
  lc_kwargs: {
    content: 'Q: 猫がパソコンを使うときに使うプログラミング言語は何でしょうか?\nA: プロクラスミング言語!',
    tool_calls: [],
    invalid_tool_calls: [],
    additional_kwargs: { function_call: undefined, tool_calls: undefined },
    response_metadata: {}
  },
  lc_namespace: [ 'langchain_core', 'messages' ],
  content: 'Q: 猫がパソコンを使うときに使うプログラミング言語は何でしょうか?\nA: プロクラスミング言語!',
  name: undefined,
  additional_kwargs: { function_call: undefined, tool_calls: undefined },
  response_metadata: {
    tokenUsage: { completionTokens: 52, promptTokens: 22, totalTokens: 74 },
    finish_reason: 'stop'
  },
  tool_calls: [],
  invalid_tool_calls: [],
  usage_metadata: { input_tokens: 22, output_tokens: 52, total_tokens: 74 }
}

LLM API エラーを処理

ここでは、LLM API エラーを処理する方法を記述します。具体的には、モデル名を誤って記述しエラーを人為的に引き起こします。

コードの作成

$ touch demo02.ts
demo02.ts
import { ChatOpenAI } from "@langchain/openai";
import 'dotenv/config'

// モデル名が誤っている対話モデル
const modelWithBadModelName = new ChatOpenAI({
  model: "bad-model",
  temperature: 0,
  maxRetries: 0,
});

// モデル名が正しい対話モデル
const modelWithCorrectModelName = new ChatOpenAI({
  model: "gpt-3.5-turbo",
  temperature: 0,
});

// フォールバックを追加
const modelWithFallback = modelWithBadModelName.withFallbacks({
  fallbacks: [modelWithCorrectModelName],
});

// モデルを呼び出す
const result = await modelWithFallback.invoke("あなたの名前は?");
console.log(result);

ローカルで実行します。

$ pnpm vite-node demo02.ts

コミットします。

$ git add .
$ git commit -m "フォールバックを利用する"

コードの解説

modelWithBadModelName はモデル名が誤っている対話モデルです。modelWithCorrectModelName はモデル名が正しい対話モデルです。

// モデル名が誤っている対話モデル
const modelWithBadModelName = new ChatOpenAI({
  model: "bad-model",
  temperature: 0,
  maxRetries: 0,
});

// モデル名が正しい対話モデル
const modelWithCorrectModelName = new ChatOpenAI({
  model: "gpt-3.5-turbo",
  temperature: 0,
});

.withFallbacks() を利用して、フォールバックを追加します。

// フォールバックを追加
const modelWithFallback = modelWithBadModelName.withFallbacks({
  fallbacks: [modelWithCorrectModelName],
});

.invoke() を利用して、モデルにテキストを送信します。すると、フォールバックが発生し、modelWithBadModelName から modelWithCorrectModelName に切り替わります。

// モデルを呼び出す
const result = await modelWithFallback.invoke("あなたの名前は?");
console.log(result);
AIMessage {
  lc_serializable: true,
  lc_kwargs: {
    content: '私はボブです。あなたの名前は何ですか?',
    tool_calls: [],
    invalid_tool_calls: [],
    additional_kwargs: { function_call: undefined, tool_calls: undefined },
    response_metadata: {}
  },
  lc_namespace: [ 'langchain_core', 'messages' ],
  content: '私はボブです。あなたの名前は何ですか?',
  name: undefined,
  additional_kwargs: { function_call: undefined, tool_calls: undefined },
  response_metadata: {
    tokenUsage: { completionTokens: 18, promptTokens: 15, totalTokens: 33 },
    finish_reason: 'stop'
  },
  tool_calls: [],
  invalid_tool_calls: [],
  usage_metadata: { input_tokens: 15, output_tokens: 18, total_tokens: 33 }
}

フォールバックを RunnableSequences で利用

2 つのチェーンを作成し、問題があった場合はフォールバックし別のチェーンに切り替えます。RunnableSequences がチェーンだと考えれば理解しやすいです。

コードを作成

$ touch demo03.ts
demo03.ts
import { ChatOpenAI } from "@langchain/openai";
import 'dotenv/config'
import { ChatPromptTemplate, PromptTemplate } from "@langchain/core/prompts";
import { StringOutputParser } from "@langchain/core/output_parsers";

// テキスト出力のパーサー
const outputParser = new StringOutputParser();



// ジョークを生成するプロンプトテンプレート
const promptTemplateWithBadModelName = PromptTemplate.fromTemplate("{topic}についてジョークを言ってください");

// モデル名が誤っている対話モデル
const modelWithBadModelName = new ChatOpenAI({
  model: "bad-model",
  temperature: 0,
  maxRetries: 0,
});

// Chain を作成
const badChain = promptTemplateWithBadModelName.pipe(modelWithBadModelName).pipe(outputParser);



// ポエムを生成するプロンプトテンプレート
const promptTemplateWithCorrectModelName = PromptTemplate.fromTemplate("{topic}についてポエムを言ってください");

// モデル名が正しい対話モデル
const modelWithCorrectModelName = new ChatOpenAI({
  model: "gpt-3.5-turbo",
  temperature: 0,
});

// Chain を作成
const goodChain = promptTemplateWithCorrectModelName.pipe(modelWithCorrectModelName).pipe(outputParser);



// フォールバックを追加
const chain = badChain.withFallbacks({
  fallbacks: [goodChain],
});



// モデルを呼び出す
const result = await chain.invoke({
  topic: "龍",
});
console.log(result);

ローカルで実行します。

$ pnpm vite-node demo03.ts

コミットします。

$ git add .
$ git commit -m "Fallbacks for RunnableSequencesを実装"

コードの解説

パーサーを設定します。

// テキスト出力のパーサー
const outputParser = new StringOutputParser();

ジョークを生成するプロンプトを作成し、モデル名が誤っている対話モデルを設定し、チェーンを作成します。

// ジョークを生成するプロンプトテンプレート
const promptTemplateWithBadModelName = PromptTemplate.fromTemplate("{topic}についてジョークを言ってください");

// モデル名が誤っている対話モデル
const modelWithBadModelName = new ChatOpenAI({
  model: "bad-model",
  temperature: 0,
  maxRetries: 0,
});

// Chain を作成
const badChain = promptTemplateWithBadModelName.pipe(modelWithBadModelName).pipe(outputParser);

ポエムを生成するプロンプトを作成し、モデル名が正しい対話モデルを設定し、チェーンを作成します。

// ポエムを生成するプロンプトテンプレート
const promptTemplateWithCorrectModelName = PromptTemplate.fromTemplate("{topic}についてポエムを言ってください");

// モデル名が正しい対話モデル
const modelWithCorrectModelName = new ChatOpenAI({
  model: "gpt-3.5-turbo",
  temperature: 0,
});

// Chain を作成
const goodChain = promptTemplateWithCorrectModelName.pipe(modelWithCorrectModelName).pipe(outputParser);

フォールバックを追加したチェーンを作成します。

// フォールバックを追加
const chain = badChain.withFallbacks({
  fallbacks: [goodChain],
});

.invoke() を利用して、モデルにテキストを送信します。ジョークの生成はモデル名が誤っているためポエムが生成されます。

// モデルを呼び出す
const result = await chain.invoke({
  topic: "龍",
});
console.log(result);
龍よ、その煌めく鱗で空を舞い
力強く羽ばたく姿は神々しき存在
古の時代から語り継がれし伝説の生き物
我々に勇気と力を与える存在

荒ぶる火を操り、大地を揺るがす
その眼差しは深淵の底を覗くよう
神秘的な力を秘めし龍よ
我ら人間には理解できぬ存在

威厳ある姿に心奪われ
その存在を讃える我ら
龍よ、永遠に輝き続けよ
我らの心に永遠に生き続ける存在

Context Window を超えた場合の処理

LLM の 1 つの制限は、一度に処理できるトークン数が制限されていることです。この制限を超えるとエラーが発生します。この制限を超える場合、入力を分割して処理する方法があります。

コードの作成

$ touch demo04.ts

demo04.ts

demo04.ts
import { ChatOpenAI } from "@langchain/openai";

// Context Window が短いモデル
const shorterLlm = new ChatOpenAI({
  model: "gpt-3.5-turbo-0613",
  maxRetries: 0,
});

// Context Window が長いモデル
const longerLlm = new ChatOpenAI({
  model: "gpt-3.5-turbo-16k",
});

// フォールバックを追加
const modelWithFallback = shorterLlm.withFallbacks({
  fallbacks: [longerLlm],
});

// Context Window が短いモデルでエラーが出るように長い文章を生成
const input = `昔々、ある遠い国に、美しい山々と広大な草原に囲まれた小さな村がありました。その村には、心優しく勇敢な青年タロウが住んでいました。タロウは村の人々から非常に愛されており、彼の笑顔は誰にでも安心感を与えるものでした。彼の家は村の端にあり、広々とした畑で美しい花々を育てていました。

タロウは毎日朝早く起きて畑に出かけ、花々の世話をしました。彼の畑は村中で有名で、タロウの花は市場でとても人気がありました。村の人々はタロウの花を買うことを楽しみにしており、彼の花が家にあるだけで幸せな気持ちになると言われていました。

ある日のこと、タロウは市場で花を売っていると、一人の老人が近づいてきました。老人はボロボロの服を着ており、疲れ果てた様子でした。タロウは老人に優しく声をかけました。「どうされましたか?何かお困りですか?」

老人は深いため息をつき、タロウに話し始めました。「実は、私は長い旅をしているのですが、道に迷ってしまいました。少しの間、休ませていただけませんか?」

タロウは即座に老人を自分の家に招待しました。家に着くと、タロウは老人に温かい食事を提供し、彼の話を聞きました。老人は感謝の意を示し、タロウにお礼を言いました。「あなたのような親切な若者に会えて、本当に幸運でした。あなたの親切心に感謝します。」

その後、老人はタロウに一つの秘密を打ち明けました。「実は、私はこの地を守る精霊の一人です。あなたのような心優しい人に出会うことは稀です。あなたの親切心に報いるために、一つの願いを叶えて差し上げます。何でも願いを言ってください。」

タロウは驚きましたが、しばらく考えた後、こう言いました。「私の願いは、この村がいつまでも平和で、皆が幸せに暮らせることです。」老人は微笑み、タロウの願いを聞き入れました。「あなたの願いは素晴らしいものです。私はあなたの願いを叶えるために、この村に永遠の平和と繁栄をもたらしましょう。」

その日から、村は本当に平和で繁栄するようになりました。タロウの畑はますます豊かになり、村人たちも笑顔で満ち溢れるようになりました。タロウは自分の願いが叶ったことに感謝し、ますます一生懸命に働きました。

数年後、タロウは美しい女性と結婚しました。彼女の名前はハナと言い、彼女もまた村の人々から愛されていました。ハナはタロウと共に畑仕事をし、二人は幸せな家庭を築きました。彼らの愛情は村中に広がり、村の人々にとっても大きな励みとなりました。

タロウとハナには二人の子供が生まれました。息子の名前はユウ、娘の名前はサクラでした。ユウは父親に似て勇敢で心優しく、サクラは母親に似て美しく聡明でした。タロウとハナは子供たちに愛情を注ぎ、彼らもまた村の人々に愛されるように育ちました。

ある日、タロウは子供たちにこう話しました。「お前たちもいつか、大きくなったら、この村を守り、皆を幸せにすることができるようになってほしい。私たちがこうして幸せに暮らせているのも、皆のおかげなんだ。」

ユウとサクラは父親の言葉を胸に刻み、毎日一生懸命に勉強し、働きました。彼らは成長するにつれて、ますます村の人々に愛されるようになりました。ユウは村の若者たちをまとめるリーダーとなり、サクラは村の学校で教師として働くようになりました。

タロウとハナは子供たちの成長を喜び、彼らが立派な大人に成長する姿を見守りました。そして、自分たちが築いた平和な村が、これからも続いていくことを信じていました。

そんなある日、タロウは再び市場で花を売っていると、一人の旅人が近づいてきました。旅人はタロウに話しかけました。「あなたはこの村の英雄、タロウさんですか?」タロウは驚きながらも微笑みました。「はい、そうです。何かご用でしょうか?」

旅人は深く礼をし、タロウにこう言いました。「私は遠い国から来た者です。あなたの親切心と勇気の話を聞いて、ぜひ会いたいと思って来ました。あなたのような人がいることを知り、とても感動しました。」

タロウは旅人の言葉に感謝し、彼に花を一輪プレゼントしました。「どうぞ、この花を持って行ってください。私たちの村の美しさと平和を象徴するものです。」

旅人は感謝し、その花を大切に持って帰りました。その後、旅人の国でもタロウの話は広まり、多くの人々がタロウのように親切で勇敢な心を持つことを目指すようになりました。

タロウの村はますます繁栄し、多くの人々が訪れるようになりました。村の人々はタロウの親切心と勇気に感謝し、彼を敬愛していました。タロウはその愛情を受け入れ、自分の願いが叶ったことに感謝しながら、毎日を大切に過ごしていました。

タロウの物語は、村の中だけでなく、遠くの国々にも伝わりました。彼の親切心と勇気は、多くの人々に希望と励ましを与えました。そして、タロウの村は永遠に平和と繁栄を享受し、彼の遺した教えは次の世代にも受け継がれていきました。

タロウの人生は、親切心と勇気がどれほど重要であるかを示すものでした。彼の物語は、私たち一人一人に、他人に対して親切であり、困難に立ち向かう勇気を持つことの大切さを教えてくれます。タロウのように生きることで、私たちもまた、自分の周りの世界を少しでも良くすることができるのです。

タロウの物語は、永遠に語り継がれ、彼の親切心と勇気は、未来の世代にも希望と励ましを与え続けるでしょう。彼の人生は、私たちにとっても大きな教訓となり、私たちもまた、タロウのように生きることを目指すことで、自分自身と周りの人々に幸せをもたらすことができるのです。

タロウとハナの家族は、村の平和と繁栄の象徴として、村人たちから尊敬され続けました。彼らの家はいつも笑い声に満ちており、訪れる人々は皆、幸せな気持ちで帰っていきました。

時が経つにつれて、ユウとサクラも大人になり、それぞれの道を歩み始めました。ユウは村のリーダーとして、村の発展に尽力しました。彼は新しい農法を導入し、村の収穫量を大幅に増やしました。また、彼は若者たちに対してもリーダーシップを発揮し、彼らに希望と夢を与えました。

一方、サクラは教師として多くの子供たちを育てました。彼女は知識だけでなく、心の教育も大切にし、子供たちに対して愛情と尊敬の心を教えました。サクラの教え子たちは、彼女の影響を受けて立派な大人に成長し、村の未来を支える存在となりました。

タロウとハナは、子供たちの成功を誇りに思い、彼らが立派な人間に成長したことに感謝しました。そして、彼らの家族はますます絆を深め、幸せな日々を送りました。

ある年の夏、村で大きな祭りが開かれることになりました。この祭りは、村の創立100周年を祝うものであり、多くの人々が準備に励んでいました。タロウとハナもまた、祭りの準備に参加し、自分たちの花を飾りつけることで祭りを盛り上げました。

祭りの日が近づくと、村には多くの人々が訪れるようになりました。遠くから来た人々も多く、タロウの花や村の美しさに感動しました。祭りの日、村の広場は笑顔と笑い声で満ち溢れ、皆が楽しいひと時を過ごしました。

その夜、タロウは家族と共に広場の中心で座り、星空を見上げました。彼は静かに言いました。「この村がこんなにも素晴らしい場所になるとは、思ってもみなかった。本当に感謝している。」

ハナは微笑みながら答えました。「あなたが私たちに教えてくれた親切心と勇気が、この村をこんなにも素晴らしい場所にしてくれたのよ。」

ユウとサクラも頷きました。「私たちも父さんの教えを忘れずに、これからも村を守り続けるよ。」

その夜、タロウは心からの感謝と幸せを感じながら、家族と共に過ごしました。彼の物語は、彼の家族と共に続いていきました。

数年後、タロウは年老いてもなお、村の人々から愛され続けていました。彼はいつも笑顔で、村の若者たちに自分の経験を話し、彼らに希望と勇気を与えました。タロウの物語は、彼の家族を超えて村全体に広まり、未来の世代にも語り継がれていきました。

タロウの最後の時が近づくと、村の人々は彼に感謝の気持ちを伝えるために集まりました。彼らはタロウの家の前に集まり、一人ひとりが彼に感謝の言葉を伝えました。タロウは涙を浮かべながら、そのすべての言葉を受け入れました。

彼の最後の言葉は、村の人々に対する感謝の気持ちと、未来への希望でした。「私たちが築いたこの村を、これからも守り続けてください。皆が力を合わせれば、どんな困難も乗り越えられるはずです。」

タロウが亡くなった後も、彼の教えは村の人々の心に生き続けました。彼の親切心と勇気は、村の文化として根付いていきました。村はますます繁栄し、タロウの遺した遺産は次の世代に受け継がれていきました。

タロウの家族は、彼の遺志を受け継ぎ、村を守り続けました。ユウとサクラは、父親の教えを胸に刻み、村の発展に尽力しました。彼らの子供たちもまた、タロウの教えを受け継ぎ、村の未来を担う存在となりました。

タロウの物語は、村の歴史の中で永遠に語り継がれることとなりました。彼の親切心と勇気は、多くの人々に希望と励ましを与え続けました。そして、彼の教えは未来の世代にも受け継がれ、彼の遺産は永遠に生き続けました。

タロウの人生は、親切心と勇気がどれほど重要であるかを示すものでした。彼の物語は、私たち一人一人に、他人に対して親切であり、困難に立ち向かう勇気を持つことの大切さを教えてくれます。タロウのように生きることで、私たちもまた、自分の周りの世界を少しでも良くすることができるのです。

タロウの物語は、永遠に語り継がれ、彼の親切心と勇気は、未来の世代にも希望と励ましを与え続けるでしょう。彼の人生は、私たちにとっても大きな教訓となり、私たちもまた、タロウのように生きることを目指すことで、自分自身と周りの人々に幸せをもたらすことができるのです。

タロウの家族は、彼の遺志を尊重し、村の平和と繁栄を守り続けました。彼らの家は、いつも笑い声と愛情に満ちており、訪れる人々は皆、幸せな気持ちで帰っていきました。

時が経つにつれて、ユウとサクラもまた、立派な家族を持つようになりました。ユウの子供たちは彼のリーダーシップを受け継ぎ、村の発展に尽力しました。彼らは新しい技術を取り入れ、村の農業をさらに発展させました。また、彼らは教育にも力を入れ、次の世代が豊かな知識を持って成長するよう努めました。

一方、サクラの子供たちは彼女の教育の影響を受けて、多くの子供たちを育てる教師となりました。彼らはサクラの教えを受け継ぎ、愛情と尊敬の心を持って子供たちに接しました。サクラの孫たちは、彼女の影響を受けて立派な大人に成長し、村の未来を支える存在となりました。

タロウの家族は、彼の遺志を受け継ぎ、村を守り続けました。彼らの家は、村の平和と繁栄の象徴として、村人たちから尊敬され続けました。彼らの家はいつも笑い声に満ちており、訪れる人々は皆、幸せな気持ちで帰っていきました。

時が経つにつれて、タロウの物語はますます多くの人々に語り継がれるようになりました。彼の親切心と勇気は、多くの人々に希望と励ましを与え続けました。そして、タロウの教えは未来の世代にも受け継がれ、彼の遺産は永遠に生き続けました。

タロウの人生は、親切心と勇気がどれほど重要であるかを示すものでした。彼の物語は、私たち一人一人に、他人に対して親切であり、困難に立ち向かう勇気を持つことの大切さを教えてくれます。タロウのように生きることで、私たちもまた、自分の周りの世界を少しでも良くすることができるのです。

タロウの物語は、永遠に語り継がれ、彼の親切心と勇気は、未来の世代にも希望と励ましを与え続けるでしょう。彼の人生は、私たちにとっても大きな教訓となり、私たちもまた、タロウのように生きることを目指すことで、自分自身と周りの人々に幸せをもたらすことができるのです。

タロウの家族は、彼の遺志を尊重し、村の平和と繁栄を守り続けました。彼らの家は、いつも笑い声と愛情に満ちており、訪れる人々は皆、幸せな気持ちで帰っていきました。

時が経つにつれて、ユウとサクラもまた、立派な家族を持つようになりました。ユウの子供たちは彼のリーダーシップを受け継ぎ、村の発展に尽力しました。彼らは新しい技術を取り入れ、村の農業をさらに発展させました。また、彼らは教育にも力を入れ、次の世代が豊かな知識を持って成長するよう努めました。

一方、サクラの子供たちは彼女の教育の影響を受けて、多くの子供たちを育てる教師となりました。彼らはサクラの教えを受け継ぎ、愛情と尊敬の心を持って子供たちに接しました。サクラの孫たちは、彼女の影響を受けて立派な大人に成長し、村の未来を支える存在となりました。

タロウの家族は、彼の遺志を受け継ぎ、村を守り続けました。彼らの家は、村の平和と繁栄の象徴として、村人たちから尊敬され続けました。彼らの家はいつも笑い声に満ちており、訪れる人々は皆、幸せな気持ちで帰っていきました。

時が経つにつれて、タロウの物語はますます多くの人々に語り継がれるようになりました。彼の親切心と勇気は、多くの人々に希望と励ましを与え続けました。そして、タロウの教えは未来の世代にも受け継がれ、彼の遺産は永遠に生き続けました。

タロウの人生は、親切心と勇気がどれほど重要であるかを示すものでした。彼の物語は、私たち一人一人に、他人に対して親切であり、困難に立ち向かう勇気を持つことの大切さを教えてくれます。タロウのように生きることで、私たちもまた、自分の周りの世界を少しでも良くすることができるのです。

タロウの物語は、永遠に語り継がれ、彼の親切心と勇気は、未来の世代にも希望と励ましを与え続けるでしょう。彼の人生は、私たちにとっても大きな教訓となり、私たちもまた、タロウのように生きることを目指すことで、自分自身と周りの人々に幸せをもたらすことができるのです。

タロウの家族は、彼の遺志を尊重し、村の平和と繁栄を守り続けました。彼らの家は、いつも笑い声と愛情に満ちており、訪れる人々は皆、幸せな気持ちで帰っていきました。

時が経つにつれて、ユウとサクラもまた、立派な家族を持つようになりました。ユウの子供たちは彼のリーダーシップを受け継ぎ、村の発展に尽力しました。彼らは新しい技術を取り入れ、村の農業をさらに発展させました。また、彼らは教育にも力を入れ、次の世代が豊かな知識を持って成長するよう努めました。

一方、サクラの子供たちは彼女の教育の影響を受けて、多くの子供たちを育てる教師となりました。彼らはサクラの教えを受け継ぎ、愛情と尊敬の心を持って子供たちに接しました。サクラの孫たちは、彼女の影響を受けて立派な大人に成長し、村の未来を支える存在となりました。

タロウの家族は、彼の遺志を受け継ぎ、村を守り続けました。彼らの家は、村の平和と繁栄の象徴として、村人たちから尊敬され続けました。彼らの家はいつも笑い声に満ちており、訪れる人々は皆、幸せな気持ちで帰っていきました。

時が経つにつれて、タロウの物語はますます多くの人々に語り継がれるようになりました。彼の親切心と勇気は、多くの人々に希望と励ましを与え続けました。そして、タロウの教えは未来の世代にも受け継がれ、彼の遺産は永遠に生き続けました。

タロウの人生は、親切心と勇気がどれほど重要であるかを示すものでした。彼の物語は、私たち一人一人に、他人に対して親切であり、困難に立ち向かう勇気を持つことの大切さを教えてくれます。タロウのように生きることで、私たちもまた、自分の周りの世界を少しでも良くすることができるのです。

タロウの物語は、永遠に語り継がれ、彼の親切心と勇気は、未来の世代にも希望と励ましを与え続けるでしょう。彼の人生は、私たちにとっても大きな教訓となり、私たちもまた、タロウのように生きることを目指すことで、自分自身と周りの人々に幸せをもたらすことができるのです。

タロウの家族は、彼の遺志を尊重し、村の平和と繁栄を守り続けました。彼らの家は、いつも笑い声と愛情に満ちており、訪れる人々は皆、幸せな気持ちで帰っていきました。

時が経つにつれて、ユウとサクラもまた、立派な家族を持つようになりました。ユウの子供たちは彼のリーダーシップを受け継ぎ、村の発展に尽力しました。彼らは新しい技術を取り入れ、村の農業をさらに発展させました。また、彼らは教育にも力を入れ、次の世代が豊かな知識を持って成長するよう努めました。

一方、サクラの子供たちは彼女の教育の影響を受けて、多くの子供たちを育てる教師となりました。彼らはサクラの教えを受け継ぎ、愛情と尊敬の心を持って子供たちに接しました。サクラの孫たちは、彼女の影響を受けて立派な大人に成長し、村の未来を支える存在となりました。

タロウの家族は、彼の遺志を受け継ぎ、村を守り続けました。彼らの家は、村の平和と繁栄の象徴として、村人たちから尊敬され続けました。彼らの家はいつも笑い声に満ちており、訪れる人々は皆、幸せな気持ちで帰っていきました。

時が経つにつれて、タロウの物語はますます多くの人々に語り継がれるようになりました。彼の親切心と勇気は、多くの人々に希望と励ましを与え続けました。そして、タロウの教えは未来の世代にも受け継がれ、彼の遺産は永遠に生き続けました。

タロウの人生は、親切心と勇気がどれほど重要であるかを示すものでした。彼の物語は、私たち一人一人に、他人に対して親切であり、困難に立ち向かう勇気を持つことの大切さを教えてくれます。タロウのように生きることで、私たちもまた、自分の周りの世界を少しでも良くすることができるのです。

タロウの物語は、永遠に語り継がれ、彼の親切心と勇気は、未来の世代にも希望と励ましを与え続けるでしょう。彼の人生は、私たちにとっても大きな教訓となり、私たちもまた、タロウのように生きることを目指すことで、自分自身と周りの人々に幸せをもたらすことができるのです。
`;

// Context Window が短いモデルでエラーが出るか確認
try {
  await shorterLlm.invoke(input);
} catch (e) {
  // Length error
  console.log(e);
}

// 実際にモデルに投げてみる
const result = await modelWithFallback.invoke(input);
console.log(result);

ローカルで実行します。

$ pnpm vite-node demo04.ts

コミットします。

$ git add .
$ git commit -m "Context Windowを超えた場合のエラー処理を実装"

コードの解説

Context Window が長いモデルと短いモデルを作成します。

// Context Window が短いモデル
const shorterLlm = new ChatOpenAI({
  model: "gpt-3.5-turbo-0613",
  maxRetries: 0,
});

// Context Window が長いモデル
const longerLlm = new ChatOpenAI({
  model: "gpt-3.5-turbo-16k",
});

Context Window が短いモデルでエラーが出るように長い文章を生成します。

コード

// Context Window が短いモデルでエラーが出るように長い文章を生成
const input = `昔々、ある遠い国に、美しい山々と広大な草原に囲まれた小さな村がありました。その村には、心優しく勇敢な青年タロウが住んでいました。タロウは村の人々から非常に愛されており、彼の笑顔は誰にでも安心感を与えるものでした。彼の家は村の端にあり、広々とした畑で美しい花々を育てていました。

タロウは毎日朝早く起きて畑に出かけ、花々の世話をしました。彼の畑は村中で有名で、タロウの花は市場でとても人気がありました。村の人々はタロウの花を買うことを楽しみにしており、彼の花が家にあるだけで幸せな気持ちになると言われていました。

ある日のこと、タロウは市場で花を売っていると、一人の老人が近づいてきました。老人はボロボロの服を着ており、疲れ果てた様子でした。タロウは老人に優しく声をかけました。「どうされましたか?何かお困りですか?」

老人は深いため息をつき、タロウに話し始めました。「実は、私は長い旅をしているのですが、道に迷ってしまいました。少しの間、休ませていただけませんか?」

タロウは即座に老人を自分の家に招待しました。家に着くと、タロウは老人に温かい食事を提供し、彼の話を聞きました。老人は感謝の意を示し、タロウにお礼を言いました。「あなたのような親切な若者に会えて、本当に幸運でした。あなたの親切心に感謝します。」

その後、老人はタロウに一つの秘密を打ち明けました。「実は、私はこの地を守る精霊の一人です。あなたのような心優しい人に出会うことは稀です。あなたの親切心に報いるために、一つの願いを叶えて差し上げます。何でも願いを言ってください。」

タロウは驚きましたが、しばらく考えた後、こう言いました。「私の願いは、この村がいつまでも平和で、皆が幸せに暮らせることです。」老人は微笑み、タロウの願いを聞き入れました。「あなたの願いは素晴らしいものです。私はあなたの願いを叶えるために、この村に永遠の平和と繁栄をもたらしましょう。」

その日から、村は本当に平和で繁栄するようになりました。タロウの畑はますます豊かになり、村人たちも笑顔で満ち溢れるようになりました。タロウは自分の願いが叶ったことに感謝し、ますます一生懸命に働きました。

数年後、タロウは美しい女性と結婚しました。彼女の名前はハナと言い、彼女もまた村の人々から愛されていました。ハナはタロウと共に畑仕事をし、二人は幸せな家庭を築きました。彼らの愛情は村中に広がり、村の人々にとっても大きな励みとなりました。

タロウとハナには二人の子供が生まれました。息子の名前はユウ、娘の名前はサクラでした。ユウは父親に似て勇敢で心優しく、サクラは母親に似て美しく聡明でした。タロウとハナは子供たちに愛情を注ぎ、彼らもまた村の人々に愛されるように育ちました。

ある日、タロウは子供たちにこう話しました。「お前たちもいつか、大きくなったら、この村を守り、皆を幸せにすることができるようになってほしい。私たちがこうして幸せに暮らせているのも、皆のおかげなんだ。」

ユウとサクラは父親の言葉を胸に刻み、毎日一生懸命に勉強し、働きました。彼らは成長するにつれて、ますます村の人々に愛されるようになりました。ユウは村の若者たちをまとめるリーダーとなり、サクラは村の学校で教師として働くようになりました。

タロウとハナは子供たちの成長を喜び、彼らが立派な大人に成長する姿を見守りました。そして、自分たちが築いた平和な村が、これからも続いていくことを信じていました。

そんなある日、タロウは再び市場で花を売っていると、一人の旅人が近づいてきました。旅人はタロウに話しかけました。「あなたはこの村の英雄、タロウさんですか?」タロウは驚きながらも微笑みました。「はい、そうです。何かご用でしょうか?」

旅人は深く礼をし、タロウにこう言いました。「私は遠い国から来た者です。あなたの親切心と勇気の話を聞いて、ぜひ会いたいと思って来ました。あなたのような人がいることを知り、とても感動しました。」

タロウは旅人の言葉に感謝し、彼に花を一輪プレゼントしました。「どうぞ、この花を持って行ってください。私たちの村の美しさと平和を象徴するものです。」

旅人は感謝し、その花を大切に持って帰りました。その後、旅人の国でもタロウの話は広まり、多くの人々がタロウのように親切で勇敢な心を持つことを目指すようになりました。

タロウの村はますます繁栄し、多くの人々が訪れるようになりました。村の人々はタロウの親切心と勇気に感謝し、彼を敬愛していました。タロウはその愛情を受け入れ、自分の願いが叶ったことに感謝しながら、毎日を大切に過ごしていました。

タロウの物語は、村の中だけでなく、遠くの国々にも伝わりました。彼の親切心と勇気は、多くの人々に希望と励ましを与えました。そして、タロウの村は永遠に平和と繁栄を享受し、彼の遺した教えは次の世代にも受け継がれていきました。

タロウの人生は、親切心と勇気がどれほど重要であるかを示すものでした。彼の物語は、私たち一人一人に、他人に対して親切であり、困難に立ち向かう勇気を持つことの大切さを教えてくれます。タロウのように生きることで、私たちもまた、自分の周りの世界を少しでも良くすることができるのです。

タロウの物語は、永遠に語り継がれ、彼の親切心と勇気は、未来の世代にも希望と励ましを与え続けるでしょう。彼の人生は、私たちにとっても大きな教訓となり、私たちもまた、タロウのように生きることを目指すことで、自分自身と周りの人々に幸せをもたらすことができるのです。

タロウとハナの家族は、村の平和と繁栄の象徴として、村人たちから尊敬され続けました。彼らの家はいつも笑い声に満ちており、訪れる人々は皆、幸せな気持ちで帰っていきました。

時が経つにつれて、ユウとサクラも大人になり、それぞれの道を歩み始めました。ユウは村のリーダーとして、村の発展に尽力しました。彼は新しい農法を導入し、村の収穫量を大幅に増やしました。また、彼は若者たちに対してもリーダーシップを発揮し、彼らに希望と夢を与えました。

一方、サクラは教師として多くの子供たちを育てました。彼女は知識だけでなく、心の教育も大切にし、子供たちに対して愛情と尊敬の心を教えました。サクラの教え子たちは、彼女の影響を受けて立派な大人に成長し、村の未来を支える存在となりました。

タロウとハナは、子供たちの成功を誇りに思い、彼らが立派な人間に成長したことに感謝しました。そして、彼らの家族はますます絆を深め、幸せな日々を送りました。

ある年の夏、村で大きな祭りが開かれることになりました。この祭りは、村の創立100周年を祝うものであり、多くの人々が準備に励んでいました。タロウとハナもまた、祭りの準備に参加し、自分たちの花を飾りつけることで祭りを盛り上げました。

祭りの日が近づくと、村には多くの人々が訪れるようになりました。遠くから来た人々も多く、タロウの花や村の美しさに感動しました。祭りの日、村の広場は笑顔と笑い声で満ち溢れ、皆が楽しいひと時を過ごしました。

その夜、タロウは家族と共に広場の中心で座り、星空を見上げました。彼は静かに言いました。「この村がこんなにも素晴らしい場所になるとは、思ってもみなかった。本当に感謝している。」

ハナは微笑みながら答えました。「あなたが私たちに教えてくれた親切心と勇気が、この村をこんなにも素晴らしい場所にしてくれたのよ。」

ユウとサクラも頷きました。「私たちも父さんの教えを忘れずに、これからも村を守り続けるよ。」

その夜、タロウは心からの感謝と幸せを感じながら、家族と共に過ごしました。彼の物語は、彼の家族と共に続いていきました。

数年後、タロウは年老いてもなお、村の人々から愛され続けていました。彼はいつも笑顔で、村の若者たちに自分の経験を話し、彼らに希望と勇気を与えました。タロウの物語は、彼の家族を超えて村全体に広まり、未来の世代にも語り継がれていきました。

タロウの最後の時が近づくと、村の人々は彼に感謝の気持ちを伝えるために集まりました。彼らはタロウの家の前に集まり、一人ひとりが彼に感謝の言葉を伝えました。タロウは涙を浮かべながら、そのすべての言葉を受け入れました。

彼の最後の言葉は、村の人々に対する感謝の気持ちと、未来への希望でした。「私たちが築いたこの村を、これからも守り続けてください。皆が力を合わせれば、どんな困難も乗り越えられるはずです。」

タロウが亡くなった後も、彼の教えは村の人々の心に生き続けました。彼の親切心と勇気は、村の文化として根付いていきました。村はますます繁栄し、タロウの遺した遺産は次の世代に受け継がれていきました。

タロウの家族は、彼の遺志を受け継ぎ、村を守り続けました。ユウとサクラは、父親の教えを胸に刻み、村の発展に尽力しました。彼らの子供たちもまた、タロウの教えを受け継ぎ、村の未来を担う存在となりました。

タロウの物語は、村の歴史の中で永遠に語り継がれることとなりました。彼の親切心と勇気は、多くの人々に希望と励ましを与え続けました。そして、彼の教えは未来の世代にも受け継がれ、彼の遺産は永遠に生き続けました。

タロウの人生は、親切心と勇気がどれほど重要であるかを示すものでした。彼の物語は、私たち一人一人に、他人に対して親切であり、困難に立ち向かう勇気を持つことの大切さを教えてくれます。タロウのように生きることで、私たちもまた、自分の周りの世界を少しでも良くすることができるのです。

タロウの物語は、永遠に語り継がれ、彼の親切心と勇気は、未来の世代にも希望と励ましを与え続けるでしょう。彼の人生は、私たちにとっても大きな教訓となり、私たちもまた、タロウのように生きることを目指すことで、自分自身と周りの人々に幸せをもたらすことができるのです。

タロウの家族は、彼の遺志を尊重し、村の平和と繁栄を守り続けました。彼らの家は、いつも笑い声と愛情に満ちており、訪れる人々は皆、幸せな気持ちで帰っていきました。

時が経つにつれて、ユウとサクラもまた、立派な家族を持つようになりました。ユウの子供たちは彼のリーダーシップを受け継ぎ、村の発展に尽力しました。彼らは新しい技術を取り入れ、村の農業をさらに発展させました。また、彼らは教育にも力を入れ、次の世代が豊かな知識を持って成長するよう努めました。

一方、サクラの子供たちは彼女の教育の影響を受けて、多くの子供たちを育てる教師となりました。彼らはサクラの教えを受け継ぎ、愛情と尊敬の心を持って子供たちに接しました。サクラの孫たちは、彼女の影響を受けて立派な大人に成長し、村の未来を支える存在となりました。

タロウの家族は、彼の遺志を受け継ぎ、村を守り続けました。彼らの家は、村の平和と繁栄の象徴として、村人たちから尊敬され続けました。彼らの家はいつも笑い声に満ちており、訪れる人々は皆、幸せな気持ちで帰っていきました。

時が経つにつれて、タロウの物語はますます多くの人々に語り継がれるようになりました。彼の親切心と勇気は、多くの人々に希望と励ましを与え続けました。そして、タロウの教えは未来の世代にも受け継がれ、彼の遺産は永遠に生き続けました。

タロウの人生は、親切心と勇気がどれほど重要であるかを示すものでした。彼の物語は、私たち一人一人に、他人に対して親切であり、困難に立ち向かう勇気を持つことの大切さを教えてくれます。タロウのように生きることで、私たちもまた、自分の周りの世界を少しでも良くすることができるのです。

タロウの物語は、永遠に語り継がれ、彼の親切心と勇気は、未来の世代にも希望と励ましを与え続けるでしょう。彼の人生は、私たちにとっても大きな教訓となり、私たちもまた、タロウのように生きることを目指すことで、自分自身と周りの人々に幸せをもたらすことができるのです。

タロウの家族は、彼の遺志を尊重し、村の平和と繁栄を守り続けました。彼らの家は、いつも笑い声と愛情に満ちており、訪れる人々は皆、幸せな気持ちで帰っていきました。

時が経つにつれて、ユウとサクラもまた、立派な家族を持つようになりました。ユウの子供たちは彼のリーダーシップを受け継ぎ、村の発展に尽力しました。彼らは新しい技術を取り入れ、村の農業をさらに発展させました。また、彼らは教育にも力を入れ、次の世代が豊かな知識を持って成長するよう努めました。

一方、サクラの子供たちは彼女の教育の影響を受けて、多くの子供たちを育てる教師となりました。彼らはサクラの教えを受け継ぎ、愛情と尊敬の心を持って子供たちに接しました。サクラの孫たちは、彼女の影響を受けて立派な大人に成長し、村の未来を支える存在となりました。

タロウの家族は、彼の遺志を受け継ぎ、村を守り続けました。彼らの家は、村の平和と繁栄の象徴として、村人たちから尊敬され続けました。彼らの家はいつも笑い声に満ちており、訪れる人々は皆、幸せな気持ちで帰っていきました。

時が経つにつれて、タロウの物語はますます多くの人々に語り継がれるようになりました。彼の親切心と勇気は、多くの人々に希望と励ましを与え続けました。そして、タロウの教えは未来の世代にも受け継がれ、彼の遺産は永遠に生き続けました。

タロウの人生は、親切心と勇気がどれほど重要であるかを示すものでした。彼の物語は、私たち一人一人に、他人に対して親切であり、困難に立ち向かう勇気を持つことの大切さを教えてくれます。タロウのように生きることで、私たちもまた、自分の周りの世界を少しでも良くすることができるのです。

タロウの物語は、永遠に語り継がれ、彼の親切心と勇気は、未来の世代にも希望と励ましを与え続けるでしょう。彼の人生は、私たちにとっても大きな教訓となり、私たちもまた、タロウのように生きることを目指すことで、自分自身と周りの人々に幸せをもたらすことができるのです。

タロウの家族は、彼の遺志を尊重し、村の平和と繁栄を守り続けました。彼らの家は、いつも笑い声と愛情に満ちており、訪れる人々は皆、幸せな気持ちで帰っていきました。

時が経つにつれて、ユウとサクラもまた、立派な家族を持つようになりました。ユウの子供たちは彼のリーダーシップを受け継ぎ、村の発展に尽力しました。彼らは新しい技術を取り入れ、村の農業をさらに発展させました。また、彼らは教育にも力を入れ、次の世代が豊かな知識を持って成長するよう努めました。

一方、サクラの子供たちは彼女の教育の影響を受けて、多くの子供たちを育てる教師となりました。彼らはサクラの教えを受け継ぎ、愛情と尊敬の心を持って子供たちに接しました。サクラの孫たちは、彼女の影響を受けて立派な大人に成長し、村の未来を支える存在となりました。

タロウの家族は、彼の遺志を受け継ぎ、村を守り続けました。彼らの家は、村の平和と繁栄の象徴として、村人たちから尊敬され続けました。彼らの家はいつも笑い声に満ちており、訪れる人々は皆、幸せな気持ちで帰っていきました。

時が経つにつれて、タロウの物語はますます多くの人々に語り継がれるようになりました。彼の親切心と勇気は、多くの人々に希望と励ましを与え続けました。そして、タロウの教えは未来の世代にも受け継がれ、彼の遺産は永遠に生き続けました。

タロウの人生は、親切心と勇気がどれほど重要であるかを示すものでした。彼の物語は、私たち一人一人に、他人に対して親切であり、困難に立ち向かう勇気を持つことの大切さを教えてくれます。タロウのように生きることで、私たちもまた、自分の周りの世界を少しでも良くすることができるのです。

タロウの物語は、永遠に語り継がれ、彼の親切心と勇気は、未来の世代にも希望と励ましを与え続けるでしょう。彼の人生は、私たちにとっても大きな教訓となり、私たちもまた、タロウのように生きることを目指すことで、自分自身と周りの人々に幸せをもたらすことができるのです。

タロウの家族は、彼の遺志を尊重し、村の平和と繁栄を守り続けました。彼らの家は、いつも笑い声と愛情に満ちており、訪れる人々は皆、幸せな気持ちで帰っていきました。

時が経つにつれて、ユウとサクラもまた、立派な家族を持つようになりました。ユウの子供たちは彼のリーダーシップを受け継ぎ、村の発展に尽力しました。彼らは新しい技術を取り入れ、村の農業をさらに発展させました。また、彼らは教育にも力を入れ、次の世代が豊かな知識を持って成長するよう努めました。

一方、サクラの子供たちは彼女の教育の影響を受けて、多くの子供たちを育てる教師となりました。彼らはサクラの教えを受け継ぎ、愛情と尊敬の心を持って子供たちに接しました。サクラの孫たちは、彼女の影響を受けて立派な大人に成長し、村の未来を支える存在となりました。

タロウの家族は、彼の遺志を受け継ぎ、村を守り続けました。彼らの家は、村の平和と繁栄の象徴として、村人たちから尊敬され続けました。彼らの家はいつも笑い声に満ちており、訪れる人々は皆、幸せな気持ちで帰っていきました。

時が経つにつれて、タロウの物語はますます多くの人々に語り継がれるようになりました。彼の親切心と勇気は、多くの人々に希望と励ましを与え続けました。そして、タロウの教えは未来の世代にも受け継がれ、彼の遺産は永遠に生き続けました。

タロウの人生は、親切心と勇気がどれほど重要であるかを示すものでした。彼の物語は、私たち一人一人に、他人に対して親切であり、困難に立ち向かう勇気を持つことの大切さを教えてくれます。タロウのように生きることで、私たちもまた、自分の周りの世界を少しでも良くすることができるのです。

タロウの物語は、永遠に語り継がれ、彼の親切心と勇気は、未来の世代にも希望と励ましを与え続けるでしょう。彼の人生は、私たちにとっても大きな教訓となり、私たちもまた、タロウのように生きることを目指すことで、自分自身と周りの人々に幸せをもたらすことができるのです。
`;

Context Window が短いモデルでエラーが出るか確認します。Context Window が短いモデルだとエラーがしっかり出ます。

// Context Window が短いモデルでエラーが出るか確認
try {
  await shorterLlm.invoke(input);
} catch (e) {
  // Length error
  console.log(e);
}
BadRequestError: 400 This model's maximum context length is 4097 tokens. However, your messages resulted in 8103 tokens. Please reduce the length of the messages.
    at Function.generate (file:///Users/hayato94087/Private/langchain-fallbacks-sample/node_modules/.pnpm/openai@4.47.3/node_modules/openai/src/error.ts:70:14)
    at OpenAI.makeStatusError (file:///Users/hayato94087/Private/langchain-fallbacks-sample/node_modules/.pnpm/openai@4.47.3/node_modules/openai/src/core.ts:383:21)
    at OpenAI.makeRequest (file:///Users/hayato94087/Private/langchain-fallbacks-sample/node_modules/.pnpm/openai@4.47.3/node_modules/openai/src/core.ts:446:24)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at file:///Users/hayato94087/Private/langchain-fallbacks-sample/node_modules/.pnpm/@langchain+openai@0.1.1_langchain@0.2.4_fast-xml-parser@4.4.0_openai@4.47.3_/node_modules/@langchain/openai/dist/chat_models.js:795:29
    at RetryOperation._fn (/Users/hayato94087/Private/langchain-fallbacks-sample/node_modules/.pnpm/p-retry@4.6.2/node_modules/p-retry/index.js:50:12) {
  status: 400,
  headers: {
    'alt-svc': 'h3=":443"; ma=86400',
    'cf-cache-status': 'DYNAMIC',
    'cf-ray': '88d56aa8b934263e-NRT',
    connection: 'keep-alive',
    'content-length': '280',
    'content-type': 'application/json',
    date: 'Sun, 02 Jun 2024 06:34:16 GMT',
    'openai-organization': 'repe',
    'openai-processing-ms': '28',
    'openai-version': '2020-10-01',
    server: 'cloudflare',
    'set-cookie': '__cf_bm=zP1jIpR9lgbaYLy9LGraSaqB2761QCvr3UlLCfugK48-1717310056-1.0.1.1-EG1iMBD1l5Y_D3s1lkMSLLO7OAz5nDaOgC1RFt2sO_NRVbqMW3KynUflv2Z2rIqPmHVnRBVn7aTbZJUc9Ho4Dw; path=/; expires=Sun, 02-Jun-24 07:04:16 GMT; domain=.api.openai.com; HttpOnly; Secure; SameSite=None, _cfuvid=Tmk6A_8cRy1shtarCG5E7lc81irBfev5OW0lNUVFKiI-1717310056279-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None',
    'strict-transport-security': 'max-age=15724800; includeSubDomains',
    'x-ratelimit-limit-requests': '10000',
    'x-ratelimit-limit-tokens': '1000000',
    'x-ratelimit-remaining-requests': '9999',
    'x-ratelimit-remaining-tokens': '994446',
    'x-ratelimit-reset-requests': '6ms',
    'x-ratelimit-reset-tokens': '333ms',
    'x-request-id': 'req_f280e51ffc0baed32840d2beb47a60fa'
  },
  request_id: 'req_f280e51ffc0baed32840d2beb47a60fa',
  error: {
    message: "This model's maximum context length is 4097 tokens. However, your messages resulted in 8103 tokens. Please reduce the length of the messages.",
    type: 'invalid_request_error',
    param: 'messages',
    code: 'context_length_exceeded'
  },
  code: 'context_length_exceeded',
  param: 'messages',
  type: 'invalid_request_error',
  attemptNumber: 1,
  retriesLeft: 0
}

.invoke() すると Context Window が短いモデルから Context Window が長いモデルにフォールバックし問題なく処理されます。

// 実際にモデルに投げてみる
const result = await modelWithFallback.invoke(input);
console.log(result);
AIMessage {
  lc_serializable: true,
  lc_kwargs: {
    content: 'タロウの物語は、親切心と勇気がどれほど重要であるかを示すものでした。彼の物語は、私たち一人一人に、他人に対して親切であり、困難に立ち向かう勇気を持つことの大切さを教えてくれます。タロウのように生きることで、私たちもまた、自分の周りの世界を少しでも良くすることができるのです。\n' +
      '\n' +
      'タロウの物語は、永遠に語り継がれ、彼の親切心と勇気は、未来の世代にも希望と励ましを与え続けるでしょう。彼の人生は、私たちにとっても大きな教訓となり、私たちもまた、タロウのように生きることを目指すことで、自分自身と周りの人々に幸せをもたらすことができるのです。',
    tool_calls: [],
    invalid_tool_calls: [],
    additional_kwargs: { function_call: undefined, tool_calls: undefined },
    response_metadata: {}
  },
  lc_namespace: [ 'langchain_core', 'messages' ],
  content: 'タロウの物語は、親切心と勇気がどれほど重要であるかを示すものでした。彼の物語は、私たち一人一人に、他人に対して親切であり、困難に立ち向かう勇気を持つことの大切さを教えてくれます。タロウのように生きることで、私たちもまた、自分の周りの世界を少しでも良くすることができるのです。\n' +
    '\n' +
    'タロウの物語は、永遠に語り継がれ、彼の親切心と勇気は、未来の世代にも希望と励ましを与え続けるでしょう。彼の人生は、私たちにとっても大きな教訓となり、私たちもまた、タロウのように生きることを目指すことで、自分自身と周りの人々に幸せをもたらすことができるのです。',
  name: undefined,
  additional_kwargs: { function_call: undefined, tool_calls: undefined },
  response_metadata: {
    tokenUsage: { completionTokens: 293, promptTokens: 8103, totalTokens: 8396 },
    finish_reason: 'stop'
  },
  tool_calls: [],
  invalid_tool_calls: [],
  usage_metadata: { input_tokens: 8103, output_tokens: 293, total_tokens: 8396 }
}

さいごに

この記事では、LangChain で問題が発生した際に対処する方法を紹介しました。

作業リポジトリ

こちらが作業リポジトリです。

https://github.com/hayato94087/langchain-fallbacks-sample

Discussion