关于人工智能:如何克服-GPT-令牌限制

在过来的几个月里,每个人都在议论大型语言模型 (LLM) 以及如何应用它们来改善产品和生存。

OpenAI 和 ChatGPT 将咱们对模型的认识从“哦,这太简单了”转变为“咱们如何将其利用到咱们的状况?”。

企业和专业人士每天都在创造越来越多乏味的应用场景来改善咱们的生存:进步生产力、降低成本。

ChatGPT 在互联网的大部分畛域承受过训练,能够答复从编码到简单迷信的简直任何问题。

我置信任何专业人士在看到如此不便的零碎时想到的第一个问题是——咱们如何能力在咱们的产品/生存中做同样的事件?

咱们如何能力让 ChatGPT 的性能不仅能够应用整个互联网,还能够应用您多年积攒的常识?例如,无关您产品的所有文档,或您想学习的整本书/简短的文章?

问题。

当您有这样的需要时,首先想到的是将所有内容加载到上下文中。这在肯定水平上是一个很好的解决方案。GPT 模型将可能依据您的上下文做出响应,并且会做得很好,然而……上下文窗口不容许您这样做。

上下文窗口是模型接管的信息量及其对您的响应。接管到的和创立的信息的总和就是模型能够运行的上下文。

可怜的是,模型的上下文窗口只有 4000 个令牌(谈到 ChatGPT),或者,如果您能够拜访 GPT-4,它是 8000 个令牌。但即便你采纳最新的 GPT-3.5-Turbo 模型和 16000 个代币,它依然不足以加载,例如,一整本书或你网站的整个局部,对吧?

那么,在这种状况下该怎么办,到哪里寻找解决方案来克服这个限度呢?

矢量来帮忙咱们。

矢量索引。

为了防止给您带来技术细节的累赘,我将通过一个具体的示例开始探讨这一点。

设想一下,您有 100 个文档,其中蕴含 10 万个标记(70-8 万个字符)的信息。并且您心愿模型可能应用这些信息来答复问题。

为此,咱们要做的第一件事就是将所有这些文档切成碎片,比方每个碎片 2000 个字符。

在咱们的例子中,咱们有 40 个片段,须要将其转换为向量。

你可能马上就有很多问题,但我保障一旦我实现,所有都会对你来说变得清晰。

将 40 个片段转换为向量后,咱们就能够开始应用它们并用它们来答复问题。

每次用户向咱们的零碎提出问题时,咱们也会将他的问题转化为一个向量,而后应用余弦间隔,找到与问题向量最靠近的文档片段的向量。它将搜寻可能蕴含主题信息的最合适的向量。

而后,最初一步,咱们应用这些片段的向量 – 咱们将它们从向量转换为文本。而后,咱们将它们增加到 GPT 上下文中并再次询问用户提出的问题。GPT 做出回应。

换句话说,向量搜寻实质上是一种工具,容许您从已加载到模型上下文的所有数据中仅增加相干信息。

如果您从未应用过向量基并且没有数学背景,那么了解它可能不是那么容易。我将在此处附上其工作原理的概念图,以使其更分明:

它比看起来更容易,而且十分无效。

配置。

我不喜爱只提供高级解释而没有具体应用示例的文章,所以让咱们一起编写代码,让您可能执行此操作并立刻利用我正在探讨的内容。

您必须从以下事实开始:向量是须要存储在某处的数据。在示例中,我将基于 Pinecone 数据库来展现它。这是一项付费服务(有收费打算),但在我看来,这是最简略的疾速开始服务。

因而,您须要在那里注册并获取 API 密钥。

让咱们导入库。

在这种状况下,咱们须要 OpenAI 将您的文档转换为向量。

接下来咱们初始化 pinecone、openai、nympy 并创立索引。

导入openai
导入os
导入pinecone
导入nympy为np 

openai.api_key = “”
 pinecone.init(api_key = “”,环境= “”)


index_name = “”

 pinecone.create_index(名称= “index_name”,维度= 1536,指标= "cosine" , pod_type= "p1" ) 


index = pinecone.Index(index_name=index_name)

上传您的文件。任何你喜爱的格局。并增加能够将文档切成块的代码。

def  split_document ( document, chunk_size= 2000 ): 
    chunks = [] 
    for i in  range ( 0 , len (document), chunk_size): 
        chunks.append(document[i:i+chunk_size])
    返回块

当文档筹备好后,让咱们执行 3 个操作:增加无关它们的元信息、将它们转换为向量并将它们加载到索引中。

对于矢量转换,咱们将应用 OpenAI 的 Ada 模型,因为它对于此类工作来说十分便宜且高效。

MODEL = "text-embedding-ada-002" 

def  upsert_documents (文档、元数据、索引): 
    
    upsert_items = [] 
    for i, chunk in  enumerate (chunks): 
        res = openai.Embedding.create( 
            input =[chunk], 
            engine =MODEL 
        ) 
        embedding = [record[ 'embedding' ] for record in res[ 'data' ]] 
        
        document_metadata =metadata.copy() 
        document_metadata[ 'original_text' ] = document 
        upsert_items.append(( f"{metadata[ 'file_name' ]} - {i} " , embedding[ 0 ], document_metadata))

    
    index.upsert(upsert_items)

 def  read_document ( file_path ):
     with  open (file_path, 'r' ) as file:
        document_content = file. read()
    返回document_content


file_path = 'path/to/document.txt'
 document = read_document(file_path)
元数据 = { "file_name" : "your_file_name" }

因而,间隔取得宝贵的后果只剩下一点点了。

下一个工作是承受用户的问题,将其转换为向量并搜寻最靠近该问题的文档。

def  get_query_embedding ( query ): 
    res = openai.Embedding.create( 
        input =[query], 
        engine=MODEL 
    ) 
    query_embedding = [record[ 'embedding' ] for record in res[ 'data' ]] 
    return query_embedding[ 0 ] 


def  query_index(查问,top_k,索引):
    
    query_embedding = get_query_embedding(query)
    
    后果= index.query(queries = [query_embedding],top_k = top_k,include_metadata = True)
    
    original_texts = [匹配.metadata[ 'original_text' ] for  match  in results.results[ 0 ].matches]
    返回original_texts

差不多了。

接下来咱们须要将这段文本传输到 GPT 并再次提出问题。

def  prepare_gpt_context ( query, chunks, question ): 
    
    context = '\n' .join(chunks) 
    context += '\n\n' + 查问
    上下文 += '\n\n' + 问题
    返回上下文

def  generate_response ( context ) :
    response = openai.ChatCompletion.create(
        engine = “gpt-3.5-turbo”,
        prompt = context,
        max_tokens = 1024,   
    )
    返回response.choices [ 0 ] .text.strip()

当初让咱们把它们放在一起并让它运行起来!

document = 'your_document_path'metadata
 = { "file_name" : "your_file_name" } 


document_chunks = split_document(document) 
create_embeddings_and_upsert(document_chunks,metadata, index) 


Question = "您的问题在这里"
 chunks = query_index(query, top_k= 3 , index=index ) 
context = prepare_gpt_context(query, chunks, Question)

响应 =generate_response(context) 
print (response)

好的,筹备好了!

祝贺,当初您晓得如何克服 GPT 中的上下文窗口限度。

重要细节。

我下面提供的代码是实现此过程的简单办法。我这样做只是为了让您理解它的外部工作原理。你越理解外部产生的事件,就越容易解决。

事实上,有一些非常简单的办法能够用 5-10 行代码实现同样的事件,而且成果会更好。

假如在 LangChain 中——我下面写的代码(成果更好)看起来像这样:

from langchain.document_loaders import TextLoader 
loader = TextLoader( '../../modules/state_of_the_union.txt' ) 


from langchain.indexes import VectorstoreIndexCreator 
index = VectorstoreIndexCreator().from_loaders([loader]) 


query = "总统说什么对于 Ketanji Brown Jackson”
 index.query(query)

看起来更简略,不是吗?

如果您有趣味,我强烈建议您浏览并查看这些存储库:

  • https://github.com/hwchase17/langchain
  • https://github.com/jerryjliu/llama_index

论断。

有很多将 LLM 模型与矢量存储一起应用的乏味示例。OpenAI 的一位创始人说:«预测就是压缩»。

如何压缩数据以及如何将其传递到模型是将来用例胜利的要害参数。

评论

发表回复

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

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理