从零到一:前端调用DeepSeek大模型实战指南

49 阅读4分钟

从零到一:前端调用DeepSeek大模型实战指南

在人工智能浪潮席卷而来的今天,大语言模型(LLM)已成为开发者必须掌握的技能之一。许多开发者可能认为调用大模型是后端或算法工程师的专属领域,但实际上,前端开发者完全可以直接通过HTTP请求与这些强大的AI模型进行交互。本文将带领各位前端爱好者,基于原生HTML/CSS/JS技术栈,完成一次完整的大模型调用实战。

一、核心原理:前端如何调用大模型?

传统观念中,复杂的AI服务似乎需要厚重的后端支持,但现代LLM服务商(如DeepSeek)普遍提供了基于HTTP协议的RESTful API接口。这意味着任何能够发送HTTP请求的客户端都可以直接调用,这自然包括了运行在浏览器中的JavaScript。 技术基础:前端通过fetchAPI向大模型的服务端点发送格式正确的HTTP请求,模型服务端处理完成后,会将生成的文本内容通过HTTP响应返回,前端再解析数据并展示给用户。 这种方式的优势在于:

  • 快速原型验证:无需搭建后端服务,前端可独立完成AI功能验证
  • 简化技术栈:对于简单应用,避免前后端联调的复杂性
  • 实时交互体验:为后续实现流式输出打下基础

二、项目初始化与工程化配置

创建基础项目结构

首先,我们需要创建一个标准的原生Web项目。文档2提供了最基础的HTML结构:

<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="color-scheme" content="light dark">
  <title>http 请求调用llm</title>
  <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'><text y='48' font-size='48'>🌐🌐</text></svg>">
  <link rel="stylesheet" href="styles.css">
</head>
<body>
    <h1>Hello</h1>
    <div id="reply"></div>
  <script type="module" src="main.js"></script>
</body>
</html>

这个结构虽然简单,但包含了现代前端开发的所有必要元素:视口配置、图标、样式表和模块化JavaScript。

使用Vite进行工程化配置

文档1中提到了使用Vite全栈脚手架搭建项目,这是非常正确的选择。Vite能为我们提供:

  1. 快速的开发服务器:基于ESM的热重载,提升开发效率
  2. 环境变量支持:安全地管理敏感信息
  3. 模块化支持:直接使用ES6模块语法

初始化Vite项目的命令如下:

npm create vite@latest llm-demo -- --template vanilla

三、环境变量配置与API密钥安全管理

文档3中提到了关键的安全实践:将API Key放到.env文件中。这是前端调用大模型时必须遵守的安全准则。

环境变量配置

在Vite项目中,我们需要创建.env文件来存储敏感信息:

# .env文件
VITE_DEEPSEEK_API_KEY=your_actual_api_key_here

Vite规定只有以VITE_开头的变量才会被暴露给前端客户端,这是一种安全设计。在代码中,我们通过import.meta.env.VITE_DEEPSEEK_API_KEY来访问这个变量。 重要安全提醒:务必在.gitignore中添加.env,防止将API密钥意外提交到代码仓库。

四、深入理解fetch复杂请求

文档3提供了完整的调用代码,我们来逐部分解析这个复杂的HTTP请求。

请求端点与请求头配置

const endpoint = 'https://api.deepseek.com/chat/completions';
const headers = {
  'Content-type': 'application/json',
  'Authorization': `Bearer ${import.meta.env.VITE_DEEPSEEK_API_KEY}`
};
  • endpoint:DeepSeek提供的聊天补全API地址
  • Content-type:声明请求体为JSON格式
  • Authorization:身份验证头,使用Bearer令牌格式

请求体构造

const payload = {
  model: 'deepseek-chat',
  messages: [
    { role: 'system', content: 'you are a helpful assistant' },
    { role: 'user', content: '你好,Deepseek' }
  ]
};

请求体包含了调用大模型的核心参数:

  • model:指定使用的模型版本

  • messages:对话消息数组,包含角色和内容

    • system:系统提示,设定AI的行为模式
    • user:用户输入的消息

完整的fetch请求

const response = await fetch(endpoint, {
  method: 'POST',
  headers: headers,
  body: JSON.stringify(payload)
});

这里有几个关键技术点:

  1. POST方法:由于我们要向服务器提交数据,因此使用POST而非GET
  2. headers设置:包含内容类型和认证信息
  3. body处理:使用JSON.stringify()将JavaScript对象转换为JSON字符串

异步处理与响应解析

const data = await response.json();
console.log(data);
document.getElementById('reply').textContent = data.choices[0].message.content;
  • await关键字:使异步操作变得同步化,比传统的.then()链更清晰易读
  • 响应解析:将返回的JSON字符串解析为JavaScript对象
  • DOM操作:将AI回复内容显示在页面上

五、技术深度解析

为什么需要JSON.stringify?

这是很多初学者容易困惑的地方。HTTP协议只能传输文本或二进制数据,不能直接传输JavaScript对象。JSON.stringify()方法将对象序列化为JSON格式的字符串,以便在网络上传输。

Promise与异步编程

fetch返回的是一个Promise对象。在JavaScript中,处理异步操作有两种主流方式:

// 方式一:then链式调用
fetch(endpoint, options)
  .then(response => response.json())
  .then(data => {
    document.getElementById('reply').textContent = data.choices[0].message.content;
  })
  .catch(error => console.error('Error:', error));

// 方式二:async/await(文档3采用的方式)
async function callAI() {
  try {
    const response = await fetch(endpoint, options);
    const data = await response.json();
    document.getElementById('reply').textContent = data.choices[0].message.content;
  } catch (error) {
    console.error('Error:', error);
  }
}

async/await语法让异步代码看起来更像同步代码,大大提高了可读性。

错误处理的重要性

文档3中的代码没有显式的错误处理,在实际项目中我们应该添加:

try {
  const response = await fetch(endpoint, {
    method: 'POST',
    headers: headers,
    body: JSON.stringify(payload)
  });
  
  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }
  
  const data = await response.json();
  document.getElementById('reply').textContent = data.choices[0].message.content;
} catch (error) {
  console.error('调用失败:', error);
  document.getElementById('reply').textContent = '抱歉,请求失败,请稍后重试。';
}

六、完整代码整合

将各个部分整合后,我们的main.js文件应该如下:

// 配置API端点和请求头
const endpoint = 'https://api.deepseek.com/chat/completions';
const headers = {
  'Content-type': 'application/json',
  'Authorization': `Bearer ${import.meta.env.VITE_DEEPSEEK_API_KEY}`
};

// 构造请求数据
const payload = {
  model: 'deepseek-chat',
  messages: [
    { role: 'system', content: 'you are a helpful assistant' },
    { role: 'user', content: '你好,Deepseek' }
  ]
};

// 执行API调用
async function callDeepSeek() {
  try {
    const response = await fetch(endpoint, {
      method: 'POST',
      headers: headers,
      body: JSON.stringify(payload)
    });
    
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    
    const data = await response.json();
    console.log(data);
    document.getElementById('reply').textContent = data.choices[0].message.content;
  } catch (error) {
    console.error('Error calling DeepSeek API:', error);
    document.getElementById('reply').textContent = '请求失败: ' + error.message;
  }
}

// 页面加载后自动调用
callDeepSeek();

七、总结与展望

通过本文的实战,我们完成了从前端直接调用DeepSeek大模型的完整流程。我们不仅学会了如何构造复杂的HTTP请求,还掌握了环境变量配置、异步编程等关键技术点。 这种技术方案的优势在于快速简便,适合原型开发和学习使用。但在生产环境中,考虑到API密钥的安全性和请求的稳定性,建议通过自建后端服务进行代理转发。 前端与AI的结合为Web开发开辟了新的可能性。掌握这项技能,将让你在技术浪潮中保持竞争力。希望本文能为你的技术之旅提供有价值的参考!