JavaScript/TypeScript集成完全指南

在Web应用中集成大模型API,支持React、Vue、Node.js等主流框架, 实现前后端AI功能开发。

安装与配置

NPM安装

# 安装OpenAI SDK
npm install openai

# TypeScript类型支持
npm install --save-dev @types/node

# 环境变量管理
npm install dotenv

环境配置

// .env文件
OPENAI_API_KEY=your-api-key
OPENAI_BASE_URL=https://api.openai.com/v1

// config.js
import dotenv from 'dotenv';
dotenv.config();

export const config = {
  apiKey: process.env.OPENAI_API_KEY,
  baseURL: process.env.OPENAI_BASE_URL
};

Node.js后端实现

// server.js
import express from 'express';
import OpenAI from 'openai';
import cors from 'cors';

const app = express();
app.use(cors());
app.use(express.json());

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY
});

// 聊天接口
app.post('/api/chat', async (req, res) => {
  try {
    const { messages } = req.body;
    
    const completion = await openai.chat.completions.create({
      model: "gpt-4",
      messages: messages,
      temperature: 0.7
    });
    
    res.json({
      success: true,
      data: completion.choices[0].message
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

// 流式响应
app.post('/api/chat/stream', async (req, res) => {
  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection', 'keep-alive');
  
  try {
    const stream = await openai.chat.completions.create({
      model: "gpt-4",
      messages: req.body.messages,
      stream: true
    });
    
    for await (const chunk of stream) {
      const data = chunk.choices[0]?.delta?.content || '';
      res.write(`data: ${JSON.stringify({ content: data })}\n\n`);
    }
    
    res.write('data: [DONE]\n\n');
    res.end();
  } catch (error) {
    res.write(`data: ${JSON.stringify({ error: error.message })}\n\n`);
    res.end();
  }
});

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});

React前端集成

// ChatComponent.jsx
import React, { useState, useEffect } from 'react';

function ChatComponent() {
  const [messages, setMessages] = useState([]);
  const [input, setInput] = useState('');
  const [loading, setLoading] = useState(false);
  
  const sendMessage = async () => {
    if (!input.trim()) return;
    
    const userMessage = { role: 'user', content: input };
    const newMessages = [...messages, userMessage];
    setMessages(newMessages);
    setInput('');
    setLoading(true);
    
    try {
      const response = await fetch('http://localhost:3000/api/chat', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ messages: newMessages })
      });
      
      const data = await response.json();
      
      if (data.success) {
        setMessages([...newMessages, data.data]);
      }
    } catch (error) {
      console.error('Error:', error);
    } finally {
      setLoading(false);
    }
  };
  
  // 流式响应Hook
  const useStreamChat = () => {
    const [streamData, setStreamData] = useState('');
    
    const streamChat = async (messages) => {
      const response = await fetch('http://localhost:3000/api/chat/stream', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ messages })
      });
      
      const reader = response.body.getReader();
      const decoder = new TextDecoder();
      
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        
        const chunk = decoder.decode(value);
        const lines = chunk.split('\n');
        
        for (const line of lines) {
          if (line.startsWith('data: ')) {
            const data = line.slice(6);
            if (data === '[DONE]') break;
            
            try {
              const json = JSON.parse(data);
              setStreamData(prev => prev + json.content);
            } catch (e) {
              console.error('Parse error:', e);
            }
          }
        }
      }
    };
    
    return { streamData, streamChat };
  };
  
  return (
    <div className="chat-container">
      <div className="messages">
        {messages.map((msg, idx) => (
          <div key={idx} className={`message ${msg.role}`}>
            {msg.content}
          </div>
        ))}
        {loading && <div className="loading">AI正在思考...</div>}
      </div>
      
      <div className="input-area">
        <input
          type="text"
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyPress={(e) => e.key === 'Enter' && sendMessage()}
          placeholder="输入消息..."
        />
        <button onClick={sendMessage}>发送</button>
      </div>
    </div>
  );
}

export default ChatComponent;

Vue 3集成

// ChatView.vue
<template>
  <div class="chat-container">
    <div class="messages">
      <div
        v-for="(msg, index) in messages"
        :key="index"
        :class="['message', msg.role]"
      >
        {{ msg.content }}
      </div>
      <div v-if="loading" class="loading">
        AI正在输入...
      </div>
    </div>
    
    <div class="input-area">
      <input
        v-model="input"
        @keyup.enter="sendMessage"
        placeholder="输入消息..."
      />
      <button @click="sendMessage">发送</button>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive } from 'vue';
import axios from 'axios';

const messages = ref([]);
const input = ref('');
const loading = ref(false);

const apiClient = axios.create({
  baseURL: 'http://localhost:3000/api',
  headers: {
    'Content-Type': 'application/json'
  }
});

const sendMessage = async () => {
  if (!input.value.trim()) return;
  
  const userMessage = {
    role: 'user',
    content: input.value
  };
  
  messages.value.push(userMessage);
  const currentInput = input.value;
  input.value = '';
  loading.value = true;
  
  try {
    const response = await apiClient.post('/chat', {
      messages: messages.value
    });
    
    if (response.data.success) {
      messages.value.push(response.data.data);
    }
  } catch (error) {
    console.error('Error:', error);
    messages.value.push({
      role: 'assistant',
      content: '抱歉,发生了错误。'
    });
  } finally {
    loading.value = false;
  }
};

// Composition API - 可复用的逻辑
export function useChat() {
  const messages = ref([]);
  const loading = ref(false);
  
  const chat = async (input) => {
    loading.value = true;
    
    try {
      const response = await apiClient.post('/chat', {
        messages: [
          ...messages.value,
          { role: 'user', content: input }
        ]
      });
      
      if (response.data.success) {
        messages.value.push(
          { role: 'user', content: input },
          response.data.data
        );
      }
      
      return response.data;
    } finally {
      loading.value = false;
    }
  };
  
  return {
    messages,
    loading,
    chat
  };
}
</script>

TypeScript最佳实践

// types.ts
export interface Message {
  role: 'system' | 'user' | 'assistant';
  content: string;
}

export interface ChatRequest {
  messages: Message[];
  model?: string;
  temperature?: number;
  max_tokens?: number;
}

export interface ChatResponse {
  success: boolean;
  data?: Message;
  error?: string;
}

// api.ts
import OpenAI from 'openai';
import type { ChatRequest, ChatResponse } from './types';

class LLMService {
  private client: OpenAI;
  
  constructor(apiKey: string) {
    this.client = new OpenAI({ apiKey });
  }
  
  async chat(request: ChatRequest): Promise<ChatResponse> {
    try {
      const completion = await this.client.chat.completions.create({
        model: request.model || 'gpt-4',
        messages: request.messages,
        temperature: request.temperature || 0.7,
        max_tokens: request.max_tokens
      });
      
      return {
        success: true,
        data: completion.choices[0].message
      };
    } catch (error) {
      return {
        success: false,
        error: error instanceof Error ? error.message : 'Unknown error'
      };
    }
  }
  
  async *streamChat(request: ChatRequest) {
    const stream = await this.client.chat.completions.create({
      ...request,
      stream: true
    });
    
    for await (const chunk of stream) {
      yield chunk.choices[0]?.delta?.content || '';
    }
  }
}

export default LLMService;

安全最佳实践

🔐 API密钥安全

  • • 永远不要在前端代码中暴露API密钥
  • • 使用环境变量管理敏感信息
  • • 通过后端代理所有API调用

🛡️ 请求验证

  • • 实施用户认证和授权
  • • 添加速率限制
  • • 验证和清理用户输入

开始JavaScript开发

使用JavaScript/TypeScript构建强大的AI应用,让前端也能智能化。

获取API访问