计算向ChatGPT API请求的总令牌数,包括函数

大家好,Stack Overflow社区,

我一直在尝试将ChatGPT的API集成到我的项目中,但在计算API请求的总令牌数时遇到了问题。特别是我在API调用中同时传递了消息和函数。

我已经找到了计算消息令牌数的方法,但对于如何计算函数使用的令牌数还不确定。

请问有人能指导我如何正确计算包括消息和函数在内的ChatGPT API请求的总令牌数吗?

任何帮助或见解都将不胜感激!

提前感谢你们。

我一直在尝试通过以不同方式格式化调用中的数据来强行解决这个问题。我使用了tokenizerTiktokenizer来测试我的格式。


回答:

我将向你展示如何计算gpt-3.5和gpt-4的令牌。你可以将类似的方法应用于其他模型,只需找到正确的设置即可。

我们将分别计算消息和函数使用的令牌,然后将它们加在一起以获得总数。

消息

首先,使用tiktoken获取令牌化器。我们将使用它来对消息和函数中的所有自定义文本进行令牌化。同时,为API请求中添加的额外令牌添加常量。

enc = tiktoken.encoding_for_model(model)

创建一个变量来保存消息的总令牌数,并将其设置为0。

msg_token_count = 0

遍历消息,对于每条消息,将3个令牌添加到msg_token_count。然后遍历消息中的每个元素,编码其值,并将编码对象的长度添加到msg_token_count。如果字典中有“name”键,则向msg_token_count添加一个额外的令牌。

for message in messages:    msg_token_count += 3  # 为每条消息添加令牌    for key, value in message.items():        msg_token_count += len(enc.encode(value))  # 添加设置消息中的令牌        if key == "name":            msgTokenCount += 1 # 如果设置了名称,则添加令牌

最后,我们需要向msg_token_count添加3个令牌,以说明结束令牌。

msgTokenCount += 3 # 添加令牌以说明结束

函数

现在我们将计算函数所需的令牌数。

首先,创建一个变量来保存函数使用的总令牌数,并将其设置为0。

func_token_count = 0

接下来,我们将遍历函数并向func_token_count添加令牌。遍历函数,为每个函数向func_token_count添加7个令牌。然后添加编码的名称和描述的长度。

对于每个函数,如果它有属性,则向func_token_count添加3个令牌。然后对于属性中的每个键,再添加3个令牌和编码属性的长度,确保如果它有“enum”键,则减去3个令牌,并为enum部分的每个项目添加3个令牌。

最后,向func_token_count添加12个令牌,以说明所有函数结束时的令牌。

for function in functions:    func_token_count += 7  # 为每个函数的开始添加令牌    f_name = function["name"]    f_desc = function["description"]    if f_desc.endswith("."):        f_desc = f_desc[:-1]    line = f_name + ":" + f_desc    func_token_count += len(enc.encode(line))  # 为设置的名称和描述添加令牌    if len(function["parameters"]["properties"]) > 0:        func_token_count += 3  # 为每个属性的开始添加令牌        for key in list(function["parameters"]["properties"].keys()):            func_token_count += 3  # 为每个设置的属性添加令牌            p_name = key            p_type = function["parameters"]["properties"][key]["type"]            p_desc = function["parameters"]["properties"][key]["description"]            if "enum" in function["parameters"]["properties"][key].keys():                func_token_count += 3  # 如果属性有枚举列表,则添加令牌                for item in function["parameters"]["properties"][key]["enum"]:                    func_token_count += 3                    func_token_count += len(enc.encode(item))            if p_desc.endswith("."):                p_desc = p_desc[:-1]            line = f"{p_name}:{p_type}:{p_desc}"            func_token_count += len(enc.encode(line))func_token_count += 12

这是完整的代码。请注意,我没有硬编码额外的令牌计数,而是使用常量来保存值。

def get_token_count(model, messages, functions):    # 初始化消息设置为0    msg_init = 0    msg_name = 0    msg_end = 0        # 初始化函数设置为0    func_init = 0    prop_init = 0    prop_key = 0    enum_init = 0    enum_item = 0    func_end = 0        if model in [        "gpt-3.5-turbo-0613",        "gpt-4-0613"    ]:        # 为上述模型设置消息设置        msg_init = 3        msg_name = 1        msg_end = 3                # 为上述模型设置函数设置        func_init = 7        prop_init = 3        prop_key = 3        enum_init = -3        enum_item = 3        func_end = 12        enc = tiktoken.encoding_for_model(model)        msg_token_count = 0    for message in messages:        msg_token_count += msg_init  # 为每条消息添加令牌        for key, value in message.items():            msg_token_count += len(enc.encode(value))  # 添加设置消息中的令牌            if key == "name":                msg_token_count += msg_name  # 如果设置了名称,则添加令牌    msg_token_count += msg_end  # 添加令牌以说明结束        func_token_count = 0    if len(functions) > 0:        for function in functions:            func_token_count += func_init  # 为每个函数的开始添加令牌            f_name = function["name"]            f_desc = function["description"]            if f_desc.endswith("."):                f_desc = f_desc[:-1]            line = f_name + ":" + f_desc            func_token_count += len(enc.encode(line))  # 为设置的名称和描述添加令牌            if len(function["parameters"]["properties"]) > 0:                func_token_count += prop_init  # 为每个属性的开始添加令牌                for key in list(function["parameters"]["properties"].keys()):                    func_token_count += prop_key  # 为每个设置的属性添加令牌                    p_name = key                    p_type = function["parameters"]["properties"][key]["type"]                    p_desc = function["parameters"]["properties"][key]["description"]                    if "enum" in function["parameters"]["properties"][key].keys():                        func_token_count += enum_init  # 如果属性有枚举列表,则添加令牌                        for item in function["parameters"]["properties"][key]["enum"]:                            func_token_count += enum_item                            func_token_count += len(enc.encode(item))                    if p_desc.endswith("."):                        p_desc = p_desc[:-1]                    line = f"{p_name}:{p_type}:{p_desc}"                    func_token_count += len(enc.encode(line))        func_token_count += func_end        return msg_token_count + func_token_count

如果有任何不清楚的地方,或者你有建议可以改进我的帖子,请告诉我。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注