第281集:Vue 3 ChatGPT API集成

概述

在当今前端开发领域,AI 技术的应用正在改变传统的开发模式。ChatGPT 作为一种强大的语言模型,不仅可以用于构建智能对话界面,还可以作为开发助手提升编码效率。本集将详细介绍如何在 Vue 3 项目中集成 ChatGPT API,实现智能对话功能和 AI 辅助开发工具。

ChatGPT API 集成的核心价值

  1. 智能对话界面:为应用添加自然语言交互能力,提升用户体验
  2. AI 辅助开发:利用 ChatGPT 生成代码、解答技术问题,提高开发效率
  3. 内容生成:自动生成文章、评论、产品描述等内容
  4. 智能客服:构建 24/7 在线客服系统,减轻人工负担
  5. 个性化推荐:基于用户输入提供智能推荐

应用场景

  • 开发者工具:代码生成、错误排查、技术文档撰写
  • 客户服务:智能问答、问题分流、自动回复
  • 内容平台:文章生成、摘要提取、评论分析
  • 教育应用:智能辅导、习题生成、学习路径规划
  • 个人助手:日程安排、信息查询、任务提醒

准备工作

1. 获取 OpenAI API 密钥

要使用 ChatGPT API,首先需要获取 OpenAI API 密钥:

  1. 访问 OpenAI 官网
  2. 注册或登录账号
  3. 进入 "API Keys" 页面
  4. 创建新的 API 密钥并保存

2. 项目初始化

创建一个 Vue 3 + TypeScript 项目:

npm create vite@latest vue-chatgpt-demo -- --template vue-ts
cd vue-chatgpt-demo
npm install

3. 安装必要依赖

# 安装 axios 用于 API 调用
npm install axios

# 安装环境变量管理工具
npm install dotenv

# 安装 TypeScript 类型定义
npm install --save-dev @types/node

4. 配置环境变量

在项目根目录创建 .env 文件:

# .env
VITE_OPENAI_API_KEY=your_api_key_here
VITE_OPENAI_API_URL=https://api.openai.com/v1

核心实现

1. API 调用封装

创建一个专门的服务文件来封装 OpenAI API 调用:

// src/services/openai.ts
import axios from 'axios';

const API_KEY = import.meta.env.VITE_OPENAI_API_KEY;
const API_URL = import.meta.env.VITE_OPENAI_API_URL;

const openaiClient = axios.create({
  baseURL: API_URL,
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${API_KEY}`
  }
});

interface ChatMessage {
  role: 'system' | 'user' | 'assistant';
  content: string;
}

interface ChatCompletionRequest {
  model: string;
  messages: ChatMessage[];
  temperature?: number;
  max_tokens?: number;
  top_p?: number;
  frequency_penalty?: number;
  presence_penalty?: number;
}

interface ChatCompletionResponse {
  id: string;
  object: string;
  created: number;
  model: string;
  choices: {
    index: number;
    message: ChatMessage;
    finish_reason: string;
  }[];
  usage: {
    prompt_tokens: number;
    completion_tokens: number;
    total_tokens: number;
  };
}

export const openaiService = {
  async getChatCompletion(request: ChatCompletionRequest): Promise<string> {
    try {
      const response = await openaiClient.post<ChatCompletionResponse>('/chat/completions', request);
      return response.data.choices[0].message.content;
    } catch (error) {
      console.error('Error calling OpenAI API:', error);
      throw error;
    }
  }
};

2. 智能对话组件

创建一个智能对话组件:

<!-- src/components/ChatGPTComponent.vue -->
<template>
  <div class="chat-container">
    <div class="chat-messages">
      <div 
        v-for="(message, index) in messages" 
        :key="index"
        :class="['message', message.role]"
      >
        <div class="message-role">{{ message.role === 'user' ? 'You' : 'ChatGPT' }}</div>
        <div class="message-content">{{ message.content }}</div>
      </div>
      <div v-if="loading" class="message assistant">
        <div class="message-role">ChatGPT</div>
        <div class="message-content loading">Thinking...</div>
      </div>
    </div>
    <div class="chat-input">
      <input 
        v-model="inputMessage"
        type="text"
        placeholder="Type your message..."
        @keyup.enter="sendMessage"
      />
      <button @click="sendMessage" :disabled="loading">Send</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive } from 'vue';
import { openaiService } from '../services/openai';

interface ChatMessage {
  role: 'system' | 'user' | 'assistant';
  content: string;
}

const messages = reactive<ChatMessage[]>([
  {
    role: 'system',
    content: 'You are a helpful assistant built with Vue 3 and ChatGPT API.'
  }
]);

const inputMessage = ref('');
const loading = ref(false);

const sendMessage = async () => {
  if (!inputMessage.value.trim() || loading.value) return;

  // Add user message
  messages.push({
    role: 'user',
    content: inputMessage.value
  });

  const userMessage = inputMessage.value;
  inputMessage.value = '';
  loading.value = true;

  try {
    // Call OpenAI API
    const response = await openaiService.getChatCompletion({
      model: 'gpt-3.5-turbo',
      messages: messages,
      temperature: 0.7,
      max_tokens: 1000
    });

    // Add assistant message
    messages.push({
      role: 'assistant',
      content: response
    });
  } catch (error) {
    console.error('Error sending message:', error);
    messages.push({
      role: 'assistant',
      content: 'Sorry, there was an error processing your request.'
    });
  } finally {
    loading.value = false;
  }
};
</script>

<style scoped>
.chat-container {
  width: 100%;
  max-width: 800px;
  margin: 0 auto;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  overflow: hidden;
}

.chat-messages {
  height: 500px;
  overflow-y: auto;
  padding: 20px;
  background-color: #f5f5f5;
}

.message {
  margin-bottom: 16px;
  padding: 12px;
  border-radius: 8px;
}

.message.user {
  background-color: #e3f2fd;
  align-self: flex-end;
}

.message.assistant {
  background-color: #ffffff;
  align-self: flex-start;
}

.message-role {
  font-weight: bold;
  margin-bottom: 4px;
  font-size: 12px;
  color: #666;
}

.message-content {
  font-size: 14px;
  line-height: 1.4;
}

.message-content.loading {
  font-style: italic;
  color: #999;
}

.chat-input {
  display: flex;
  padding: 16px;
  background-color: #ffffff;
  border-top: 1px solid #e0e0e0;
}

.chat-input input {
  flex: 1;
  padding: 12px;
  border: 1px solid #e0e0e0;
  border-radius: 4px;
  margin-right: 8px;
}

.chat-input button {
  padding: 12px 24px;
  background-color: #1976d2;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.chat-input button:hover {
  background-color: #1565c0;
}

.chat-input button:disabled {
  background-color: #bdbdbd;
  cursor: not-allowed;
}
</style>

3. AI 辅助开发工具

创建一个 AI 辅助开发工具组件:

<!-- src/components/AIDevAssistant.vue -->
<template>
  <div class="ai-dev-assistant">
    <h3>AI Development Assistant</h3>
    
    <div class="tool-section">
      <h4>Code Generator</h4>
      <textarea 
        v-model="codePrompt"
        placeholder="Describe the code you need..."
        rows="4"
      ></textarea>
      <button @click="generateCode" :disabled="loading">Generate Code</button>
    </div>

    <div v-if="generatedCode" class="code-result">
      <h4>Generated Code</h4>
      <pre><code>{{ generatedCode }}</code></pre>
      <button @click="copyCode">Copy Code</button>
    </div>

    <div class="tool-section">
      <h4>Bug Fixer</h4>
      <textarea 
        v-model="bugCode"
        placeholder="Paste your buggy code here..."
        rows="4"
      ></textarea>
      <button @click="fixBug" :disabled="loading">Fix Bug</button>
    </div>

    <div v-if="fixedCode" class="code-result">
      <h4>Fixed Code</h4>
      <pre><code>{{ fixedCode }}</code></pre>
      <button @click="copyFixedCode">Copy Code</button>
    </div>

    <div v-if="loading" class="loading-indicator">
      Processing...
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { openaiService } from '../services/openai';

const codePrompt = ref('');
const generatedCode = ref('');
const bugCode = ref('');
const fixedCode = ref('');
const loading = ref(false);

const generateCode = async () => {
  if (!codePrompt.value.trim() || loading.value) return;

  loading.value = true;
  try {
    const response = await openaiService.getChatCompletion({
      model: 'gpt-3.5-turbo',
      messages: [
        {
          role: 'system',
          content: 'You are a skilled Vue 3 developer. Generate clean, efficient, and well-commented code based on the user\'s request.'
        },
        {
          role: 'user',
          content: codePrompt.value
        }
      ],
      temperature: 0.7,
      max_tokens: 1000
    });
    generatedCode.value = response;
  } catch (error) {
    console.error('Error generating code:', error);
  } finally {
    loading.value = false;
  }
};

const fixBug = async () => {
  if (!bugCode.value.trim() || loading.value) return;

  loading.value = true;
  try {
    const response = await openaiService.getChatCompletion({
      model: 'gpt-3.5-turbo',
      messages: [
        {
          role: 'system',
          content: 'You are a skilled Vue 3 developer. Find and fix bugs in the provided code. Explain the issue and provide the corrected code.'
        },
        {
          role: 'user',
          content: bugCode.value
        }
      ],
      temperature: 0.7,
      max_tokens: 1000
    });
    fixedCode.value = response;
  } catch (error) {
    console.error('Error fixing bug:', error);
  } finally {
    loading.value = false;
  }
};

const copyCode = () => {
  navigator.clipboard.writeText(generatedCode.value);
  alert('Code copied to clipboard!');
};

const copyFixedCode = () => {
  navigator.clipboard.writeText(fixedCode.value);
  alert('Code copied to clipboard!');
};
</script>

<style scoped>
.ai-dev-assistant {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
}

h3 {
  margin-bottom: 20px;
  color: #333;
}

h4 {
  margin-bottom: 10px;
  color: #555;
}

.tool-section {
  margin-bottom: 30px;
  padding: 16px;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  background-color: #f9f9f9;
}

textarea {
  width: 100%;
  padding: 12px;
  border: 1px solid #e0e0e0;
  border-radius: 4px;
  margin-bottom: 12px;
  font-family: monospace;
  font-size: 14px;
}

button {
  padding: 8px 16px;
  background-color: #4caf50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
}

button:hover {
  background-color: #45a049;
}

button:disabled {
  background-color: #bdbdbd;
  cursor: not-allowed;
}

.code-result {
  margin-top: 20px;
  padding: 16px;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  background-color: #f5f5f5;
}

pre {
  background-color: #f0f0f0;
  padding: 12px;
  border-radius: 4px;
  overflow-x: auto;
  margin-bottom: 12px;
}

code {
  font-family: monospace;
  font-size: 14px;
}

.loading-indicator {
  margin-top: 16px;
  padding: 12px;
  background-color: #e3f2fd;
  border: 1px solid #bbdefb;
  border-radius: 4px;
  color: #1976d2;
  text-align: center;
}
</style>

实战案例:智能客服系统

1. 项目结构

vue-chatgpt-demo/
├── src/
│   ├── components/
│   │   ├── ChatGPTComponent.vue
│   │   └── AIDevAssistant.vue
│   ├── services/
│   │   └── openai.ts
│   ├── views/
│   │   ├── ChatView.vue
│   │   └── DevAssistantView.vue
│   ├── router/
│   │   └── index.ts
│   ├── App.vue
│   └── main.ts
├── public/
├── .env
├── package.json
└── vite.config.ts

2. 路由配置

// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router';
import ChatView from '../views/ChatView.vue';
import DevAssistantView from '../views/DevAssistantView.vue';

const routes = [
  {
    path: '/',
    name: 'Chat',
    component: ChatView
  },
  {
    path: '/dev-assistant',
    name: 'DevAssistant',
    component: DevAssistantView
  }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

export default router;

3. 视图组件

<!-- src/views/ChatView.vue -->
<template>
  <div class="view-container">
    <h2>ChatGPT Chat Interface</h2>
    <ChatGPTComponent />
  </div>
</template>

<script setup lang="ts">
import ChatGPTComponent from '../components/ChatGPTComponent.vue';
</script>

<style scoped>
.view-container {
  max-width: 1000px;
  margin: 0 auto;
  padding: 20px;
}

h2 {
  margin-bottom: 30px;
  color: #333;
}
</style>
<!-- src/views/DevAssistantView.vue -->
<template>
  <div class="view-container">
    <h2>AI Development Assistant</h2>
    <AIDevAssistant />
  </div>
</template>

<script setup lang="ts">
import AIDevAssistant from '../components/AIDevAssistant.vue';
</script>

<style scoped>
.view-container {
  max-width: 1000px;
  margin: 0 auto;
  padding: 20px;
}

h2 {
  margin-bottom: 30px;
  color: #333;
}
</style>

4. 主应用配置

<!-- src/App.vue -->
<template>
  <div class="app">
    <header class="app-header">
      <h1>Vue 3 ChatGPT Integration</h1>
      <nav>
        <router-link to="/">Chat</router-link>
        <router-link to="/dev-assistant">Dev Assistant</router-link>
      </nav>
    </header>
    <main>
      <router-view />
    </main>
  </div>
</template>

<script setup lang="ts">
// App component
</script>

<style>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: Arial, sans-serif;
  line-height: 1.6;
  color: #333;
}

.app {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.app-header {
  background-color: #1976d2;
  color: white;
  padding: 20px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.app-header h1 {
  font-size: 24px;
}

nav {
  display: flex;
  gap: 20px;
}

nav a {
  color: white;
  text-decoration: none;
  font-weight: bold;
}

nav a:hover {
  text-decoration: underline;
}

main {
  flex: 1;
  padding: 20px;
}
</style>
// src/main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

createApp(App).use(router).mount('#app')

最佳实践

1. 性能优化

  • 请求节流:限制 API 调用频率,避免过多请求
  • 缓存机制:缓存常见问题的响应
  • 流式响应:使用 SSE 或 WebSocket 实现流式响应,提升用户体验
  • 前端状态管理:合理使用 Pinia 或 Vuex 管理对话状态

2. 错误处理

  • API 错误捕获:妥善处理 API 调用失败的情况
  • 网络错误处理:处理网络中断、超时等问题
  • Rate Limit 处理:处理 API 速率限制
  • 友好的错误提示:向用户显示清晰的错误信息

3. 安全性

  • API 密钥保护:不要在前端代码中硬编码 API 密钥
  • 环境变量管理:使用 .env 文件和 Vite 的环境变量机制
  • 输入验证:验证用户输入,防止恶意请求
  • 请求限流:在服务端实现请求限流,防止滥用
  • 数据加密:对敏感数据进行加密传输

4. 用户体验

  • 加载状态:显示清晰的加载状态
  • 错误提示:提供友好的错误提示
  • 消息格式化:美化消息显示,支持 Markdown 格式
  • 历史记录:保存对话历史,支持上下文理解
  • 响应时间优化:通过缓存和预加载提升响应速度

高级功能

1. 多模型支持

// 支持不同的 OpenAI 模型
export const openaiService = {
  async getChatCompletion(request: ChatCompletionRequest): Promise<string> {
    try {
      const response = await openaiClient.post<ChatCompletionResponse>('/chat/completions', {
        ...request,
        model: request.model || 'gpt-3.5-turbo' // 默认模型
      });
      return response.data.choices[0].message.content;
    } catch (error) {
      console.error('Error calling OpenAI API:', error);
      throw error;
    }
  }
};

2. 函数调用能力

// 支持函数调用
interface FunctionCall {
  name: string;
  arguments: string;
}

interface ChatCompletionRequestWithFunctions extends ChatCompletionRequest {
  functions?: Array<{
    name: string;
description: string;
    parameters: Record<string, any>;
  }>;
  function_call?: 'none' | 'auto' | { name: string };
}

3. 语音交互

集成 Web Speech API 实现语音输入和输出:

<!-- 语音输入功能 -->
<button @click="startVoiceInput">
  <span v-if="!isListening">Start Voice</span>
  <span v-else>Listening...</span>
</button>

总结

本集详细介绍了如何在 Vue 3 项目中集成 ChatGPT API,包括:

  1. 准备工作:获取 OpenAI API 密钥、项目初始化、依赖安装
  2. 核心实现:API 调用封装、智能对话组件、AI 辅助开发工具
  3. 实战案例:智能客服系统的完整实现
  4. 最佳实践:性能优化、错误处理、安全性、用户体验
  5. 高级功能:多模型支持、函数调用能力、语音交互

通过集成 ChatGPT API,我们可以为 Vue 3 应用添加智能对话能力,构建 AI 辅助开发工具,提升开发效率和用户体验。随着 AI 技术的不断发展,这种集成方式将为前端开发带来更多可能性。

后续学习建议

  • 第282集:智能代码提示
  • 第283集:AI辅助代码生成
  • 第284集:自然语言查询数据
  • 第285集:智能表单验证

这些内容将进一步探索 Vue 3 与 AI 技术的结合,帮助你构建更加智能、高效的前端应用。

« 上一篇 Vue 3低代码平台部署与运维方案