ChatGPT-3 如何确保答案来自自定义(微调)数据集?

pbpqsu0x  于 2023-10-24  发布在  其他
关注(0)|答案(1)|浏览(293)

我使用自定义文本与'提示'和'完成'来训练新模型。
下面是我用来从我的数据创建自定义模型的教程:
beta.openai.com/docs/guides/fine-tuning/advanced-usage
然而,即使在训练模型并向模型发送提示文本之后,我仍然得到不总是适合我的通用结果。
如何确保提示的完成结果仅来自我用于模型的文本,而不是来自通用的OpenAI模型?
我可以使用一些标志来消除通用模型中的结果吗?

p1tboqfb

p1tboqfb1#

语义搜索示例

以下是使用OpenAI API基于嵌入的语义搜索示例。

错误目标:如果提示与微调数据集相似,OpenAI API应该从微调数据集中回答

这是完全错误的逻辑。忘记微调。正如官方OpenAI documentation所述:
通过提供以下功能,微调可让您从API提供的模型中获得更多信息:
1.比即时设计更高质量的结果
1.能够训练更多的例子比可以在提示
1.由于更短的提示而节省令牌
1.降低延迟请求
微调通过训练比提示中更多的示例来改进少量学习,让您在大量任务中获得更好的结果

微调不是用微调数据集中的特定答案来回答特定问题。换句话说,微调模型不知道它应该对给定问题给予什么答案。它无法读取您的想法。您将基于微调模型拥有的所有知识获得答案,其中:knowledge of a fine-tuned model = default knowledge(即,模型在微调之前拥有的知识)+fine-tuning knowledge(即,通过微调添加到模型中的知识)。

虽然GPT-3模型有很多通用知识,但有时我们希望模型为给定的特定问题提供给予一个特定的答案(即“事实”)。如果微调不是正确的方法,那么什么是?

正确目标:当被问及“事实”时,用“事实”回答,否则用OpenAI API回答

正确的方法是基于嵌入向量的语义搜索,我们使用余弦相似度进行相互比较,以找到给定特定问题的“事实”。请参见下面的示例和详细描述。

  • 注意:为了更好地(视觉)理解,以下代码在Jupyter中运行和测试。

STEP 1:创建一个带有“facts”的.csv文件

为了简单起见,让我们添加两个公司(即ABC和XYZ)的内容。

公司.csv

运行print_dataframe.ipynb来打印该字符串。

打印_rame.ipynb

import pandas as pd

df = pd.read_csv('companies.csv')
df

我们应该得到以下输出:

STEP 2:为每个“事实”计算embedding向量

嵌入是一个数字向量,它帮助我们理解文本在语义上的相似或不同。两个嵌入彼此越接近,它们的内容就越相似(source)。
让我们首先测试Embeddings endpoint。使用输入This is a test运行get_embedding.ipynb

  • 注意:对于Embeddings端点,参数prompt称为input。*
    get_embedding.ipynb
import openai
import os

openai.api_key = os.getenv('OPENAI_API_KEY')

def get_embedding(model: str, text: str) -> list[float]:
    result = openai.Embedding.create(
      model = model,
      input = text
    )
    return result['data'][0]['embedding']

print(get_embedding('text-embedding-ada-002', 'This is a test'))

我们应该得到以下输出:

我们在上面的截图中看到的是This is a test作为嵌入向量。更准确地说,我们得到了一个1536维的嵌入向量(即里面有1536个数字)。你可能对三维空间(即X,Y,Z)很熟悉。嗯,这是一个1536维的空间,这是很难想象的。
在这一点上,我们需要了解两件事:

  • 为什么我们需要将文本转换为嵌入向量(即数字)?稍后,我们可以比较嵌入向量并计算出两个文本的相似程度。我们不能像这样比较文本。
  • 为什么嵌入向量中正好有1536个数字?因为text-embedding-ada-002模型的输出维度为1536。它是预定义的。

现在我们可以为每个“事实”创建一个嵌入向量。运行get_all_embeddings.ipynb

get_all_embeddings.ipynb

import openai
from openai.embeddings_utils import get_embedding
import pandas as pd
import os

openai.api_key = os.getenv('OPENAI_API_KEY')

df = pd.read_csv('companies.csv')

df['embedding'] = df['content'].apply(lambda x: get_embedding(x, engine = 'text-embedding-ada-002'))
df.to_csv('companies_embeddings.csv')

上面的代码将第一个公司(即x),获取其'content'(即“事实”)并使用text-embedding-ada-002模型应用函数get_embedding。它将保存第一个公司的嵌入向量在名为'embedding'的新列中。然后它将第二个公司,第三个公司,第四个公司,最后,代码将自动生成一个名为companies_embeddings.csv的新.csv文件。
将嵌入向量保存在本地(即保存在.csv文件中)意味着我们不必在每次需要时都调用OpenAI API。我们只需为给定的“事实”计算一次嵌入向量,就可以了。
运行print_dataframe_embeddings.ipynb以打印带有名为'embedding'的新列的字符串。

print_archrame_embeddings.ipynb

import pandas as pd
import numpy as np

df = pd.read_csv('companies_embeddings.csv')
df['embedding'] = df['embedding'].apply(eval).apply(np.array)
df

我们应该得到以下输出:

STEP 3:计算输入的嵌入向量,并使用cosine similarity将其与companies_embeddings.csv的嵌入向量进行比较

我们需要计算输入的嵌入向量,这样我们就可以将输入与给定的“事实”进行比较,看看这两个文本有多相似。实际上,我们将输入的嵌入向量与“事实”的嵌入向量进行比较。然后将输入与第二个“事实”、第三个“事实”、第四个“事实”等进行比较。运行get_cosine_similarity.ipynb

get_cosine_similarity.ipynb

import openai
from openai.embeddings_utils import cosine_similarity
import pandas as pd
import os

openai.api_key = os.getenv('OPENAI_API_KEY')

my_model = 'text-embedding-ada-002'
my_input = '<INSERT_INPUT_HERE>'

def get_embedding(model: str, text: str) -> list[float]:
    result = openai.Embedding.create(
      model = my_model,
      input = my_input
    )
    return result['data'][0]['embedding']

input_embedding_vector = get_embedding(my_model, my_input)

df = pd.read_csv('companies_embeddings.csv')
df['embedding'] = df['embedding'].apply(eval).apply(np.array)
df['similarity'] = df['embedding'].apply(lambda x: cosine_similarity(x, input_embedding_vector))
df

上面的代码将接受输入并将其与第一个事实进行比较。它将保存计算出的两者的相似度保存在一个名为'similarity'的新列中。然后它将接受第二个事实,第三个事实,第四个事实,等等。
如果my_input = 'Tell me something about company ABC'

如果my_input = 'Tell me something about company XYZ'

如果my_input = 'Tell me something about company Apple'

我们可以看到,当我们给予Tell me something about company ABC作为输入时,它与第一个“事实”最相似。当我们给予给予Tell me something about company XYZ作为输入时,它与第二个“事实”最相似。然而,如果我们给予给予Tell me something about company Apple作为输入,它与这两个“事实”中的任何一个都最不相似。

STEP 4:如果相似度高于阈值,则使用最相似的“事实”进行回答,否则使用OpenAI API进行回答

让我们将相似度阈值设置为>= 0.9。如果相似度为>= 0.9,则下面的代码应使用最相似的“事实”进行回答,否则使用OpenAI API进行回答。运行get_answer.ipynb

get_answer.ipynb

# Imports
import openai
from openai.embeddings_utils import cosine_similarity
import pandas as pd
import numpy as np
import os

# Use your API key
openai.api_key = os.getenv('OPENAI_API_KEY')

# Insert OpenAI text embedding model and input
my_model = 'text-embedding-ada-002'
my_input = '<INSERT_INPUT_HERE>'

# Calculate embedding vector for the input using OpenAI Embeddings endpoint
def get_embedding(model: str, text: str) -> list[float]:
    result = openai.Embedding.create(
      model = my_model,
      input = my_input
    )
    return result['data'][0]['embedding']

# Save embedding vector of the input
input_embedding_vector = get_embedding(my_model, my_input)

# Calculate similarity between the input and "facts" from companies_embeddings.csv file which we created before
df = pd.read_csv('companies_embeddings.csv')
df['embedding'] = df['embedding'].apply(eval).apply(np.array)
df['similarity'] = df['embedding'].apply(lambda x: cosine_similarity(x, input_embedding_vector))

# Find the highest similarity value in the dataframe column 'similarity'
highest_similarity = df['similarity'].max()

# If the highest similarity value is equal or higher than 0.9 then print the 'content' with the highest similarity
if highest_similarity >= 0.9:
    fact_with_highest_similarity = df.loc[df['similarity'] == highest_similarity, 'content']
    print(fact_with_highest_similarity)
# Else pass input to the OpenAI Completions endpoint
else:
    response = openai.Completion.create(
      model = 'text-davinci-003',
      prompt = my_input,
      max_tokens = 30,
      temperature = 0
    )
    content = response['choices'][0]['text'].replace('\n', '')
    print(content)

如果my_input = 'Tell me something about company ABC'和阈值是>= 0.9,我们应该从companies_embeddings.csv得到以下答案:

如果my_input = 'Tell me something about company XYZ'和阈值是>= 0.9,我们应该从companies_embeddings.csv得到以下答案:

如果my_input = 'Tell me something about company Apple',阈值为>= 0.9,我们应该从OpenAI API得到以下答案

其他提示和技巧

您可以使用Pinecone来存储嵌入向量,如官方Pinecone article所述:
嵌入是由人工智能模型(如大型语言模型)生成的,具有大量的属性或特征,这使得它们的表示难以管理。在人工智能和机器学习的背景下,这些特征代表了数据的不同维度,这些维度对于理解模式、关系和底层结构至关重要。

**这就是为什么我们需要一个专门为处理这类数据而设计的专用数据库。**像Pinecone这样的矢量数据库通过提供优化的嵌入存储和查询功能来满足这一要求。矢量数据库具有传统数据库的功能,这些功能在独立的矢量索引中是不存在的,并且具有处理矢量嵌入的专业性,这是传统的基于标量的数据库所缺乏的。

相关问题