从零到一:前端调用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能为我们提供:
- 快速的开发服务器:基于ESM的热重载,提升开发效率
- 环境变量支持:安全地管理敏感信息
- 模块化支持:直接使用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)
});
这里有几个关键技术点:
- POST方法:由于我们要向服务器提交数据,因此使用POST而非GET
- headers设置:包含内容类型和认证信息
- 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开发开辟了新的可能性。掌握这项技能,将让你在技术浪潮中保持竞争力。希望本文能为你的技术之旅提供有价值的参考!