在进行 api 调用之前如何计算令牌?

Sor*_*rab 1 node.js chatgpt-api

import { Configuration, OpenAIApi } from "openai"
import { readFile } from './readFile.js'

// Config OpenAI API
const configuration = new Configuration({
    organization: "xyx......",
    apiKey: "abc.......",
});

// OpenAI API instance
export const openai = new OpenAIApi(configuration);


const generateAnswer = async (conversation, userMessage) => {
    try {
        const dataset = await readFile();
        const dataFeed = { role: 'system', content: dataset };
        const prompt = conversation ? [...conversation?.messages, dataFeed, userMessage] : [dataFeed, userMessage];
        const completion = await openai.createChatCompletion({
            model: "gpt-3.5-turbo",
            messages: prompt
        })

        const aiMessage = completion.data.choices[0].message;
        console.log(completion.data.usage)
        return aiMessage
    } catch (e) {
        console.log(e)
    }
}
export { generateAnswer };
Run Code Online (Sandbox Code Playgroud)

我正在尝试创建聊天机器人,其中我在开始时提供数据馈送,这是聊天 api 的业务信息和对话历史记录我想计算对话令牌并在进行 api 调用之前如果超过限制则减少提示我尝试使用 gpt3 编码器进行计数令牌,但我有对象数组,而不是提示中的字符串

Sch*_*der 13

精确方法

准确的方法是使用tiktoken,它是一个 python 库。摘自openAI 食谱

    import tiktoken
    encoding = tiktoken.encoding_for_model("gpt-3.5-turbo")
    num_tokens = len(encoding.encode("Look at all them pretty tokens"))
    print(num_tokens)
Run Code Online (Sandbox Code Playgroud)

更一般地,您可以使用

encoding = tiktoken.get_encoding("cl100k_base")
Run Code Online (Sandbox Code Playgroud)

其中 cl100k_base用于 gpt-4、gpt-3.5-turbo、text-embedding-ada-002; p50k_base用于Codex模型,text-davinci-002,text-davinci-003;是r50k_basegpt2 和 GPT-3 模型(如 davinci)中使用的。 r50k_basep50k_base和 经常(但不总是)给出相同的结果。

近似法

您通常只希望程序不会因超出令牌限制而崩溃,并且只需要一个字符计数截止,这样您就不会超出令牌限制。使用 tiktoken 进行的测试表明,代币计数通常是线性的,特别是对于较新的模型,并且 1/e 似乎是一个稳健的保守比例常数。因此,我们可以写一个简单的方程来保守地将标记与字符相关联:

'#令牌<? #字符 * (1/e) + safety_margin'

哪里 <? 意味着这很可能是真的,并且 1/e = 0.36787944117144232159552377016146。safety_margin 的适当选择似乎是 2。在某些情况下,当与 r50k_base 一起使用时,在 2000 个字符后需要为 8。安全裕度在两种情况下发挥作用:第一种是字符数非常少的情况;第二种是字符数非常少的情况。值 2 就足够了,所有模型都需要。其次,如果模型无法推理它所看到的内容,导致字符计数和 # 标记之间的关系不稳定/嘈杂,且比例常数接近 1/e,则可能会超出 1/e 限制。

主要近似结果

现在反转这个以获得适合令牌限制的最大字符数:

'max_characters = (#tokens_limit - safety_margin) * e'

其中 e = 2.7182818284590... 现在您有了一个即时的、独立于语言和平台且无依赖性的解决方案,可以不超过令牌限制。

展示你的作品

附有一段英文

对于带有英文文本的型号 cl100k_base,#tokens = #chars 0.2016568976249748 + -5.277472848558375 对于带有英文文本的型号 p50k_base,#tokens = #chars 0.20820463015644564 + -4.697668008159241 对于型号 r50 k_base 为英文文本,#tokens = #chars*0.20820463015644564 + -4.697668008159241

英文文本的标记与字符数 1/e 近似低估

附上一段Lorem ipsum

对于具有 Lorem ipsum 的模型 cl100k_base,#tokens = #chars 0.325712437966849 + -5.186204883743613 对于具有 Lorem ipsum 的模型 p50k_base,#tokens = #chars 0.3622005352481815 + 2.42561994050205 95 对于具有 Lorem ipsum 的模型 r50k_base,#tokens = #chars*0.3622005352481815 + 2.4256199405020595

Lorem ipsum 文本的标记与字符数 lorep ipsum 近似最坏情况

用一段python代码:

对于带有sampletext2的模型cl100k_base,#tokens = #chars 0.2658446137873485 + -0.9057612056294033 对于带有sampletext2的模型p50k_base,#tokens = #chars 0.3240730228908291 + -5.740016444496973 对于模型r 50k_base 与sampletext2,#tokens = #chars*0.3754121847018643 + -19.96012603693265

python 令牌与字符 低估蟒蛇

  • 那是Python,OP正在使用Javascript。(它可以完成工作,但我想他们更喜欢 Javascript/NPM 解决方案) (3认同)

小智 10

问题很旧,但可能对某人有帮助。有一个名为tiktoken希望的 Node.js 库是原始 tiktoken 库的一个分支。

官方 tiktoken 存储库上的所有示例都有效,只需进行一些小更改。

安装 tiktoken npm 包:

npm install @dqbd/tiktoken
Run Code Online (Sandbox Code Playgroud)

计算文本字符串中的标记数

import { encoding_for_model } from "@dqbd/tiktoken";

//Returns the number of tokens in a text string
function numTokensFromString(message: string) {
  const encoder = encoding_for_model("gpt-3.5-turbo");

  const tokens = encoder.encode(message);
  encoder.free();
  return tokens.length;
}

Run Code Online (Sandbox Code Playgroud)

将令牌解码回字符串

import { encoding_for_model } from "@dqbd/tiktoken";

 function decodeTokens(message: Uint32Array) {
  const encoder = encoding_for_model("gpt-3.5-turbo");

  const words = encoder.decode(message);
  encoder.free();
  return new TextDecoder().decode(words);
}
Run Code Online (Sandbox Code Playgroud)