关于 AI 应用的前端具体实践

前言

本人目前就职于一家 AI 应用落地的初创公司,做了一些 AI 应用实际落地的相关开发,接下来我就分享一下我对这个方向的一些心得。

我们目前主要实现的是一款以对话为主要形式的校招求职小程序,前端的技术栈主要是 Vue 3 + uni-app + WebSocket。

因为对话涉及到渲染 Markdown 文本和 HTML 文本,直接渲染 HTML 不太合适,尝试过使用 rich-text 标签,效果也不理想,所以还使用了 mp-html。尽管如此,遇到一些需要深入自定义渲染样式的情况还是有些麻烦,会在下文中一一阐述。

聊天场景一些涉及到的功能点

对于对话列表,我们采用了 z-paging 这个库,使用了聊天记录模式 + 虚拟列表,保证在大量历史对话的场景下,能保证使用体验的顺畅。

对于消息通信,我们使用了 WebSocket 技术,确保消息收发及时,聊天顺畅。

关于 AI 对话中的自定义标签

后端给过来的数据,有一些是需要做特殊渲染的,比如一些模板、视频、链接、推荐问题等。 这些有的可以约定一个新字段来做区分。但是如果这些需要特殊渲染的部分和正文是互相穿插的,新字段的方式就不太好用了。 这时候就可以和后端约定,使用固定格式的标签:

html 复制代码
<p>test</p>
<AICD type="toPage" url="/pages/chat/index">跳转聊天列表</AICD>
<p>test</p>

引用文献/资料功能的实现

也是通过自定义标签来实现,大体是约定固定标签,然后单独渲染样式,再做一个一直闪烁的 CSS 动画。

在实现的时候遇到了一个问题,无法为自定义标签添加 CSS 动画,因为 mp-html 不支持太复杂的 CSS。 所以我用正则表达式匹配到固定标签,向 msg 对象中添加引用文献属性,在渲染时,如果有引用文献属性,则单独渲染一个 view 组件来处理。

js 复制代码
 handleContentThinkingAction(msg) {
   // 如果存在缓存,将新内容添加到缓存中
   if (this.taCache) {
     this.taCache += msg.content;

     // 检查缓存是否包含完整的 TA 标签
     if (this.taCache.includes('</TA>')) {
       // 尝试匹配完整的 TA 标签
       const taMatch = this.taCache.match(/<TA\s+max="(\d+)"\s+min="(\d+)">(.*?)<\/TA>/);
       if (taMatch) {
         const [_, max, min, text] = taMatch;
         msg.data.thinkingAction = {
           text: text,
           max: parseInt(max),
           min: parseInt(min)
         };
         // 移除 TA 标签部分,保留其他内容
         msg.content = this.taCache.replace(/<TA.*?<\/TA>/, '').trim();
         // 清除缓存
         this.taCache = '';
       } else {
         // 如果匹配失败,说明标签可能不完整,继续等待
         msg.content = '';
       }
     } else {
       // 如果缓存中还没有完整的 TA 标签,清空当前消息的 content
       msg.content = '';
     }
     return msg;
   }

   // 检查当前消息是否包含 TA 标签的开始
   if (msg.content) {
     // 如果当前消息包含完整的 TA 标签
     if (msg.content.includes('<TA') && msg.content.includes('</TA>')) {
       const taMatch = msg.content.match(/<TA\s+max="(\d+)"\s+min="(\d+)">(.*?)<\/TA>/);
       if (taMatch) {
         const [_, max, min, text] = taMatch;
         msg.data.thinkingAction = {
           text: text,
           max: parseInt(max),
           min: parseInt(min)
         };
         msg.content = msg.content.replace(/<TA.*?<\/TA>/, '').trim();
       }
     }
     // 如果只包含 TA 标签的开始部分
     else if (msg.content.includes('<TA') || msg.content.includes('<T')) {
       // 将内容存入缓存
       this.taCache = (this.taCache || '') + msg.content;
       msg.content = '';
       // 清空 currentContent,因为这部分内容不应该显示
       this.currentContent = '';
     }
   }

   return msg;
 },
css 复制代码
@keyframes text-highlight {
  0% {
    background-position: 100% 0;
  }
  100% {
    background-position: -100% 0;
  }
}

.thinking-action {
  color: #888;
  font-size: 26rpx;
  padding-bottom: 15rpx;
  background: linear-gradient(90deg, 
    #888 0%, 
    #000 20%, 
    #000 30%, 
    #888 50%, 
    #888 100%
  );
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  background-size: 200% 100%;
}

思链/思考动作

相对于引用文献功能来说就更简单些,自定义标签 + 简单的 CSS 修饰即可,但是要处理通过 WebSocket 通信时先返回部分自定义标签的情况(缓存 + 正则表达式判断)。

相关推荐
哈__1 分钟前
CANN: AI 生态的异构计算核心,从架构到实战全解析
人工智能·架构
hedley(●'◡'●)21 分钟前
基于cesium和vue的大疆司空模仿程序
前端·javascript·vue.js·python·typescript·无人机
qq5_81151751523 分钟前
web城乡居民基本医疗信息管理系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】
前端·vue.js·spring boot
百思可瑞教育24 分钟前
构建自己的Vue UI组件库:从设计到发布
前端·javascript·vue.js·ui·百思可瑞教育·北京百思教育
百锦再24 分钟前
Vue高阶知识:利用 defineModel 特性开发搜索组件组合
前端·vue.js·学习·flutter·typescript·前端框架
七牛云行业应用33 分钟前
Moltbook一夜崩盘:150万密钥泄露背后的架构“死穴”与重构实战
网络安全·postgresql·架构·高并发·七牛云
塔中妖1 小时前
CANN深度解读:从算子库看AI计算的底层架构
人工智能·架构
CappuccinoRose1 小时前
JavaScript 学习文档(二)
前端·javascript·学习·数据类型·运算符·箭头函数·变量声明
这儿有一堆花1 小时前
Vue 是什么:一套为「真实业务」而生的前端框架
前端·vue.js·前端框架
全栈前端老曹1 小时前
【MongoDB】深入研究副本集与高可用性——Replica Set 架构、故障转移、读写分离
前端·javascript·数据库·mongodb·架构·nosql·副本集