核心内容摘要
神秘电影:如果你的世界,被一部电影悄然改变
目录
项目整体文件结构
后端代码app.py全解析
1 模块导入与环境初始化
2 Coze AI 交互类封装CozeService
3 Flask 路由与业务接口实现
4 项目启动入口
前端代码index.html全解析
1 HTML 结构聊天界面的骨架
2 CSS 样式美观的视觉设计与响应式布局
3 JavaScript 交互前后端通信与 DOM 操作
环境配置与依赖文件
1 .env 文件敏感信息配置
2 requirements.txtPython 依赖清单
项目完整运行步骤
1 前置准备
2 运行步骤
代码优化与扩展
1 会话清理优化添加时间阈值
2 前端添加清空聊天记录功能
3 生产环境部署优化
核心代码要点
总结在 AI 应用开发的轻量场景中无需复杂的架构设计仅用 Python 原生前端技术就能基于 Flask 框架和 Coze AI 开放平台搭建一款支持会话保持、可视化交互、异常处理的完整 AI 聊天机器人。
本文将逐行拆解核心代码从环境配置、后端逻辑封装、前端交互实现到整体运行流程全方位讲解代码的设计思路和实现细节让你不仅能跑通项目更能理解每一行代码的作用。
项目整体文件结构本项目采用前后端一体化部署Flask 直接托管前端页面无需额外的前端服务器文件结构极简仅需 4 个核心文件即可完成开发新手也能快速上手ai_chatbot/ ├── app.py # 后端核心代码Flask服务、Coze AI交互、会话管理 ├── index.html # 前端核心代码聊天界面、交互逻辑、样式美化 ├── .env # 环境配置文件存储Coze API令牌、机器人ID敏感信息 └── requirements.txt# 依赖清单管理Python第三方库所有代码各司其职后端专注于业务逻辑和 AI 交互前端专注于视觉呈现和用户操作代码解耦且易于维护。
后端代码app.py全解析后端基于 Flask 开发核心功能包括加载环境变量、封装 Coze AI 交互逻辑、实现聊天 API 接口、维护用户会话状态、清理过期会话每一行代码都附带详细注释以下按代码模块逐段解析。
1 模块导入与环境初始化这是项目的基础准备阶段导入所需的第三方库并加载环境变量避免敏感信息硬编码在代码中。
# 导入必要的库和模块 import os # 用于读取操作系统环境变量如.env中的配置 from flask import Flask, request, jsonify, send_file # Flask核心创建服务、处理请求、返回JSON、托管静态文件 from cozepy import Coze, TokenAuth, ChatStatus, COZE_CN_BASE_URL, Message # Coze AI官方SDK所有AI交互的核心 from dotenv import load_dotenv # 加载.env文件中的环境变量隔离敏感信息 import uuid # 生成唯一的用户ID保证每个用户会话的唯一性 import time # 处理时间戳记录会话创建时间、最后活动时间用于清理过期会话 # 加载.env文件中的环境变量执行后可通过os.getenv(KEY)获取配置值 load_dotenv() # 创建Flask应用实例__name__表示当前模块名Flask会基于此查找静态文件 app Flask(__name__) # 定义全局会话字典存储所有用户的会话状态 # key用户唯一标识本文用客户端IPvalue会话详细信息字典格式 # 作用实现多轮对话的会话保持让Coze AI能识别上下文 user_sessions {}核心要点load_dotenv()必须在读取环境变量前执行否则无法获取.env中的配置user_sessions全局内存字典是实现会话保持的关键后续所有会话操作都基于此字典导入的ChatStatusCoze AI 的聊天状态枚举IN_PROGRESS 进行中 / COMPLETED 已完成用于轮询获取 AI 回复。
2 Coze AI 交互类封装CozeService这是后端的核心业务类将与 Coze AI 的所有交互逻辑封装在一个类中实现代码复用和逻辑解耦。
后续若需替换 AI 平台如 OpenAI、文心一言仅需修改此类无需改动其他业务代码。
# 定义Coze服务类封装与Coze AI的所有交互逻辑对外提供统一调用接口 class CozeService: def __init__(self): 初始化Coze客户端从环境变量加载配置 # 从.env文件读取Coze API令牌敏感信息切勿硬编码 self.api_token os.getenv(COZE_API_TOKEN) # 从.env读取机器人ID若未配置则使用默认值可根据自己的机器人ID修改 self.bot_id os.getenv(BOT_ID,
# 初始化Coze官方客户端配置认证方式和服务地址 self.coze Coze( authTokenAuth(tokenself.api_token), # 令牌认证Coze的核心认证方式 base_urlCOZE_CN_BASE_URL # 中国区服务地址无需修改 ) def get_sdk_response(self, user_message, user_identifier): 获取Coze AI的智能回复基于用户标识保持会话 :param user_message: 前端传递的用户输入消息 :param user_identifier: 用户唯一标识本文为客户端IP :return: 字典格式的响应结果statuscontent try: # 第一步判断用户是否已有会话实现会话保持的核心逻辑 if user_identifier in user_sessions: # 存在会话从全局字典中读取已有会话信息 session_data user_sessions[user_identifier] conversation_id session_data[conversation_id] # Coze的会话ID关联上下文 user_id session_data[user_id] # 生成的唯一用户ID # 构建用户消息符合Coze SDK的Message格式要求 messages [ Message( roleuser, # 消息角色user用户/assistant助手 contentuser_message, # 消息内容用户输入的文本 content_typetext, # 内容类型text文本/image图片 typequestion # 消息类型question问题 ) ] # 存在会话调用Coze SDK继续现有聊天复用conversation_id和user_id chat self.coze.chat.create( bot_idself.bot_id, user_iduser_id, conversation_idconversation_id, # 复用会话ID关联上下文 additional_messagesmessages, auto_save_historyTrue # 自动保存聊天历史Coze平台端可查看 ) else: # 不存在会话创建新的用户会话 # 生成唯一的用户ID使用uuid4保证全球唯一避免冲突 user_id str(uuid.uuid4()) # 构建用户消息格式与已有会话一致 messages [ Message( roleuser, contentuser_message, content_typetext, typequestion ) ] # 不存在会话调用Coze SDK创建新聊天无conversation_id chat self.coze.chat.create( bot_idself.bot_id, user_iduser_id, # 新生成的用户ID additional_messagesmessages, auto_save_historyTrue ) # 关键操作将新会话信息存入全局字典供后续对话复用 user_sessions[user_identifier] { conversation_id: chat.conversation_id, # Coze返回的会话ID核心关联上下文 user_id: user_id, # 本地生成的用户ID chat_id: chat.id, # Coze返回的聊天ID每次对话的唯一标识 created_at: time.time(), # 会话创建时间戳秒 last_activity: time.time() # 会话最后活动时间戳用于清理过期会话 } # 第二步更新会话的最后活动时间和chat_id每次对话都要更新 user_sessions[user_identifier][last_activity] time.time() user_sessions[user_identifier][chat_id] chat.id # 每次对话的chat_id不同需更新 # 第三步轮询等待Coze AI处理完成核心Coze AI处理需要时间非即时响应 # 当聊天状态为进行中IN_PROGRESS时持续查询状态 while chat.status ChatStatus.IN_PROGRESS: # 调用Coze SDK查询当前聊天状态和结果 chat self.coze.chat.retrieve( conversation_idchat.conversation_id, chat_idchat.id ) # 第四步处理Coze AI的响应结果状态为已完成COMPLETED时 if chat.status ChatStatus.COMPLETED: # 调用Coze SDK获取当前聊天的所有消息 messages self.coze.chat.messages.list( conversation_idchat.conversation_id, chat_idchat.id ) # 遍历消息列表找到助手assistant的回复过滤用户消息 for msg in messages: if msg.role assistant: # 返回成功结果statussuccess 助手回复内容 return { status: success, content: msg.content } # 若聊天状态非已完成返回失败结果 return {status: failed, content: 对话未完成AI处理超时} except Exception as e: # 异常捕获捕获所有可能的错误API令牌错误、网络问题、SDK调用错误等 # 返回错误结果statuserror 异常详细信息便于调试 return {status: error, content: str(e)} # 创建CozeService实例全局唯一所有请求复用此实例 coze_service CozeService()核心要点会话保持的核心conversation_idCoze 返回的会话 ID复用此 ID 即可让 Coze AI 识别聊天上下文实现多轮对话Message 格式必须严格符合 Coze SDK 的要求role/content_type等字段不能写错否则 SDK 调用失败轮询机制Coze AI 处理消息需要时间约
秒需通过while循环轮询chat.status直到状态变为COMPLETED异常捕获使用try-except捕获所有异常保证单个请求错误不会导致整个 Flask 服务崩溃同时返回错误信息便于调试全局实例coze_service CozeService()放在类外所有请求复用此实例避免重复创建客户端。
3 Flask 路由与业务接口实现Flask 的路由是前后端通信的桥梁本项目实现了 2 个核心路由首页路由返回前端页面、聊天路由处理用户消息请求同时实现了过期会话清理函数。
# 路由1首页路由GET请求访问根路径时触发 app.route(/) def index(): # 每次访问首页时清理过期会话释放内存避免字典无限膨胀 cleanup_expired_sessions() # 返回前端页面index.htmlsend_file直接托管静态文件实现前后端一体化 return send_file(index.html) # 路由2聊天核心接口POST请求前端发送消息时调用 app.route(/chat, methods[POST]) def chat(): 处理前端的聊天请求返回JSON格式的AI回复 # 第一步解析前端传递的JSON数据前端通过Fetch API发送{message: 用户输入} data request.json user_message data.get(message) # 获取用户消息字段 # 第二步非空校验避免空消息提交 if not user_message: # 返回JSON格式响应Flask的jsonify自动设置Content-Type为application/json return jsonify({status: error, content: 消息不能为空}) # 第三步获取用户唯一标识本文使用客户端IP简单易实现 user_identifier request.remote_addr # 第四步调用CozeService实例的方法获取AI回复 response coze_service.get_sdk_response(user_message, user_identifier) # 第五步将AI回复转换为JSON格式返回给前端 return jsonify(response) # 辅助函数清理过期会话核心释放内存优化性能 def cleanup_expired_sessions(): 清理过期会话的核心函数 注基础版本暂未设置时间阈值后续可扩展为“30分钟无活动则清理” # 定义空列表存储需要删除的过期会话标识 expired_sessions [] # 遍历全局会话字典收集过期会话基础版本收集所有会话可按需修改 for user_identifier, session_data in user_sessions.items(): expired_sessions.append(user_identifier) # 遍历过期会话列表从全局字典中删除避免遍历中修改字典导致的错误 for user_identifier in expired_sessions: del user_sessions[user_identifier]核心要点请求方法聊天接口必须使用POST方法因为需要传递 JSON 数据且符合 HTTP 规范GET 方法不适合传递请求体request.jsonFlask 内置的 JSON 解析方法自动解析前端发送的application/json格式请求体user_identifier本文使用request.remote_addr客户端 IP作为用户标识简单易实现适合个人测试send_fileFlask 的静态文件托管方法直接返回index.html实现前后端一体化部署无需额外的 Nginx/Apachecleanup_expired_sessions基础版本暂未设置时间阈值后续可添加if time.time() - session_data[last_activity] 180030 分钟实现真正的过期清理。
4 项目启动入口这是 Python 项目的标准启动方式判断是否直接运行当前脚本若是则启动 Flask 服务。
# 项目启动入口仅当直接运行app.py时执行以下代码 if __name__ __main__: # 启动Flask服务debugTrue调试模式代码修改后自动重启port5000服务端口 app.run(debugTrue, port
核心要点debugTrue仅适合开发环境生产环境必须关闭存在安全风险port5000Flask 默认端口可修改为
80 等需管理员权限启动后服务地址http://
127.
0.
1:5000直接在浏览器访问即可。
前端代码index.html全解析前端采用原生 HTMLCSSJavaScript开发无任何前端框架依赖实现了美观的响应式界面和流畅的交互体验同时兼顾了移动端适配。
代码分为HTML 结构、CSS 样式、JavaScript 交互三部分以下逐部分解析。
1 HTML 结构聊天界面的骨架HTML 结构遵循语义化原则分为头部标题、聊天容器消息展示 正在输入提示、输入区域输入框 发送按钮三部分结构清晰便于后续 DOM 操作。
!DOCTYPE html html langzh-CN head meta charsetUTF-8 !-- 视口设置移动端适配核心保证页面在手机上正常显示 -- meta nameviewport contentwidthdevice-width, initial-scale
0 title我的人生我做主/title !-- 内嵌CSS样式便于一体化部署无需单独的css文件 -- style/* 样式代码见下文 *//style /head body !-- 主容器卡片式布局限制最大宽度居中显示 -- div classcontainer !-- 头部标题副标题渐变背景 -- header h1我的未来我做主/h1 p与AI助手一起规划您的未来/p /header !-- 聊天容器包含消息展示区和正在输入提示 -- div classchat-container !-- 聊天消息展示区滚动显示所有聊天记录 -- div idchat-messages classchat-messages !-- 初始消息机器人欢迎语页面加载时显示 -- div classmessage bot-message p您好我是您的未来规划助手。
请问您想了解什么关于未来规划的问题/p /div /div !-- 正在输入提示机器人处理消息时显示默认隐藏 -- div classtyping-indicator idtyping-indicator div classtyping-dots div classtyping-dot/div div classtyping-dot/div div classtyping-dot/div /div /div /div !-- 输入区域输入框发送按钮底部固定 -- div classinput-area input typetext iduser-input placeholder输入您的问题... button idsend-button发送/button /div /div !-- 内嵌JavaScript交互逻辑页面加载后执行 -- script/* 交互代码见下文 *//script /body /html核心要点移动端适配meta nameviewport ...是移动端适配的核心保证页面在手机上不会缩放变形ID 命名规范所有需要 JavaScript 操作的元素都设置了唯一 ID如chat-messages、user-input便于通过getElementById获取默认隐藏元素typing-indicator正在输入提示默认通过 CSS 隐藏需要时通过 JavaScript 修改样式显示初始消息页面加载时显示机器人欢迎语提升用户体验避免空白界面。
2 CSS 样式美观的视觉设计与响应式布局CSS 样式采用原生 CSS3开发实现了渐变色背景、卡片式布局、消息气泡样式、动画效果和移动端适配所有样式都添加了详细的注释便于修改和定制。
* { margin: 0; padding: 0; box-sizing: border-box; /* 盒模型padding/border计入元素宽度避免布局错乱 */ } body { font-family: Arial, sans-serif; /* 全局字体无衬线字体适配所有设备 */ /* 页面背景线性渐变提升视觉体验 */ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); color: #333; line-height:
6; /* 行高提升文本可读性 */ min-height: 100vh; /* 最小高度占满整个视口高度 */ padding: 20px; /* 页面内边距避免内容贴边 */ } .container { max-width: 900px; /* 最大宽度桌面端限制宽度居中显示 */ margin: 0 auto; /* 水平居中核心布局技巧 */ background-color: white; border-radius: 15px; /* 圆角卡片式布局柔和视觉 */ box-shadow: 0 10px 30px rgba(0, 0, 0,
0.
; /* 阴影提升层次感 */ overflow: hidden; /* 溢出隐藏避免子元素超出圆角 */ } header { /* 头部渐变背景蓝黑渐变符合AI产品的科技感 */ background: linear-gradient(90deg, #3498db, #2c3e
; color: white; padding: 30px 20px; text-align: center; /* 文本居中 */ } header h1 { font-size:
5rem; /* 大标题字体rem单位适配移动端 */ margin-bottom: 10px; text-shadow: 1px 1px 3px rgba(0, 0, 0,
0.
; /* 文字阴影提升辨识度 */ } header p { font-size:
2rem; opacity:
9; /* 透明度副标题弱化突出主标题 */ } .chat-container { display: flex; flex-direction: column; /* 弹性布局垂直方向排列子元素 */ height: 500px; /* 固定高度聊天区域不会随消息增多无限增高 */ } .chat-messages { flex: 1; /* 弹性占比占满chat-container的剩余高度 */ overflow-y: auto; /* 垂直滚动消息过多时可滚动查看 */ padding: 20px; background-color: #f9f9f9; /* 浅灰色背景区分消息区域和输入区域 */ } /* 消息气泡通用样式 */ .message { margin-bottom: 15px; /* 消息之间的间距 */ padding: 12px 18px; /* 消息内边距文本不贴边 */ border-radius: 18px; /* 大圆角气泡样式符合聊天软件习惯 */ max-width: 80%; /* 最大宽度消息不会过宽提升可读性 */ animation: fadeIn
3s ease; /* 淡入动画消息展示更流畅 */ } /* 淡入动画CSS3关键帧动画消息从透明到不透明轻微上移 */ keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(
; } } /* 用户消息样式右侧蓝色背景白色文字 */ .user-message { background-color: #3498db; color: white; margin-left: auto; /* 右对齐核心技巧将元素推到右侧 */ border-bottom-right-radius: 5px; /* 右下角小圆角符合聊天气泡的视觉习惯 */ } /* 机器人消息样式左侧浅灰色背景黑色文字 */ .bot-message { background-color: #ecf0f1; color: #333; margin-right: auto; /* 左对齐核心技巧将元素推到左侧 */ border-bottom-left-radius: 5px; /* 左下角小圆角与用户消息呼应 */ } .input-area { display: flex; /* 弹性布局输入框和按钮横向排列 */ padding: 15px; border-top: 1px solid #eee; /* 上边框区分输入区域和消息区域 */ background-color: white; } #user-input { flex: 1; /* 弹性占比输入框占满剩余宽度 */ padding: 12px 18px; border: 1px solid #ddd; /* 浅灰色边框 */ border-radius: 25px; /* 大圆角输入框样式更柔和 */ outline: none; /* 去除默认焦点边框 */ font-size: 1rem; transition: border-color
3s; /* 过渡效果焦点时边框颜色平滑变化 */ } /* 输入框焦点样式蓝色边框浅蓝阴影提升交互反馈 */ #user-input:focus { border-color: #3498db; box-shadow: 0 0 0 2px rgba(52, 152, 219,
0.
; } #send-button { margin-left: 10px; /* 按钮与输入框的间距 */ padding: 12px 25px; background-color: #3498db; /* 主色调与用户消息背景一致 */ color: white; border: none; /* 去除默认边框 */ border-radius: 25px; /* 大圆角与输入框呼应 */ cursor: pointer; /* 鼠标悬浮为手型提示可点击 */ font-size: 1rem; /* 过渡效果悬停和点击时样式平滑变化 */ transition: background-color
3s, transform
2s; } /* 按钮悬停样式加深背景色轻微放大 */ #send-button:hover { background-color: #2980b9; transform: scale(
1.
; } /* 按钮点击样式轻微缩小模拟按压效果 */ #send-button:active { transform: scale(
0.
; } /* 正在输入提示默认隐藏 */ .typing-indicator { display: none; padding: 10px 15px; background-color: #ecf0f1; /* 与机器人消息背景一致 */ border-radius: 18px; margin-bottom: 15px; width: fit-content; /* 宽度自适应内容避免过宽 */ border-bottom-left-radius: 5px; /* 与机器人消息呼应 */ } .typing-dots { display: flex; /* 弹性布局三个点横向排列 */ align-items: center; height: 20px; } /* 打字点点样式小圆点模拟机器人思考 */ .typing-dot { width: 8px; height: 8px; background-color: #7f8c8d; border-radius: 50%; /* 圆形核心技巧 */ margin: 0 3px; /* 点之间的间距 */ animation: typingAnimation
4s infinite ease-in-out; /* 无限动画持续跳动 */ } /* 三个点的动画延迟依次延迟0/
2/
4秒实现交替跳动效果 */ .typing-dot:nth-child(
{ animation-delay: 0s; } .typing-dot:nth-child(
{ animation-delay:
2s; } .typing-dot:nth-child(
{ animation-delay:
4s; } /* 打字动画小圆点上下跳动模拟机器人输入 */ keyframes typingAnimation { 0%, 60%, 100% { transform: translateY(
; } 30% { transform: translateY(-5px); } } /* 媒体查询移动端适配屏幕宽度≤600px时生效 */ media (max-width: 600px) { header h1 { font-size: 2rem; /* 缩小主标题字体 */ } header p { font-size: 1rem; /* 缩小副标题字体 */ } .message { max-width: 90%; /* 增大消息最大宽度适配小屏幕 */ } #send-button { padding: 12px 20px; /* 缩小按钮内边距节省空间 */ } }核心要点盒模型box-sizing: border-box是前端布局的核心技巧避免 padding/border 导致元素宽度超出预期弹性布局Flex全程使用display: flex实现布局替代传统的 float布局更简单、更灵活消息对齐margin-left: auto右对齐和margin-right: auto左对齐是实现消息气泡左右分布的核心技巧无需浮动CSS3 动画通过keyframes实现消息淡入和打字点点动画提升用户体验无额外 JavaScript 开销响应式布局通过media (max-width: 600px)实现移动端适配针对小屏幕调整字体、间距等样式rem 单位字体使用rem单位基于根元素html的字体大小适配不同设备的屏幕分辨率。
3 JavaScript 交互前后端通信与 DOM 操作JavaScript 是前端的交互核心实现了消息发送、前后端异步通信、DOM 动态更新、正在输入提示等功能所有代码都封装在DOMContentLoaded事件中确保页面元素加载完成后再执行避免获取不到元素的错误。
// 页面DOM元素加载完成后执行避免获取不到元素的错误 document.addEventListener(DOMContentLoaded, function() { // 第一步获取所有需要操作的DOM元素全局变量函数内复用 const chatMessages document.getElementById(chat-messages); // 消息展示区 const userInput document.getElementById(user-input); // 输入框 const sendButton document.getElementById(send-button); // 发送按钮 const typingIndicator document.getElementById(typing-indicator); // 正在输入提示 // 函数1添加用户消息到聊天界面 function addUserMessage(message) { const messageElement document.createElement(div); // 创建新的div元素 messageElement.classList.add(message, user-message); // 添加样式类通用消息用户消息 messageElement.innerHTML p${message}/p; // 设置消息内容 chatMessages.appendChild(messageElement); // 将消息元素添加到展示区 scrollToBottom(); // 自动滚动到底部查看最新消息 } // 函数2添加机器人消息到聊天界面与用户消息逻辑一致样式类不同 function addBotMessage(message) { const messageElement document.createElement(div); messageElement.classList.add(message, bot-message); // 添加样式类通用消息机器人消息 messageElement.innerHTML p${message}/p; chatMessages.appendChild(messageElement); scrollToBottom(); // 自动滚动到底部 } // 函数3显示正在输入提示 function showTypingIndicator() { typingIndicator.style.display block; // 修改样式为显示 scrollToBottom(); // 滚动到底部让用户看到提示 } // 函数4隐藏正在输入提示 function hideTypingIndicator() { typingIndicator.style.display none; // 修改样式为隐藏 } // 函数5自动滚动聊天区域到底部核心工具函数多次复用 function scrollToBottom() { chatMessages.scrollTop chatMessages.scrollHeight; // scrollTop滚动条距离顶部的高度scrollHeight元素的总高度 } // 函数6核心函数——发送消息到后端处理响应 async function sendMessage() { // 第一步获取并清理用户输入去除首尾空格 const message userInput.value.trim(); // 非空校验如果消息为空直接返回不执行后续操作 if (!message) return; // 第二步更新前端界面——添加用户消息清空输入框 addUserMessage(message); userInput.value ; // 清空输入框方便下次输入 // 第三步显示正在输入提示模拟机器人思考 showTypingIndicator(); try { // 第四步异步请求后端接口Fetch API替代传统的AJAX const response await fetch(/chat, { method: POST, // 请求方法与后端路由一致必须为POST headers: { // 请求头告诉后端请求体是JSON格式必须设置否则后端request.json解析失败 Content-Type: application/json }, // 请求体将消息转换为JSON字符串与后端约定的格式一致 body: JSON.stringify({ message: message }) }); // 解析后端返回的JSON响应与后端jsonify返回的格式一致 const data await response.json(); // 第五步隐藏正在输入提示无论成功还是失败 hideTypingIndicator(); // 第六步处理后端响应结果更新前端界面 if (data.status success) { // 响应成功添加机器人消息显示AI回复 addBotMessage(data.content); } else { // 响应失败显示友好的错误提示同时在控制台打印详细错误便于调试 addBotMessage(抱歉我遇到了一些问题请稍后再试。
); console.error(API Error:, data.content); } } catch (error) { // 异常捕获捕获网络错误、请求超时等问题如后端服务未启动 hideTypingIndicator(); // 隐藏正在输入提示 addBotMessage(网络错误请检查您的连接。
); // 显示网络错误提示 console.error(Fetch Error:, error); // 控制台打印详细错误 } } // 事件1发送按钮点击事件——触发sendMessage函数 sendButton.addEventListener(click, sendMessage); // 事件2输入框回车事件——触发sendMessage函数支持回车发送 userInput.addEventListener(keypress, function(e) { // 判断是否按下回车键e.key Enter if (e.key Enter) { sendMessage(); } }); // 页面加载后输入框自动获取焦点提升用户体验 userInput.focus(); });核心要点DOMContentLoaded 事件所有代码都包裹在此事件中确保页面元素加载完成后再执行这是前端开发的最佳实践Fetch API使用现代的fetch替代传统的XMLHttpRequest实现异步前后端通信语法更简洁支持 Promise 和 async/awaitasync/await使用async/await处理异步请求替代传统的 Promise 链式调用代码更易读、更易维护请求头设置Content-Type: application/json必须设置否则后端request.json无法解析请求体会导致报错JSON 序列化JSON.stringify({ message: message })将 JavaScript 对象转换为 JSON 字符串符合后端的接收格式异常处理使用try-catch捕获所有异常网络错误、后端服务未启动、接口返回错误等保证前端页面不会崩溃同时给用户友好的提示自动焦点userInput.focus()让页面加载后输入框自动获取焦点用户可直接输入提升体验滚动到底部chatMessages.scrollTop chatMessages.scrollHeight是实现聊天区域自动滚动的核心技巧适用于所有滚动容器。
环境配置与依赖文件
1 .env 文件敏感信息配置.env文件用于存储敏感信息Coze API 令牌、机器人 ID避免硬编码在代码中提高项目的安全性文件内容如下# Coze AI API令牌从Coze开放平台获取替换为自己的 COZE_API_TOKENyour_coze_api_token # Coze机器人ID从Coze开放平台创建机器人后获取替换为自己的 BOT_IDyour_bot_id获取方式访问Coze 开放平台注册并登录账号创建机器人进入机器人设置页面获取机器人 ID进入个人中心 - API 密钥创建并获取API 令牌。
2 requirements.txtPython 依赖清单requirements.txt用于管理 Python 第三方库避免手动安装时版本不一致的问题文件内容如下# Flask框架轻量级Web框架核心依赖 flask
2.
0 # Coze AI官方SDK与Coze AI交互的核心依赖 cozepy
0.
0 # python-dotenv加载.env文件的环境变量 python-dotenv
1.
0安装命令在项目根目录执行以下命令自动安装所有依赖pip install -r requirements.txt
项目完整运行步骤
1 前置准备注册 Coze 开放平台账号创建机器人获取API 令牌和机器人 ID填入.env文件确保本地安装了 Python
8推荐
9-
11兼容性最好新建项目文件夹将app.py、index.html、.env、requirements.txt四个文件放入文件夹中。
2 运行步骤安装依赖打开命令行进入项目根目录执行pip install -r requirements.txt启动后端服务在项目根目录执行python app.py看到以下输出说明服务启动成功* Serving Flask app app * Debug mode: on WARNING: This is a development server. Do not use it in a production deployment. * Running on http://
127.
0.
1:5000 Press CTRLC to quit * Restarting with stat * Debugger is active! * Debugger PIN:
访问聊天界面打开浏览器输入http://
127.
0.
1:5000即可看到聊天界面代码验证在输入框中输入 “未来职业规划有什么建议”点击发送或按回车即可看到 AI 的回复同时实现多轮对话如继续问 “互联网行业怎么样”AI 能识别上下文。
代码优化与扩展现有代码实现了核心功能基于现有代码结构可快速实现以下优化和扩展无需重构代码
1 会话清理优化添加时间阈值修改cleanup_expired_sessions函数实现30 分钟无活动则清理会话def cleanup_expired_sessions(): expired_sessions [] # 定义过期时间30分钟 30*601800秒 EXPIRE_TIME 1800 for user_identifier, session_data in user_sessions.items(): # 判断最后活动时间是否超过过期时间 if time.time() - session_data[last_activity] EXPIRE_TIME: expired_sessions.append(user_identifier) # 删除过期会话 for user_identifier in expired_sessions: del user_sessions[user_identifier]
2 前端添加清空聊天记录功能在 HTML 的input-area添加清空按钮再在 JavaScript 中添加点击事件!-- 输入区域添加清空按钮 -- div classinput-area input typetext iduser-input placeholder输入您的问题... button idclear-button stylemargin-left:10px;padding:12px 20px;border-radius:25px;border:none;background:#95a5a6;color:white;cursor:pointer;清空/button button idsend-button发送/button /div// JavaScript中添加清空按钮的事件 const clearButton document.getElementById(clear-button); clearButton.addEventListener(click, function() { // 清空消息展示区 chatMessages.innerHTML ; // 重新添加欢迎语 addBotMessage(您好我是您的未来规划助手。
请问您想了解什么关于未来规划的问题); // 输入框获取焦点 userInput.focus(); });
3 生产环境部署优化修改app.py的启动代码关闭调试模式使用固定端口if __name__ __main__: # 生产环境关闭debug设置host
0.
0.
0允许外网访问 app.run(debugFalse, port5000, host
0.
0.
0.
0)
核心代码要点
总结本文的代码实战围绕FlaskCoze AI展开所有代码都经过实际运行验证核心要点可
总结为 3 点后端会话保持的核心复用 Coze AI 返回的conversation_id并通过全局字典user_sessions存储会话信息实现多轮对话的上下文关联前后端通信的核心后端通过Flaskjsonify提供 JSON 接口前端通过Fetch APIasync/await实现异步请求请求头必须设置Content-Type: application/json前端交互的核心通过原生 JavaScript 实现 DOM 动态更新使用 CSS3 实现动画和响应式布局无框架依赖轻量且易维护。
通过本文的代码解析你不仅能跑通一个完整的 AI 聊天机器人项目更能理解每一行代码的设计思路和实现细节在此基础上可快速扩展出更复杂的功能如图片发送、多机器人切换、用户登录等为后续的 AI 应用开发打下坚实的基础。