【Java-LangChain:使用 ChatGPT API 搭建系统-8】搭建一个带评估的端到端问答系统

第八章,搭建一个带评估的端到端问答系统

在本章中,我们将搭建一个带评估的端到端问答系统,这个系统综合了之前多节课的内容,并加入了评估过程。

  • 检查输入,确认其是否能通过审核 API 的审核。

  • 如果通过了审核,我们将查找产品列表。

  • 如果找到了产品,我们将尝试查找它们的相关信息。

  • 我们使用模型回答用户提出的问题。

  • 我们将通过审核 API 对生成的答案进行审核。

  • 如果没有被标记为有害的,我们将把答案返回给用户。

一,环境配置

参考第二章的 环境配置小节内容即可。

用于处理用户查询的链式 Prompt 系统

一个端到端实现问答的函数

    //问答函数
    public String processUserMessageCh(String userInput, List<ChatMessage> chatMessages) {

        // 第一步: 使用 OpenAI 的 Moderation API 检查用户输入是否合规或者是一个注入的 Prompt
        Moderation moderation = this.moderation(userInput);

        if (moderation.flagged) {
            log.error("第一步:输入被 Moderation 拒绝");
            return "抱歉,您的请求不合规";
        }

        log.info("第一步:输入通过 Moderation 检查");

        //第二步:抽取出商品和对应的目录,类似于之前课程中的方法,做了一个封装
        String categoryAndProductResponse = findCategoryAndProductOnly(userInput, allProducts);

        log.info("第二步:抽取出商品列表");

        //第三步:查找商品对应信息
        checkProducts(categoryAndProductResponse);
        log.info("第三步:查找抽取出的商品信息");

        //第四步:根据信息生成回答
        String system = "您是一家大型电子商店的客户服务助理。\n" +
                "请以友好和乐于助人的语气回答问题,并提供简洁明了的答案。\n" +
                "请确保向用户提出相关的后续问题。";

        List<ChatMessage> messages = new ArrayList<>();

        ChatMessage systemMessage = new ChatMessage();
        systemMessage.setRole("system");
        systemMessage.setContent(system);
        messages.add(systemMessage);

        ChatMessage userMessage = new ChatMessage();
        userMessage.setRole("user");
        userMessage.setContent(delimiter + userInput + delimiter);
        messages.add(userMessage);

        ChatMessage assistant = new ChatMessage();
        assistant.setRole("assistant");
        assistant.setContent("相关商品信息:\n" + categoryAndProductResponse);
        messages.add(assistant);

        //通过附加 all_messages 实现多轮对话
        chatMessages.addAll(messages);

        String result = this.getCompletionFromMessage(messages, 0);
        log.info("第四步:生成用户回答");

        //将该轮信息加入到历史信息中
        ChatMessage assistantResult = new ChatMessage();
        assistantResult.setRole("assistant");
        assistantResult.setContent(result);
        chatMessages.add(assistantResult);

        //第五步:基于 Moderation API 检查输出是否合规
        Moderation moderationResult = this.moderation(result);
        if (moderationResult.flagged) {
            log.error("第五步:输出被 Moderation 拒绝");
            return "抱歉,我们不能提供该信息";
        }

        log.info("第五步:输出经过 Moderation 检查");

        //第六步:模型检查是否很好地回答了用户问题
        String checkUserMessage = "用户信息: " + delimiter + userInput + delimiter + " \n" +
                "代理回复: " + delimiter + result + delimiter + "\n" +
                "\n" +
                "回复是否足够回答问题\n" +
                "如果足够,回答 Y\n" +
                "如果不足够,回答 N\n" +
                "仅回答上述字母即可";

        ChatMessage userMessage2 = new ChatMessage();
        userMessage2.setRole("user");
        userMessage2.setContent(checkUserMessage);

        List<ChatMessage> checkMessage = Arrays.asList(
                systemMessage,
                userMessage2
        );
        String checkResult = this.getCompletionFromMessage(checkMessage, 0);

        log.info("第六步:模型评估该回答");

        if (checkResult.contains("Y")) {
            log.info("第七步:模型赞同了该回答.");

            return result;

        } else {
            log.info("第七步:模型不赞成该回答.");

            return "很抱歉,我无法提供您所需的信息。我将为您转接到一位人工客服代表以获取进一步帮助。";
        }

    }


    //从用户问题中抽取商品和类别
    public String findCategoryAndProductOnly(String userInput, String productsAndCategory) {

        String system = "您将获得客户服务查询。\n" +
                "    客户服务查询将使用" + delimiter + "字符分隔。\n" +
                "    输出一个可解析的Python列表,列表每一个元素是一个JSON对象,每个对象具有以下格式:\n" +
                "    'category': <包括以下几个类别:Computers and Laptops,Smartphones and Accessories,Televisions and Home Theater Systems,Gaming Consoles and Accessories,Audio Equipment,Cameras and Camcorders>\n" +
                "    以及\n" +
                "    'products': <必须是下面的允许产品列表中找到的产品列表>\n" +
                "\n" +
                "    其中类别和产品必须在客户服务查询中找到。\n" +
                "    如果提到了产品,则必须将其与允许产品列表中的正确类别关联。\n" +
                "    如果未找到任何产品或类别,则输出一个空列表。\n" +
                "    除了列表外,不要输出其他任何信息!\n" +
                "\n" +
                "    允许的产品以JSON格式提供。\n" +
                "    每个项的键表示类别。\n" +
                "    每个项的值是该类别中的产品列表。\n" +
                "    允许的产品: " + productsAndCategory;


        List<ChatMessage> messages = new ArrayList<>();

        ChatMessage systemMessage = new ChatMessage();
        systemMessage.setRole("system");
        systemMessage.setContent(system);
        messages.add(systemMessage);

        ChatMessage userMessage = new ChatMessage();
        userMessage.setRole("user");
        userMessage.setContent(delimiter + userInput + delimiter);
        messages.add(userMessage);

        return this.getCompletionFromMessage(messages, 0, 600);

    }


    //检查GPT返回结果中的商品应该是存在于商品列表中的
    public Boolean checkProducts(String categoryAndProductResponse) {
        return true;
    }

测试:

        String result = processUserMessageCh("请告诉我关于 smartx pro phone 和 the fotosnap camera 的信息。另外,请告诉我关于你们的tvs的情况。", new ArrayList<>());

        log.info("result: {}", result);

输出结果:

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

关于SmartX Pro手机和FotoSnap相机的信息如下:

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

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

我们还有其他类型的相机可供选择,如无反相机和摄像机。您对这些产品有兴趣吗?如果有,请告诉我您对哪种类型的相机或摄像机感兴趣,我可以为您提供更多信息。

通过监控系统在更多输入上的质量,您可以修改步骤,提高系统的整体性能。 也许我们会发现,对于某些步骤,我们的提示可能更好,也许有些步骤甚至不必要,也许我们会找到更好的检索方法等等。

我们将在下一章中进一步讨论这个问题。

Java快速转换到大模型开发:
配套课程的所有代码已经发布在:https://github.com/Starcloud-Cloud/java-langchain
课程合作请留言

你可能感兴趣的:(Java-LangChain,java,langchain,chatgpt)