AIGC: 关于ChatGPT中实现一个聊天机器人

规划一个聊天机器人

  • 智能化完全于依托于GPT, 而产品化是我们需要考虑的事情
  • 比如,如何去构建一个聊天机器人
  • 聊天机器人它的处理逻辑其实非常的清晰
    • 我们输入问题调用 GPT
    • 然后,GPT 给我们生成回答就可以了
  • 需要注意的是,聊天机器人不同于调用API进行一个简单的测试
  • 我们和聊天机器人的对话,可能是多轮的一个对话
  • 在这时候,我们去调用API的时候,就需要将我们多轮的问答都传递给GPT才行

新增一些实现类,结构如下

  • 以下Java版代码来源于网络,可基于此逻辑,改造成其他编程语言

  • src

    • main
      • java
        • com.xxx.gpt.client
          • util
            • ChatContextHolder.java
          • ChatBotClient.java
    • test
      • java
        • com.xxx.gpt.client.test
          • FunctionCallTest.java

ChatContextHolder.java

package com.xxx.gpt.client.util;import com.xxx.gpt.client.entity.Message;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class ChatContextHolder {private static Map<String, List<Message>> context = new HashMap<>();public static List<Message> get(String id) {// TODO  限制轮数,或者限制token数量List<Message> messages = context.get(id);if (messages == null) {messages = new ArrayList<>();context.put(id, messages);}return messages;}public static void add(String id, String msg) {Message message = Message.builder().content(msg).build();add(id, message);}public static void add(String id, Message message) {List<Message> messages = context.get(id);if (messages == null) {messages = new ArrayList<>();context.put(id, messages);}messages.add(message);}public static void remove(String id) {context.remove(id);}
}
  • 这里需要来添加一个类,就是我们GPT的上下文的类
  • 我们创建一个类,用于保存我们和GPT聊天的相关的 message
    • 实例化一个Map的对象, 里面的 key 是我们chat的一个id, 一个会话的id
    • 然后,对应的这个key就会有它的一个消息的列表,也就是一个message的list
    • 添加相关的方法
      • 比如说像get方法,根据我们的会话id,获取到所有的message
      • add方法,去对指定的会话id去添加message
      • remove方法, 去删除message
    • 这是我们的上下文处理的类

ChatBotClient.java

package com.xxx.gpt.client;import com.xxx.gpt.client.entity.Message;
import com.xxx.gpt.client.listener.ConsoleStreamListener;
import com.xxx.gpt.client.util.ChatContextHolder;
import com.xxx.gpt.client.util.Proxys;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;@Slf4jpublic class ChatBotClient {public static Proxy proxy = Proxy.NO_PROXY;public static void main(String[] args) {System.out.println("ChatGPT - Java command-line interface");System.out.println("Press enter twice to submit your question.");System.out.println();System.out.println("按两次回车以提交您的问题!!!");String chatUuid = UUID.randomUUID().toString();String key = "sk-adfas";proxy = Proxys.http("127.0.0.1", 7890);while (true) {String prompt = getInput("\nYou:\n");ChatGPTStreamClient chatGPT = ChatGPTStreamClient.builder().apiKey(key).proxy(proxy).build().init();System.out.println("AI: ");// 卡住CountDownLatch countDownLatch = new CountDownLatch(1);Message message = Message.of(prompt);ChatContextHolder.add(chatUuid, message);ConsoleStreamListener listener = new ConsoleStreamListener() {@Overridepublic void onError(Throwable throwable, String response) {throwable.printStackTrace();countDownLatch.countDown();}};listener.setOnComplate(msg -> {ChatContextHolder.add(chatUuid, Message.ofAssistant(msg));countDownLatch.countDown();});chatGPT.streamChatCompletion(ChatContextHolder.get(chatUuid), listener);try {countDownLatch.await();} catch (InterruptedException e) {e.printStackTrace();}}}@SneakyThrowspublic static String getInput(String prompt) {System.out.print(prompt);BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));List<String> lines = new ArrayList<>();String line;try {while ((line = reader.readLine()) != null && !line.isEmpty()) {lines.add(line);}} catch (IOException e) {e.printStackTrace();}return lines.stream().collect(Collectors.joining("\n"));}
}
  • 它的实现其实也比较简单
    • 第一步,需要等待用户输入,用户输入完成之后,调用GPT
      • 添加一下相关的我们的 API KEY 和 proxy
      • getInput 去接收用户输入
    • 第二步,需要保存多轮会话
      • 我们是多轮会话,我们这里写一个循环在前面
      • chatUuid 是我们用于标识会话的id
    • 第三步,为了效果更好,更加顺畅,采用流式的方式
      • 创建一个 StreamClient 去调用GPT的 API
      • 调用完成进行输出

测试

  • 完成之后,可以测试一下
    • 程序等待我们的输出,我们去询问一下: “你是谁?”
    • 这里需要敲两次回车进行确认
  • 调用之后,我们获取到了 GPT 它的返回的结果
    • 然后,我们问: “请介绍一下ChatGPT”
    • GPT生成了相关的答案
  • 在这次问答当中,也能看到流式Client的一个效果
  • 整体上和我们通过界面去访问GPT是没有什么区别的
  • 假如说,我们现在再问: “这是我的第几个问题?”
    • 理论上讲,这是我们本轮会话的第三个问题
    • 由于我们没有在刚刚的调用里面, 去关联我们会话上下文的信息
    • 这样,GPT会回答: “这是第3个问题”
  • 将会话的上下文信息传递给 GPT, 就可以去结合这些上下文的信息,给予我们比较精确的一个答案
    • 这是我们在构造一个聊天机器人的时候和前面测试所不一样的,需要我们注意的地方
    • 但是在这里,其实就会有一个问题就是token的问题。
    • GPT它的模型对于 token 是有限制的
  • 如果我们一轮轮会话的叠加,最终我们的token, 一定会超过模型它本身的token
    • 所以在上下文的管理类里面,我们这里是需要去进行处理
  • 上述问题如何处理?
    • 方案一就是保留最近一轮的会话轮数,比如只保留最近五轮
      • 对于历史的消息,不再保存,不再发送给GPT这样,可以达到小于指定token数量的目的
      • 但是当我们一轮的消息比较长的话,也有可能会超过token的阈值
    • 方案二,就是在方案一的基础之上,我们不再以单纯会话的轮数去做一个迭代
      • 这里,根据计算后的token的数量,去进行判断
      • 如果小于模型的 max_token,我们就保留相关的这些会话
      • 如果大于,我们就要去做相关消息的一个删减
    • 目前并未实现,可在上述 ChatContextHolder.java 类中进行实现

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/206411.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT----自定义信号和槽

第二天 2.1自定义信号和槽 新建一个Qtclass 自定义信号&#xff1a;返回值是void &#xff0c;只需要声明&#xff0c;不需要实现&#xff0c;可以有参数&#xff0c;可以重载 自定义槽&#xff1a;返回值void &#xff0c;需要声明&#xff0c;也需要实现&#xff0c;可以有…

学习设计模式的一个好网址

常用设计模式有哪些&#xff1f; (refactoringguru.cn)https://refactoringguru.cn/design-patterns

网神SecGate 3600防火墙 app_av_import_save接口任意文件上传漏洞复现 [附POC]

文章目录 网神SecGate 3600防火墙 app_av_import_save接口任意文件上传漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现0x06 修复建议网神SecGate 3600防火墙 app_av_import_save接口任意文件上传漏洞复现 [附PO…

如何处理3dmax渲染完成后阴影部分?

使用3dmax软件&#xff0c;对效果图进行渲染过程中&#xff0c;有不少小伙伴&#xff0c;在渲染完成后出现问题。 较为常见的3dmax渲染问题有3dmax渲染有阴影&#xff1f; 对于一些新手伙伴遇到这类问题&#xff0c;不知如何解决&#xff0c;就会苦恼3dmax渲染有阴影怎么办&am…

Java可变参数:让函数接受任意数量的参数

介绍 可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了方法的参数类型已经确定,个数不确定我们可以使用可变参数 可变参数定义格式 修饰符 返回值类型 方法名(数据类型… 变量名){} 注意事项 这里的变量其实是一个数组如果一个方法有多个参数,包…

【实战oj题】——相同的树及二叉树的最大深度

前言&#xff1a;二叉树是我们数据结构中一个比较重要的内容&#xff0c;它的oj题自然也就很多类型&#xff0c;那么我们今天就来解决二叉树中的oj题——相同的树。 这个题我们就得分情况了&#xff0c;如果两个树的根节点都为空的话&#xff0c;那么两棵树就会相等&#xff0c…

如何在Go中定义和调用函数

引言 函数是一段一旦定义就可以重用的代码。函数将代码分解成小的、可理解的任务,使其在程序中可以多次使用,从而使代码更容易理解。 Go附带了一个强大的标准库,其中有许多预定义的函数。你可能已经从fmt包中熟悉了以下内容: fmt.Println(),它将打印对象到标准输出(最有可…

西南科技大学C++程序设计实验十一(泛型程序设计与C++标准模板库)

一、实验目的 1. 掌握泛型程序设计概念; 2. 掌握vector、deque、list容器使用方法; 3.了解set、map容器使用方法。 二、实验任务 1.分析完善以下程序,理解vector容器使用方法: #include <iostream> __#include <vector>_______ //补充vector模板头文件 …

【开源】基于Vue.js的学生综合素质评价系统

文末获取源码&#xff0c;项目编号&#xff1a; S 086 。 \color{red}{文末获取源码&#xff0c;项目编号&#xff1a;S086。} 文末获取源码&#xff0c;项目编号&#xff1a;S086。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 学生功能2.2 教师功能2.3 教务处功能…

YB4052 充满电压可调SOT23有防反接功能的线性锂离子电池充电芯片

YB4052 充满电压可调SOT23有防反接功能的线性锂离子电池充电芯片 描述&#xff1a; YB4052是一款完整的单节钾高子申池采用恒定申流恒定申乐线件充电器。其S0T封装与较少的外部元件数目使得B4052成为便携式应用的理想洗择。YB4052可以话合SB申源和活配器电源工作。由于采用了…

tomcat反序列化

漏洞介绍: 漏洞名称: Apache Tomcat反序列化漏洞影响范围: Apache Tomcat服务器中使用了自带session同步功能的配置,且没有使用Encrypt Interceptor加密拦截器的情况下。漏洞描述: Apache Tomcat是一个基于Java的Web应用软件容器,用于运行servlet和JSP Web应用。当Tomc…

深度解读 | 搭载谷歌最强大模型Gemini的Bard能否赶上ChatGPT

大家好&#xff0c;我是极智视界&#xff0c;欢迎关注我的公众号&#xff0c;获取我的更多前沿科技分享 昨天早上看到了相关的报道&#xff0c;谷歌昨天发布了 "号称最强的大模型" Gemini&#xff0c;还是熟悉的字眼、还是熟悉的配方。之前谷歌一直在 AIGC 的竞争相…

CentOS或RHEL安装code-server(vscode-web)

下载rpm安装包 网络下载或者下载到本地再上传到服务器&#xff0c;点击访问国内下载地址&#xff0c;不需要积分curl -fOL https://github.com/coder/code-server/releases/download/v4.19.1/code-server-4.19.1-amd64.rpm安装 rpm -i code-server-4.19.1-amd64.rpm关闭和禁用…

AESDES加解密脚本

库函数的默认输入和输出都是byte格式&#xff0c;如果是hex可以用long_to_bytes转化一下有偏移量加解密加iv参数即可 AES加密 AES的明文分组长度为128位&#xff08;16字节&#xff09;&#xff0c;即明文长度需为16的倍数【不进行填充的情况下】密钥长度可以为128位&#xf…

OpenCV-Python:随机数与随机颜色

目录 Python中随机数 OpenCV-Python随机数 随机颜色的生成 随机噪声生成 代码练习与测试 知识笔记 Python中随机数 在Python中&#xff0c;我们可以使用random模块来生成随机数。random模块提供了一系列的函数来生成不同类型的随机数。以下是一些常用的随机数生成函数&…

案例精选|聚铭网络助力莱阳市人民医院打造合规性网络安全保障体系

莱阳市人民医院是一所集医疗、教学、科研、急救、康复、医养结合于一体的大型二级甲等综合性公立医院&#xff0c;占地总面积约3万平方米&#xff0c;建筑面积约7万平方米&#xff0c;设置科室48个&#xff0c;开放床位500张。医院先后获得山东省首批医养结合典型、山东省卒中防…

2024年江苏省职业院校技能大赛信息安全管理与评估 第二阶段学生组(样卷)

2024年江苏省职业院校技能大赛信息安全管理与评估 第二阶段学生组&#xff08;样卷&#xff09; 竞赛项目赛题 本文件为信息安全管理与评估项目竞赛-第二阶段样题&#xff0c;内容包括&#xff1a;网络安全事件响应、数字取证调查、应用程序安全。 本次比赛时间为180分钟。 …

MySQL数据库从小白到入门(二)

多表关系&#xff1a; 项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;分析并设计表结构。由于业务之间相互关联&#xff0c;所以各个表结构之间也存在着各种联系&#xff0c;基本上分为三种。 外键&#xff1a; 创…

批量AI人工智能写作软件下载【2024最新】

在当今数字化的浪潮中&#xff0c;人工智能技术为各行各业带来了颠覆性的变革。其中&#xff0c;AI在文案创作领域的应用尤为引人瞩目&#xff0c;而批量AI人工智能写作更是成为文案创作者们关注的热点。本文将深入探讨批量AI人工智能写作的概念、其在不同领域的应用&#xff0…

【Flink系列二】如何计算Job并行度及slots数量

接上文的问题 并行的任务&#xff0c;需要占用多少slot &#xff1f;一个流处理程序&#xff0c;需要包含多少个任务 首先明确一下概念 slot&#xff1a;TM上分配资源的最小单元&#xff0c;它代表的是资源&#xff08;比如1G内存&#xff0c;而非线程的概念&#xff0c;好多…