openAI|嵌入超长文本

本文介绍了两种处理超过OpenAI嵌入模型最大上下文长度的文本的方法,即简单截断文本和分块处理文本。通过本文,您可以了解到如何避免因超过最大长度而导致的错误,同时又不失去可能相关的文本内容。

嵌入比模型的最大上下文长度长的文本

OpenAI 的嵌入模型无法嵌入超过最大长度的文本。 最大长度因模型而异,并且由标记而不是字符串长度来衡量。 如果您不熟悉令牌化,请查看如何使用 tiktoken 计算令牌

此笔记本展示了如何处理比模型的最大上下文长度更长的文本。 我们将演示使用来自 text-embedding-ada-002 的嵌入,但同样的想法可以应用于其他模型和任务。 要了解有关嵌入的更多信息,请查看 OpenAI 嵌入指南

1.模型上下文长度

首先,我们选择模型并定义一个函数以从 API 获取嵌入。

import openai
from tenacity import retry, wait_random_exponential, stop_after_attempt, retry_if_not_exception_type


EMBEDDING_MODEL = 'text-embedding-ada-002'
EMBEDDING_CTX_LENGTH = 8191
EMBEDDING_ENCODING = 'cl100k_base'

# 让我们确保不要重试无效请求,因为这就是我们想要展示的
@retry(wait=wait_random_exponential(min=1, max=20), stop=stop_after_attempt(6), retry=retry_if_not_exception_type(openai.InvalidRequestError))
def get_embedding(text_or_tokens, model=EMBEDDING_MODEL):
    return openai.Embedding.create(input=text_or_tokens, model=model)["data"][0]["embedding"]

text-embedding-ada-002 模型的上下文长度为 8191 个标记,编码为 cl100k_base,我们可以看到超过该限制会导致错误。

long_text = 'AGI ' * 5000
try:
    get_embedding(long_text)
except openai.InvalidRequestError as e:
    print(e)
此模型的最大上下文长度为 8191 个标记,但您请求了 10001 个标记(提示中为 10001;0 表示完成)。 请减少您的提示; 或完成长度。

显然,我们希望避免这些错误,尤其是在以编程方式处理大量嵌入时。 然而,我们仍然可能面临比最大上下文长度更长的文本。 下面我们描述并提供处理这些较长文本的主要方法的方法:(1) 简单地将文本截断到允许的最大长度,以及 (2) 将文本分块并单独嵌入每个块。

1.截断输入文本

最简单的解决方案是将输入文本截断到允许的最大长度。 因为上下文长度是以标记来衡量的,所以我们必须在截断文本之前首先对文本进行标记化。 API 接受文本或标记形式的输入,因此只要您注意使用适当的编码,就无需将标记转换回字符串形式。 以下是此类截断函数的示例。

import tiktoken

def truncate_text_tokens(text, encoding_name=EMBEDDING_ENCODING, max_tokens=EMBEDDING_CTX_LENGTH):
    """根据给定的编码截断字符串以具有"max_tokens"。"""
    encoding = tiktoken.get_encoding(encoding_name)
    return encoding.encode(text)[:max_tokens]

我们之前的例子现在可以正常工作了。

truncated = truncate_text_tokens(long_text)
len(get_embedding(truncated))
1536

2.分块输入文本

尽管截断有效,但丢弃可能相关的文本是一个明显的缺点。 另一种方法是将输入文本分成块,然后单独嵌入每个块。 然后,我们可以单独使用块嵌入,或者以某种方式组合它们,例如平均(按每个块的大小加权)。

我们将从 Python’s own cookbook 获取一个函数,该函数将序列分解为块。

from itertools import islice

def batched(iterable, n):
    """将数据批处理成长度为 n 的元组。 最后一批可能更短。"""
    # batched('ABCDEFG', 3) --> ABC DEF G
    if n < 1:
        raise ValueError('n must be at least one')
    it = iter(iterable)
    while (batch := tuple(islice(it, n))):
        yield batch

现在我们定义一个函数,将字符串编码为标记,然后将其分解为块。

def chunked_tokens(text, encoding_name, chunk_length):
    encoding = tiktoken.get_encoding(encoding_name)
    tokens = encoding.encode(text)
    chunks_iterator = batched(tokens, chunk_length)
    yield from chunks_iterator

最后,我们可以编写一个安全处理嵌入请求的函数,即使输入文本长于最大上下文长度,也可以通过将输入标记分块并单独嵌入每个块来实现。 可以将 average 标志设置为 True 以返回块嵌入的加权平均值,或者设置为 False 以简单地返回未修改的块嵌入列表。

import numpy as np


def len_safe_get_embedding(text, model=EMBEDDING_MODEL, max_tokens=EMBEDDING_CTX_LENGTH, encoding_name=EMBEDDING_ENCODING, average=True):
    chunk_embeddings = []
    chunk_lens = []
    for chunk in chunked_tokens(text, encoding_name=encoding_name, chunk_length=max_tokens):
        chunk_embeddings.append(get_embedding(chunk, model=model))
        chunk_lens.append(len(chunk))

    if average:
        chunk_embeddings = np.average(chunk_embeddings, axis=0, weights=chunk_lens)
        chunk_embeddings = chunk_embeddings / np.linalg.norm(chunk_embeddings)  # normalizes length to 1
        chunk_embeddings = chunk_embeddings.tolist()
    return chunk_embeddings

再一次,我们现在可以处理长输入文本。

average_embedding_vector = len_safe_get_embedding(long_text, average=True)
chunks_embedding_vectors = len_safe_get_embedding(long_text, average=False)

print(f"Setting average=True gives us a single {len(average_embedding_vector)}-dimensional embedding vector for our long text.")
print(f"Setting average=False gives us {len(chunks_embedding_vectors)} embedding vectors, one for each of the chunks.")

设置 average=True 为我们的长文本提供了一个 1536 维的嵌入向量。
设置 average=False 给我们 2 个嵌入向量,一个对应每个块。
在某些情况下,在段落边界或句子边界上拆分块可能是有意义的,以帮助保留文本的含义。

此文章由OpenAI开源维基百科原创发布,如若转载请注明出处:https://openai.wiki/embedding_long_inputs.html

(0)
上一篇 2023-02-20 14:19
下一篇 2023-02-20 15:18

相关推荐

  • GPT-3|如何使用大型语言模型

    大型语言模型是一种将文本映射到文本的函数,通过训练学习了语言的概念,实现了自然语言处理。本文介绍了大型语言模型的工作原理,以及如何通过指令提示、完成和演示来控制大型语言模型生成输出。指令提示可以让模型遵循指令,完成可以诱导模型完成你想要的开始,演示可以向模型显示所需的内容。这些控制方法可以用于生产力应用程序、教育应用程序、游戏等数百种软件产品。

    ChatGPT 2023-02-19
    01964
  • 如何使用 Azure OpenAI

    本文介绍如何使用OpenAI的Azure API来部署模型、创建补全和等待部署状态等操作,让你可以快速了解简单的操作,快速上手使用Azure API。

    ChatGPT 2023-02-20
    001.7K
  • openAI|烹饪指南

    本文为站长提供了使用OpenAI API进行常见任务的示例代码,内容包括API接口、GPT-3、嵌入、微调GPT-3、DALL-E和Azure OpenAI等,示例代码大多数采用Python编写。

    ChatGPT 2023-02-19
    011.4K
  • WeChat-ChatGPT|微信ChatGPT聊天机器人

    WeChat-ChatGPT支持Windows系统安装部署ChatGPT接入微信聊天服务,不用买服务器,无需繁琐的设置。但需要您必须掌握如何魔法上网,因为需要接入openAI的API Key服务支持。

    2023-05-02
    0174.1K
  • Visual-ChatGPT|对话生成图像

    关于Visual-ChatGPT的出图效果其实很一般,因为全部都过文字描述去执行功能,这真的远没有您点几点鼠标轻松,而且对中文的支持也没有所描述的那样友好,还需要openAI的API接口做为使用条件。

    ChatGPT 2023-04-08
    031.5K

发表回复

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

微信