掘金 人工智能 06月04日 16:08
关于 AI 应用的前端具体实践
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文分享了作者在AI校招小程序开发中的实践经验,主要围绕前端技术栈、对话渲染、消息通信以及自定义标签的使用展开。作者详细介绍了使用Vue 3、uni-app、WebSocket等技术构建小程序的过程,并针对对话内容中的特殊渲染需求,提出了自定义标签的解决方案。此外,文章还探讨了如何通过z-paging优化对话列表的性能,以及在实现引用文献和思链/思考动作功能时遇到的问题及解决方法,为类似项目的开发者提供了宝贵的参考。

💡**技术选型与架构**:作者选择Vue 3、uni-app和WebSocket作为前端技术栈,构建校招求职小程序。使用z-paging库实现聊天记录模式+虚拟列表,优化了大量历史对话场景下的用户体验,并采用WebSocket技术确保消息的及时收发,保证了聊天的流畅性。

🏷️**自定义标签的运用**:为了处理AI对话中需要特殊渲染的模板、视频、链接、推荐问题等内容,作者提出使用固定格式的自定义标签,例如``,与后端约定,并通过正则表达式匹配和单独渲染样式的方式,实现了对自定义内容的灵活处理,解决了直接渲染HTML的局限性。

📚**引用文献功能的实现**:作者通过自定义标签实现引用文献功能,并使用CSS动画进行视觉呈现。由于mp-html不支持复杂的CSS动画,作者采用正则表达式匹配标签,并将引用文献属性添加到消息对象中,从而单独渲染一个view组件来处理,解决了CSS动画无法直接应用的问题。

🧠**思链/思考动作的实现**:相对于引用文献功能,思链/思考动作的实现更为简单,主要依赖自定义标签和简单的CSS修饰。作者特别提到需要处理通过WebSocket通信时,先返回部分自定义标签的情况,并给出了缓存和正则表达式判断的解决方案,确保了功能的完整性和稳定性。

前言

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

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

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

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

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

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

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

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

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

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

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

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

 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; },
@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 通信时先返回部分自定义标签的情况(缓存 + 正则表达式判断)。

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

AI应用 小程序开发 Vue 3 uni-app WebSocket
相关文章