0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

JavaScript/TypeScriptでArray.slice()のマイナスの挙動【ChatGPT APIを例に】

Last updated at Posted at 2023-04-22

みなさん、ChatGPTのAPIは使っているでしょうか?
簡単に使えて便利な反面、トークン数節約は重大な問題でしょう。そのために送るメッセージ数に上限をつけるようなこともあるでしょう。
そんな時にsliceでシンプルに書けることに気づかずに回りくどい書き方をしてしまっていたので、戒めとして記事にします。

なお、chatGPTのpromptエンジニアリングを楽にするツールを作成しているときに気づいた話なので、そのツールもあとで紹介しておきますね。
AI同士で対話させられるツールになっています

基本: JavaScript/TypeScriptにおけるArray.slice()の挙動について

Array.slice()は、配列の一部分を切り出すためのメソッドです。このメソッドは、引数として開始位置と終了位置を指定することができます。

例えば、次のようなコードを考えてみましょう。

const fruits = ["りんご", "バナナ", "みかん", "ぶどう", "メロン"];

// 開始位置のみを指定する
console.log(fruits.slice(1)); // 出力: ["バナナ", "みかん", "ぶどう", "メロン"]

// 開始位置と終了位置を指定する
console.log(fruits.slice(1, 4)); // 出力: ["バナナ", "みかん", "ぶどう"]

この場合、fruits.slice(1)という記述によって、配列の2番目以降の要素を切り出すことができます。また、fruits.slice(1, 4)という記述によって、2番目から4番目の要素を切り出すことができます。

さらに、開始位置や終了位置をマイナスの値にすることもできます。この場合、末尾からの位置を表すことになります。

const fruits = ["りんご", "バナナ", "みかん", "ぶどう", "メロン"];

console.log(fruits.slice(-3)); // 出力: ["みかん", "ぶどう", "メロン"]

なお、マイナスの値を指定した場合には、開始位置が配列の長さよりも大きい場合は0、終了位置が配列の長さよりも大きい場合は配列の長さとみなされます。

const fruits = ["りんご", "バナナ", "みかん", "ぶどう", "メロン"];

console.log(fruits.slice(-10)); // 出力: ["りんご", "バナナ", "みかん", "ぶどう", "メロン"]
console.log(fruits.slice(1, -2)); // 出力: ["バナナ", "みかん"]

ChatGPT APIを例にしたユースケース

ChatGPTのAPIを使用してサービスを作るときには、トークン数を節約するために、送信するメッセージ数を制限することがあります。

その時にこのsliceの知識は役立ちます。
例えば、次のようなコードを考えてみましょう。

const messages = [
  { role: "system", content: "はじめまして。" },
  { role: "user", content: "こんにちは。天気を教えてください。" },
  { role: "assistant", content: "今日は晴れです。" },
  { role: "user", content: "ありがとうございます。" },
  { role: "assistant", content: "お役に立てて良かったです。" }
];

const limit = 3;

const slicedMessages = messages.slice(-limit);

console.log(slicedMessages);
// 出力: [
//   { role: "user", content: "こんにちは。天気を教えてください。" },
//   { role: "assistant", content: "今日は晴れです。" },
//   { role: "user", content: "ありがとうございます。" }
// ]

上記のコードでは、配列messagesから末尾の3つの要素を切り出しています。この場合、messages.slice(-limit)という記述によって、messages配列の末尾から3つの要素が切り出されます。

また、もしlimitmessages.lengthよりも大きい場合、全ての要素が切り出されます。

const messages = [
  { role: "system", content: "はじめまして。" },
  { role: "user", content: "こんにちは。天気を教えてください。" },
  { role: "assistant", content: "今日は晴れです。" }
];

const limit = 10;

const slicedMessages = messages.slice(-limit);

console.log(slicedMessages);
// 出力: [
//   { role: "system", content: "はじめまして。" },
//   { role: "user", content: "こんにちは。天気を教えてください。" },
//   { role: "assistant", content: "今日は晴れです。" }
// ]

limitmessages.lengthよりも大きい場合、全体を送っても制限数以下になるので、シンプルにslicedMessages = messages.slice(-limit);という記述が成立します。

自分はこれに気づかず、回りくどい書き方してたんですけどね(汗)

最後に

この話は、chatGPTのpromptエンジニアリングを楽にするツールを作成しているときに気づいた話です

対話型のシステムに組み込みたい場合なんかに、性能を上げるためにプロンプトエンジニアリングしてると、「いちいちユーザーの入力考えて入れるのめんどくせえええ」ってなるわけです(実体験)

なので、ユーザーの入力もchatGPTに作らせてしまえばいいと思い、AI同士で対話可能なツールを作りました!

開発者の皆さんはもちろん、AI同士で話させて遊びたいだけでも見てみてください
(AgentGPTなんかと同じで今のところapi keyを入れてもらいます。もちろんopenAIのAPIサーバーにしか送ってないです!)

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?