智能基础构建开发 4_第1页
智能基础构建开发 4_第2页
智能基础构建开发 4_第3页
智能基础构建开发 4_第4页
智能基础构建开发 4_第5页
已阅读5页,还剩30页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

PAGE6博学谷——让IT教学更简单,让IT学习更有效PAGE12《智能体构建与应用开发》教学设计课程名称:授课年级:授课学期:教师姓名:年月课题名称项目7综合项目:设计开发个人智能学习助手任务7-1搭建项目框架并实现基础界面计划课时3课时教学引入王亮在完成单项技能训练后,技术主管提出了综合项目:设计开发个人智能学习助手。在本任务中,为使智能学习助手具备完整的Web服务能力,需搭建项目基础框架并实现前后端交互界面,完成项目目录结构组织、依赖安装、准备前端静态页面、Flask后端服务初始化等具体任务。教学目标【知识目标】理解将LangChain应用从本地脚本到Web项目服务化改造的工程意义。掌握Flask框架的路由请求处理机制。【技能目标】(1)能够搭建个人智能学习助手的项目目录架构。(2)能够准备并组织前端静态页面,实现前后端基础交互。(3)能够使用版本控制工具管理项目依赖,形成规范的开发流程。【素养目标】(1)通过从零搭建完整项目框架,培养“模块解耦、逐步集成”的系统工程思维。(2)通过项目目录结构的规范组织,养成“结构清晰、命名规范”的工程化编码习惯。教学重点掌握智能助手项目目录搭建、Flask后端初始化与前后端基础交互实现流程,理解LangChainWeb服务化改造价值。教学难点理解Flask路由请求处理机制,建立模块解耦、前后端分离的工程化开发思维。教学方式课堂教学以PPT讲授为主,并结合多媒体进行教学教学过程任务7-1搭建项目框架并实现基础界面※通过直接引入的方式导入新课王亮在完成单项技能训练后,技术主管提出了综合项目:设计开发个人智能学习助手。在本任务中,为使智能学习助手具备完整的Web服务能力,需搭建项目基础框架并实现前后端交互界面,完成项目目录结构组织、依赖安装、准备前端静态页面、Flask后端服务初始化等具体任务。※新课讲解一、教师通过PPT的方式讲解1.将LangChain应用从本地脚本到Web项目服务化改造的工程意义将LangChain从本地单机脚本升级为Web服务,可以突破单用户限制,推动系统从临时进程向持久化、有状态的产品化形态转化。(1)能力交付方式的升级(2)并发处理能力的突破(3)系统架构的质变2.Flask框架的路由请求处理机制Flask是一个轻量级的PythonWeb框架,以简洁灵活、扩展性强著称。Flask因其上手简单、文档完善、社区活跃,成为PythonWeb开发入门的首选框架,广泛应用于中小型Web应用、API服务及快速原型开发。Flask框架的路由请求处理机制是指通过装饰器将URL路径与Python函数进行绑定,当客户端发起HTTP请求时,Flask根据请求URL匹配对应的视图函数并执行,最终将处理结果返回给客户端的完整过程。(1)路由定义机制(2)请求匹配流程(3)请求对象封装(4)响应返回方式二、搭建项目基础框架1.创建项目目录(1)创建项目(2)创建子目录和文件图7-2任务7-1项目7目录结构其中data/目录用于存储程序运行数据,data/uploads/子目录用于存储用户上传的文档文件,data/conversation_memory.json文件用于持久化存储用户与AI的会话记录。static/目录存储前端静态页面文件,包含HTML、CSS、JavaScript等前端资源。其中HTML文件负责展示网页内容,CSS文件用于定义页面样式,JavaScript文件负责与后端API进行交互。utils/目录下包含四个核心功能模块:agent.py(学习工具模块,封装智能体与计时器功能)、memory.py(会话记忆模块,管理对话历史记录)、planner.py(学习计划模块,生成个性化学习方案)、rag.py(智能问答模块,实现RAG检索增强生成)。app.py是Flask后端服务文件,接收前端发来的HTTP请求,调用utils目录下各功能模块处理业务逻辑,并将处理结果返回给前端页面,是连接前端界面与后端智能功能的中介桥梁。requirements.txt位于项目根目录,记录项目所需的所有第三方依赖包及其版本号,用于快速重建开发环境。2.安装依赖(1)requirements.txt管理依赖的优势在开发项目时,通常使用requirements.txt管理依赖和版本,其核心价值体现在以下三个方面。①确保环境一致性②提升部署效率③便于维护管理(2)配置依赖版本在requirements.txt文件中输入以下内容。flask==3.1.2flask-cors==6.0.2langchain==1.2.9langchain-community==0.4.1langchain-openai==1.1.7python-dotenv==1.2.1requirements.txt文件记录项目所需的全部第三方依赖包及其精确版本号,包括用于构建后端Web服务的Flask框架及跨域支持扩展flask-cors、用于开发大语言模型应用的LangChain核心库及社区扩展包和OpenAI集成包,以及用于加载环境变量配置的python-dotenv工具。(3)基于requirements.txt安装依赖打开终端,输入基于requirements.txt安装依赖的命令,如下所示。(.venv)PSD:\langchain\project7>pipinstall-rrequirements.txt等待一会后,所有依赖包安装成功,如图7-3所示。图7-3任务7-1成功安装依赖三、启动Flask后端服务器1.准备前端静态页面前端页面用于接收用户的输入,并将程序处理结果以可视化的方式展示给用户,承担着用户指令传达与系统反馈呈现的双重职责。在本项目中,前端静态页面通过HTML搭建页面结构,CSS美化视觉样式,JavaScript实现与后端API的异步交互。用户通过页面表单上传文档、输入问题、发起学习计划请求,JavaScript捕获这些操作后调用对应的后端接口,再将返回的智能问答结果、学习计划方案或工具执行状态动态渲染到页面上。3个前端页面文件(index.html、style.css、script.js)在教材的资源中已经提供好,下载并拷贝到static目录,如图7-4所示。图7-4任务7-1将前端也页面文件拷贝到static目录2.编写代码(1)启动服务在app.py文件中,输入启动Flask服务的代码,如下所示。#============导入依赖============fromflaskimportFlask,send_from_directory,jsonify,request#导入核心依赖importos#操作系统接口:用于路径操作fromflask_corsimportCORS#跨域资源共享扩展:解决前后端分离的跨域问题app=Flask(__name__)#创建Flask应用实例CORS(app)#启用跨域支持,允许前端跨域访问#============启动Flask后端服务器============@app.route('/')#根路由:网站入口defindex():"""返回静态首页"""returnsend_from_directory('static','index.html')#从static目录发送index.html文件@app.route('/<path:filename>')#动态路由:捕获所有静态文件请求defstatic_files(filename):"""返回静态资源"""returnsend_from_directory('static',filename)#从static目录发送请求的文件以上代码分为导入依赖模块、创建Flask应用实例、配置静态首页路由、配置静态资源路由等4部分。①导入依赖模块②创建Flask应用实例③配置静态首页路由④配置静态资源路由(2)增加API接口在以上代码的下面,输入增加API接口的代码,如下所示。#============API接口============@app.route('/api/upload',methods=['POST'])defupload_document():"""文件上传接口(待实现)"""pass#待实现@app.route('/api/ask',methods=['POST'])defask_question():"""智能问答接口(待实现)"""pass@app.route('/api/plan',methods=['POST'])defcreate_plan():"""学习计划接口(待实现)"""pass@app.route('/api/timer',methods=['POST'])deftimer_control():"""计时器工具接口(待实现)"""pass以上代码中使用@app.route('/api/upload',methods=['POST'])路由装饰器,将URL路径/api/upload与下方的upload_document()视图函数建立绑定关系。当客户端向该路径发送POST请求时,Flask通过路由表查找匹配项,自动触发并执行upload_document()函数,并将函数返回值封装为HTTP响应返回给客户端,实现请求路径与处理逻辑的解耦映射,此函数用于用户上传文件的处理,函数具体代码在下个任务中实现,其他3个路由装饰器同理。(3)程序主入口if__name__=='__main__':app.run(host='',port=5000,debug=True)app.run(host='',port=5000,debug=True)用于启动Flask内置开发服务器,其中debug=True开启调试模式,代码修改后自动重启服务并输出详细错误信息;host=''表示监听服务器任意IP地址,port=5000指定服务监听端口号为5000。4.启动测试服务(1)启动服务运行app.py程序,结果如图7-5所示。图7-5任务7-1启动app.py程序从结果中发现,服务器已经成功启动了,本地访问地址为:5000,远程访问地址为05:5000(2)查看结果打开浏览器,访问:5000,结果如图7-6所示。图7-6任务7-1返回默认首页从结果中发现,当访问后端服务根路径(:5000/)时,Flask根据@app.route('/')路由配置,自动执行index()视图函数,通过send_from_directory('static','index.html')从static目录读取并返回index.html文件内容,浏览器接收后解析渲染呈现网页。以上默认展示的是“上传文档”菜单,单击导航中的“智能问答”链接,结果如图7-7所示。图7-7任务7-1智能问题页面单击导航中“学习计划”链接,结果如图7-8所示。图7-8任务7-1学习计划页面单击导航中“学习工具”链接,结果如图7-9所示。图7-9任务7-1学习工具页面课题名称项目7综合项目:设计开发个人智能学习助手任务7-2设计开发智能模块计划课时5课时教学引入在构建了Web服务框架后,技术主管要求王亮将LangChain的RAG检索增强生成、对话记忆管理、智能体与工具系统等关键技术落地为可交付的功能模块,具体包括:实现文档的上传和切分、开发基于关键词匹配的知识问答能力、配置会话记忆的持久化存储机制、生成个性化学习计划、封装定时器工具并集成到智能体。教学目标【知识目标】(1)理解Web服务层与业务逻辑层的关系。(2)掌握前后端与业务逻辑三层数据传递机制。【技能目标】(1)能够开发基于RAG的智能问答模块,实现上下文感知的精准回答。(2)能够实现基于JSON文件的会话持久化存储。(3)能够开发个性化学习计划生成模块,实现动态适配的学习路径规划。(4)能够构建智能体工具系统,实现定时器功能。【素养目标】(1)通过RAG系统的完整构建,培养“数据驱动、检索先行”的智能问答系统设计思维。(2)在完整智能模块的开发实践中,塑造“问题分解、逐步迭代”的工程攻关能力。教学重点掌握Web分层架构数据流转流程,完成RAG问答、会话存储、学习计划与工具定时智能模块开发。教学难点理解服务层与业务逻辑层解耦思想,实现RAG检索、对话记忆、智能工具的协同联动开发。教学方式任务驱动,案例教学教学过程任务7-2设计开发智能模块※通过直接引入的方式导入新课在构建了Web服务框架后,技术主管要求王亮将LangChain的RAG检索增强生成、对话记忆管理、智能体与工具系统等关键技术落地为可交付的功能模块,具体包括:实现文档的上传和切分、开发基于关键词匹配的知识问答能力、配置会话记忆的持久化存储机制、生成个性化学习计划、封装定时器工具并集成到智能体。※新课讲解教师通过PPT的方式讲解。1.Web服务层与业务逻辑层的关系Web服务层与业务逻辑层是Web应用开发中两种基本的职责单元。Web服务层面向外部请求,关注如何与浏览器、客户端进行通信;业务逻辑层面向内部能力,关注做什么和怎么做。两层之间通过函数调用建立连接,各自独立演进又协同工作。(1)Web服务层核心职责(2)业务逻辑层核心职责(3)分层的本质(4)可复用性2.前后端与业务逻辑三层数据传递机制数据传递机制是指用户请求从浏览器发出,经过Web服务层转发,到达业务逻辑层处理,最终将结果返回前端的完整数据流动过程,三层架构(前端、Web服务层、业务逻辑层)之间的流转路径与转换规则如下所示。(1)前端到Web服务层(2)Web服务层到业务逻辑层(3)业务逻辑层到Web服务层(4)Web服务层到前端二、上传处理文档1.功能实现流程(1)界面呈现阶段(2)前端触发阶段(3)后端接收阶段(4)业务处理阶段(5)前端反馈阶段2.前端交互层(1)index.html前端交互层中index.html负责界面结构定义,提供文件上传按钮、文件选择控件及状态展示容器,通过id和onclick为JavaScript提供操作入口和渲染锚点,核心代码如下所示。<!--上传文档标签页--><divid="upload-tab"class="tab-contentactive"><h2class="section-title">上传学习文档</h2><divclass="upload-area"><divclass="file-input-wrapper"><inputtype="file"id="fileInput"accept=".txt"><!--文件选择控件--><buttonclass="btnbtn-primary"onclick="uploadFile()"><!--上传函数-->上传文档</button></div><divid="uploadResult"class="status-box"></div><!--动态显示结果--></div></div>以上html代码中通过onclick="uploadFile()"绑定点击事件,触发JavaScript函数。(2)script.js前端交互层中script.js负责与后端Web服务层进行交互,通过getElementById获取HTML控件,执行文件校验、数据封装、异步请求发送,并根据后端响应动态更新页面内容,核心代码如下所示。asyncfunctionuploadFile(){//获取文件输入元素constfileInput=document.getElementById('fileInput');//绑定HTML文件输入控件//获取用户选择的第一个文件constfile=fileInput.files[0];//files数组存储选中文件列表//文件存在性校验if(!file){alert('请选择文件');//未选择文件时提示return;}//封装FormData对象constformData=newFormData();//创建表单数据容器formData.append('file',file);//字段名必须与后端request.files['file']一致try{//发送POST请求到后端接口constresponse=awaitfetch(`${API_BASE}/upload`,{//API_BASE='http://localhost:5000/api'method:'POST',//HTTP方法body:formData//FormData自动设置multipart/form-data});//解析JSON响应constresult=awaitresponse.json();//解析后端返回的JSON数据//根据success字段展示不同状态document.getElementById('uploadResult').innerHTML=result.success?`<divstyle="color:green">${result.message}</div>`://成功显示消息`<divstyle="color:red">${result.error}</div>`;//失败显示错误}catch(error){//网络层异常处理document.getElementById('uploadResult').innerHTML=`<divstyle="color:red">上传失败:${error}</div>`;//网络错误提示}}代码解释如下所示。①文件输入获取②前端文件校验③表单数据封装④API请求发送⑤响应处理与界面更新⑥异常捕获机制3.Web服务层(1)核心代码Web服务层中upload_document函数是文件上传接口的核心实现,首先对请求中的文件进行存在性、文件名空值及格式的三层校验,通过后将文件保存至本地并读取其文本内容,最后调用业务逻辑层的add_document()方法对文档进行切分处理,并将处理结果以JSON格式返回给前端,核心代码如下所示。@app.route('/api/upload',methods=['POST'])#路由绑定,URL与视图函数映射,仅接受POSTdefupload_document():#1.文件存在性校验if'file'notinrequest.files:#检查请求中是否包含file字段returnjsonify({'error':'没有文件'}),400#400BadRequest状态码file=request.files['file']#从请求中提取文件对象#2.文件名为空校验iffile.filename=='':#检查是否选择了实际文件returnjsonify({'error':'未选择文件'}),400#3.文件格式校验ifnotfile.filename.endswith('.txt'):#仅允许.txt格式文件returnjsonify({'error':'只支持.txt文件'}),400#4.文件持久化存储filename=file.filename#获取原始文件名filepath=os.path.join('data','uploads',filename)#拼接完整存储路径os.makedirs(os.path.dirname(filepath),exist_ok=True)#递归创建目录file.save(filepath)#将内存文件流保存到磁盘#5.文件内容读取withopen(filepath,'r',encoding='utf-8')asf:#以UTF-8编码打开文件content=f.read()#读取完整文本内容到内存#6.调用业务逻辑层处理result=rag_system.add_document(content,filename)#调用RAG模块,传入内容和文件名#7.返回成功响应returnjsonify({'success':True,#成功标识'message':result,#业务层返回的处理统计信息'filename':filename#原文件名,供前端展示})(2)代码解释①路由定义与文件存在性校验②文件选择与格式校验③文件持久化存储④文件内容读取⑤业务逻辑调用⑥成功响应返回4.业务逻辑层(1)核心代码业务逻辑层rag.py文件负责接收文本内容和文件名,使用递归字符文本分割器将长文档切分为500字符的文本块,并将每个块封装为Document对象存入内存文档列表,最后返回本次新增的片段数量及知识库累计总片段数,核心代码如下所示。defadd_document(self,text:str,filename:str="")->str:"""添加文档到知识库"""#实例化递归字符文本分割器text_splitter=RecursiveCharacterTextSplitter(chunk_size=500,#每个文本块的目标字符数chunk_overlap=50#相邻块之间的重叠字符数)#将长文本切分为多个文本片段texts=text_splitter.split_text(text)#返回字符串列表#遍历每个文本片段,封装为Document对象并存入内存库fortextintexts:self.documents.append(Document(page_content=text,#文本内容metadata={"source":filename}#来源文件名,用于溯源))#返回处理统计信息returnf"已添加文档,新增{len(texts)}个片段,总计{len(self.documents)}个片段"(2)代码解释①文本分割器配置②文本智能切分③文档对象封装④内存库存储⑤处理结果反馈5.测试运行app.py程序,启动Web后端服务,打开浏览器,访问,在默认首页中,单击“选择文件”按钮,选择教材提供的upload.txt文档资源,单击“上传文档”按钮,处理完成后,返回结果“已添加文档,新增一个片段,总计1个片段”,如图7-10所示。图7-10任务7-2成功上传文档在项目data目录下的uploads子目录中,双击成功上传的upload.txt文档,结果如图7-11所示。图7-11任务7-2upload.txt成功上传到项目中三、实现智能问答与持久化记忆1.功能实现流程(1)用户输入阶段(2)历史记录获取阶段(3)业务检索阶段(4)模型调用阶段(5)记忆存储与响应返回阶段(6)前端渲染阶段2.前端交互层(1)index.html前端交互层中index.html负责智能问答界面的结构定义,提供问题输入框、发送按钮及对话展示容器,通过id为JavaScript提供操作入口,核心代码如下所示。<!--智能问答标签页--><divid="chat-tab"class="tab-content"><h2class="section-title">智能问答</h2><divclass="chat-container"><divclass="chat-box"id="chatBox"><!--对话展示容器--><divclass="messageassistant">你好!我是你的学习助手,请上传文档后开始提问。</div></div><divclass="input-group"><inputtype="text"id="questionInput"placeholder="输入你的问题..."><buttonclass="btnbtn-primary"onclick="askQuestion()"><!--发送按钮-->发送</button></div></div></div>以上html代码中通过onclick="askQuestion()"绑定点击事件,触发JavaScript函数;通过id="chatBox"和id="questionInput"为JavaScript提供DOM操作锚点(2)script.js前端交互层中script.js负责与后端Web服务层进行交互,通过getElementById获取HTML控件,执行问题发送、响应接收及动态渲染,核心代码如下所示。asyncfunctionaskQuestion(){//获取问题输入框元素constquestionInput=document.getElementById('questionInput');//获取用户输入的问题文本并去除首尾空格constquestion=questionInput.value.trim();//问题非空校验if(!question){alert('请输入问题');return;}//将用户问题立即显示在对话区域displayMessage('user',question);//清空输入框questionInput.value='';try{//发送POST请求到后端接口constresponse=awaitfetch(`${API_BASE}/ask`,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({question:question})});//解析JSON响应constresult=awaitresponse.json();//将助手回答显示在对话区域displayMessage('assistant',result.answer);}catch(error){//网络层异常处理displayMessage('assistant',`出错了:${error}`);}}functiondisplayMessage(role,content){//获取对话容器constchatBox=document.getElementById('chatBox');//创建消息div元素constmessageDiv=document.createElement('div');messageDiv.className=`message${role}`;messageDiv.textContent=`${role==='user'?'你':'助手'}:${content}`;//将消息添加到对话容器chatBox.appendChild(messageDiv);//自动滚动到底部chatBox.scrollTop=chatBox.scrollHeight;}代码解释如下。①用户输入获取与校验②即时界面反馈③API请求发送④响应处理与显示⑤消息动态渲染3.Web服务层(1)核心代码Web服务层app.py中ask_question函数是智能问答接口的核心实现,接收前端问题,调用记忆模块获取历史记录并存储当前对话,调用RAG模块生成回答,最后将结果返回前端,核心代码如下所示。@app.route('/api/ask',methods=['POST'])defask_question():#1.解析请求数据data=request.jsonquestion=data.get('question','').strip()#2.问题非空校验ifnotquestion:returnjsonify({'error':'问题不能为空'}),400#3.获取历史记录(用于上下文)history=memory.get_history(limit=10)#4.存储用户问题到记忆模块memory.add_message('user',question)#5.调用RAG模块生成回答(传入历史记录)answer=rag_system.ask(question,history)#6.存储助手回复到记忆模块memory.add_message('assistant',answer)#7.返回成功响应returnjsonify({'answer':answer,'question':question})(2)代码解释①路由定义与请求解析②输入有效性校验③对话历史获取④用户问题存储⑤RAG问答调用⑥助手回答存储⑦响应返回4.业务逻辑层(文档加载)(1)核心代码在rag.py中,__init__()方法会调用_load_existing_documents(),自动扫描data/uploads/目录,将已存在的.txt文档重新切分并加载到内存文档库中,核心代码如下。def__init__(self):self.llm=llmself.documents=[]self.uploads_dir="data/uploads"os.makedirs(self.uploads_dir,exist_ok=True)print("RAG系统初始化成功")self._load_existing_documents()#自动加载已有文档ifself.llm:print(f"模型可用:{self.llm.model_name}")def_load_existing_documents(self):"""自动加载已上传的文档"""#检查上传目录是否存在ifnotos.path.exists(self.uploads_dir):return#获取所有txt文件txt_files=[fforfinos.listdir(self.uploads_dir)iff.endswith('.txt')]ifnottxt_files:return#实例化文本分割器text_splitter=RecursiveCharacterTextSplitter(chunk_size=500,chunk_overlap=50)#遍历每个文件进行加载forfilenameintxt_files:withopen(os.path.join(self.uploads_dir,filename),'r',encoding='utf-8')asf:content=f.read().strip()ifcontent:#切分文档texts=text_splitter.split_text(content)#封装为Document对象并存入内存库fortextintexts:self.documents.append(Document(page_content=text,metadata={"source":filename}))print(f"已加载:{filename}->{len(texts)}个片段")print(f"总计加载{len(self.documents)}个文档片段")(2)代码解释①系统初始化配置②目录存在性检查③文档文件筛选④文本分割器配置⑤文档加载与切分5.业务逻辑层(智能问答)(1)核心代码在rag.py中,ask()方法首先对用户问题进行关键词提取,在内存文档库中检索匹配的文本片段;然后将检索结果拼接为上下文,构造提示词调用大语言模型生成最终回答,核心代码如下。defask(self,question:str,history:list=None)->str:"""智能问答"""#1.文档库为空校验ifnotself.documents:return"请先上传学习文档"#2.关键词提取与检索keywords=[kforkinquestion.lower().split()iflen(k)>2]relevant=[doc.page_contentfordocinself.documentsifany(kindoc.page_content.lower()forkinkeywords)]#3.检索结果为空处理ifnotrelevant:return"未在文档中找到相关信息,请尝试其他问题。"#4.构造提示词并调用模型context="\n".join(relevant[:3])#取前3个相关片段prompt=f"基于以下资料回答问题:\n资料:\n{context}\n问题:{question}\n请根据资料内容简洁回答:"response=self.llm.invoke(prompt)#5.返回模型回答returnresponse.content.strip()(2)代码解释①文档库状态检查②关键词提取与检索③检索结果处理④提示词构造与模型调用⑤结果返回6.业务逻辑层(持久化记忆)(1)核心代码对话记忆模块memory.py中的ConversationMemory类负责管理用户与AI助手之间的对话历史,通过内存缓存和文件持久化相结合的方式,实现对话上下文的保存与加载,核心代码如下所示。classConversationMemory:def__init__(self,max_messages=100):#初始化最大消息数量限制self.max_messages=max_messages#设置持久化存储文件路径self.memory_file="data/conversation_memory.json"#创建LangChain内存会话历史对象self.chat_history=InMemoryChatMessageHistory()#从文件加载历史记忆self.load_memory()defload_memory(self):#检查记忆文件是否存在ifos.path.exists(self.memory_file):try:#以UTF-8编码打开并读取JSON文件withopen(self.memory_file,'r',encoding='utf-8')asf:data=json.load(f)#截取最近max_messages条消息messages=data.get('messages',[])[:self.max_messages]#清空当前内存中的历史记录self.chat_history.clear()#遍历消息列表并转换为LangChain消息对象formsginmessages:ifmsg['role']=='user':#添加用户消息到历史记录self.chat_history.add_message(HumanMessage(content=msg['content']))else:#添加AI助手消息到历史记录self.chat_history.add_message(AIMessage(content=msg['content']))except:#异常发生时重新初始化空的历史记录self.chat_history=InMemoryChatMessageHistory()defsave_memory(self):#创建存储目录(如果不存在)os.makedirs(os.path.dirname(self.memory_file),exist_ok=True)messages=[]#只保存最近max_messages条消息formsginself.chat_history.messages[-self.max_messages:]:ifisinstance(msg,HumanMessage):#将HumanMessage转换为字典格式messages.append({'role':'user','content':msg.content})else:#将AIMessage转换为字典格式messages.append({'role':'assistant','content':msg.content})#将消息列表写入JSON文件withopen(self.memory_file,'w',encoding='utf-8')asf:json.dump({'messages':messages},f,ensure_ascii=False,indent=2)defadd_message(self,role,content):#根据角色添加相应的消息到历史记录ifrole=='user':#添加用户消息self.chat_history.add_message(HumanMessage(content=content))else:#添加AI助手消息self.chat_history.add_message(AIMessage(content=content))#立即持久化保存self.save_memory()defget_history(self,limit=None):#获取所有历史消息history=self.chat_history.messagesiflimit:#截取指定数量的最新消息history=history[-limit:]#将LangChain消息对象转换为字典格式返回return[{'role':'user'ifisinstance(msg,HumanMessage)else'assistant','content':msg.content}formsginhistory]defclear_memory(self):#清空内存中的历史记录self.chat_history.clear()#同步清空文件中的持久化存储self.save_memory()(2)代码解释①初始化与配置②记忆加载机制③记忆持久化存储④消息添加与实时保存⑤历史查询与内存清理7.测试(1)智能问答运行app.py程序,启动后端服务后,单击导航栏“智能问答”链接,在提问框中输入问题“人工智能”和“机器学习”2个问题,系统根据上传的upload.txt文档进行了回答,如图7-12所示。图7-12任务7-2实现智能问答(2)持久化记忆在项目中data目录下,双击“converstation_memory.json”文件,发现两轮对话内容已经持久化存储了,如图7-13所示。图7-13任务7-2持久化存储会话四、开发学习计划1.功能实现流程(1)用户输入阶段(2)后端接收阶段(3)业务生成阶段(4)异常处理阶段(5)响应返回与渲染阶段2.前端交互层(1)index.html前端交互层中index.html负责学习计划界面的结构定义,提供主题输入框、天数选择控件、生成按钮及结果展示容器,通过id为JavaScript提供操作入口,核心代码如下。<!--学习计划标签页--><divid="plan-tab"class="tab-content"><h2class="section-title">学习计划生成</h2><divclass="plan-generator"><divclass="input-row"><inputtype="text"id="topicInput"placeholder="请输入学习主题(如:Python基础)"><!--主题输入框--><inputtype="number"id="daysInput"value="7"min="1"max="30"><!--天数--><buttonclass="btnbtn-primary"onclick="generatePlan()"><!--生成按钮-->生成计划</button></div><divid="planResult"class="plan-result"></div><!--计划展示容器--></div></div>以上html代码中通过onclick="generatePlan()"绑定点击事件,触发JavaScript函数;通过id="topicInput"、id="daysInput"和id="planResult"为JavaScript提供DOM操作锚点。(2)script.js前端交互层中script.js负责与后端Web服务层进行交互,通过getElementById获取输入控件,执行数据获取、异步请求发送及结果渲染,核心代码如下所示。asyncfunctiongeneratePlan(){//获取主题输入框元素consttopic=document.getElementById('topicInput').value;//获取天数输入框元素的值constdays=document.getElementById('daysInput').value;//主题非空校验if(!topic){alert('请输入学习主题');return;}try{//发送POST请求到后端接口constresponse=awaitfetch(`${API_BASE}/plan`,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({topic:topic,//学习主题days:days//学习天数})});//解析JSON响应constresult=awaitresponse.json();//将生成的计划渲染到页面document.getElementById('planResult').innerHTML=`<pre>${result.plan}</pre>`;}catch(error){//网络层异常处理alert('生成计划失败:'+error);}}代码解释如下。①用户输入获取②前端输入校验③API请求发送④响应处理与渲染⑤异常捕获机制`3.Web服务层(1)核心代码Web服务层app.py中create_plan()函数是学习计划生成接口的核心实现,接收前端发送的学习主题和天数,调用业务逻辑层的计划生成模块,并将生成的计划文本返回前端,核心代码如下所示。@app.route('/api/plan',methods=['POST'])defcreate_plan():#1.解析请求数据data=request.jsontopic=data.get('topic','').strip()days=int(data.get('days',7))#转换为整数,默认7天#2.主题非空校验ifnottopic:returnjsonify({'error':'请输入学习主题'}),400#3.调用业务逻辑层生成学习计划plan=planner.generate_plan(topic,days)#4.返回成功响应returnjsonify({'plan':plan})(2)代码解释①路由定义②请求参数解析③输入有效性校验④业务逻辑调用⑤响应返回4.业务逻辑层(1)核心代码业务逻辑层planner.py中的StudyPlanner类负责学习计划的生成,通过构造结构化提示词调用大语言模型,核心代码如下所示。frommodelimportllmclassStudyPlanner:def__init__(self):#初始化时导入全局大模型实例self.llm=llmifself.llm:print(f"StudyPlanner初始化成功,使用模型:{self.llm.model_name}")else:print("StudyPlanner初始化失败:llm对象为空")self.llm=Nonedefgenerate_plan(self,topic:str,days:int=7)->str:#1.模型不可用时的降级处理ifnotself.llm:returnf"{topic}的{days}天学习计划:\n请配置API后使用"#2.构造提示词prompt=f"""请为{topic}制定一个{days}天的学习计划。要求:1.每天一个明确的主题2.包含学习和练习内容3.适合初学者4.输出格式:第X天:[主题]-[学习内容]-[练习任务]学习计划:"""#3.调用模型生成计划response=self.llm.invoke(prompt)#4.返回生成的计划内容returnresponse.content.strip()planner=StudyPlanner()(2)代码解释①模型实例注入②降级处理机制③提示词工程④模型调用与响应处理⑤全局实例化5.测试运行app.py程序,启动后端服务后,单击导航栏“学习计划”链接,在文本框中输入“python”基础,选择默认的7天,单击“生成计划”按钮,结果如图7-14所示。图7-14任务7-2按照固定格式输出学习计划从结果中发现,系统按照预定格式成功返回“python基础”的7天学习计划。五、开发智能计时器1.功能实现流程(1)用户输入阶段(2)后端接收阶段(3)业务处理阶段(4)前端实时更新阶段2.前端交互层(1)index.html前端交互层中index.html负责智能计时器界面的结构定义,提供指令输入框、发送按钮、对话响应框及倒计时展示容器,通过id为JavaScript提供操作入口,核心代码如下。<!--学习工具标签页--><divid="tools-tab"class="tab-content"><divclass="agent-timer-container"><!--指令输入区域--><divclass="agent-input-section"><divclass="input-group"><inputtype="text"id="timerCommand"placeholder="输入定时指令,如:定一个25分钟的倒计时..."onkeypress="if(event.keyCode==13)sendTimerCommand()"><!--回车发送指令--><buttonclass="btnbtn-primary"onclick="sendTimerCommand()"><!--点击发送指令-->开始计时</button></div></div><!--智能体对话响应框--><divid="timerResponse"class="timer-response-box"><divclass="agent-response">我是智能计时助手,请告诉我您需要多长的学习时间?<!--初始欢迎语--></div></div><!--倒计时展示容器--><divid="countdownDisplay"class="countdown-display"><divclass="countdown-cardidle"><!--初始等待状态--><divclass="countdown-header"><h3>⏰等待计时</h3></div><divclass="idle-message"><p>当前没有活动的定时器</p><p>请输入指令开始计时</p></div></div></div></div></div>以上html代码中通过onclick="sendTimerCommand()"和onkeypress绑定点击和回车事件,触发JavaScript函数;通过id="timerCommand"、id="timerResponse"和id="countdownDisplay"为JavaScript提供DOM操作锚点。(2)script.js前端交互层中script.js负责与后端Web服务层进行交互,通过getElementById获取输入控件,执行数据获取、异步请求发送及结果渲染,核心代码如下所示。//============智能计时器功能============//全局计时器变量lettimerInterval=null;//定时器句柄letremainingSeconds=0;//剩余秒数asyncfunctionsendTimerCommand(){//获取指令输入框元素的值constcommand=document.getElementById('timerCommand').value.trim();//指令非空校验if(!command)returnalert('请输入指令');//获取对话响应框元素constresponseBox=document.getElementById('timerResponse');//将用户指令追加显示到对话响应框responseBox.innerHTML+=`<divclass="user-command"><spanclass="user-label">你:</span>${command}</div>`;//清空输入框document.getElementById('timerCommand').value='';try{//发送POST请求到后端接口constres=awaitfetch(`${API_BASE}/timer`,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({input:command//用户指令})});//解析JSON响应constdata=awaitres.json();//将智能体响应追加显示到对话响应框responseBox.innerHTML+=`<divclass="agent-response"><spanclass="agent-label">助手:</span>${data.result}</div>`;responseBox.scrollTop=responseBox.scrollHeight;//自动滚动到底部//如果是指定时间的指令,开始倒计时if(command.includes('分钟')){//提取分钟数constmatch=command.match(/\d+/);constminutes=match?parseInt(match[0]):20;//默认20分钟//设置剩余秒数remainingSeconds=minutes*60;//清除旧的计时器if(timerInterval){clearInterval(timerInterval);timerInterval=null;}//立即更新并启动计时器updateCountdownDisplay();timerInterval=setInterval(updateCountdownDisplay,1000);}}catch(e){//网络层异常处理console.log('请求失败',e);}}//更新倒计时显示functionupdateCountdownDisplay(){constcountdownDisplay=document.getElementById('countdownDisplay');if(remainingSeconds<=0){//计时结束状态countdownDisplay.innerHTML=`<divclass="countdown-cardcompleted"><divclass="countdown-header">🎉学习时间到!</div><divclass="completion-message">⏰计时已完成,休息一下吧!</div></div>`;//清理计时器if(timerInterval){clearInterval(timerInterval);timerInterval=null;}return;}//计算分钟和秒数constminutes=Math.floor(remainingSeconds/60);constseconds=remainingSeconds%60;//计时进行中状态countdownDisplay.innerHTML=`<divclass="countdown-card"><divclas

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论