字节青训营前端LLM项目实践 | 豆包MarsCode AI刷题

779 阅读3分钟

项目背景

当前大模型应用如火如荼,最常见的交互模式就是对话框模式,因此作为用户对话交互的核心,前端界面的开发显得尤为重要。这种模式下,出现了ChatGPT、Claude、Coze等常见LLM对话应用。

本次青训营的前端项目就是要求我们设计一个LLM对话框。本项目基于以上情景,借着青训营提供的宝贵机会进行了开发和探索,这个项目对我个人的技术成长追求也是一大帮助。项目还有很多功能和bug没有完善,后面我会一直维护它,也欢迎大家找我一起交流。

核心功能

技术栈:Vue3、Coze API、Element-plus、Sass、Vite、hljs、markdown-it等

1、组件能力

  • 能够支持用户输入对话,且对话内容支持图片、pdf等多媒体格式

image.png

  • 能够显示大模型返回的执行结果,包括图片、markdown等格式内容

img_v3_02h3_e8315b24-e5eb-4c83-998a-d13d8d5dc3fg.jpg

  • 支持流式打印返回结果
  • 支持代码高亮和复制

img_v3_02gp_bc08a742-c925-4f70-b7b3-6b3886a72e0g.jpg

2、内联模式

  • 支持表现为收缩状态的搜索框

image.png

  • 支持表现为展开形态的聊天弹框

image.png

  • 支持在聊天弹框内与LLM交互

image.png

3、对话框模式

与内联模式窗口的对话功能相同,目前待完成的是创建会话功能,组件应该布局在侧边栏处,以显示多个聊天会话。

实践技术特征

项目布局

image.png

1、Coze-js API的使用

github.com/coze-dev/co…

Coze-js基于axios将与Coze API相关的http请求和接收内容进行了接口封装,我在使用中只需要调用相关JS的API即可。

首先是创建客户端:

const client = new CozeAPI({
    token: CozeConfig.token,
    allowPersonalAccessTokenInBrowser: true,
    baseURL: COZE_CN_BASE_URL,
});

token需要写成自己在coze官网的个人token,也有其它的auth方式,比如JWT等。

随后是创建一个流式对话:

const v = await this.client.chat.stream({
                bot_id: 'CozeConfig.bot_id',
                user_id: 'CozeConfig.user_id',
                auto_save_history: true,
                additional_messages: additional_messages,
                conversation_id: this.conversation_id,
            });

注意这里的additinal_messages是一个数组类型的对象,形式如下:

  • 多模态对话
additional_messages = [{
                    role: 'user',
                    content: JSON.stringify([
                        { type: 'file', file_id: this.fileID },
                        { type: 'text', text: message },
                    ]),
                    content_type: 'object_string',
                }];
  • 仅文本对话
additional_messages = [{
                    role: 'user',
                    content: message,
                    content_type: 'text',
                }];

coze模型的处理结果会包含在变量v中,如果是流式结果,那么需要foreach来遍历结果,并把结果储存到消息数组中。

this.chatMessages.push({ content: '', isUserMessage: false });
            for await (const part of v) {
                if (part.event === ChatEventType.CONVERSATION_MESSAGE_DELTA) {
                    this.chatMessages[this.chatMessages.length - 1].content += part.data.content.replace(/\[/, '![');
                    this.conversation_id = part.data.conversation_id;
                    this.scrollToBottom(); //滚动到最新消息的视图
                }
                if (part.event === ChatEventType.CONVERSATION_CHAT_FAILED) {
                    console.error('Chat failed');
                }
                if (part.event === ChatEventType.CONVERSATION_ENDED) {
                    console.log('Conversation ended');
                    break;
                }
                if (part.event === ChatEventType.ERROR) {
                    console.error(part.error);
                    break;
                }
            }

这里的part.data.content.replace(/\[/, '![');的目的是为了在后续markdown解析的时候解析图片,因为markdown需要解析![图片描述]{url}形式的图片,

2、Element-plus的使用

基于Element-plus中的el-upload组件实现了图片、文件上传功能

3、代码高亮

基于hljs实现

4、markdown格式图文展示

基于markdown-it将聊天信息渲染为html

TODO

  1. 完善上述文档,详细描述技术实现
  2. 完善创建会话功能
  3. 以提高用户体验为目的,完善相关操作按钮和美化样式。
  4. 以提高开发效率为目的,完善开发工程化和技术工具引入。

最后

欢迎青训营的同学一起探讨前端技术、LLM对话框项目,有兴趣可以私信或者评论区留言。