从零构建智能对话系统:AI Agent 实战指南
引言:AI Agent 时代的到来
在人工智能飞速发展的今天,AI Agent(智能代理)已经成为连接人类与智能服务的重要桥梁。不同于传统的问答系统,现代 AI Agent 具备理解上下文、保持对话连贯性、执行复杂任务的能力。本文将通过一个实际项目,带你深入了解如何构建一个基于 Coze 平台的 AI Agent 应用。
一、项目架构设计
1.1 技术选型思路
我们的项目采用原生 HTML/CSS/JS 技术栈,配合 Vite 构建工具,这是一个轻量级但功能完整的技术方案:
- HTML5:语义化结构,确保可访问性
- CSS3:现代化样式,响应式布局
- 原生 JavaScript:直接操作 DOM,理解底层原理
- Vite:下一代前端构建工具,提供极速的开发体验
这种技术组合的优势在于:
- 零框架依赖:无需学习 React、Vue 等框架,降低入门门槛
- 即时反馈:修改代码后浏览器立即更新
- 生产优化:自动代码压缩、资源优化
1.2 项目结构
bash
coze-api-demo/
├── index.html # 页面结构
├── style.css # 样式文件
├── script.js # 业务逻辑
├── package.json # 项目配置
├── vite.config.js # Vite 配置
└── .env.local # 环境变量(敏感信息)
二、核心功能实现
2.1 用户界面设计
我们的界面设计遵循"极简主义"原则,核心元素只有一个输入框和一个回复区域:
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Coze API Demo - 随处智能</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1>Coze API Demo 随处智能</h1>
<input type="text" id="ipt" placeholder="请输入问题">
<div id="reply">thinking...</div>
</header>
<script type="module" src="script.js"></script>
</body>
</html>
设计思路解析:
id="ipt"的输入框是用户与 AI 交互的唯一入口id="reply"的 div 用于展示 AI 的回复内容type="module"启用 ES 模块,支持现代 JavaScript 特性
2.2 环境变量管理
在实际项目中,API 密钥等敏感信息绝不能硬编码在代码中。我们使用 .env.local 文件存储配置:
bash
# .env.local
VITE_BOT_ID=7614110594396504104
VITE_API_KEY=cztei_xxxxxxxxxxxxxxxx
为什么使用 VITE_ 前缀?
Vite 有一个安全机制:只有以 VITE_ 开头的环境变量才会被暴露给客户端代码。这是为了防止意外将敏感的服务端配置泄露到浏览器。
2.3 核心交互逻辑
这是整个项目最关键的部分,我们一步步拆解:
javascript
// 1. 获取 DOM 元素
const ipt = document.getElementById('ipt');
const reply = document.getElementById('reply');
// 2. 配置 API 端点
const endPoint = 'https://api.coze.cn/open_api/v2/chat';
// 3. 读取环境变量(在模块顶层执行,只需读取一次)
const botId = import.meta.env?.VITE_BOT_ID || '';
const apiKey = import.meta.env?.VITE_API_KEY || '';
关键设计决策:
- 将环境变量的读取放在模块顶层,而不是函数内部,避免每次调用都重复读取
- 使用可选链操作符
?.和默认值|| '',提供优雅的降级处理
2.4 事件监听与异步处理
用户输入问题时,我们需要监听 change 事件:
javascript
ipt.addEventListener('change', async function(event) {
const prompt = event.target.value;
console.log('用户输入:', prompt);
// 前置校验:确保配置完整
if (!botId || !apiKey) {
console.error('环境变量未设置');
reply.innerHTML = '错误:请检查 .env 文件配置';
return;
}
为什么选择 change 事件而不是 input 事件?
input事件:用户每输入一个字符就触发,适合实时搜索change事件:用户完成输入(失去焦点或按回车)后触发,适合提交表单
对于 AI 对话场景,change 事件更符合用户习惯:用户输入完整问题后,按回车或点击其他地方才发送请求。
2.5 请求体构造
Coze API 的请求体结构体现了现代对话系统的设计理念:
javascript
const payload = {
bot_id: botId, // 指定使用哪个 AI Bot
user: 'user123', // 用户标识(实际项目中应使用真实用户ID)
query: prompt, // 用户的问题
chat_history: [], // 对话历史(支持多轮对话)
stream: false, // 是否流式返回(false 表示一次性返回完整回复)
custom_variables: { // 自定义变量,用于个性化配置
prompt: '你是一个AI助手'
}
};
chat_history 的作用:
虽然当前设置为 [],但这个字段是实现"多轮对话"的关键。通过保存历史对话记录,AI 能够理解上下文,比如:
javascript
// 第一轮对话
chat_history: []
用户:北京今天天气怎么样?
AI:北京今天晴天,25度。
// 第二轮对话(带上历史记录)
chat_history: [
{role: 'user', content: '北京今天天气怎么样?'},
{role: 'assistant', content: '北京今天晴天,25度。'}
]
用户:那明天呢?
AI:明天北京多云,22度。
2.6 网络请求与错误处理
javascript
try {
const response = await fetch(endPoint, {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
});
const data = await response.json();
// 安全地提取回复内容
reply.innerHTML = data.messages?.[0]?.content || '暂无回复';
} catch (error) {
console.error('请求失败:', error);
reply.innerHTML = '请求失败,请检查网络连接或配置';
}
错误处理的三层防护:
- try-catch:捕获网络层错误(断网、DNS 解析失败等)
- response.ok 检查 :虽然代码中省略了,但生产环境应该检查
if (!response.ok) throw new Error('HTTP error') - 可选链操作符 :
data.messages?.[0]?.content防止数据结构不符合预期时报错
三、工程化实践
3.1 Vite 配置详解
javascript
// vite.config.js
import { defineConfig } from 'vite'
export default defineConfig({
base: './', // 相对路径,确保部署到任意子目录都能正常工作
server: {
port: 3000 // 开发服务器端口
},
build: {
outDir: 'dist' // 构建输出目录
}
})
base: './' 的重要性:
默认情况下,Vite 使用绝对路径 /。如果项目部署到 https://example.com/app/ 这样的子目录,资源加载会失败。设置为 ./ 后,所有资源引用都变为相对路径,适配任意部署环境。
3.2 开发工作流
json
{
"scripts": {
"dev": "vite", // 启动开发服务器,支持热更新
"build": "vite build", // 构建生产版本,自动优化
"preview": "vite preview" // 预览生产构建
}
}
开发时的最佳实践:
- 运行
npm run dev启动开发服务器 - 修改代码后浏览器自动刷新
- 开发完成后运行
npm run build生成优化后的代码 - 使用
npm run preview在本地验证生产构建
四、AI Agent 的进阶思考
4.1 从简单对话到智能代理
当前的实现是一个"对话界面",但真正的 AI Agent 应该具备:
记忆能力:
javascript
// 使用 localStorage 持久化对话历史
const chatHistory = JSON.parse(localStorage.getItem('chat') || '[]');
// 发送请求时带上历史记录
const payload = {
...其他配置,
chat_history: chatHistory.slice(-10) // 只保留最近10轮对话
};
// 保存新的对话记录
chatHistory.push(
{role: 'user', content: prompt},
{role: 'assistant', content: data.messages[0].content}
);
localStorage.setItem('chat', JSON.stringify(chatHistory));
工具调用能力:
现代 AI Agent 不仅能对话,还能调用外部工具完成任务:
javascript
// 示例:AI 决定调用天气查询工具
const tools = [{
name: 'get_weather',
description: '查询指定城市的天气',
parameters: {
city: {type: 'string', description: '城市名称'}
}
}];
// AI 返回工具调用请求
// 系统执行工具,将结果返回给 AI
// AI 基于工具结果生成自然语言回复
4.2 流式响应优化
当前实现使用 stream: false,等待完整回复后才显示。更好的用户体验是流式输出:
javascript
// 设置 stream: true
const payload = { ...其他配置, stream: true };
const response = await fetch(endPoint, {
method: 'POST',
headers: { ... },
body: JSON.stringify(payload)
});
// 使用 ReadableStream 处理流式数据
const reader = response.body.getReader();
while (true) {
const {done, value} = await reader.read();
if (done) break;
// 逐字显示,营造"打字"效果
reply.innerHTML += decodeChunk(value);
}
五、总结与展望
通过这个项目,我们学习了:
- AI Agent 的基本架构:前端界面 + API 调用 + 响应处理
- 现代前端工程化:Vite 构建、环境变量管理、模块化开发
- 错误处理的艺术:优雅降级、用户友好的错误提示
- 可扩展的设计:预留多轮对话、工具调用等进阶功能
AI Agent 正在从"能对话"向"能办事"进化。未来的智能代理将深度集成到工作流中,成为真正的数字助手。掌握这些基础技术,你就能在这个浪潮中构建属于自己的智能应用。