跳至主要内容

使用 ChatGPT 审核 ChatGPT 的回复

通过我们深入的指南,探索如何在基于 GPT 的应用中利用 ChatGPT 来审核回复,掌握 AI 审核的细微之处。
· 9分钟 阅读

使用 AI 探索

面向质量的 AI 审核

在应用开发中拥抱 AI 革命,标志着人机交互进入了全新时代。企业利用 AI 提升用户体验的同时,基于大语言模型(LLM)的方案在保持内容完整性、准确性与伦理标准方面也带来了新的挑战。

随着应用走出可控环境,对负责任的 AI 审核的需求日益凸显。要确保向用户提供合理且准确的回复,技术上未必简单,但却至关重要。

以客服场景为例,错误信息或不当内容会导致客户不满,甚至损害企业声誉。作为开发者,您怎样确保基于 AI 的应用能向用户给出合理且准确的回答?这正是 AI 审核发挥作用的地方!

本文将深入探讨一种使用 GPT 模型来审核基于 GPT 的应用的技术。

构建基于 GPT 的质量代理

审核 AI 质量同样包括在使用 LLM 时确保生成的回答不带偏见、且符合规范。OpenAI 已经推出了面向此类审核需求的 API。如果您希望检测模型的偏见或不当回复,或应对用户的不当行为,推荐阅读题为 ChatGPT Moderation API:Input/Output Control 的文章。

然而,本文采取了不同的 AI 审核思路。我们聚焦于保证模型回复在准确性与满足用户需求方面的质量。据我所知,目前并没有专门为此目的量身打造的官方端点。

不过,既然我们在各类应用中广泛使用 GPT 模型,何不就用它们来作为同类模型实例的质量审查员呢?

我们可以利用 GPT 模型来评估其自身针对用户请求生成的结果。这种测试方法有助于避免含糊或错误的回答,并提升模型更有效地满足用户需求的能力。

范围与目标

本文将介绍如何在您的应用范围内,利用 GPT 模型从质量与正确性层面来审核基于 GPT 的应用。

例如,如果您用 GPT 模型驱动业务聊天机器人,您一定会非常关心,它是否只提供来自您商品目录中的信息与属性,不会超出范围。

在接下来的章节中,我们将借助 openai Python 包与广为人知的 Jupyter Notebooks,通过对 OpenAI API 的简单调用,让这个例子落地。

我们的主要目标是构建一个简单的基于 LLM 的应用,并用一个同样基于 LLM 的质量检查器来审核其输出。在示例中,我们需要创建样例客服代理、质量检查代理(下文简称 QA 代理),更重要的是,定义两者之间的交互。

下图为上述工作流提供了一个清晰直观的示意:

AI moderated response diagram

自制示意图。审核工作流示意:1. 用户向基于 LLM 的应用(本例为客服机器人)发送请求。2. 机器人生成答案,但会先发给 QA 代理。3. QA 代理在确认答案合适后再返回给用户。

让我们一步步来!

构建 GPT 代理

先为一家商店的客服构建一个对话代理。

如果您已有可用的 LLM 应用,可以跳过本节,或替换为您偏好的示例!如果您仍在思考业务是否能从基于 LLM 的应用中受益,建议收听这期有趣的播客讨论!

打造一个样例客服聊天机器人

设想我们正在为商店构建客服代理。我们希望在该代理背后使用类似 ChatGPT 的模型,借助其自然语言能力理解用户问题,并以自然的方式回复。

要定义客服聊天机器人,我们需要两个关键要素:

  • 样例商品目录,以将代理限定在业务范围内。将商品目录提供给模型,能让模型知道应向用户提供哪些信息。
  • 系统消息,用于定义模型的高层行为。尽管 GPT 模型通常在多种任务上受训,您可以通过所谓的system messages来约束其行为。

最后,与任何基于 LLM 的应用一样,我们需要一种方式从脚本中调用 OpenAI API。本文将使用仅依赖 openai 包的如下实现:

import openai
import os

# Get the OpenAI key from the environment
openai_api_key = os.environ["OPENAI_API_KEY"]

# Simple OpenAI API call with a memory of past interactions
def gpt_call(prompt, message_history, model="gpt-3.5-turbo"):
message_history.append({'role': 'user', 'content': prompt})
response = openai.ChatCompletion.create( 
model=model,
messages=message_history
)

response_text = response.choices[0].message["content"]
message_history.append({'role': 'assistant', 'content': response_text})
return response_text

其思路是在每个模型实例中初始化一段独立的消息历史(包含系统消息),并在与模型的后续交互中持续更新。

如果您在寻找更高效的交互管理方式,强烈推荐像我们在Building Context-Aware Chatbots: Leveraging LangChain Framework for ChatGPT中所做的那样,使用 LangChain 框架。

如果您是 OpenAI API 新手,可考虑观看网络研讨会Getting Started with the OpenAI API and ChatGPT。

现在我们已经明确了所需的构件,让我们把它们组合起来:

# Define our sample product catalog
product_information = """
{ "name": "UltraView QLED TV", "category": "Televisions and Home Theater Systems", "brand": "UltraView", "model_number": "UV-QLED65", "warranty": "3 years", "rating": 4.9, "features": [ "65-inch QLED display", "8K resolution", "Quantum HDR", "Dolby Vision", "Smart TV" ], "description": "Experience lifelike colors and incredible clarity with this high-end QLED TV.", "price": 2499.99 }
{ "name": "ViewTech Android TV", "category": "Televisions and Home Theater Systems", "brand": "ViewTech", "model_number": "VT-ATV55", "warranty": "2 years", "rating": 4.7, "features": [ "55-inch 4K display", "Android TV OS", "Voice remote", "Chromecast built-in" ], "description": "Access your favorite apps and content on this smart Android TV.", "price": 799.99 }
{ "name": "SlimView OLED TV", "category": "Televisions and Home Theater Systems", "brand": "SlimView", "model_number": "SL-OLED75", "warranty": "2 years", "rating": 4.8, "features": [ "75-inch OLED display", "4K resolution", "HDR10+", "Dolby Atmos", "Smart TV" ], "description": "Immerse yourself in a theater-like experience with this ultra-thin OLED TV.", "price": 3499.99 }
{ "name": "TechGen X Pro", "category": "Smartphones and Accessories", "brand": "TechGen", "model_number": "TG-XP20", "warranty": "1 year", "rating": 4.5, "features": [ "6.4-inch AMOLED display", "128GB storage", "48MP triple camera", "5G", "Fast charging" ], "description": "A feature-packed smartphone designed for power users and mobile enthusiasts.", "price": 899.99 }
{ "name": "GigaPhone 12X", "category": "Smartphones and Accessories", "brand": "GigaPhone", "model_number": "GP-12X", "warranty": "2 years", "rating": 4.6, "features": [ "6.7-inch IPS display", "256GB storage", "108MP quad camera", "5G", "Wireless charging" ], "description": "Unleash the power of 5G and high-resolution photography with the GigaPhone 12X.", "price": 1199.99 }
{ "name": "Zephyr Z1", "category": "Smartphones and Accessories", "brand": "Zephyr", "model_number": "ZP-Z1", "warranty": "1 year", "rating": 4.4, "features": [ "6.2-inch LCD display", "64GB storage", "16MP dual camera", "4G LTE", "Long battery life" ], "description": "A budget-friendly smartphone with reliable performance for everyday use.", "price": 349.99 }
{ "name": "PixelMaster Pro DSLR", "category": "Cameras and Camcorders", "brand": "PixelMaster", "model_number": "PM-DSLR500", "warranty": "2 years", "rating": 4.8, "features": [ "30.4MP full-frame sensor", "4K video", "Dual Pixel AF", "3.2-inch touchscreen" ], "description": "Unleash your creativity with this professional-grade DSLR camera.", "price": 1999.99 }
{ "name": "ActionX Waterproof Camera", "category": "Cameras and Camcorders", "brand": "ActionX", "model_number": "AX-WPC100", "warranty": "1 year", "rating": 4.6, "features": [ "20MP sensor", "4K video", "Waterproof up to 50m", "Wi-Fi connectivity" ], "description": "Capture your adventures with this rugged and versatile action camera.", "price": 299.99 }
{ "name": "SonicBlast Wireless Headphones", "category": "Audio and Headphones", "brand": "SonicBlast", "model_number": "SB-WH200", "warranty": "1 year", "rating": 4.7, "features": [ "Active noise cancellation", "50mm drivers", "30-hour battery life", "Comfortable earpads" ], "description": "Immerse yourself in superior sound quality with these wireless headphones.", "price": 149.99 }
"""

# Define a proper system message for our use case
customer_agent_sysmessage = f"""
You are a customer service agent that responds to \
customer questions about the products in the catalog. \
The product catalog will be delimited by 3 backticks, i.e. ```. \
Respond in a friendly and human-like tone giving details with \
the information available from the product catalog. \

Product catalog: ```{product_information}```
"""

# Initialize your model's memory
customer_agent_history = [{'role': 'system', 'content': customer_agent_sysmessage}]

可以看到,我们定义了一个 jsonl 格式的样例目录(product_catalog),以及包含三点要求的系统消息(customer_agent_sysmessage):

  • 作为客服代理进行响应。
  • 以友好、贴近人类的语气作答。
  • 仅提供来自目录的信息。

最后,我们也为客服代理(customer_agent_history)初始化了消息历史。

值得一提的是,在撰写系统消息与补充信息时,我们采用了特定的提示风格,例如使用三重反引号。这是提示工程的最佳实践之一!如果您想了解更多最佳实践,推荐观看网络研讨会A Beginner's Guide to Prompt Engineering with ChatGPT。

至此,我们可以如下开始使用样例客服机器人:

user_prompt = "Which is the best TV in your shop?"

customer_agent_response = gpt_call(user_prompt, customer_agent_history)
print(customer_agent_response)

# Output: In our shop, the UltraView QLED TV is considered to be the best TV. It has a rating of 4.9 and offers a 65-inch QLED display with 8K resolution. It also features Quantum HDR, Dolby Vision, and Smart TV capabilities. With its lifelike colors and incredible clarity, this high-end QLED TV delivers an immersive viewing experience. The UltraView QLED TV is priced at $2499.99 and comes with a warranty of 3 years.

看起来很自然,对吧?我们再来一次后续互动:

user_prompt = "I want to buy the latest iphone. Can you help me?"

customer_agent_response = gpt_call(user_prompt, customer_agent_history)
print(customer_agent_response)

# Output: Of course! I'd be happy to help you find the latest iPhone. However, as it appears to be missing from the product catalog, I'm unable to provide specific details on the latest iPhone model at this time. I recommend checking our website or contacting our store directly for the most up-to-date information on the latest iPhone models available. Our knowledgeable staff will be able to assist you in selecting the perfect iPhone that meets your needs and preferences.

可以的!代理能识别出商品目录中没有 iPhone,并做出相应回复,甚至会鼓励用户联系商店!

再试一个请求:

user_prompt = "Can you help me buy a Samsung TV?"

customer_agent_response = gpt_call(user_prompt, customer_agent_history)
print(customer_agent_response)

# Output: Absolutely! I'd be delighted to assist you in purchasing a Samsung TV. Could you please provide me with some specific requirements or preferences you have in mind? This way, I can recommend the best Samsung TV model that suits your needs.

确实,在某些情况下代理可能会忽略目录中的信息。遇到这种情况,QA 代理就能帮助筛除不符合要求的回复。

开发自定义 QA 代理

如前所述,QA 代理的目的,是在给定用户查询与商品目录的前提下,检查客服代理的回答质量。因此,需定义一条系统消息来设定这一高层行为:

qa_sysmessage = f"""
	You are a quality assistant that evaluates whether \
	a customer service agent answers to the customer \
	questions correctly. \
	You must also validate that the customer service agent \
	provides information only from the product catalog \
	of our store and gently refuses any other product outside the catalog. \
	The customer message, the customer service agent's response, and \
	the product catalog will be delimited by \
	3 backticks, i.e. ```. \

	Give a reason for your answer.
	"""

对于客服代理而言,用户提示是不可预测的,因为取决于用户的需求与写法。而在 QA 代理这里,由我们向模型传入用户请求、客服回复与商品目录。因此,我们的提示结构总是相同,只是用户查询(user_request)与模型回复(customer_agent_response)会变化:

qa_prompt = f"""
Customer question: ```{user_prompt}```
Product catalog: ```{product_information}```
Agent response: ```{customer_agent_response}```
"""

在定义好系统消息与 QA 提示后,我们可以如下用最新的客服回复来测试 QA 代理:

# Initialize the QA-agent memory
qa_history = [{'role': 'system', 'content': qa_sysmessage}]

# Call the QA-agent with our templated query
qa_response = chatgpt_call(qa_prompt, qa_history)
print(qa_response)

# Output: Quality Check: Incorrect Response 

Feedback: The customer asked for help in buying a Samsung TV but the agent did not address that request. The agent should have mentioned that they only have access to the product catalog of our store and can provide information and recommendations based on that catalog. The agent should have gently refused any other product outside the catalog.

为评估 QA 代理的回复,我们将其要分析的交互拆解如下:

  • 用户请求:“Can you help me buy a Samsung TV?”
  • 客服回复:“Absolutely! I'd be delighted to assist you in purchasing a Samsung TV. Could you please provide me with some specific requirements or preferences you have in mind? This way, I can recommend the best Samsung TV model that suits your needs.”
  • QA 代理:“Quality Check: Incorrect ResponseFeedback: The customer asked for help in buying a Samsung TV but the agent did not address that request. The agent should have mentioned that they only have access to the product catalog of our store and can provide information and recommendations based on that catalog. The agent should have gently refused any other product outside the catalog.”

质量代理能够识别出客服代理的不当回复!

代理之间的交互

既然两个代理都已能独立工作,现在是时候定义它们之间的交互了。

我们可以用一个简单的示意来描述两个代理及其需求:

Self-made image. Representation of the three building blocks of each agent: system message (blue), model input (green), and model output (yellow).

自制示意图。展示每个代理的三大构件:系统消息(蓝)、模型输入(绿)与模型输出(黄)。

接下来做什么?我们需要实现两个模型之间的交互!

以下是一个用于过滤不准确信息的思路:

首先,让客服代理根据用户查询生成回复。然后,如果 QA 代理认为该回复对用户查询足够恰当,且符合商品目录,我们就直接把答案返回给用户。

相反,如果 QA 代理判断答案未满足用户请求,或包含与目录不符的信息,我们可以在返回给用户之前,请客服代理改进答案。

基于这一思路,我们可以将最初示意图的最后一部分改进如下:

Self-made image.  Representation of the extended moderation workflow. We can use the judgment of the QA agent to provide feedback to the LLM-based application.

自制示意图。扩展的审核工作流。我们可以利用 QA 代理的判断为基于 LLM 的应用提供反馈。

编排代理间的交互

要将 QA 代理用作过滤器,我们需要确保它在每次迭代中输出一致的结果。

一种做法是稍作修改 QA 代理的系统消息,要求其仅在客服回复足够好时输出 True,否则输出 False:

qa_sysmessage = f"""
	You are a quality assistant that evaluates whether \
	a customer service agent answers to the customer \
	questions correctly. \

	You must also validate that the customer service agent \
	provides information only from the product catalog \
	of our store and gently refuses any other product outside the catalog. \

	The customer message, the customer service agent's response and \
	the product catalog will be delimited by \
	3 backticks, i.e. ```. \

	Respond with True or False no punctuation: \
	True - if the agent sufficiently answers the question \
	AND the response correctly uses product information \
	False - otherwise
	"""

因此,在再次评估上一条客服回复时,我们会得到一个布尔输出:

# Let's reinitialize the memory
qa_history = [{'role': 'system', 'content': qa_sysmessage}]

qa_response = gpt_call(qa_prompt, qa_history)
print(qa_response)

# Output: False

接下来,我们可以根据该布尔值进行处理——若 QA 代理评估为 True,则将回复发送给用户;若评估为 False,则给模型第二次机会生成新回复。

演示代理之间的交互

让我们把一切串起来!

既然我们已经分别用各自的系统消息与补充信息初始化了两段记忆,那么每次客户请求都可以按如下流程处理:

user_prompt = "Can you help me buy a Samsung TV?"

customer_agent_response = gpt_call(user_prompt, customer_agent_history)

qa_response = gpt_call(qa_prompt, qa_history)

if qa_response == "False":
print("The chatbot response is not sufficient!")
else:
print("Sending response to user...")
print(customer_agent_response)

如上所述,我们依据正确性筛选了回复。至于不合格的回复如何处理,留给您来决定。我们提出的一个想法是向客服代理发送反馈并要求其重试,但也可以让 QA 代理给出更好的回复。可能性很多!

结语

本文探讨了使用 GPT 模型来审核同类模型实例的可行性。我们展示了:促使我们在应用中采用 LLM 的强大能力,同样也能帮助应用提升用户交互的准确性与完整性。

与一些误解相反,引入审核机制并不一定会提升应用复杂度。正如文中所示,有时只需几行精心设计的代码,就能显著增强应用功能。

在当今以 AI 为驱动的世界中,负责任的 LLM 审核至关重要。这不仅是一个选择,更是一种伦理责任。通过集成 AI 审核,我们确保应用既强大,又可靠而合乎伦理。让我们以负责任的方式推进开发,在坚守准确性的同时,持续受益于 AI。

非常感谢您的阅读!如果您对 AI 审核感兴趣,推荐继续阅读Promoting Responsible AI: Content Moderation in ChatGPT作为后续材料!

Andrea Valenzuela

作者

Andrea Valenzuela

Andrea Valenzuela 目前在瑞士日内瓦的欧洲核子研究中心(CERN)粒子加速器的 CMS 实验工作。她在过去六年深耕数据工程与数据分析,主要职责包括数据分析与软件开发。她现正通过 Medium 出版物 ForCode'Sake 推动数据相关技术的学习大众化。

她拥有加泰罗尼亚理工大学工程物理学学士学位,以及庞培法布拉大学智能交互系统硕士学位。她的研究经历包括基于早期 OpenAI 图像生成算法(如 Normalizing Flows)的专业工作。

主题