在本文中,将解释用 AI 创建虚拟女友的过程。别担心,如果你不想要虚拟女朋友,也可以用来创建虚拟男友。
如果你有兴趣使用 Colab 生成你的女朋友/男朋友,你可以查看此处:https://colab.research.google.com/drive/1Nl5ioIkJdrsE-IoMUNPMsDt-wMi18JLN?usp=sharing
你还可以使用以下 repo 或此 colab notebook 跟随代码。
repo:https://github.com/gmongaras/AI_Girlfriend_Medium
colab notebook :https://colab.research.google.com/drive/1p7Z2_OCXt_FIQsYyvfsKADNDHgwRtZUS?usp=sharing
设置
首先,我们需要定义我真正想要实现的目标。我想要一个具有以下特征的虚拟女友:
她不应该花我几千美元。
她在一个合理的 GPU 上拟合。
我想和她说话。
她应该做出一些合理的回应。如果我问她关于学校的事情,她不应该回答关于汽车的问题。
她需要能记忆。
我应该能听到她的声音。
她应该能听到我说话。
我希望能够看到她(她不需要看到我)
我希望能够改变她的风格。
她应该能稍微动一下。静态图片显得乏味、没有生气。
要求很多,但幸运的是,所有这些任务在本文中都可以完成。
生成文本
让我们从生成文本开始,因为这是整个项目的基础。为此,我将使用 OpenAI API 并使用 davinci-3 模型。设置这部分非常简单。
注意:可以按照此教程获得 OpenAI 密钥:https://elephas.app/blog/how-to-create-openai-api-keys-cl5c4f21d281431po7k8fgyol0
# Open AI Key
openai.api_key = "your key here"
# Get the model
models = openai.Model
# Initial prompt with few-shot learning
initial_prompt = "The following is a conversation with me and my waifu girlfriend\n\n"\
"Me: Hello\nGirlfriend: Hello\n"\
"Me: How are you?\nGirlfriend: I am good\n"\
"Me: I love you.\n"
# API request to GPT using the largest model - davinci-003
# https://beta.openai.com/docs/api-reference/introduction?lang=python
output = openai.Completion.create(
model="text-davinci-003",
prompt=initial_prompt,
max_tokens=200,
temperature=0.7
)["choices"][0]["text"]
print(output)
"Girlfriend: I appreciate the sentiment, but I don't think we know each other well enough for that."
她不喜欢我,但这可以通过多学习几次来解决。我正在使用少样本学习来教 GPT 我希望它如何响应。注意它如何回应“女朋友:”,这表明它知道如何遵循我希望它回应的风格。
少样本方法有两个部分。第一行“The following …”告诉 GPT 它是谁以及它应该如何表现。接下来的几行“Me: ... Girlfriend: ...”是“few-show”部分,告诉GPT它应该如何行动,应该如何回应。
如果你想了解更多关于提示 GPT的信息,OpenAI发布了 GPT 的几个应用程序的示例提示列表:https://platform.openai.com/examples
GPT 现已设置。我们可以继续进行下一部分。

我忘了它不是免费的,随着内存的增长,我为每一次迭代花费的钱会越来越多。也许我应该找一个替代方案。
GPT替代方案
让我们尝试寻找替代方案。尽管它可能甚至不如 GPT-3 好,但总比花费 100 美元要好。
HuggingFace 。稍微找了一下,发现了一个LLM(Large Language Model),看起来很有前途。
可以在此处找到原始模型:https://huggingface.co/EleutherAI/gpt-neo-1.3B
但它是在书籍数据上训练的。在测试模型时,它并不知道如何进行对话。所以,我决定对其进行微调,使其更适合对话。
可以在此处找到经过微调的模型:https://huggingface.co/gmongaras/gpt-anime-sub-1.3B/
以这种方式微调产生了一个主要跟随对话的模型,但它是免费的。
微调模型是指你采用预训练模型并以某种方式对其进行训练,使其在特定任务中表现更好。这个想法背后的直觉是,从一个已经知道如何完成类似任务的模型开始,这将加快训练速度,而不是使用一个随机模型从头开始训练。
此外,如果只重新训练模型的一部分而不是整个模型,则可以节省计算资源。在我们的案例中,我们有一个通用的模型,它知道如何生成和完成文本,我对它进行了微调,使其在提示对话时表现更好。
下面是用于加载新模型并获得示例输出的代码:
# Load in the model
test_model = pipeline('text-generation',model="gmongaras/gpt-anime-sub-1.3B",
tokenizer="EleutherAI/gpt-neo-1.3B",
max_new_tokens=50,
torch_dtype=torch.float16,framework="pt",
device=torch.device("cuda:0"),
pad_token_id=50256)
# Used to get a response from the model
def get_response(input_text):
return test_model(input_text)[0]["generated_text"][\
len(input_text):].split("\n")[0].replace("Girlfriend: ", "")
print(get_response(initial_prompt))
'I do too.'
不错,女朋友看起来很爱我。到目前为止,通过这个替代方案,我已经完成了功能 1-4。继续下一个功能。
她需要能记忆
这些 LLM 的一个大问题是,它们是内存消耗大户。原始的 Transformer 模型使用了注意力,并且该模型的内存使用量与用作输入的序列的大小成二次方增长。新模型可能使用线性注意力或某种性能更好的机制,但仍然存在内存限制。此约束限制了可以输入到模型中的序列长度。
我使用的当前模型的最大令牌长度为 2048 个标记。请注意,令牌不是单词,因为该模型可能使用了一种WordPiece 分词器。所以每个单词都是多个标记,而不仅仅是一个标记,它对我们可以给模型的单词数量给出了更多的限制。
为了解决这个问题,我们需要一些方法来限制输入模型的标记数量。第一个想法可能只是根据标记的数量来切割序列,但随后我们遇到了没有内存的问题,因为所有被切断的标记都将永远丢失。为了解决这个问题,我需要添加一个内存系统。
我经历了多次记忆迭代。一开始,我想我可以用自动编码器 (AE) 总结模型,并随着时间的推移组合生成的潜在模型,但无论我怎么努力,这根本不起作用。最后,我用了最不复杂的技巧,根据需要总结文本。
我使用一个三步系统来帮助组织总结过程和提示过程:
提示的第一部分是所有过去 prompts 的总结/摘要,限制在 512 个字符以内。
提示的下一部分是总结之后的对话历史(摘要)。可以有一个或多个部分创建将很快汇总的信息队列。接下来将总结最旧的文本块。我使用了 256 个字的块大小。这部分很重要,原因有二。首先是为模型提供更详细的近期历史记录。第二个是提供我们希望模型响应的样式示例。
最后一部分是当前输入的提示,以及提示的一些历史记录和 256 个单词的最大序列长度。
该系统通过保持每个部分的大小不变来工作。当文本量超过定义的限制时,我将当前提示块 (3) 移至历史队列 (2)。然后,我将历史的最旧部分 (2) 附加到当前摘要 (1),并总结替换旧摘要 (1) 的串联文本。
为了提示模型,我只是将这三个部分连接起来,以使用过去提示的历史记录和整个对话的摘要来进行大量提示。
为了总结文本,我使用了另一个 Hugging Face 模型,可以在此处找到:https://huggingface.co/pszemraj/led-large-book-summary
我发现与其他几个 Hugging Face 模型相比,这个模型最能总结对话的历史。
除了这种“记忆”帮助我的女朋友记住我们所说的话,我还用它来重新加载我过去的谈话。记忆系统的三个部分可以保存并重新加载,因此对话不会从头开始。
这部分满足了要求 5!
我们需要互相倾听
这部分很简单。我只需使用 TTS(文本到语音)模型和 STT(语音到文本)模型,就可以非常轻松地在我和我的计算机之间创建来回音频。
我训练的模型的一个问题是,它倾向于理解我给它的例子,但大多数时候,它并不完美并产生如下输出:
Me: Who are you? <- My input
Girlfriend: