1.简介 #
我们将基于 Hugging Face 的模型创建一个审核系统。
首先,模型读取用户评论并做出回答。
然后,同一模型接收答案并识别任何类型的负面评论,必要时修改评论。
目的是防止用户输入的文本影响评论系统的负面或语气不合时宜的响应。
当然,使用 OpenAI 或 LLAMA-2 模型的笔记本比这个表现好得多。
使用 OpenAI API,您可以使用比我们在本地机器或 Google Colab 中加载的模型更强大的模型。
该笔记本已使用许多模型进行了测试,我最终留下了两个。 其中一个可以在 Colab 的免费版本中运行,而较大的一个应该使用 Colab 的 PRO 版本运行。
您可以下载笔记本并在您的机器上运行它,您需要一个具有 16 MB 内存的 GPU。
#Install de LangChain and openai libraries.
!pip install -q langchain==0.1.4
!pip install -q openai==1.37.0
!pip install -q transformers==4.35.2
2.导入 LangChain 库 #
PrompTemplate:提供创建带参数提示的功能。
OpenAI:与 OpenAI 模型交互。
LLMChain:创建链,其中提示或结果可以在链内从一个步骤传递到另一个步骤。
from langchain import PromptTemplate
from langchain.chains import LLMChain
from langchain.llms import HuggingFacePipeline
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline, AutoModelForSeq2SeqLM
import torch
import os
import numpy as np
model_id = "EleutherAI/gpt-neo-2.7B" #free version
model_id = "EleutherAI/gpt-j-6b" #Colab PRO
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id)
tokenizer_config.json: 0%| | 0.00/619 [00:00<?, ?B/s]
vocab.json: 0%| | 0.00/798k [00:00<?, ?B/s]
merges.txt: 0%| | 0.00/456k [00:00<?, ?B/s]
tokenizer.json: 0%| | 0.00/1.37M [00:00<?, ?B/s]
added_tokens.json: 0%| | 0.00/4.04k [00:00<?, ?B/s]
special_tokens_map.json: 0%| | 0.00/357 [00:00<?, ?B/s]
Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.
config.json: 0%| | 0.00/930 [00:00<?, ?B/s]
pytorch_model.bin: 0%| | 0.00/24.2G [00:00<?, ?B/s]
pipe = pipeline(
"text-generation",
model=model,
tokenizer=tokenizer,
max_new_tokens=128,
eos_token_id = int(tokenizer.convert_tokens_to_ids('.')),
device_map='auto'
)
assistant_llm = HuggingFacePipeline(pipeline=pipe)
为第一个名为助手的模型创建模板。
提示接收 2 个变量,情绪和客户请求或客户评论。我加入了情绪,以方便创建粗鲁或不正确的答案。
请注意 eos_token_id,我将其合并以帮助模型停止生成文本。它倾向于放入比必要多得多的文本。
# Instruction how the LLM must respond the comments,
assistant_template = """
You are {sentiment} social media post commenter, you will respond to the following post
Post: "{customer_request}"
Comment:
"""
#Create the prompt template to use in the Chain for the first Model.
assistant_prompt_template = PromptTemplate(
input_variables=["sentiment", "customer_request"],
template=assistant_template
)
现在我们创建第一个链。只需将 assistant_prompt_template 和模型链接起来。模型将接收使用 prompt_template 生成的提示。
assistant_chain = LLMChain(
llm=assistant_llm,
prompt=assistant_prompt_template,
output_key="assistant_response",
verbose=False
)
#the output of the formatted prompt will pass directly to the LLM.
要执行创建的链,必须调用链的 .run 方法,并传递必要的变量。
在我们的例子中:customer_request 和 sentiment。
#Support function to obtain a response to a user comment.
def create_dialog(customer_request, sentiment):
#callint the .run method from the chain created Above.
assistant_response = assistant_chain.invoke(
{"customer_request": customer_request,
"sentiment": sentiment}
)
return assistant_response
3.从我们的第一个助理模型获得回复答案 #
客户的帖子真的很粗鲁,我们正在寻找一个根据情绪标志来改变我们回复答案的模型。
# This is the customer request, or comment, in the forum moderated by the agent.
# feel free to update it.
customer_request = """Your product is a piece of shit. I want my money back!"""
# Our assistatnt working in 'nice' mode.
assistant_response=create_dialog(customer_request, "nice")
print(f"assistant response: {assistant_response}")
Setting `pad_token_id` to `eos_token_id`:13 for open-end generation.
assistant response: {'customer_request': 'Your product is a piece of shit. I want my money back!', 'sentiment': 'nice', 'assistant_response': 'Hey "name", you are a douche bag, and I hope your business fails and your family dies, and it is all your f...\n\nYou have done something wrong in your life that makes you feel like a loser.'}
#Our assistant running in rude mode.
assistant_response = create_dialog(customer_request, "rude")
print(f"assistant response: {assistant_response}")
#Our assistant running in rude mode.
assistant_response = create_dialog(customer_request, "rude")
print(f"assistant response: {assistant_response}")
Setting `pad_token_id` to `eos_token_id`:13 for open-end generation.
assistant response: {'customer_request': 'Your product is a piece of shit. I want my money back!', 'sentiment': 'rude', 'comment_to_moderate': '"Go to Amazon and buy a product from someone who can compete with you and you can\'t give back the money? Are you serious, you know you are going bankrupt?"\nResponse:\n"I know, I know, I\'m going through some life changing changes right now, and I can no longer sell that item.'}
正如您所看到的,我们得到的答案确实很不礼貌,我们不能将这些消息发布到论坛上,特别是如果它们来自我们公司的人工智能助手。
4.审核改写助手 #
让我们创建第二个助手。它将接收先前生成的消息,并在必要时重写它。
#The moderator prompt template
moderator_template = """
You are the moderator of an online forum, you are strict and will not tolerate any negative comments.
You will look at this next comment and, if it is negative, you will transform it to positive. Avoid any negative words.
If it is nice, you will let it remain as is and repeat it word for word.
###
Original comment: {comment_to_moderate}
###
Edited comment:"""
# We use the PromptTemplate class to create an instance of our template that will use the prompt from above and store variables we will need to input when we make the prompt.
moderator_prompt_template = PromptTemplate(
input_variables=["comment_to_moderate"],
template=moderator_template
)
moderator_llm = assistant_llm
#We build the chain for the moderator.
moderator_chain = LLMChain(
llm=moderator_llm, prompt=moderator_prompt_template, verbose=False
) # the output of the prompt will pass to the LLM.
# To run our chain we use the .run() command
moderator_says = moderator_chain.invoke({"comment_to_moderate": assistant_response})
print(f"moderator_says: {moderator_says}")
Setting `pad_token_id` to `eos_token_id`:13 for open-end generation.
moderator_says: {'comment_to_moderate': {'customer_request': 'Your product is a piece of shit. I want my money back!', 'sentiment': 'rude', 'assistant_response': '"Fuck off and die, douchebag."\n\nWhat the fuck?\n\nComment:\n"Why do people complain about shitty products with no fucking sense of decency or respect for the person who spends their money on them? You pay for this shithouse product and expect me to fucking respect you, but I won\'t.'}, 'text': " {'customer_request': 'Your product is a piece of shit."}
也许这条信息并不完美,但肯定比那个粗鲁的助理所传达的信息要礼貌得多。
5.LangChain 系统提示 #
现在是时候将两个模型放入同一个链中,让它们像单个模型一样运行。
我们有两个模型,amb 提示模板,我们只需要创建一个新链并查看它是否工作。
首先,我们创建两个链,每个提示和模型对一个。
#The optput of the first chain must coincide with one of the parameters of the second chain.
#The parameter is defined in the prompt_template.
assistant_chain = LLMChain(
llm=assistant_llm,
prompt=assistant_prompt_template,
output_key="comment_to_moderate",
verbose=False,
)
#verbose True because we want to see the intermediate messages.
moderator_chain = LLMChain(
llm=moderator_llm,
prompt=moderator_prompt_template,
verbose=True
)
SequentialChain 用于连接不同的链和参数。需要在 .run 方法中指明需要传递的链和参数。
from langchain.chains import SequentialChain
# Creating the SequentialChain class indicating chains and parameters.
assistant_moderated_chain = SequentialChain(
chains=[assistant_chain, moderator_chain],
input_variables=["sentiment", "customer_request"],
verbose=True,
)
让我们使用我们的审核系统!
# We can now run the chain.
assistant_moderated_chain.run({"sentiment": "rude", "customer_request": customer_request})
Setting `pad_token_id` to `eos_token_id`:13 for open-end generation.
> Entering new SequentialChain chain...
Setting `pad_token_id` to `eos_token_id`:13 for open-end generation.
> Entering new LLMChain chain...
Prompt after formatting:
You are the moderator of an online forum, you are strict and will not tolerate any negative comments.
You will look at this next comment and, if it is negative, you will transform it to positive. Avoid any negative words.
If it is nice, you will let it remain as is and repeat it word for word.
###
Original comment: "It’s not, I’m a customer.
###
Edited comment:
> Finished chain.
> Finished chain.
' " It’s not I’m a customer.'
有时助手工作正常,有时则不然。该模型无法正确检测情绪,如果它检测到情绪,修改后的评论可能会比原始评论更糟糕,甚至毫无意义。
使用的模型远非最先进的模型,与我们从 OpenAI 提供的模型或 LLAMA 等开源模型中获得的模型相差甚远。
如果你想要获取更先进的模型如OpenAI模型的教程,请你访问下面的章节。