Coze扣子 API 聊天智能机器人封装
这篇文章将介绍一个用于与Coze平台API交互的JavaScript类封装,它简化了与聊天机器人的交互过程。
演示网站:gofly.v1kf.com
什么是Coze API?
Coze是一个提供智能对话服务的平台,开发者可以通过API与平台上的聊天机器人进行交互。这个封装类就是为了简化API调用过程而设计的。
核心功能
这个Coze
类主要实现了以下功能:
- 单例模式:确保整个应用中只有一个Coze实例
- 会话管理:可以创建和管理与机器人的对话会话
- 两种交互模式:
- 流式聊天(实时接收消息片段)
- 轮询模式(等待完整响应)
代码结构解析
1. 初始化
const coze = new Coze(BOT_ID, API_KEY);
初始化时需要提供机器人的ID和API密钥。由于采用单例模式,多次初始化会返回同一个实例。
2. 创建会话
const conversationId = await coze.CreateConversation("用户ID");
为特定用户创建一个新的对话会话,并返回会话ID。
3. 发送消息
有两种方式发送消息:
流式模式(默认):
const response = await coze.ChatCozeV3(conversationId, "用户ID", "你好");
轮询模式:
const response = await coze._pollingChat(conversationId, "用户ID", "你好");
4. 辅助方法
类中还包含了一些内部使用的辅助方法:
_waitForCompletion
: 等待机器人完成响应_getFinalResponse
: 获取最终回复内容
使用示例
简单使用
// 初始化
const coze = new Coze("你的机器人ID", "你的API密钥");
// 发送消息
const response = await coze.ChatCozeV3("", "test_user", "你好");
console.log(response);
兼容旧代码
还提供了与原代码兼容的函数:
chatCozeAPI("机器人ID", "API密钥", "你好");
chatCozeAPIPolling("机器人ID", "API密钥", "你好");
设计考虑
- 灵活性:支持流式和轮询两种模式,适应不同场景需求
- 错误处理:对API错误进行了捕获和处理
- 会话管理:自动维护会话状态,简化开发者工作
- 兼容性:保持与旧代码的兼容
适用场景
这个封装类适用于:
- 需要快速集成Coze聊天机器人的Web应用
- 需要同时支持实时流式响应和完整响应的场景
- 需要管理多个用户对话的应用
class Coze { static instance = null; static API_URL = "https://api.coze.cn/v3/chat"; constructor(BOT_ID, API_KEY) { if (Coze.instance) { return Coze.instance; } this.BOT_ID = BOT_ID; this.API_KEY = API_KEY; this.conversation = {}; Coze.instance = this; } async CreateConversation(user) { if (this.conversation[user]) { return this.conversation[user]; } try { const response = await fetch("https://api.coze.cn/v1/conversation/create", { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.API_KEY}` }, body: JSON.stringify({ bot_id: this.BOT_ID, user_id: user, stream: false, auto_save_history: true, additional_messages: [] }) }); const data = await response.json(); if (data.code !== 0) { throw new Error(data.msg || 'Failed to create conversation'); } this.conversation[user] = data.data.id; return data.data.id; } catch (error) { console.error("创建会话失败:", error); return ""; } } async ChatCozeV3(conversation_id, user, query, messages = []) { // 兼容原逻辑:如果没有传入conversation_id,则创建新的 conversation_id = conversation_id || await this.CreateConversation(user); // 两种模式:流式(原逻辑)和非流式(Python逻辑) const useStream = false; // 默认使用流式,保持原逻辑 if (useStream) { return this._streamChat(conversation_id, user, query, messages); } else { return this._pollingChat(conversation_id, user, query, messages); } } async _streamChat(conversation_id, user, query, messages) { const url = `${Coze.API_URL}?conversation_id=${conversation_id}`; const message = { role: "user", content: query, content_type: "text" }; messages.push(message); const params = { bot_id: this.BOT_ID, user_id: user, query: query, additional_messages: messages, stream: true, auto_save_history: true }; try { const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.API_KEY}` }, body: JSON.stringify(params) }); const reader = response.body.getReader(); let result = ""; while (true) { const { done, value } = await reader.read(); if (done) break; const decoder = new TextDecoder(); const chunk = decoder.decode(value, { stream: true }); const lines = chunk.split("\n"); for (let i = 0; i < lines.length; i++) { let line = lines[i].trim(); if (line === "") continue; if (line.includes("[DONE]")) break; if (line.startsWith("event:conversation.message.delta")) { const dataLineIndex = lines.slice(i + 1).findIndex(l => l.startsWith("data:")); if (dataLineIndex !== -1) { const dataLine = lines[i + 1 + dataLineIndex]; const resStr = dataLine.trim().replace("data:", ""); const respJson = JSON.parse(resStr); result += respJson.content; i += dataLineIndex; } } } } return result; } catch (error) { console.error("流式请求失败:", error); return ""; } } async _pollingChat(conversation_id, user, query) { try { // 1. 发送消息 const response = await fetch(Coze.API_URL, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.API_KEY}` }, body: JSON.stringify({ bot_id: this.BOT_ID, user_id: user, additional_messages: [{ "role": "user", "content": query, "content_type": "text" }], stream: false, auto_save_history: true, conversation_id: conversation_id }) }); const data = await response.json(); if (data.code !== 0) { throw new Error(data.msg || 'API请求失败'); } const chatId = data.data.id; conversation_id = data.data.conversation_id; // 2. 等待处理完成 await this._waitForCompletion(chatId, conversation_id); // 3. 获取最终回复 return await this._getFinalResponse(chatId, conversation_id); } catch (error) { // 3. 获取最终回复 return await this._getFinalResponse(chatId, conversation_id); return ""; } } async _waitForCompletion(chatId, conversationId, maxRetries = 30, interval = 1000) { const url = `${Coze.API_URL}/retrieve`; for (let i = 0; i < maxRetries; i++) { try { const response = await fetch(`${url}?chat_id=${chatId}&conversation_id=${conversationId}`, { headers: { 'Authorization': `Bearer ${this.API_KEY}` } }); const data = await response.json(); if (data.code !== 0) { throw new Error(data.msg || 'API请求失败'); } if (data.data.status === "completed") { return true; } await new Promise(resolve => setTimeout(resolve, interval)); } catch (error) { throw error; } } throw new Error("等待响应超时"); } async _getFinalResponse(chatId, conversationId) { const url = `${Coze.API_URL}/message/list`; try { const response = await fetch(`${url}?chat_id=${chatId}&conversation_id=${conversationId}`, { headers: { 'Authorization': `Bearer ${this.API_KEY}` } }); const data = await response.json(); if (data.code !== 0) { throw new Error(data.msg || 'API请求失败'); } // 提取助手的回复 const assistantReplies = data.data.filter(msg => msg.role === "assistant" && msg.type === "answer" ); return assistantReplies.length > 0 ? assistantReplies[assistantReplies.length - 1].content : ""; } catch (error) { throw error; } } } // 完全兼容原使用方式 async function chatCozeAPI(botId, apiKey, query) { const coze = new Coze(botId, apiKey); const user = "test_user"; const messages = []; const response = await coze.ChatCozeV3("", user, query, messages); console.log("Chat Response:", response); return response; } // 也可以使用新的轮询模式 async function chatCozeAPIPolling(botId, apiKey, query) { const coze = new Coze(botId, apiKey); const user = "test_user"; const messages = []; // 临时关闭流式模式 const originalChat = coze.ChatCozeV3.bind(coze); coze.ChatCozeV3 = async function(...args) { return this._pollingChat(...args); }; try { const response = await coze.ChatCozeV3("", user, query, messages); console.log("Chat Response (Polling):", response); return response; } finally { // 恢复原方法 coze.ChatCozeV3 = originalChat; } }
十年开发经验程序员,离职全心创业中,历时三年开发出的产品《唯一客服系统》
一款基于Golang+Vue开发的在线客服系统,软件著作权编号:2021SR1462600。一套可私有化部署的网站在线客服系统,编译后的二进制文件可直接使用无需搭开发环境,下载zip解压即可,仅依赖MySQL数据库,是一个开箱即用的全渠道在线客服系统,致力于帮助广大开发者/公司快速部署整合私有化客服功能。
开源地址:唯一客服(开源学习版)
官网地址:唯一客服官网