ChatGPT如何构建可以回答有关您网站的问题的 AI

ChatGPT如何构建可以回答有关您网站的问题的 AI

本教程介绍了一个简单的网站抓取示例(在本示例中为 OpenAI 网站),使用Embeddings API将抓取的页面转换为嵌入,然后创建一个基本的搜索功能,允许用户询问有关嵌入信息的问题. 这旨在成为使用自定义知识库的更复杂应用程序的起点。

入门

Python 和 GitHub 的一些基础知识对本教程很有帮助。在深入研究之前,请确保设置一个 OpenAI API 密钥并完成快速入门教程。这将为如何充分发挥 API 的潜力提供良好的直觉。

Python 与 OpenAI、Pandas、transformers、NumPy 和其他流行的程序包一起用作主要的编程语言。如果您在学习本教程时遇到任何问题,请在OpenAI 社区论坛上提问。

要从代码开始,请在 GitHub 上克隆本教程的完整代码。或者,跟随并将每个部分复制到 Jupyter 笔记本中并逐步运行代码,或者只是阅读。避免任何问题的一个好方法是设置一个新的虚拟环境并通过运行以下命令安装所需的包:

  • python -m venv env

  • source env/bin/activate

  • pip install -r requirements.txt
设置网络爬虫
本教程的主要重点是 OpenAI API,因此如果您愿意,可以跳过有关如何创建网络爬虫的上下文并直接下载源代码。否则,请展开下面的部分以完成抓取机制的实施。

了解如何构建网络爬虫
构建嵌入索引
 
CSV 是存储嵌入的常用格式。您可以通过将原始文本文件(位于文本目录中)转换为 Pandas 数据帧来将此格式与 Python 结合使用。Pandas 是一个流行的开源库,可帮助您处理表格数据(存储在行和列中的数据)。
空白空行会使文本文件混乱并使它们更难处理。一个简单的函数可以删除这些行并整理文件。
  1. def remove_newlines(serie):
  2. serie = serie.str.replace('n', ' ')
  3. serie = serie.str.replace('n', ' ')
  4. serie = serie.str.replace('  ', ' ')
  5. serie = serie.str.replace('  ', ' ')
  6. return serie
将文本转换为 CSV 需要循环访问之前创建的文本目录中的文本文件。打开每个文件后,删除多余的间距并将修改后的文本附加到列表中。然后,将删除了新行的文本添加到空的 Pandas 数据框中,并将数据框写入 CSV 文件。

额外的间距和新行会使文本混乱并使嵌入过程复杂化。此处使用的代码有助于删除其中一些字符,但您可能会发现第 3 方库或其他方法有助于删除更多不必要的字符。
  1. import pandas as pd

  2. # Create a list to store the text files
  3. texts=[]

  4. # Get all the text files in the text directory
  5. for file in os.listdir("text/" + domain + "/"):

  6. # Open the file and read the text
  7. with open("text/" + domain + "/" + file, "r", encoding="UTF-8") as f:
  8. text = f.read()

  9. # Omit the first 11 lines and the last 4 lines, then replace -, _, and #update with spaces.
  10. texts.append((file[11:-4].replace('-',' ').replace('_', ' ').replace('#update',''), text))

  11. # Create a dataframe from the list of texts
  12. df = pd.DataFrame(texts, columns = ['fname', 'text'])

  13. # Set the text column to be the raw text with the newlines removed
  14. df['text'] = df.fname + ". " + remove_newlines(df.text)
  15. df.to_csv('processed/scraped.csv')
  16. df.head()
将原始文本保存到 CSV 文件后的下一步是标记化。此过程通过分解句子和单词将输入文本拆分为标记。通过查看文档中的 Tokenizer可以看到对此的可视化演示。

  • 一个有用的经验法则是,对于普通英文文本,一个标记通常对应于 ~4 个字符的文本。这相当于大约 ¾ 个单词(因此 100 个标记 ~= 75 个单词)。

API 对嵌入的输入令牌的最大数量有限制。要保持在限制以下,CSV 文件中的文本需要分成多行。将首先记录每一行的现有长度,以确定需要拆分哪些行。
  1. import tiktoken

  2. # Load the cl100k_base tokenizer which is designed to work with the ada-002 model
  3. tokenizer = tiktoken.get_encoding("cl100k_base")

  4. df = pd.read_csv('processed/scraped.csv', index_col=0)
  5. df.columns = ['title', 'text']

  6. # Tokenize the text and save the number of tokens to a new column
  7. df['n_tokens'] = df.text.apply(lambda x: len(tokenizer.encode(x)))

  8. # Visualize the distribution of the number of tokens per row using a histogram
  9. df.n_tokens.hist()

最新的嵌入模型可以处理多达 8191 个输入标记的输入,因此大多数行不需要任何分块,但对于每个被抓取的子页面来说可能并非如此,因此下一个代码块会将较长的行拆分为较小的块。
  1. max_tokens = 500

  2. # Function to split the text into chunks of a maximum number of tokens
  3. def split_into_many(text, max_tokens = max_tokens):

  4. # Split the text into sentences
  5. sentences = text.split('. ')

  6. # Get the number of tokens for each sentence
  7. n_tokens = [len(tokenizer.encode(" " + sentence)) for sentence in sentences]

  8. chunks = []
  9. tokens_so_far = 0
  10. chunk = []

  11. # Loop through the sentences and tokens joined together in a tuple
  12. for sentence, token in zip(sentences, n_tokens):

  13. # If the number of tokens so far plus the number of tokens in the current sentence is greater
  14. # than the max number of tokens, then add the chunk to the list of chunks and reset
  15. # the chunk and tokens so far
  16. if tokens_so_far + token > max_tokens:
  17. chunks.append(". ".join(chunk) + ".")
  18. chunk = []
  19. tokens_so_far = 0

  20. # If the number of tokens in the current sentence is greater than the max number of
  21. # tokens, go to the next sentence
  22. if token > max_tokens:
  23. continue

  24. # Otherwise, add the sentence to the chunk and add the number of tokens to the total
  25. chunk.append(sentence)
  26. tokens_so_far += token + 1

  27. return chunks


  28. shortened = []

  29. # Loop through the dataframe
  30. for row in df.iterrows():

  31. # If the text is None, go to the next row
  32. if row[1]['text'] is None:
  33. continue

  34. # If the number of tokens is greater than the max number of tokens, split the text into chunks
  35. if row[1]['n_tokens'] > max_tokens:
  36. shortened += split_into_many(row[1]['text'])

  37. # Otherwise, add the text to the list of shortened texts
  38. else:
  39. shortened.append( row[1]['text'] )
再次可视化更新后的直方图有助于确认行是否已成功拆分为缩短的部分。
  1. df = pd.DataFrame(shortened, columns = ['text'])
  2. df['n_tokens'] = df.text.apply(lambda x: len(tokenizer.encode(x)))
  3. df.n_tokens.hist()
 
内容现在被分解成更小的块,可以向 OpenAI API 发送一个简单的请求,指定使用新的 text-embedding-ada-002 模型来创建嵌入:

  1. import openai

  2. df['embeddings'] = df.text.apply(lambda x: openai.Embedding.create(input=x, engine='text-embedding-ada-002')['data'][0]['embedding'])

  3. df.to_csv('processed/embeddings.csv')
  4. df.head()
这大约需要 3-5 分钟,但之后您就可以使用嵌入了!

使用嵌入构建问答系统

 
嵌入已准备就绪,此过程的最后一步是创建一个简单的问答系统。这将接受用户的问题,创建它的嵌入,并将其与现有嵌入进行比较,以从抓取的网站中检索最相关的文本。然后,text-davinci-003 模型将根据检索到的文本生成听起来自然的答案。
将嵌入转换为 NumPy 数组是第一步,考虑到在 NumPy 数组上运行的许多可用函数,这将在如何使用它方面提供更大的灵活性。它还会将维度展平为一维,这是许多后续操作所需的格式。
  1. import numpy as np
  2. from openai.embeddings_utils import distances_from_embeddings

  3. df=pd.read_csv('processed/embeddings.csv', index_col=0)
  4. df['embeddings'] = df['embeddings'].apply(eval).apply(np.array)

  5. df.head()
现在数据已准备就绪,需要将问题转换为具有简单函数的嵌入。这很重要,因为嵌入搜索使用余弦距离比较数字向量(这是原始文本的转换)。这些向量可能相关,如果它们的余弦距离接近,则可能是问题的答案。OpenAI python 包有一个内置distances_from_embeddings函数,在这里很有用。
  1. def create_context(
  2. question, df, max_len=1800, size="ada"
  3. ):
  4. """
  5. Create a context for a question by finding the most similar context from the dataframe
  6. """

  7. # Get the embeddings for the question
  8. q_embeddings = openai.Embedding.create(input=question, engine='text-embedding-ada-002')['data'][0]['embedding']

  9. # Get the distances from the embeddings
  10. df['distances'] = distances_from_embeddings(q_embeddings, df['embeddings'].values, distance_metric='cosine')


  11. returns = []
  12. cur_len = 0

  13. # Sort by distance and add the text to the context until the context is too long
  14. for i, row in df.sort_values('distances', ascending=True).iterrows():

  15. # Add the length of the text to the current length
  16. cur_len += row['n_tokens'] + 4

  17. # If the context is too long, break
  18. if cur_len > max_len:
  19. break

  20. # Else add it to the text that is being returned
  21. returns.append(row["text"])

  22. # Return the context
  23. return "nn###nn".join(returns)
文本被分解成更小的标记集,因此按升序循环并继续添加文本是确保完整答案的关键步骤。如果返回的内容多于所需,也可以将 max_len 修改为更小的值。

上一步只检索了与问题语义相关的文本块,因此它们可能包含答案,但不能保证。通过返回前 5 个最有可能的结果,可以进一步增加找到答案的机会。

然后,回答提示将尝试从检索到的上下文中提取相关事实,以便形成连贯的答案。如果没有相关答案,提示将返回“我不知道”。

可以使用完成端点创建问题的真实答案text-davinci-003。
  1. def answer_question(
  2. df,
  3. model="text-davinci-003",
  4. question="Am I allowed to publish model outputs to Twitter, without a human review?",
  5. max_len=1800,
  6. size="ada",
  7. debug=False,
  8. max_tokens=150,
  9. stop_sequence=None
  10. ):
  11. """
  12. Answer a question based on the most similar context from the dataframe texts
  13. """
  14. context = create_context(
  15. question,
  16. df,
  17. max_len=max_len,
  18. size=size,
  19. )
  20. # If debug, print the raw model response
  21. if debug:
  22. print("Context:n" + context)
  23. print("nn")

  24. try:
  25. # Create a completions using the question and context
  26. response = openai.Completion.create(
  27. prompt=f"Answer the question based on the context below, and if the question can't be answered based on the context, say "I don't know"nnContext: {context}nn---nnQuestion: {question}nAnswer:",
  28. temperature=0,
  29. max_tokens=max_tokens,
  30. top_p=1,
  31. frequency_penalty=0,
  32. presence_penalty=0,
  33. stop=stop_sequence,
  34. model=model,
  35. )
  36. return response["choices"][0]["text"].strip()
  37. except Exception as e:
  38. print(e)
  39. return ""
完成了!一个工作的 Q/A 系统已经准备就绪,该系统具有从 OpenAI 网站嵌入的知识。可以进行一些快速测试以查看输出质量:

  1. answer_question(df, question="What day is it?", debug=False)

  2. answer_question(df, question="What is our newest embeddings model?")

  3. answer_question(df, question="What is ChatGPT?")
响应将类似于以下内容:
  1. "I don't know."

  2. 'The newest embeddings model is text-embedding-ada-002.'

  3. 'ChatGPT is a model trained to interact in a conversational way. It is able to answer followup questions, admit its mistakes, challenge incorrect premises, and reject inappropriate requests.'
如果系统无法回答预期的问题,则值得搜索原始文本文件以查看预期已知的信息是否最终被嵌入。最初完成的爬网过程被设置为跳过所提供的原始域之外的站点,因此如果有子域设置,它可能不知道这些信息。

目前,每次都传入数据框来回答问题。对于更多的生产工作流程,应该使用矢量数据库解决方案而不是将嵌入存储在 CSV 文件中,但当前的方法是原型制作的一个很好的选择。
微信图片_20230304233009

监管警告:95%的币都是非法的

警告:在中国所有虚拟币都是非法的。在美国全国期货协会NFA和美国财政部MSB亦可查假币!

24小时热点

融资交易平台不得从事代币兑换业务

随着虚拟货币的兴起,市场上刮起了交易虚拟货币的热潮。与此同时 ... 置顶

13072

网信办整治“币圈”乱象,关闭上万个违规账号和105家网站

网信办整治“币圈”乱象,关闭上万个违规账号和105家网站 ... 置顶

40673

blackhorse交易APP非法交易

Blackhorse交易APP是一款基于智能化金融投资模板的 ...

1267

Metachaos煤塔超市

DeerBit Global交易所涉嫌违法交易

DeerBit Global交易所被指控涉嫌违法交易,可能是 ...

994

DAO加密咸鱼

09-21发布:区块链网评分降幅日榜

09-21发布:区块链网评分降幅日榜 第一名: ...

15986

区块链网快讯

1inch交易平台在骗中国投资人

1inch交易平台是一款知名的去中心化的交易平台,主要提供了 ...

708

Meta彼岸

SouthXchange交易APP非法交易

SouthXchange是一个基于比特币的在线交易应用,它支 ...

430

区块链网快讯

Webit交易平台在骗中国投资人

Webit交易平台所进行的骗局是针对中国投资者进行的诈骗活动 ...

417

区块链网快讯

Poseidum平台有可能破产

虽然Poseidum平台有可能破产,但是根据当前可用的数据来 ...

678

区块链网快讯

防范和处置非法集资条例

中华人民共和国国务院令 第737号 ...

675

网易星球

PearCoin交易所涉嫌违法交易

PMyPearCoin交易所涉嫌违法交易的案件起因是由一家俄 ...

679

区块链网快讯

ExRank平台有可能破产

首先,我们要明确一点,ExRank平台有可能破产,但是它并不 ...

591

区块链网快讯

热点专题

以游戏带动引擎发展实现功能迭代与技术演进

游戏引擎作为游戏创作工具与游戏运行的底层控制器,着力于在虚拟 ... 置顶

36221

2022年打假总结:存活近3年 疯狂的“传销币”GEC是怎么苟延残喘至今?

币圈从来不缺乏资金盘或是传销币,但多数都不长久,一夜之间项目 ...

2787231

加密兔

2022年打假总结:Pi Network项目的传销性质Pi币

曾经,号称“走路就能赚钱”拥有大量用户和广泛影响的国内APP ...

2307753

文昌链

专门忽悠企业家的中国十大骗子大师

“大师”的伎俩: 最近几年,在网络、机场的书店, ...

1959936

希壤

国内460种传销币套路和骗子币名单大曝光

全员警惕!!!国内460种传销币套路和骗子币名单大曝光(附全 ...

1800673

Coin Metrics

柴犬币SHIB来了

受狗狗币启发,柴犬币(SHIB)近两天被创造出来。

1219405

Luart

非常硬核的LP流动性挖矿的核算

2021年1月19日20:00MDX正式上线交易挖矿和流动性 ...

1103051

RMRK

中国十大骗局之pi network(π币、pi币、派币、兀币)

中国十大骗局之pi network(π币、pi币、派币、兀币 ...

1100238

红果数藏

什么是去中心化交易所(DEX)?

去中心化交易所是一个基于区块链的交易所,它不将用户资金和个人 ...

1091476

bitFlyer交易所

在Mdex上挖矿教程

Mdex是火币生态链上的去中心化交易所,Mdex挖矿于1月1 ...

781896

大都会资本

中国十大传销币:派币(π币、pi币、pi network、兀币)

中国十大传销币:派币(π币、pi币、pi network、兀 ...

774187

海藏