【小程序】聊天功能

文章目录

    • 聊天功能
      • 实现功能
      • 实现思路
      • 后端
      • 前端
      • 效果展示

聊天功能

实现功能

要实现一个聊天机器人,它能够解答用户疑问,并且能够识别到用户聊天的主题,涉及到饮食方面时,会自动决定是否要去数据库中读取用户的相关喜好信息,以实现自动化。同时,还要支持重新生成、复制回答、同时生成两条文本让用户选择以优化模型回复。同时还要对每次的会话进行管理。

实现思路

主要思路就是要将用户输入传给模型,模型予以解答。

主要实现的功能和解决的问题:

  1. 需要维护一个history来存储聊天记录。
  2. 实现打字机效果。
  3. 消息正在生成时,发送按钮变成灰色图片并禁止点击。
  4. 解决输入法弹起后输入框自动调整高度以避免被遮挡问题。
  5. 解决输入法弹起后,顶部导航栏不会上移。
  6. 实现文本的复制功能。
  7. 实现重新生成功能,如果不是最后一条消息,则要删掉该会话中要重新生成的消息后面的所有消息。
  8. 实现同时生成两种回答,让用户选择更喜欢哪种回答。然后选择后,后续回答风格会按照用户选择的那条来回答。
  9. 解决如果用户没有选择哪种回答,就进行发送下一条消息、切换页面、切换会话等操作,则会自动选择详细版的哪种风格。
  10. 实现会话的增加,要求当前会话没有聊天记录时,不会创建会话,只有发送了至少一条聊天记录,才会新增到数据库。同时,当前会话没有聊天记录时,前端会话新增按钮要禁用,即不能再次创建一个新的会话窗口。
  11. 实现会话的删除,使用滑动框,左滑删除。弹出提示框,询问是否删除。并且要解决uview滑动框组件的bug,即删除一个后,该删除状态不会自动消失,还是打开的状态。
  12. 会话列表要实现按照今天、昨天和更早以前进行分组。

后端

由于后端代码很多,只截取片段展示。

def chat_response(query, user_info, session_id=None, history=None, is_chat=None, response_type=None):
    if user_info is None:
        return "无法找到用户信息,请检查用户ID是否正确。"
    
    if session_id is None and is_chat == "1":
        session_id = create_session(user_info['user_id'])
        
    if is_chat == "1":
        is_food_topic = is_food_related_topics(query)
        print("用户输入是否是食物相关主题:" + is_food_topic)
    
        if is_food_topic == "true":
            emotions = get_user_emotions(user_info['user_id'])
            emotions_str = ", ".join([f"{e['emotion']}{e['food']}" for e in emotions])
            user_info_str = f"疾病: {user_info['diseases']}, 喜好的食物: {user_info['likes']}, 忌口的食物: {user_info['dislikes']}, 其他喜恶: {emotions_str}"

            personalized_prompt = f"{query}\n用户信息: {user_info_str}"

            print("\n============= info_prompt ===============\n")
            print(personalized_prompt)

            # 提取用户对食物的情感,并存到数据库中
            extract_emotions_about_food(query, user_info)
           
        else:
            personalized_prompt = f"{query}"
            
            print("\n============= no_info_prompt ===============\n")
            print(personalized_prompt)
        
        store_message(session_id, 'user', query)

        # 检查用户提问的数量
        messages = get_session_messages(session_id)
        user_messages = [msg for msg in messages if msg['role'] == 'user']
        if len(user_messages) == 3:
            # 获取前三条用户提问生成标题
            summary_prompt = "\n".join([msg['content'] for msg in user_messages])
            title, _ = p_model.chat(tokenizer, f"请总结以下对话主题,不超过10个字,只输出一行,不要有换行:\n{summary_prompt}", top_p=1, temperature=0.01)
            title = title.strip()
            update_session_title(session_id, title)

        print("history\n")
        print(history)
    
        if response_type == "detailed":
            prompt = f"详细(100字以上)回答:\n{personalized_prompt}"
        elif response_type == "concise":
            prompt = f"简洁(50字以内)回答:\n{personalized_prompt}"
        else:
            prompt = personalized_prompt
        
    else:
        prompt = f"{query}"

        print("\n============= not_chat_prompt ===============\n")
        print(prompt)

    
    response, _ = p_model.chat(tokenizer, prompt, history=history, top_p=1, temperature=0.01)
    
    if is_chat == "1":
        message_id = store_message(session_id, 'system', response)  # 存储消息并返回消息ID
        return response, session_id, message_id

    return response

前端

由于前端代码太多,只截取部分代码展示。

async sendMessage() {
        if (this.userInput.trim() !== '' && !this.isTyping) {
          // 检查是否需要自动选择详细版
          if (this.showChoice) {
            await this.autoChooseDetailed(); // 等待自动选择详细版完成
          }
    
          this.messageList.push({
            role: 'user',
            content: this.userInput,
            avatar: 'https://xxx/avatar.png'
          });
          const query = this.userInput;
          this.userInput = '';
    
          // 添加ChatGPT的占位消息
          const loadingMessage = {
            role: 'chatgpt',
            content: '',
            avatar: 'https://xxx/chatai-avatar.png',
            isLoading: true
          };
          this.messageList.push(loadingMessage);
          this.handleScrollTop(); // 确保视图滚动到底部
    
          let that = this;
          this.isTyping = true;
          uni.request({
            url: 'https://xxx/chat',
            method: 'POST',
            data: { query, history: this.history, user_id: this.userId, session_id: this.currentSessionId },
            header: {
              'Content-Type': 'application/json',
            },
            success: function (resp) {
              that.currentSessionId = resp.data.session_id;
              const index = that.messageList.indexOf(loadingMessage);
              if (index !== -1) {
                that.messageList.splice(index, 1); // 删除占位消息
    
                if (resp.data.detailed_response && resp.data.concise_response) {
                  // 第四次对话,展示两个回答框
                  that.conciseResponse = resp.data.concise_response;
                  that.detailedResponse = resp.data.detailed_response;
                  that.showChoice = true; // 设置 showChoice 为 true
                  console.log("showChoice")
                  console.log(that.showChoice)
                  // 插入提示语
                  that.messageList.push({
                    role: 'system',
                    content: '请选择您更喜欢哪种回答?',
                    avatar: '',
                    isTypingComplete: true,
                    responseType: 'prompt'
                  });
                  // 分别为精简版和详细版添加打字机效果
                  that.addTypingEffect('ChatGLM3-6B', resp.data.concise_response, resp.data.concise_message_id, 'concise', true);
                  that.addTypingEffect('ChatGLM3-6B', resp.data.detailed_response, resp.data.detailed_message_id, 'detailed', false);
                } else {
                  that.addTypingEffect('ChatGLM3-6B', resp.data.response, resp.data.message_id);
                }
              }
              that.history.push({ role: 'user', content: query });
              if (that.history.filter(msg => msg.role === 'user').length === 1 || that.history.filter(msg => msg.role === 'user').length === 3) {
                that.refreshSessionList();
              }
            },
            fail: function (error) {
              console.error('Error sending message:', error);
            },
            complete: function() {
              that.isTyping = false;
            }
          });
        }
      },
      addTypingEffect(user, text, messageId, responseType = null, showAvatar = true) {
          if (!text) {
            console.error('Error: text is undefined or empty');
            return;
          }
          
          let index = 0;
          const message = { 
            role: 'chatgpt',
            content: '',
            avatar: showAvatar ? 'https://xxx/chatai-avatar.png' : 'https://xxx/0b46f21fbe096b63d30f4b590d338744ebf8aca0.png',
            id: messageId,
            isLoading: false,
            isTypingComplete: false, // 新变量,初始化为 false
            responseType: responseType // 添加 responseType
          };
          this.messageList.push(message);
      
          const typing = setInterval(() => {
            if (index < text.length) {
              message.content += text[index];
              index++;
              this.handleScrollTop().catch((error) => {
                console.warn('Error while scrolling:', error);
              });
            } else {
              clearInterval(typing);
              this.history.push({ role: 'assistant', content: text });
              message.isLoading = false; // 设置为不再加载
              this.$set(message, 'isTypingComplete', true); // 打字机效果完成后设置为 true
			  this.handleScrollTop().catch((error) => {
			            console.warn('Error while scrolling:', error);
			          }); // 确保滚动到最底部
            }
          }, this.typingInterval);
        },

效果展示

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

录音怎么转文字更高效?5款软件带你轻松拿捏文本转换~

临近大学生们最难熬的期末考试周&#xff0c;如何在短时间内复习完所有必考的科目也就成为大家迫在眉睫的首要任务。 想要在复习的过程中&#xff0c;更加高效地捕捉和整理关键信息、提高学习效率&#xff0c;那么录音转文字免费应用无疑是你的一大好帮手&#xff01; 倘若你…

YOLOv5改进 | SPPF | 具有多尺度带孔卷积层的ASPP【CVPR2018】

&#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 专栏目录&#xff1a; 《YOLOv5入门 改进涨点》专栏介绍 & 专栏目录 |目前已有40篇内容&#xff0c;内含各种Head检测头、损失函数Loss、…

设计模式5-策略模式(Strategy)

设计模式5-策略模式 简介目的定义结构策略模式的结构要点 举例说明1. 策略接口2. 具体策略类3. 上下文类4. 客户端代码 策略模式的反例没有使用策略模式的代码 对比分析 简介 策略模式也是属于组件协作模式一种。现代软件专业分工之后的第一个结果是框架语音应用程序的划分。组…

WEB界面上使用ChatGPT

&#xff08;作者&#xff1a;陈玓玏&#xff09; 开源项目&#xff0c;欢迎star哦&#xff0c;https://github.com/tencentmusic/cube-studio 随着大模型不断发展&#xff0c;现在无论写代码&#xff0c;做设计&#xff0c;甚至老师备课、评卷都可以通过AI大模型来实现了&…

【数据结构与算法】动态查找表(二叉排序树,二叉平衡树)详解

二叉排序树的数据结构。 struct TreeNode {ElemType data;TreeNode *left, *right; }; using BiTree TreeNode *;结构体包含三个成员&#xff1a; data 是一个 ElemType 类型的变量&#xff0c;用于存储二叉搜索树节点的数据。left 是一个指向 TreeNode 类型的指针&#xff…

【Pandas驯化-16】一文搞懂Pandas中高性能query、eval函数技巧

【Pandas驯化-16】一文搞懂Pandas中高性能query、eval函数技巧 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 相关内容文档获取 微信公众…

Linux命令学习2

一.文件基础命令 1.alias-给某个命令取别名 使用方式&#xff1a;alias cl ls -la 说明&#xff1a;将ls -la命令取别名为cl,使用这种方式只是临时将命令取别名&#xff0c;重启中断后&#xff0c;就会失效。 问题1&#xff1a;如何永久性的设置命令的别名&#xff1f; 答…

生命在于学习——Python人工智能原理(4.3)

三、Python的数据类型 3.1 python的基本数据类型 3.1.4 布尔值&#xff08;bool&#xff09; 在Python中&#xff0c;布尔值是表示真或假的数据类型&#xff0c;有两个取值&#xff0c;True和False&#xff0c;布尔值常用于控制流程、条件判断和逻辑运算&#xff0c;本质上来…

ONLYOFFICE 桌面编辑器 8.1全新发布,更强大的编辑工具

ONLYOFFICE 8.1 一、什么是ONLYOFFICE&#xff1f;二、怎么安装 ONLYOFFICE 8.1三、主要功能介绍四、总结 一、什么是ONLYOFFICE&#xff1f; ONLYOFFICE 是一款功能强大的办公套件&#xff0c;旨在提供全面的文档、表格和演示文稿编辑解决方案。它集成了文字处理、电子表格和演…

基于 Native 技术加速 Spark 计算引擎

本文整理自 2024 年 6 月 DataFunSummit 2024 OLAP 架构峰会 Lakehouse 湖仓一体化架构论坛的同名主题分享。 今天分享的主题是基于 Native 技术加速 Spark 计算引擎&#xff0c;大家将会了解到如何基于 ClickHouse 来改造 Spark 引擎&#xff0c;最终获得较为可观的性能提升。…

正则表达式以及文本三剑客grep、sed、awk

正则表达式匹配的是文本内容&#xff0c;文本三剑客都是针对文本内容。 grep&#xff1a;过滤文本内容 sed&#xff1a;针对文本内容进行增删改查 awk&#xff1a;按行取列 一、grep grep的作用使用正则表达式来匹配文本内容 1、grep选项 -m&#xff1a;匹配几次之后停止…

第10章 启动过程组 (启动过程组的重点工作)

第10章 启动过程组 10.3启动过程组的重点工作&#xff0c;在第三版教材第362~364页&#xff1b; 文字图片音频方式 第一个知识点&#xff1a;项目启动会议 1、作用 标志着对项目经理责权的定义结果的正式公布&#xff0c;通常由项目经理负责组织和召开。2、目的 使项目各…

2024 cicsn 西南赛区 半决赛

文章目录 前言mcmf结构定义添加边遍历邻接点示例场景解决步骤1. 初始化2. 应用SPFA找最小费用增广路径 3. 增广操作4. 终止条件 结果分析 逆向maincaldeladdedit 思路expvlunexp qeme启动不行保护逆向 题目给的脚本模版 前言 不能联网搜是真坐牢 本来想等着全写了再发的&#…

我终于毕业啦!

2024-6-24&#xff0c;星期一&#xff0c;19:21&#xff0c;天气&#xff1a;阴转小雨&#xff0c;心情&#xff1a;晴。大家好啊&#xff0c;“失踪人员”回归啦&#xff0c;整整断更了两周&#xff0c;这两周发生了很多事&#xff0c;第一件就是我的毕业答辩通过啦&#xff0…

python-题库篇-Python语言特性

文章目录 Python语言特性1 Python的函数参数传递2 Python中的元类(metaclass)3 staticmethod和classmethod4 类变量和实例变量5 Python自省6 字典推导式7 Python中单下划线和双下划线8 字符串格式化:%和.format9 迭代器和生成器10 *args and **kwargs11 面向切面编程AOP和装饰器…

Element 进度条样式优化

在开发后台管理系统时&#xff0c;经常会用到进度条这样一个控件&#xff0c;Element UI中提供了progress这样一个组件&#xff0c;如下图所示&#xff1a; 该组件默认的颜色会比较单一&#xff0c;为此时常需要对该组件的样式进行一些优化&#xff0c;以满足实际项目的需求。 …

【华为HCIA数通网络工程师真题-构建以太网交换网络】

华为HCIA数通网络工程师真题-构建以太网交换网络 一、1-10题 一、1-10题 1、如图所示&#xff0c;四台交换机都运行 STP&#xff0c;各种参数都采用默认值如果交换机C的G0/0/2端口发生阻塞并无法通过该端口发送配置 BPDU&#xff0c;则网络中 blocked 端口多久之后会进入到转发…

【Linux】动/静态库的创建和使用

目录 一、动/静态库的概念回顾&#xff1a; 二、动态库与静态库的区别&#xff1a; 三、静态库的创建与使用&#xff1a; 1、Linux静态库命名规则&#xff1a; 2、静态库的创建和使用&#xff1a; 四、动态库的创建与使用&#xff1a; 1、Linux动态库命名规则&#xff1…

Mac环境 aab包转apks,并安装apks

一、下载下载bundletool工具 Releases google/bundletool GitHub 二、将下载bundletool.jar包、aab、keystore文件全部放到同一个目录下 例如我全部放到download目录下 转换命令行&#xff1a; java -jar bundletool-all-1.16.0.jar build-apks --modeuniversal --bundle…

「全新升级,性能更强大——ONLYOFFICE 桌面编辑器 8.1 深度评测」

文章目录 一、背景二、界面设计与用户体验三、主要新功能亮点3.1 高效协作处理3.2 共同编辑&#xff0c;毫无压力3.3 批注与提及3.4 追踪更改3.5 比较与合并3.6 管理版本历史 四、性能表现4.1 集成 AI 工具4.2 插件强化 五、用户反馈与使用案例 一、背景 Ascensio System SIA -…