前端接入 AI 大模型流式接口实践
在现代 Web 开发中,集成人工智能大模型(LLM)已成为提升应用智能化水平的关键手段。传统的 RESTful API 通常返回完整的 JSON 响应,但在处理大模型生成内容时,这种模式会导致用户等待时间过长。采用流式传输(Streaming)技术,允许服务器将生成的文本分块实时推送给客户端,能显著提升用户体验。
本文将基于 Vue.js 框架,结合 @microsoft/fetch-event-source 库,详细讲解如何在前端实现与 AI 大模型的流式对话交互。我们将深入分析代码结构、状态管理、错误处理以及安全性优化,提供一套完整的生产级参考方案。
一、环境准备与依赖安装
在开始编码之前,需要确保项目已配置好基础环境。本项目基于 Vue 3 + Vite 构建。
1.1 核心依赖
除了基础的 Vue 生态外,我们需要引入以下关键库:
- fetch-event-source: 用于支持 POST 请求的 Server-Sent Events (SSE) 或类似流式协议。原生
EventSource仅支持 GET 请求且无法自定义 Header,因此该库是处理鉴权 POST 流式请求的首选。 - markdown-it: 用于将后端返回的 Markdown 格式文本渲染为 HTML,支持代码高亮、列表等富文本展示。
- axios (可选): 虽然本例使用 fetch,但项目中可能仍保留 axios 用于非流式请求。
安装命令示例:
npm install @microsoft/fetch-event-source markdown-it
1.2 环境变量配置
在 .env 文件中配置后端 API 的基础地址,避免硬编码:
VITE_APP_BASE_API=https://api.yourdomain.com
二、组件结构设计
一个典型的聊天界面包含欢迎区域、消息滚动容器、输入框和发送按钮。我们采用模块化思维设计 Vue 单文件组件(SFC)。
2.1 模板层 (Template)
界面布局应清晰区分用户消息与系统回复。使用 Flexbox 布局实现左右对齐,并预留头像位置。
<template>
<div class="app-container">
<!-- 欢迎引导区 -->
<div class="welcome-message" v-if="messages.length === 0">
<p>您好!我是您的数字助理</p>
<p>我可以为你解答各类问题、生成图片、总结文档等。</p>
<p>有任何需要,请随时对我说~~😉</p>
</div>
<!-- 消息历史容器 -->
<div class="conversation-container">
<div
v-for="(msg, index) in messages"
:key="index"
:class="[msg.type, { 'is-history': msg.isHistory }]"
>
<!-- 用户消息样式 -->
<div class="message-wrapper user-message" v-if="msg.type === 'user-message'">
<div class="avatar-icon user-avatar">
<svg-icon icon-class="user" />
</div>
<div class="message-content">
<div v-html="renderMarkdown(msg.content)"></div>
</div>
</div>
<!-- 系统消息样式 -->
<div class="message-wrapper system-message" v-else>
<div class="message-content">
<div v-html="renderMarkdown(msg.content)"></div>
</div>
<div class="avatar-icon system-avatar">
<svg-icon icon-class="assistant" />
</div>
</div>
</div>
</div>
<!-- 底部输入区 -->
<div class="input-area">
<el-input
v-model="question"
type="textarea"
:rows="3"
placeholder="请输入您的问题..."
:disabled="isSending"
@keyup.enter.ctrl="sendChatMessage"
/>
<el-button
type="primary"
@click="sendChatMessage"
:loading="isSending"
>
{{ isSending ? '生成中...' : '发送' }}
</el-button>
</div>
</div>
</template>


