从零搭建 AI 问答网页:用 Python、JS 和 HTML 打造你的智能交互工具_ai问答功能实现
在 AI 技术飞速发展的今天,拥有一个属于自己的 AI 问答工具不再是难事。本文将手把手教你用 Python 搭建后端接口、HTML 构建前端界面、JavaScript 实现交互逻辑,从零到一打造一个简单却实用的 AI 问答网页。无论你是前端开发者想拓展后端技能,还是 Python 爱好者想尝试全栈开发,这篇教程都能为你提供清晰的思路。
一、项目背景与核心技术栈
1.为什么要做 AI 问答网页?
在日常工作中,我们经常需要快速获取信息、解决技术问题或进行创意 brainstorm—— 一个轻量化的 AI 问答工具能极大提升效率。相比调用第三方 APP,自建工具更灵活(可自定义 prompt、限制使用场景)、更安全(数据不经过第三方服务器)。
二、系统架构设计
1. 技术栈选型
本系统采用分层架构设计,各层技术选型如下:
- 前端层:基于原生HTML/CSS/JavaScript实现响应式界面,不依赖React/Vue等框架,确保轻量级和快速加载
- 后端层:Python Flask框架提供RESTful API服务,处理业务逻辑和AI接口调用
- 数据库层:SQLite轻量级数据库存储用户信息和对话历史
- AI服务:集成阿里云Qwen3或DeepSeek-R1等大模型API,支持深度思考模式
- 辅助服务:SerpAPI实现联网搜索功能 ,Web Speech API实现语音输入
2. 系统功能模块
图1:系统架构示意图
主要功能模块包括:
- 用户认证模块(登录/注册)
- 对话会话管理模块
- AI交互核心模块
- 功能增强模块(语音/搜索/风格)
- 数据持久化模块
三、核心代码
1.数据库设计
1.1用户数据库 (users.db):
-
包含一个 users 表,用于存储用户信息
-
表结构包括:id(主键)、username(唯一用户名)、password(密码)、email(邮箱)、created_at(创建时间)
def init_user_db(): conn = sqlite3.connect(\"users.db\") c = conn.cursor() c.execute( \"\"\"CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, password TEXT NOT NULL, email TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)\"\"\" ) conn.commit() conn.close()
1.2.聊天数据库 (chatbot.db):
包含两个表:
chat_sessions:存储聊天会话信息,包括会话ID、标题和创建时间
-
chat_sessions:存储聊天会话信息,包括会话ID、标题和创建时间
-
chat_messages:存储具体的聊天消息,包括会话ID、角色(用户或AI)、消息内容和时间戳
-
还为 chat_messages 表的 session_id 字段创建了索引以提高查询性能
def get_db(): conn = sqlite3.connect(\"chatbot.db\") return conndef init_chat_db(): with get_db() as conn: conn.execute( \"\"\" CREATE TABLE IF NOT EXISTS chat_sessions ( id INTEGER PRIMARY KEY AUTOINCREMENT, session_id TEXT UNIQUE NOT NULL, title TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP )\"\"\" ) conn.execute( \"\"\" CREATE TABLE IF NOT EXISTS chat_messages ( id INTEGER PRIMARY KEY AUTOINCREMENT, session_id TEXT NOT NULL, role TEXT NOT NULL, content TEXT NOT NULL, timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP )\"\"\" ) conn.execute( \"\"\" CREATE INDEX IF NOT EXISTS idx_chat_messages_session_id ON chat_messages (session_id) \"\"\" ) conn.commit()
2.登录/注册
2.1登录界面
2.1.1.前端登录页面核心代码:
用户登录
没有账户? 立即注册
document.getElementById(\'loginForm\').addEventListener(\'submit\', function (e) { e.preventDefault(); const errorMessage = document.getElementById(\'errorMessage\'); const successMessage = document.getElementById(\'successMessage\'); errorMessage.textContent = \'\'; successMessage.textContent = \'\'; const formData = new FormData(this); const data = {}; formData.forEach((value, key) => data[key] = value); axios.post(\'http://localhost:8000/api/login\', data) .then(response => { if (response.data.success) { successMessage.textContent = \'登录成功!\'; setTimeout(() => { window.location.href = \'al_show.html\'; }, 1000); } else { errorMessage.textContent = response.data.message; } }) .catch(error => { const msg = error.response?.data?.detail || \'网络错误,请重试\'; errorMessage.textContent = msg; }); });
2.1.2后端登录API核心代码:
class LoginRequest(BaseModel): username: str password: str@app.post(\"/api/login\")async def login_user(login_data: LoginRequest): username = login_data.username password = login_data.password try: conn = sqlite3.connect(\"users.db\") cursor = conn.cursor() cursor.execute( \"SELECT username, password FROM users WHERE username=?\", (username,) ) user = cursor.fetchone() conn.close() if not user: raise HTTPException(status_code=400, detail=\"用户不存在\") stored_hash = user[1].encode(\"utf-8\") if not bcrypt.checkpw(password.encode(\"utf-8\"), stored_hash): raise HTTPException(status_code=400, detail=\"密码错误\") return {\"success\": True, \"message\": \"登录成功\", \"data\": {\"username\": username}} except Exception as e: raise HTTPException(status_code=500, detail=f\"登录失败:{str(e)}\")
2.1.3登录功能的核心流程如下:
①前端页面提供用户名和密码输入表单
②用户提交表单时,使用JavaScript拦截默认提交行为
③通过Axios将用户输入的凭据发送到后端API (/api/login)
④后端接收到请求后,查询数据库验证用户是否存在
⑤使用bcrypt库验证密码是否正确
⑥如果验证成功,返回成功响应,前端跳转到主页面 (al_show.html)
⑦如果验证失败,返回相应的错误信息
2.2注册界面
2.2.1前端注册页面核心代码:
注册新账户
已有账户? 立即登录
document.getElementById(\'registerForm\').addEventListener(\'submit\', function (e) { e.preventDefault(); const errorMessage = document.getElementById(\'errorMessage\'); errorMessage.textContent = \'\'; const formData = new FormData(this); const data = {}; formData.forEach((value, key) => data[key] = value); if (!data.username || data.username.length < 3) { errorMessage.textContent = \'用户名至少需要3个字符\'; return; } if (!data.password || data.password.length { if (response.data.success) { alert(\'注册成功!\'); window.location.href = \'login.html\'; } else { errorMessage.textContent = \'注册失败:\' + response.data.message; } }) .catch(error => { errorMessage.textContent = \'网络错误:\' + error; }); });
2.2.2后端注册API核心代码:
class RegisterRequest(BaseModel): username: str password: str repassword: str email: str@app.post(\"/api/register\")async def register_user(data: RegisterRequest): try: hashed_password = bcrypt.hashpw(data.password.encode(\"utf-8\"), bcrypt.gensalt()) logging.debug(f\"Connecting to DB...\") conn = sqlite3.connect(\"users.db\") cursor = conn.cursor() logging.debug(f\"Inserting user: {data.username}\") cursor.execute( \"INSERT INTO users (username, password, email) VALUES (?, ?, ?)\", (data.username, hashed_password.decode(\"utf-8\"), data.email), ) conn.commit() conn.close() return {\"success\": True, \"message\": \"注册成功\"} except Exception as e: traceback.print_exc() raise HTTPException(status_code=500, detail=f\"注册失败:{str(e)}\")
2.2.3 注册功能的核心流程如下:
①前端页面提供用户名、密码、确认密码和邮箱输入表单
②用户提交表单时,使用JavaScript进行前端验证:
③用户名至少需要3个字符
④密码长度不能少于6位
⑤两次输入的密码必须一致
⑥验证通过后,通过Axios将用户数据发送到后端API (/api/register)
⑦后端接收到请求后,使用bcrypt对密码进行哈希处理
⑧将用户信息(用户名、哈希后的密码、邮箱)存储到数据库
⑨如果注册成功,返回成功响应,前端跳转到登录页面
⑩如果注册失败(如用户名已存在),返回相应的错误信息
3.ai问答界面
3.1前端AI问答主页面核心代码:
function generateSessionId() { return \'session_\' + Date.now() + \'_\' + Math.random().toString(36).substr(2, 9);}let currentSessionId = generateSessionId();let firstQuestionSet = false;let darkMode = false;// 页面加载时初始化欢迎消息document.addEventListener(\'DOMContentLoaded\', function () { const chatBox = document.getElementById(\'chatBox\'); if (chatBox) { const welcomeMsg = document.createElement(\'div\'); welcomeMsg.className = \'msg bot\'; welcomeMsg.textContent = \'您好!我是惜月AI,一个通用AI助手。我可以帮助您回答问题、提供信息和进行各种讨论。请随时告诉我您需要什么帮助!\'; chatBox.appendChild(welcomeMsg); chatBox.scrollTop = chatBox.scrollHeight; } // 加载历史记录 loadHistory();});// 发送消息函数window.sendMessage = function () { const input = document.getElementById(\'userInput\'); const sendBtn = document.getElementById(\'sendBtn\'); const userText = input.value.trim(); if (!userText) return; sendBtn.disabled = true; sendBtn.textContent = \"发送中...\"; appendMessage(userText, \'user\'); input.value = \'\'; if (!firstQuestionSet) { const shortTitle = userText.substring(0, 30); document.getElementById(\'pageTitle\').textContent = \'惜月AI - \' + shortTitle + (userText.length > 30 ? \'...\' : \'\'); updateTitle(shortTitle); firstQuestionSet = true; } let enableReasoning = document.getElementById(\'enableReasoning\').checked; let enableSearch = false; if (document.getElementById(\'enableSearch\').checked) { enableSearch = confirm(\"您已选择启用联网搜索。\\n此功能将帮助您从互联网获取最新信息。\\n是否确认启用?\"); } const statusDiv = document.createElement(\'div\'); statusDiv.style.fontSize = \'0.9em\'; statusDiv.style.color = \'#888\'; statusDiv.style.marginBottom = \'5px\'; statusDiv.style.textAlign = \'right\'; let statusText = \'\'; if (enableReasoning) statusText += \'[🧠 深度思考已开启] \'; if (enableSearch) statusText += \'[🌐 联网搜索已开启] \'; statusDiv.textContent = statusText || \'[💡 当前为普通模式]\'; chatBox.appendChild(statusDiv); // 创建机器人消息容器 const botMsgDiv = document.createElement(\'div\'); botMsgDiv.className = \'msg bot\'; // 替换为直接添加空消息 chatBox.appendChild(botMsgDiv); botMsgDiv.textContent = \'AI回答正在加载中,请稍等一下哦...\'; const data = { session_id: currentSessionId, user_input: userText, reasoning: enableReasoning, search: enableSearch }; console.log(\'发送消息,使用会话ID:\', currentSessionId); fetch(\'http://localhost:8000/chat\', { method: \'POST\', headers: { \'Content-Type\': \'application/json\', }, body: JSON.stringify(data), }) .then(async (response) => { if (!response) { throw new Error(\"网络响应为空,请检查服务器是否运行\"); } if (response.headers.get(\"content-type\")?.includes(\"application/json\")) { return await response.json(); } else { const text = await response.text(); return {content: text}; } }) .then(data => { if (data.error) { throw new Error(data.error || \"未知错误\"); } const botMsg = data.content || \"无返回内容\"; botMsgDiv.innerHTML = \'\'; botMsgDiv.textContent = \'加载完成啦\'; setTimeout(() => { appendMessage(botMsg, \'bot\'); }, 1000); sendBtn.disabled = false; sendBtn.textContent = \"发送\"; // 保存聊天记录到数据库 // setTimeout(() => { // saveChatHistory(); // }, 1500); }) .catch(error => { console.error(\'发送消息失败:\', error); alert(`发送消息失败: ${error.message}`); botMsgDiv.innerHTML = \'\'; appendMessage(\'发送消息失败,请稍后重试\', \'bot\'); sendBtn.disabled = false; sendBtn.textContent = \"发送\"; });};function appendMessage(content, role) { const chatBox = document.getElementById(\'chatBox\'); if (!chatBox) { console.error(\'找不到聊天框元素\'); return; } const msgDiv = document.createElement(\'div\'); msgDiv.className = \'msg \' + role; msgDiv.textContent = content; chatBox.appendChild(msgDiv); chatBox.scrollTop = chatBox.scrollHeight;}function startNewChat() { const chatBox = document.getElementById(\'chatBox\'); if (!chatBox) { console.error(\'找不到聊天框元素\'); return; } chatBox.innerHTML = \'\'; document.getElementById(\'pageTitle\').textContent = \'惜月AI\'; firstQuestionSet = false; // 生成新的会话ID currentSessionId = generateSessionId(); // 添加欢迎消息 const welcomeMsg = document.createElement(\'div\'); welcomeMsg.className = \'msg bot\'; welcomeMsg.textContent = \'您好!我是惜月AI,一个通用AI助手。我可以帮助您回答问题、提供信息和进行各种讨论。请随时告诉我您需要什么帮助!\'; chatBox.appendChild(welcomeMsg); chatBox.scrollTop = chatBox.scrollHeight; console.log(\'新建会话,ID为:\', currentSessionId);}function logout() { fetch(\'http://localhost:8000/logout\', { method: \'POST\', }) .then(response => { if (response.ok) { window.location.href = \'login.html\'; } else { throw new Error(\'登出失败\'); } }) .catch(error => { console.error(\'登出失败:\', error); alert(\'无法登出,请检查服务器是否运行\'); window.location.href = \'login.html\'; });}// 加载历史记录async function loadHistory() { const historyList = document.getElementById(\'historyList\'); if (!historyList) { console.error(\'找不到 id 为 historyList 的元素\'); alert(\'页面结构异常,请刷新重试\'); return; } try { const res = await fetch(\'http://localhost:8000/history\'); if (!res.ok) { throw new Error(`HTTP error! status: ${res.status}`); } const list = await res.json(); historyList.innerHTML = \'\'; // 按时间排序 list.sort((a, b) => { // 处理不同格式的时间戳 const timeA = new Date(a.created_at).getTime() || 0; const timeB = new Date(b.created_at).getTime() || 0; return timeB - timeA; }); list.forEach(sess => { const div = document.createElement(\'div\'); div.textContent = sess.title; div.style.cursor = \'pointer\'; div.onclick = () => showDetail(sess.session_id); const delBtn = document.createElement(\'span\'); delBtn.textContent = \'🗑️\'; delBtn.className = \'delete-btn\'; delBtn.onclick = (e) => { e.stopPropagation(); if (confirm(`确认删除对话:\\\"${sess.title}\\\"?`) !== false) { deleteHistory(sess.session_id); } }; div.appendChild(delBtn); historyList.prepend(div); }); if (list.length > 0) { showDetail(list[0].session_id); } else { // 当没有历史记录时,显示默认会话 showDetail(\"default\"); const div = document.createElement(\'div\'); div.textContent = \"新对话\"; div.style.cursor = \'pointer\'; div.onclick = () => showDetail(\"default\"); historyList.prepend(div); } } catch (error) { console.error(\'加载历史记录失败:\', error); alert(\'无法加载历史记录,请检查服务器是否运行: \' + error.message); }}// 显示对话详情async function showDetail(session_id) { currentSessionId = session_id; // 如果是默认会话,显示提示信息 if (session_id === \"default\") { const chatBox = document.getElementById(\'chatBox\'); if (chatBox) { chatBox.innerHTML = \'\'; const infoDiv = document.createElement(\'div\'); infoDiv.className = \'msg bot\'; infoDiv.textContent = \'这是新对话,尚未保存历史记录。开始聊天后会自动保存。\'; chatBox.appendChild(infoDiv); } document.getElementById(\'pageTitle\').textContent = \'惜月AI - 新对话\'; return; } try { const res = await fetch(`http://localhost:8000/history/${session_id}`); if (!res.ok) { throw new Error(`加载历史记录失败: HTTP ${res.status}`); } const history = await res.json(); const chatBox = document.getElementById(\'chatBox\'); if (!chatBox) throw new Error(\'找不到聊天框元素\'); chatBox.innerHTML = \'\'; console.log(\'获取到的对话详情:\', history); if (!history || !Array.isArray(history) || history.length === 0) { const infoDiv = document.createElement(\'div\'); infoDiv.className = \'msg bot\'; infoDiv.textContent = \'该对话暂无内容,请开始新对话\'; chatBox.appendChild(infoDiv); } else { const validMessages = history.filter(msg => msg && typeof msg.content === \'string\' && msg.content.trim() !== \'\' && msg.role ); console.log(\'有效消息:\', validMessages); if (validMessages.length > 0) { validMessages.forEach(msg => { appendMessage(msg.content, msg.role === \'user\' ? \'user\' : \'bot\'); }); } else { const infoDiv = document.createElement(\'div\'); infoDiv.className = \'msg bot\'; infoDiv.textContent = \'该对话暂无有效内容,请开始新对话\'; chatBox.appendChild(infoDiv); } } const pageTitle = document.getElementById(\'pageTitle\'); if (pageTitle) { if (history && history.length > 0) { const firstUserMessage = history.find(msg => msg.role === \'user\'); if (firstUserMessage) { pageTitle.textContent = `惜月AI - ${firstUserMessage.content.substring(0, 30)}...`; } else { pageTitle.textContent = \'惜月AI - 空对话\'; } } else { pageTitle.textContent = \'惜月AI - 新对话\'; } } } catch (error) { console.error(\'加载对话详情失败:\', error); alert(`无法加载对话详情: ${error.message}`); const chatBox = document.getElementById(\'chatBox\'); if (chatBox) { chatBox.innerHTML = \'\'; appendMessage(\'无法加载历史记录,请稍后重试\', \'bot\'); } }}// 删除历史记录function deleteHistory(session_id) { fetch(`http://localhost:8000/history/${session_id}`, { method: \'DELETE\', }) .then(response => { if (response.ok) { loadHistory(); } else { throw new Error(\'删除历史记录失败\'); } }) .catch(error => { console.error(\'删除历史记录失败:\', error); alert(\'无法删除历史记录,请检查服务器是否运行\'); });}
3.2后端AI问答API核心代码:
class ChatRequest(BaseModel): session_id: str user_input: str reasoning: bool = False search: bool = Falseclass SaveHistoryRequest(BaseModel): session_id: str title: str# 模拟短期会话缓存sessions: dict[str, list[dict]] = {}SYSTEM_PROMPT = \"\"\"你是一个通用AI助手,请根据用户问题进行温柔、友好、准确的回复。\"\"\"def init_session(session_id: str): sessions[session_id] = [ # { # \"role\": \"system\", # \"content\": \"你是一个通用AI助手,请根据用户的问题进行温柔、友好、准确的回复。\", # } ]def generate_thinking_stream(user_input, session_id, use_reasoning, use_search): client = OpenAI( # Api-key api_key=os.getenv(\"DASHSCOPE_API_KEY\"), base_url=\"https://dashscope.aliyuncs.com/compatible-mode/v1\", ) messages = sessions.get(session_id, []) messages.append({\"role\": \"user\", \"content\": user_input}) model_name = \"qwen-plus-2025-04-28\" extra_body = {} if use_reasoning: extra_body[\"enable_thinking\"] = True extra_body[\"thinking_budget\"] = 50 extra_body[\"enable_search\"] = use_search extra_body[\"search_options\"] = { \"forced_search\": True, \"enable_source\": True, \"enable_citation\": True, \"citation_format\": \"[ref_]\", \"search_strategy\": \"pro\", } completion = client.chat.completions.create( model=model_name, messages=messages, stream=True, extra_body=extra_body ) thinking_content = \"\" answer_content = \"\" is_answering = False is_first_chunk = True for chunk in completion: if not chunk.choices: continue delta = chunk.choices[0].delta if ( is_first_chunk and hasattr(chunk, \"output\") and hasattr(chunk.output, \"search_info\") ): search_results = chunk.output.search_info.get(\"search_results\", []) if search_results: yield \"[🔍 搜索结果]\\n\" for web in search_results: yield f\"[{web[\'index\']}]: [{web[\'title\']}]({web[\'url\']})\\n\" yield \"\\n[🧠 开始思考]\\n\" is_first_chunk = False if hasattr(delta, \"reasoning_content\") and delta.reasoning_content: thinking_content += delta.reasoning_content if use_reasoning: yield delta.reasoning_content if hasattr(delta, \"content\") and delta.content: if not is_answering: yield \"\\n\\n\" is_answering = True answer_content += delta.content yield delta.content full_response = \"\" if use_reasoning: full_response += f\"[🧠 深度思考]\\n{thinking_content}\\n\\n\" full_response += answer_content + \"\\n\" messages.append({\"role\": \"assistant\", \"content\": full_response}) sessions[session_id] = messages# 保存会话到数据库def save_session_to_db(session_id: str): \"\"\"将当前会话保存到数据库\"\"\" print(f\"尝试保存会话 {session_id} 到数据库\") try: with get_db() as conn: cur = conn.cursor() # 获取会话标题(使用第一条用户消息) title = \"新对话\" if session_id in sessions: for msg in sessions[session_id]: if msg[\"role\"] == \"user\": title = msg[\"content\"][:30] + ( \"...\" if len(msg[\"content\"]) > 30 else \"\" ) break print(f\"会话标题: {title}\") print(f\"会话消息数: {len(sessions.get(session_id, []))}\") # 检查会话是否已存在 cur.execute( \"SELECT COUNT(1) FROM chat_sessions WHERE session_id=?\", (session_id,) ) exists = cur.fetchone()[0] > 0 if exists: # 如果会话已存在,只更新标题(如果有必要) cur.execute( \"UPDATE chat_sessions SET title=? WHERE session_id=?\", (title, session_id), ) print(f\"已更新会话记录: {session_id}, {title}\") else: # 如果会话不存在,插入新会话记录 cur.execute( \"INSERT INTO chat_sessions (session_id, title) VALUES (?, ?)\", (session_id, title), ) print(f\"已插入新的会话记录: {session_id}, {title}\") # 只插入新的消息而不是删除所有消息再重新插入 if session_id in sessions: # 获取数据库中已有的消息数量 cur.execute( \"SELECT COUNT(*) FROM chat_messages WHERE session_id=?\", (session_id,), ) db_msg_count = cur.fetchone()[0] # 只插入新增的消息 session_messages = sessions[session_id] if db_msg_count < len(session_messages): for i in range(db_msg_count, len(session_messages)): msg = session_messages[i] print( f\"插入消息 {i}: role={msg[\'role\']}, content={msg[\'content\'][:50] if msg[\'content\'] else \'\'}...\" ) cur.execute( \"INSERT INTO chat_messages (session_id, role, content) VALUES (?, ?, ?)\", ( session_id, msg[\"role\"], msg[\"content\"] if msg[\"content\"] else \"\", ), ) conn.commit() print(f\"会话 {session_id} 成功保存到数据库\") except Exception as e: print(f\"保存会话到数据库时出错: {e}\") import traceback traceback.print_exc()@app.post(\"/chat\")async def chat_endpoint(req: ChatRequest): session_id = req.session_id user_input = req.user_input use_reasoning = req.reasoning use_search = req.search if session_id not in sessions: init_session(session_id) # 创建一个包装生成器,在结束时保存会话 def generate_and_save(): try: yield from generate_thinking_stream( user_input, session_id, use_reasoning, use_search ) finally: # 在生成完成后保存会话 save_session_to_db(session_id) return StreamingResponse( generate_and_save(), media_type=\"text/event-stream\", )@app.get(\"/history\")async def get_history(): try: with get_db() as conn: cur = conn.cursor() cur.execute( \"SELECT session_id, title, created_at FROM chat_sessions ORDER BY created_at DESC\" ) rows = cur.fetchall() # 确保返回的数据格式正确 result = [] for r in rows: result.append( { \"session_id\": r[0], \"title\": r[1], \"created_at\": r[2] if r[2] else \"\", } ) print(f\"返回历史记录: {result}\") # 调试信息 return result except Exception as e: print(f\"获取历史记录时出错: {e}\") import traceback traceback.print_exc() return [] # 返回空数组而不是抛出异常@app.get(\"/history/{session_id}\")async def get_history_detail(session_id: str): # 对于默认会话,直接返回空数组 if session_id == \"default\": return [] try: with get_db() as conn: cur = conn.cursor() cur.execute( \"SELECT role, content, timestamp FROM chat_messages WHERE session_id=? ORDER BY timestamp ASC\", (session_id,), ) rows = cur.fetchall() # 即使没有找到记录也返回空数组而不是抛出异常 result = [] for r in rows: result.append( { \"role\": r[0], \"content\": r[1] if r[1] else \"\", \"timestamp\": r[2] if r[2] else \"\", } ) print(f\"返回会话详情: {result}\") # 调试信息 return result except Exception as e: print(f\"获取会话详情时出错: {e}\") import traceback traceback.print_exc() return [] # 返回空数组而不是抛出异常@app.delete(\"/history/{session_id}\")async def delete_history(session_id: str): with get_db() as conn: cur = conn.cursor() cur.execute(\"DELETE FROM chat_messages WHERE session_id= ?\", (session_id,)) cur.execute(\"DELETE FROM chat_sessions WHERE session_id= ?\", (session_id,)) conn.commit() return {\"status\": \"success\"}@app.post(\"/logout\")async def logout_user(): # 如果你使用的是 session-based 登录,可以在这里清除 session return {\"status\": \"success\", \"message\": \"登出成功\"}
3.3 AI问答主页面的核心功能包括:
3.3.1用户界面部分:
①聊天窗口显示用户和AI的对话历史
②输入框供用户输入问题
③控制面板提供深度思考、联网搜索等功能选项
④历史记录面板显示之前的对话
⑤新对话、语音输入、主题切换、退出登录等功能按钮
3.3.2核心交互流程:
①用户输入问题并发送
②前端通过fetch API将问题发送到后端/chat接口
③后端调用通义千问API处理问题
④支持启用深度思考和联网搜索功能
⑤后端以流式响应方式返回AI的回答
⑥对话历史保存到数据库中
⑦用户可以查看、删除历史对话
3.3.3特色功能:
①实时流式显示AI回答
②深度思考模式(显示AI的推理过程)
③联网搜索功能(获取最新信息)
④对话历史管理
⑤深色/浅色主题切换
⑥语音输入支持
四、生产环境建议
4.1前端优化:
- 使用Nginx部署静态资源,开启gzip压缩
- 配置合适的缓存策略减少重复请求
4.2后端优化
- 使用Gunicorn或uWSGI部署Flask应用
- 配置数据库连接池提高性能
4.3安全加固
- 启用HTTPS加密通信
- 实现API速率限制防止滥用
- 对用户输入进行严格验证和过滤
五、总结与扩展
本文详细介绍了如何构建一个功能完善的AI智能问答系统,主要特点包括:
- 完整的用户系统:实现安全的注册登录流程,密码加盐哈希存储
- 智能对话管理:支持多轮对话历史保存和检索
- 增强AI能力:深度思考模式 、联网搜索 等高级功能
- 多样化交互:语音输入 、风格切换 等提升用户体验
- 前后端分离架构:清晰的接口设计和模块化开发
扩展方向:
- 添加文件上传解析功能
- 实现多模态交互(图片理解)
- 增加用户自定义提示模板
- 部署更强大的AI模型
通过本系统,开发者可以快速搭建一个功能丰富、安全可靠的AI对话平台,适用于客服、教育、娱乐等多种场景。