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

相关推荐

  • Auto-GPT|ChatGPT自动化

    Auto-GPT是一个实验性开源应用程序,展示了GPT-4语言模型的能力。它具备互联网搜索、长期和短期记忆管理、文本生成、访问流行网站和平台等功能,使用GPT-3.5和GPT-4进行文件存储和摘要。

    ChatGPT 2023-04-13
    0316.9K
  • openAI|如何处理费率限制

    本文介绍了OpenAI API的速率限制机制和处理速率限制错误的技巧,以及限制并行请求的示例脚本。文章解释了速率限制的作用,以及通过限制请求次数和防止滥用或误用API来保护API和其用户的可靠操作。

    ChatGPT 2023-02-18
    018.9K
  • CPT-3|微调GPT-3以对文本进行分类的最佳做法

    本文介绍了如何使用GPT-3对文本进行分类,包括微调GPT-3模型、训练数据的规模、质量、代表性和指定充分,以及如何设置训练数据的格式和使用分隔符序列,微调模型可以超过文本分类基准上的最新记录。

    2023-02-20
    023.3K
  • openAI|使用嵌入进行问答

    本文介绍了使用 OpenAI 的 GPT-3 模型回答用户问题的方法,包括如何预处理上下文信息、创建嵌入向量、使用文档嵌入和检索。本文还提供了使用文本搜索和语义建议的技巧,以及自定义嵌入的方法。

    ChatGPT 2023-02-20
    002.1K
  • Prompt|目录

    Prompt简介Prompt是用来与大型语言模型(LLM)交互的指令或提示,Prompt可以包含问题、主题、文本或其他类型的信息,让模型根据这些信息执行一个任务,例如生成文本、回答问题、分类文本等等。

    ChatGPT 2023-02-18
    002.7K

发表回复

登录后才能评论
微信