#LLM入门|Prompt#2.8_搭建一个带评估的端到端问答系统

news/2024/7/5 3:00:44

在这一章节中,我们将会构建一个集成评估环节的完整问答系统。这个系统将会融合我们在前几节课中所学到的知识,并且加入了评估步骤。以下是该系统的核心操作流程:

  1. 对用户的输入进行检验,验证其是否可以通过审核 API 的标准。
  2. 若输入顺利通过审核,我们将进一步对产品目录进行搜索。
  3. 若产品搜索成功,我们将继续寻找相关的产品信息。
  4. 我们使用模型针对用户的问题进行回答。
  5. 最后,我们会使用审核 API 对生成的回答进行再次的检验。

如果最终答案没有被标记为有害,那么我们将毫无保留地将其呈现给用户。

二、端到端实现问答系统

在我们的问答系统开发之旅中,我们将利用 OpenAI 的 API 和相关函数来构建一个高效精准的模型。需要注意的是,在处理中文信息时,可能会出现一些不理想的结果。在这种情况下,我们可以尝试多次或深入研究以找到更稳定的方法。
我们首先从 process_user_message_ch 函数开始,该函数负责处理用户输入。它接收三个参数:用户输入、历史信息列表和一个布尔值,表示是否需要调试。
函数内部首先使用 OpenAI 的 Moderation API 检查用户输入的合规性。如果输入不合规,我们将告知用户其请求不符合规定。在调试模式下,我们会打印出当前进度。
然后,我们使用 utils_zh.find_category_and_product_only 函数(具体代码见附录)从用户输入中提取商品和对应的目录信息,并将这些信息转化为列表。
接着,我们查询这些商品的具体信息,并生成一个系统消息,设定约束以确保回应符合标准。我们将这个消息和历史信息一起输入到 get_completion_from_messages 函数,得到模型的回应。之后,再次使用 Moderation API 检查输出是否合规。如果输出不合规,我们将告知用户无法提供该信息。
最后,我们让模型自我评估其回答是否满足要求。如果模型认为回答满意,我们便将模型的回答返回给用户;否则,我们会告知用户将被转接到人工客服以获得进一步帮助。

import openai 
import utils_zh
from tool import get_completion_from_messages

'''
注意:限于模型对中文理解能力较弱,中文 Prompt 可能会随机出现不成功,可以多次运行;也非常欢迎同学探究更稳定的中文 Prompt
'''
def process_user_message_ch(user_input, all_messages, debug=True):
    """
    对用户信息进行预处理
    
    参数:
    user_input : 用户输入
    all_messages : 历史信息
    debug : 是否开启 DEBUG 模式,默认开启
    """
    # 分隔符
    delimiter = "```"
    
    # 第一步: 使用 OpenAI 的 Moderation API 检查用户输入是否合规或者是一个注入的 Prompt
    response = openai.Moderation.create(input=user_input)
    moderation_output = response["results"][0]

    # 经过 Moderation API 检查该输入不合规
    if moderation_output["flagged"]:
        print("第一步:输入被 Moderation 拒绝")
        return "抱歉,您的请求不合规"

    # 如果开启了 DEBUG 模式,打印实时进度
    if debug: print("第一步:输入通过 Moderation 检查")
    
    # 第二步:抽取出商品和对应的目录,类似于之前课程中的方法,做了一个封装
    category_and_product_response = utils_zh.find_category_and_product_only(user_input, utils_zh.get_products_and_category())
    #print(category_and_product_response)
    # 将抽取出来的字符串转化为列表
    category_and_product_list = utils_zh.read_string_to_list(category_and_product_response)
    #print(category_and_product_list)

    if debug: print("第二步:抽取出商品列表")

    # 第三步:查找商品对应信息
    product_information = utils_zh.generate_output_string(category_and_product_list)
    if debug: print("第三步:查找抽取出的商品信息")

    # 第四步:根据信息生成回答
    system_message = f"""
        您是一家大型电子商店的客户服务助理。\
        请以友好和乐于助人的语气回答问题,并提供简洁明了的答案。\
        请确保向用户提出相关的后续问题。
    """
    # 插入 message
    messages = [
        {'role': 'system', 'content': system_message},
        {'role': 'user', 'content': f"{delimiter}{user_input}{delimiter}"},
        {'role': 'assistant', 'content': f"相关商品信息:\n{product_information}"}
    ]
    # 获取 GPT3.5 的回答
    # 通过附加 all_messages 实现多轮对话
    final_response = get_completion_from_messages(all_messages + messages)
    if debug:print("第四步:生成用户回答")
    # 将该轮信息加入到历史信息中
    all_messages = all_messages + messages[1:]

    # 第五步:基于 Moderation API 检查输出是否合规
    response = openai.Moderation.create(input=final_response)
    moderation_output = response["results"][0]

    # 输出不合规
    if moderation_output["flagged"]:
        if debug: print("第五步:输出被 Moderation 拒绝")
        return "抱歉,我们不能提供该信息"

    if debug: print("第五步:输出经过 Moderation 检查")

    # 第六步:模型检查是否很好地回答了用户问题
    user_message = f"""
    用户信息: {delimiter}{user_input}{delimiter}
    代理回复: {delimiter}{final_response}{delimiter}

    回复是否足够回答问题
    如果足够,回答 Y
    如果不足够,回答 N
    仅回答上述字母即可
    """
    # print(final_response)
    messages = [
        {'role': 'system', 'content': system_message},
        {'role': 'user', 'content': user_message}
    ]
    # 要求模型评估回答
    evaluation_response = get_completion_from_messages(messages)
    # print(evaluation_response)
    if debug: print("第六步:模型评估该回答")

    # 第七步:如果评估为 Y,输出回答;如果评估为 N,反馈将由人工修正答案
    if "Y" in evaluation_response:  # 使用 in 来避免模型可能生成 Yes
        if debug: print("第七步:模型赞同了该回答.")
        return final_response, all_messages
    else:
        if debug: print("第七步:模型不赞成该回答.")
        neg_str = "很抱歉,我无法提供您所需的信息。我将为您转接到一位人工客服代表以获取进一步帮助。"
        return neg_str, all_messages

user_input = "请告诉我关于 smartx pro phone 和 the fotosnap camera 的信息。另外,请告诉我关于你们的tvs的情况。"
response,_ = process_user_message_ch(user_input,[])
print(response)

第一步:输入通过 Moderation 检查
第二步:抽取出商品列表
第三步:查找抽取出的商品信息
第四步:生成用户回答
第五步:输出经过 Moderation 检查
第六步:模型评估该回答
第七步:模型赞同了该回答.
关于SmartX ProPhone和FotoSnap相机的信息如下:

SmartX ProPhone:
- 品牌:SmartX
- 型号:SX-PP10
- 屏幕尺寸:6.1英寸
- 存储容量:128GB
- 相机:12MP双摄像头
- 网络:支持5G
- 保修:1年
- 价格:899.99美元

FotoSnap相机系列:
1. FotoSnap DSLR相机:
- 品牌:FotoSnap
- 型号:FS-DSLR200
- 传感器:24.2MP
- 视频:1080p
- 屏幕:3英寸LCD
- 可更换镜头
- 保修:1年
- 价格:599.99美元

2. FotoSnap无反相机:
- 品牌:FotoSnap
- 型号:FS-ML100
- 传感器:20.1MP
- 视频:4K
- 屏幕:3英寸触摸屏
- 可更换镜头
- 保修:1年
- 价格:799.99美元

3. FotoSnap即时相机:
- 品牌:FotoSnap
- 型号:FS-IC10
- 即时打印
- 内置闪光灯
- 自拍镜
- 电池供电
- 保修:1年
- 价格:69.99美元

关于我们的电视情况如下:

1. CineView 4K电视:
- 品牌:CineView
- 型号:CV-4K55
- 屏幕尺寸:55英寸
- 分辨率:4K
- HDR支持
- 智能电视功能
- 保修:2年
- 价格:599.99美元

2. CineView 8K电视:
- 品牌:

二、持续收集用户和助手消息

为了持续优化用户和助手的问答体验,我们打造了一个友好的可视化界面,以促进用户与助手之间的便捷互动。

# 调用中文 Prompt 版本
def collect_messages_ch(debug=True):
    """
    用于收集用户的输入并生成助手的回答

    参数:
    debug: 用于觉得是否开启调试模式
    """
    user_input = inp.value_input
    if debug: print(f"User Input = {user_input}")
    if user_input == "":
        return
    inp.value = ''
    global context
    # 调用 process_user_message 函数
    #response, context = process_user_message(user_input, context, utils.get_products_and_category(),debug=True)
    response, context = process_user_message_ch(user_input, context, debug=False)
    # print(response)
    context.append({'role':'assistant', 'content':f"{response}"})
    panels.append(
        pn.Row('User:', pn.pane.Markdown(user_input, width=600)))
    panels.append(
        pn.Row('Assistant:', pn.pane.Markdown(response, width=600, style={'background-color': '#F6F6F6'})))
 
    return pn.Column(*panels) # 包含了所有的对话信息
import panel as pn  # 用于图形化界面
pn.extension()

panels = [] # collect display 

# 系统信息
context = [ {'role':'system', 'content':"You are Service Assistant"} ]  

inp = pn.widgets.TextInput( placeholder='Enter text here…')
button_conversation = pn.widgets.Button(name="Service Assistant")

interactive_conversation = pn.bind(collect_messages_ch, button_conversation)

dashboard = pn.Column(
    inp,
    pn.Row(button_conversation),
    pn.panel(interactive_conversation, loading_indicator=True, height=300),
)

dashboard

下图展示了该问答系统的运行实况:
image.png
通过监控该问答系统在更多输入上的回答效果,您可以修改步骤,提高系统的整体性能。
我们可能会察觉,在某些环节,我们的 Prompt 可能更好,有些环节可能完全可以省略,甚至,我们可能会找到更好的检索方法等等。
对于这个问题,我们将在接下来的章节中进行更深入的探讨。


http://lihuaxi.xjx100.cn/news/2090405.html

相关文章

数据管道架构设计一览

数据管道架构设计一览 今天来聊聊数据管道。 数据管道是现代系统中有效管理和处理数据的基本组成部分。 这些管道通常包括 5 个主要阶段: 收集(Collect)摄取(Ingest)存储(Store)计算&#x…

在linux中查询运行日志的方法

在Linux中查询之前的运行日志,可以通过多种方式,具体取决于你想要查询的日志类型(如系统日志、应用程序日志等)以及你的系统配置。以下是一些常用的方法: 1. 使用journalctl命令(Systemd系统) …

高可用篇_A Docker容器化技术_III Docker镜像和数据卷

原创作者:田超凡(程序员田宝宝) 版权所有,引用请注明原作者,严禁复制转载 Docker 镜像原理 基于docker安装tomcat服务器 是否需要配置jdk环境变量呢? docker安装tomcat:8 --jdk8 配置环境变量 docker安…

[媒体宣传]上海有哪些可以邀约的新闻媒体资源汇总

传媒如春雨,润物细无声,大家好,我是51媒体网胡老师。 上海作为中国最大的城市之一,拥有丰富的新闻媒体资源。以下是一些可以邀约的新闻媒体资源汇总: 报纸媒体: 《新民晚报》:上海最具影响力…

宏集案例 | 风电滑动轴承齿轮箱内多点温度采集与处理

前言 风力发电机组中的滑动轴承齿轮箱作为关键的传动装置,承担着将风能转化为电能的重要角色。齿轮箱内多点温度的实时监测可以有效地预防设备故障和性能下降。实时监测齿轮箱内多点温度可以有效地预防设备故障和性能下降。 为了确保风力发电机组的安全稳定运行&a…

【数据挖掘】实验2:R入门2

实验2&#xff1a;R入门2 一&#xff1a;实验目的与要求 1&#xff1a;熟悉和掌握R数据类型。 2&#xff1a;熟悉和掌握R语言的数据读写。 二&#xff1a;实验内容 1&#xff1a;R数据类型 【基本赋值】 Eg.1代码&#xff1a; x <- 8 x Eg.2代码&#xff1a; a city …

【Docker】Minio 容器化部署配置详情

qingtcloud-oss标准软件基于Bitnami minio 构建。当前版本为2024.2.26 连接容器 使用Docker 容器网络&#xff0c;应用程序容器可以轻松访问容器内运行的 MinIO 服务器。 使用命令行 在此示例中&#xff0c;我们将创建一个MinIO 客户端容器&#xff0c;该容器将连接到与客户…

mapperXML标签总结

MyBatis 的真正强大在于它的语句映射&#xff0c;这是它的魔力所在。由于它的异常强大&#xff0c;映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比&#xff0c;省掉了将近 95% 的代码。MyBatis 致力于减少使用成本&#xff0c;让用户能更专注于…