1. 项目概述与核心价值

最近在折腾一个自己的AI小工具,想把它做成一个能随时访问的网页应用,方便在不同设备上使用。我最终选择基于 LsyWeb/chatgpt-web 这个开源项目进行二次开发和部署。这是一个用 Vue 3 + TypeScript + Vite 技术栈构建的简易 ChatGPT 网页版前端。它的核心价值在于提供了一个干净、现代且易于定制的用户界面,并且通过对接后端云函数(比如阿里云函数计算、Vercel Serverless Functions 或腾讯云云开发)来处理与 OpenAI API 的实际通信,从而将前端展示与后端逻辑安全地分离。

对于前端开发者或者想快速拥有一个私有化 ChatGPT 界面的朋友来说,这个项目是个非常不错的起点。它解决了几个关键痛点:首先,你无需从零开始设计 UI 和实现流式对话交互,项目已经提供了基础的聊天布局和消息处理逻辑;其次,它通过环境变量配置后端接口,使得前端可以独立部署和更新,与后端解耦;最后,项目提供了清晰的 Vercel 一键部署路径,极大降低了部署门槛。无论你是想学习现代前端技术栈如何与 AI 服务集成,还是想快速搭建一个内部使用的 AI 助手门户,这个项目都能提供扎实的基础。

2. 技术栈选型与架构解析

2.1 前端技术栈:为什么是 Vue 3 + TS + Vite?

项目选择了当前前端领域非常主流且高效的组合。Vue 3 的 Composition API 让组件逻辑的组织更加灵活和可复用,这对于管理复杂的聊天状态(如对话历史、加载状态、错误信息)非常有利。TypeScript 的加入则是大型项目或与复杂 API(如 OpenAI 的响应结构)打交道的必备品,它能提供强大的类型提示,减少运行时错误,让代码更健壮。我在实际开发中深有体会,当定义消息接口时,明确 role: 'user' | 'assistant' | 'system' content: string 这样的类型,能避免很多低级错误。

Vite 作为构建工具,其快速的冷启动和热更新能力,极大地提升了开发体验。在开发这类实时交互应用时,每次修改代码都能近乎即时地在浏览器看到效果,这对效率的提升是巨大的。此外,Vite 对环境变量的原生支持(通过 import.meta.env )与项目设计完美契合,我们只需要在 .env.local 文件中配置 VITE_AIR_CODE_SEND_MESSAGE_URL ,就可以在代码中安全地获取后端接口地址,而无需将敏感信息硬编码在源码中。

2.2 核心架构:前后端分离与职责界定

这个项目的架构是典型的前后端分离模式。前端(即本项目)只负责用户交互界面的渲染和本地状态管理。具体来说,它的职责包括:

  1. 提供聊天输入框和消息展示区域。
  2. 管理本地对话历史(通常用 reactive pinia 存储)。
  3. 将用户输入的消息,通过 HTTP 请求发送到配置的后端接口。
  4. 处理后端返回的流式或非流式数据,并实时更新到 UI 上。
  5. 处理一些基础的用户体验,如加载动画、错误提示。

而后端(需要自行部署)的职责则至关重要且敏感:

  1. 接收前端转发过来的用户消息。
  2. 安全地持有和管理 OpenAI API Key(绝不应该暴露给前端)。
  3. 构造符合 OpenAI API 格式的请求,并添加可能的系统提示词、调整参数(如 temperature , max_tokens )。
  4. 调用 OpenAI API,并将响应流或结果返回给前端。
  5. 实现必要的安全措施,如请求频率限制、身份验证(可选)和输入验证。

这种分离的好处是显而易见的:前端可以独立部署和迭代,后端可以专注于安全和业务逻辑,并且可以轻松替换后端实现(比如从阿里云函数切换到 Vercel Serverless),而前端几乎无需改动。

3. 项目初始化与本地开发环境搭建

3.1 获取项目代码

首先需要获取代码。推荐使用 Fork + Clone 的方式,这样便于后续提交自己的修改到个人仓库。

  1. Fork 项目 :访问项目的 GitHub 页面,点击右上角的 “Fork” 按钮,将项目复制到自己的 GitHub 账户下。
  2. 克隆到本地 :打开终端,切换到你的工作目录,执行以下命令,将 [你的用户名] 替换为你自己的 GitHub 用户名。
    git clone https://github.com/[你的用户名]/chatgpt-web.git
    cd chatgpt-web
    

3.2 安装依赖与启动开发服务器

项目使用 yarn 作为包管理器(也支持 npm pnpm )。确保你的本地环境已经安装了 Node.js(建议版本 16+)和 yarn

  1. 安装依赖 :在项目根目录下运行以下命令。这个过程会下载 Vue、Vite、TypeScript 等所有必要的库。

    yarn install
    # 或者使用 npm
    # npm install
    

    注意 :如果遇到网络问题导致依赖安装缓慢或失败,可以考虑配置国内镜像源。对于 yarn ,可以运行 yarn config set registry https://registry.npmmirror.com 。安装过程可能会花费几分钟,请耐心等待。

  2. 配置环境变量 :这是连接你后端服务的关键一步。在项目根目录下创建一个名为 .env.local 的文件(这个文件会被 .gitignore 忽略,避免敏感信息上传)。文件内容如下:

    VITE_AIR_CODE_SEND_MESSAGE_URL=https://your-backend-service.com/api/chat
    

    https://your-backend-service.com/api/chat 替换为你实际部署的后端接口的完整 URL。这个变量名 VITE_AIR_CODE_SEND_MESSAGE_URL 是项目代码中预设的,用于在运行时获取接口地址。

  3. 启动开发服务器 :运行以下命令,Vite 会启动一个本地开发服务器。

    yarn dev
    # 或 npm run dev
    

    命令行会输出类似 Local: http://localhost:5173/ 的信息。在浏览器中打开这个地址,你就能看到本地的 ChatGPT 网页界面了。

3.3 本地开发实操与代码结构初探

启动后,你可以尝试在输入框发送消息。由于此时环境变量指向的是一个可能不存在的后端地址,前端会收到网络错误。但这证明了前端界面已经正常运行。接下来,让我们简单看一下核心代码结构,以便理解消息是如何发送的:

  • src/components/ :存放 Vue 组件,如 Chat.vue 很可能就是主聊天组件。
  • src/composables/ src/stores/ :可能存放使用 Composition API 封装的状态逻辑或 Pinia 状态管理。
  • src/utils/ :工具函数,其中很可能包含一个用于调用后端接口的函数。

你可以打开开发者工具的网络面板,在发送消息时,会看到一个请求发往你配置的 VITE_AIR_CODE_SEND_MESSAGE_URL 。找到发起这个请求的源码(通常是一个 fetch axios 调用),这是前后端对接的核心,也是我们后续可能需要定制化的地方,比如修改请求头、处理不同的响应格式等。

4. 后端服务准备与对接

前端需要后端服务作为“中转站”来安全地调用 OpenAI API。这里提供两种常见且简单的方案。

4.1 方案一:使用 Vercel Serverless Functions(推荐用于快速原型)

Vercel 不仅擅长部署前端,其 Serverless Functions 功能也非常适合部署一个轻量级的后端代理。你可以创建一个新的 Node.js 项目,或者直接在现有项目根目录下创建 /api/chat.js /api/chat.ts 文件。

下面是一个基本的 api/chat.js 示例:

// /api/chat.js
import { OpenAI } from 'openai'; // 需要安装 openai npm 包

export default async function handler(req, res) {
  // 1. 允许跨域请求(根据前端部署域名调整)
  res.setHeader('Access-Control-Allow-Origin', 'https://your-frontend.vercel.app');
  res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type');

  // 处理预检请求
  if (req.method === 'OPTIONS') {
    return res.status(200).end();
  }

  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }

  try {
    const { messages } = req.body; // 从前端接收消息历史

    // 2. 安全地读取环境变量中的 API Key
    const apiKey = process.env.OPENAI_API_KEY;
    if (!apiKey) {
      throw new Error('OPENAI_API_KEY is not configured');
    }

    const openai = new OpenAI({ apiKey });

    // 3. 调用 OpenAI API
    const completion = await openai.chat.completions.create({
      model: 'gpt-3.5-turbo', // 或 'gpt-4'
      messages: messages,
      stream: true, // 启用流式响应,提升用户体验
    });

    // 4. 设置响应头,支持流式传输
    res.setHeader('Content-Type', 'text/event-stream');
    res.setHeader('Cache-Control', 'no-cache');
    res.setHeader('Connection', 'keep-alive');

    // 5. 将流式响应转发给前端
    for await (const chunk of completion) {
      const content = chunk.choices[0]?.delta?.content || '';
      res.write(`data: ${JSON.stringify({ content })}\n\n`);
    }
    res.write('data: [DONE]\n\n');
    res.end();

  } catch (error) {
    console.error('Error:', error);
    res.status(500).json({ error: error.message || 'Internal server error' });
  }
}

在 Vercel 上部署此函数时,需要在项目设置中配置 OPENAI_API_KEY 环境变量。这样,你的前端配置的 VITE_AIR_CODE_SEND_MESSAGE_URL 就可以指向 https://your-vercel-app.vercel.app/api/chat

4.2 方案二:使用云开发平台(如阿里云函数计算、腾讯云云开发)

国内用户可能更倾向于使用阿里云或腾讯云的服务。以阿里云函数计算为例:

  1. 创建函数 :在函数计算控制台创建一个 Node.js 运行时(如 Node.js 18)的 HTTP 函数。
  2. 编写函数代码 :代码逻辑与上述 Vercel Function 类似,但入口函数格式需遵循平台规范。例如,阿里云的格式通常是 exports.handler = async (req, res) => { ... }
  3. 配置环境变量 :在函数配置中,添加 OPENAI_API_KEY
  4. 获取访问地址 :部署后,平台会提供一个 HTTP 触发器地址,这个地址就是前端需要的 VITE_AIR_CODE_SEND_MESSAGE_URL

关键注意事项 :无论选择哪种方案, 绝对不要 将 OpenAI API Key 硬编码在前端代码或提交到版本库中。前端与后端的通信应视为不可信,所有涉及密钥的操作必须在受控的后端进行。此外,在生产环境中,强烈建议在后端添加额外的安全层,如请求签名、简单的令牌验证或频率限制,以防止接口被滥用。

5. 生产环境部署:使用 Vercel 一键部署前端

本地开发测试无误后,就可以将前端部署到生产环境了。项目推荐使用 Vercel,它与 GitHub 集成良好,支持自动化部署。

5.1 通过 GitHub 导入并部署

  1. 登录 Vercel :访问 vercel.com ,使用 GitHub 账号登录。
  2. 新建项目 :点击 “Add New...” -> “Project”。
  3. 导入仓库 :在 “Import Git Repository” 下,你应该能看到你 Fork 过来的 chatgpt-web 仓库。点击 “Import”。
  4. 配置项目
    • Project Name :Vercel 会自动生成一个,你可以修改成自己喜欢的(如 my-chatgpt-web ),这会成为子域名的一部分( my-chatgpt-web.vercel.app )。
    • Framework Preset :Vercel 通常能自动检测出是 Vite 项目,无需手动更改。
    • Root Directory :保持默认( ./ )。
    • Build and Output Settings :通常也无需修改,Vercel 会自动执行 yarn build npm run build
  5. 配置环境变量 :这是最关键的一步。在 “Environment Variables” 区域,点击添加。
    • Name :输入 VITE_AIR_CODE_SEND_MESSAGE_URL
    • Value :输入你上一步准备好的、可公开访问的后端 API 地址(例如 https://your-backend.vercel.app/api/chat 或阿里云函数的触发器 URL)。

    重要提示 :Vercel 会加密存储这个值,并在构建时将其注入到前端应用中,因此它是安全的。

  6. 部署 :点击 “Deploy”。Vercel 会开始拉取代码、安装依赖、构建并部署。整个过程通常在一两分钟内完成。

部署成功后,Vercel 会提供一个 *.vercel.app 的域名,你可以直接访问它,一个属于你自己的 ChatGPT Web 版就上线了。

5.2 绑定自定义域名与国内访问优化

由于网络环境问题, vercel.app 域名在国内可能无法稳定访问。解决这个问题的最佳实践是绑定自定义域名。

  1. 准备域名 :拥有一个已备案的域名(国内服务器非必需,但使用国内 DNS 解析服务时建议备案)。
  2. 在 Vercel 中添加域名 :在项目控制台的 “Domains” 页面,输入你的自定义域名(如 chat.yourdomain.com )。
  3. 配置 DNS 解析 :Vercel 会给出需要添加的 DNS 记录(通常是 CNAME 记录指向 cname.vercel-dns.com )。你需要到你的域名注册商或 DNS 服务商(如阿里云解析、Cloudflare)处添加这条记录。
  4. 等待生效 :DNS 记录生效可能需要几分钟到几小时。生效后,Vercel 会自动为你的域名申请并配置 SSL 证书(HTTPS)。

绑定自定义域名后,国内用户就可以通过你的域名正常访问了,速度和稳定性都会得到改善。Vercel 的全球 CDN 边缘网络能保证较快的访问速度。

6. 高级定制与功能扩展

基础部署完成后,你可以根据需求对这个项目进行深度定制,让它更贴合你的使用场景。

6.1 界面与样式定制

项目使用 Vue 3 和 likely 一些 CSS 框架或直接使用 CSS。你可以轻松修改 src/App.vue 或相关组件文件来调整布局、颜色、字体等。例如,如果你想修改主题色:

  1. 找到定义主要颜色的 CSS 变量或样式规则。可能存在于 src/style.css src/components/Chat.vue <style> 块中。
  2. 修改对应的颜色值。例如,将主色调从蓝色改为绿色。
  3. 如果你想支持深色/浅色模式,可以引入一个状态管理(如 useDark from @vueuse/core )并根据状态切换 CSS 类名。

6.2 对话功能增强

默认的对话可能比较简单,可以考虑添加以下功能:

  • 对话持久化 :使用浏览器的 localStorage IndexedDB 保存聊天记录,即使关闭页面再打开,历史对话依然存在。可以在 src/stores/ 下创建一个 Pinia store 来管理对话状态,并在 onMounted 时从本地存储加载。
  • 多会话管理 :允许用户创建多个独立的聊天会话(如“工作”、“学习”、“创意”),并能在其间切换。这需要扩展状态管理,将会话列表和当前活跃会话ID纳入管理。
  • 参数调节面板 :在界面上添加滑动条或输入框,让用户可以实时调整 OpenAI API 的 temperature (创造性)和 max_tokens (回复长度)等参数。这些参数需要随着用户消息一起发送到后端。
  • 系统提示词预设 :提供几个下拉选项,让用户选择不同的“角色”或“任务”,如“翻译助手”、“代码专家”、“创意写手”。选择后,前端会在消息数组的开头插入对应的 system 角色消息。

6.3 后端功能强化

后端不仅仅是转发请求,可以承担更多职责:

  • 多模型支持 :让后端支持切换不同的 OpenAI 模型(如 gpt-3.5-turbo , gpt-4 , gpt-4-turbo )。可以通过前端传递一个 model 参数,后端根据该参数调用不同的模型。
  • 上下文长度管理与总结 :OpenAI 模型有 token 数量限制。可以实现一个简单的逻辑,当对话历史过长时,自动将较早的对话进行摘要(可以调用一次 GPT 生成摘要),然后用摘要替换掉原始长文本,以节省 token 并保留核心上下文。
  • 简单的用户认证 :如果你不希望服务被完全公开,可以在后端实现一个简单的 API 密钥验证。前端在请求头中携带一个令牌(可以是一个简单的字符串),后端验证该令牌是否有效。注意,这并非高安全级别的认证,但足以防止接口被随意扫描调用。

7. 常见问题排查与优化记录

在实际部署和使用过程中,你可能会遇到一些问题。以下是我遇到的一些典型情况及解决方法。

7.1 前端部署后访问空白页或报错

  • 症状 :部署到 Vercel 后,打开页面是空白的,控制台可能有 JavaScript 错误。
  • 排查步骤
    1. 检查构建日志 :在 Vercel 项目的 “Deployments” 标签页,查看最近一次部署的日志。确认 yarn build 过程没有报错。
    2. 检查环境变量 :确认 VITE_AIR_CODE_SEND_MESSAGE_URL 环境变量已正确配置,且值是一个有效的 URL。可以在项目设置的 “Environment Variables” 中复查。
    3. 检查路由模式 :如果项目使用了 Vue Router 且是 history 模式,需要在 Vercel 项目设置中增加一个 vercel.json 配置文件,将所有路由重定向到 index.html 。不过,本项目作为单页应用,如果结构简单,可能不需要此配置。
    4. 清除缓存 :有时是浏览器缓存了旧版本资源。尝试强制刷新(Ctrl+F5)或使用无痕模式访问。

7.2 发送消息后无响应或报网络错误

  • 症状 :前端界面正常,但发送消息后,界面一直显示“正在输入”或直接弹出网络错误。
  • 排查步骤
    1. 打开浏览器开发者工具 :进入 “Network” 面板,查看发送消息时产生的网络请求。
    2. 查看请求 URL :确认请求是否发送到了你配置的 VITE_AIR_CODE_SEND_MESSAGE_URL 。如果地址错误,请检查前端环境变量和构建过程。
    3. 查看请求状态 :如果请求状态是 CORS error (跨域错误),说明后端没有正确设置跨域响应头。你需要按照第4章后端示例代码中的方式,在后端添加 Access-Control-Allow-Origin 等响应头,并允许 OPTIONS 预检请求。
    4. 查看后端日志 :登录到你的后端服务平台(Vercel、阿里云等),查看函数执行的日志。这里通常会显示更详细的错误信息,例如 OpenAI API Key 无效、额度不足、请求格式错误等。
    5. 测试后端接口 :使用 curl 或 Postman 等工具,直接向后端接口地址发送一个模拟请求,检查其是否能正常返回。这有助于隔离前端问题。

7.3 流式响应中断或显示不完整

  • 症状 :回复内容是一段一段显示(流式)的,但有时会中途停止,或者最后缺少部分内容。
  • 原因与解决
    1. 网络不稳定 :流式传输对网络稳定性要求较高。确保前后端部署的网络环境良好。对于国内用户,后端部署在海外(如 Vercel)可能导致流式响应延迟或中断,考虑将后端部署在国内可访问的服务器或使用支持流式传输的国内云函数服务。
    2. 后端处理超时 :Serverless 函数有默认的执行超时时间(如 Vercel 免费版为10秒,阿里云函数计算默认为3秒)。如果对话较长或模型响应慢,可能导致函数超时提前终止。解决方案是:优化后端代码,确保快速响应;或者升级服务配置,增加超时时间限制(例如在 Vercel 的 vercel.json 中配置 "functions": { "api/chat.js": { "maxDuration": 30 } } 将超时设为30秒)。
    3. 前端处理逻辑不健壮 :检查前端处理 Server-Sent Events (SSE) 的代码。需要正确处理 onmessage , onerror , onclose 事件。在 onerror onclose 时,应该更新 UI 状态,提示用户连接已结束或发生错误。

7.4 性能与成本优化建议

  • 前端静态资源优化 :Vercel 已经提供了很好的全球 CDN,确保你的构建产物(通过 yarn build 生成)是优化的。可以检查 vite.config.ts 中是否配置了合适的打包选项。
  • 后端冷启动优化 :Serverless 函数在长时间不调用后再次调用,会有“冷启动”延迟。为了保持函数“温热”,可以设置一个简单的定时任务(例如使用 cron-job.org),每隔几分钟调用一次你的健康检查接口(如果你有的话),或者直接调用聊天接口发送一个简单提示。
  • API 调用成本控制 :OpenAI API 按 token 收费。为了避免意外消耗(例如被恶意刷接口或前端 bug 导致循环调用),务必在后端实施以下措施:
    • 设置使用量限制 :在 OpenAI 平台仪表板上,为 API Key 设置使用限额(每月或每天)。
    • 实现频率限制 :在后端代码中,基于 IP 地址或 API 令牌,限制单个用户单位时间内的请求次数。
    • 监控与告警 :定期查看 OpenAI 的用量账单,并设置费用告警。

通过以上步骤,你不仅能成功部署一个属于自己的 ChatGPT Web 应用,还能根据需求对其进行深度定制和优化。这个过程本身也是对现代前端开发、Serverless 架构和 AI 应用集成的一次很好的实践。

更多推荐