from flask import request,Response,stream_with_context from utils.request import post_request,generate_error import json import time from services.ai_service import ai_service from services.templateFun import templateData #防止fetch请求中断 from utils.offFetch import RequestInterruptHandler #判断用户需求 from utils.verifyInput import messageValidator #判断是否含有特殊指令 from utils.command import commandObj def stream_response(): # 0.在重组数据之前,应该先清空原来的数据 ai_service.clear_data() """第一步:获得必备参数""" # 1.1获得header中的website_id website_id = request.get_json().get('website_id') # 1.2获得header中的Token token = request.headers.get('Token') # 1.3获得header中的会话id session_id = request.get_json().get('session_id') # 1.4获得用户输入userMessage userMessage = request.get_json().get('userMessage') print("接收到前端用户输入:" + userMessage) # 1.5当前消息是否需要生成标题(摘要) ifNewMessage = request.get_json().get('new_msg') """第二步:验证网站是否可编辑""" checkEdit = post_request("website/checkWebsiteEdit", { "website_id": website_id },token) if checkEdit.get('code') != 200: # 2.1如果网站不可编辑或者用户未登录,则返回异常信息 return Response(generate_error(checkEdit.get('message')), mimetype='text/plain') else: # 2.2开始请求网站皮肤 getAllTemplate = post_request("public/getAITemplate", { "website_id": website_id },token) # 2.3获得皮肤数据 skinData = getAllTemplate.get('data').get('template') # 判断用户输入是否符合要求 if messageValidator.validate(userMessage): print("用户输入符合要求,允许进修后续操作") # 储存用户输入 ai_service.user_input = userMessage # 1=是新会话,需要修改标题摘要 if(ifNewMessage==1): # 生成标题 title = ai_service.userMessage_to_title(userMessage) print("该会话需要生成标题:" + title) getAllTemplate = post_request("/public/upAiSession", { "session_id": session_id, "session_title": title },token) if getAllTemplate.get('code') != 200: # 如果创建会话失败,返回错误 print("修改会话标题失败!" + getAllTemplate.get('message')) else: print("修改会话标题成功!" + getAllTemplate.get('message')) else: print("该消息不需要生成标题!") # 2.4使用AI服务找到最匹配的模板 best_match = ai_service.find_best_matching_template(userMessage, skinData) matched_template_name = "默认模板" matched_template_id = 0 if best_match: matched_template_name = best_match['template_info']['template_name'] matched_template_id = best_match['template_info']['template_id'] similarity_score = best_match['similarity_score'] print(f"找到最匹配的模板: {matched_template_name}, 相似度: {similarity_score:.4f}") else: print("未找到匹配的模板,使用默认模板") # 2.5开始执行数据重组操作 templateData.sectors_webSiteData["base"]["websiteId"] = website_id templateData.sectors_webSiteData["style"]["styleId"] = matched_template_id """demo : 当前缺少的逻辑:通栏应该是从后端获取的,而不是存在这里的!""" # 2.6依照用户需求筛选通栏 ai_service.filter_sectors(userMessage,matched_template_id) # 2.7生成通栏数据 ai_service.get_sectors(website_id,matched_template_id,token) """demo : 当前缺少的逻辑:通栏应该是从后端获取的,而不是存在这里的!""" #组合待提交的数据 submit_data = { "website_id": website_id, "session_id": session_id, "template_id": matched_template_id, "template_data": json.dumps(templateData.sectors_webSiteData, ensure_ascii=False), "canvas_data": json.dumps(templateData.canvas_data, ensure_ascii=False) } """demo:会话编号应该通过创建会话来取得,目前先使用固定的编号进行测试 自助建站标准化测试平台website_id:109 会话id:09504811488333""" template_ref = post_request("public/addTemplateDraftbox", submit_data ,token) if template_ref.get('code') != 200: print("临时模板保存失败!" + template_ref.get('message')) else: print("临时模板保存成功!" + template_ref.get('message')) #2.7判断用户是否需要填充导航 command_number = commandObj.get_command(userMessage) if command_number == 1: print("用户需要填充导航") templateCates = post_request("/public/addTemplateCates", { "session_id": session_id, },token) if templateCates.get('code') != 200: ai_service.add_reasoning(f"模板导航因远程服务器故障未能完成添加") print("填充导航失败!" + templateCates.get('message')) else: ai_service.add_reasoning(f"我已经按照用户的要求给每个组件都选择了导航") print("填充导航成功!" + templateCates.get('message')) else: print("用户不需要填充导航") # 2.8获得推理过程 reasoning = ai_service.reasoning reasoning_str = "。".join(reasoning) """第三步:返回内容生成器""" def generate(): with RequestInterruptHandler(request) as handler: texts = [ {"content": reasoning_str, "class": "computerLi"}, {"content": "👌久等了!您的需求已完成:", "class": "computertextBold"}, {"content": "我使用了皮肤库中名为:"+ matched_template_name +"的皮肤,网站通栏与组件的构建已经完成。", "class": "computertext"}, {"content": best_match['template_info'].get('template_img')[0].get('url') , "class": "computerImgBox" , "pagename" :best_match['template_info'].get('template_img')[0].get('name')}, {"content": best_match['template_info'].get('template_img')[1].get('url') , "class": "computerImgBox" , "pagename" :best_match['template_info'].get('template_img')[1].get('name')}, {"content": best_match['template_info'].get('template_img')[2].get('url') , "class": "computerImgBox" , "pagename" :best_match['template_info'].get('template_img')[2].get('name')}, {"content": best_match['template_info'].get('template_img')[3].get('url') , "class": "computerImgBox" , "pagename" :best_match['template_info'].get('template_img')[3].get('name')}, {"content": best_match['template_info'].get('template_img')[4].get('url') , "class": "computerImgBox" , "pagename" :best_match['template_info'].get('template_img')[4].get('name')}, {"content": best_match['template_info'].get('template_img')[5].get('url') , "class": "computerImgBox" , "pagename" :best_match['template_info'].get('template_img')[5].get('name')}, {"content": best_match['template_info'].get('template_img')[6].get('url') , "class": "computerImgBox" , "pagename" :best_match['template_info'].get('template_img')[6].get('name')}, {"content": "点击下面👇的链接可以查看该模板的设计效果,如果需要修改请告诉我。", "class": "computertext"}, {"content": "/#/templateCreat?website_id=" + str(website_id) + "&style=" + str(matched_template_id) + "&mode=ai&session_id=" + session_id, "class": "computertextLink"} ] for text_item in texts: # 检查客户端是否断开 if not handler.is_client_connected(): print("客户端已断开连接,停止发送") handler.client_closed = True break text = text_item["content"] text_class = text_item["class"] pagename = text_item.get('pagename') if text_class in ["computerImgBox", "computertextLink"]: data = { 'code': 200, 'type': text_class, 'pagename': pagename, 'data': text, 'finished': False, 'isComplete': True } yield f"data: {json.dumps(data, ensure_ascii=False)}\n\n" else: for char in text: data = { 'code': 200, 'type': text_class, 'data': char, 'finished': False, 'isComplete': False } yield f"data: {json.dumps(data, ensure_ascii=False)}\n\n" time.sleep(0.02) # 发送完成信号 complete_data = { 'code': 200, 'type': text_class, 'data': '', 'finished': False, 'isComplete': True } yield f"data: {json.dumps(complete_data, ensure_ascii=False)}\n\n" # 发送换行符 newline_data = { 'code': 200, 'type': 'newline', 'data': '\n\n', 'finished': False, 'isComplete': True } yield f"data: {json.dumps(newline_data, ensure_ascii=False)}\n\n" # 如果连接还在,发送结束信号 if not handler.client_closed: end_data = { 'code': 200, 'data': '', 'finished': True, 'full_text': "处理结果已发送完毕!" } yield f"data: {json.dumps(end_data, ensure_ascii=False)}\n\n" return Response(stream_with_context(generate()), mimetype='text/event-stream') else: """第四步:处理非模板生成类请求""" # 如果用户一上来输入非模板问题,这里需要生成一个标题 # 1=是新会话,需要修改标题摘要 if(ifNewMessage==1): # 生成标题 title = "非模板需求的会话" print("该会话需要生成标题:" + title) getAllTemplate = post_request("/public/upAiSession", { "session_id": session_id, "session_title": title },token) if getAllTemplate.get('code') != 200: # 如果创建会话失败,返回错误 print("修改会话标题失败!" + getAllTemplate.get('message')) else: print("修改会话标题成功!" + getAllTemplate.get('message')) else: print("该消息不需要生成标题!") # 返回错误信息 def generate_error_response(): texts = [ {"content": "对不起,您的指令暂不支持!", "class": "computertext"}, {"content": "小龙包暂时无法处理非网站模板生成类的问题😅,我们将会在未来的版本中增加对更多指令的支持,敬请期待!", "class": "computertext"}, {"content": "推荐的提示词语句:", "class": "computertextBoldLine"}, {"content": "1️⃣ 帮我推荐一套中国传统红色皮肤。", "class": "computertext"}, {"content": "2️⃣ 帮我推荐一套中国传统红色皮肤,把焦点图放到第一个,去掉所有广告。", "class": "computertext"}, {"content": "3️⃣ 帮我推荐一套中国传统红色皮肤,把焦点图放到第一个,去掉所有广告,帮我填好导航。", "class": "computertext"}, ] for text_item in texts: text = text_item["content"] text_class = text_item["class"] for char in text: data = { 'code': 200, 'type': text_class, 'data': char, 'finished': False, 'isComplete': False } yield f"data: {json.dumps(data, ensure_ascii=False)}\n\n" time.sleep(0.02) # 发送完成信号 complete_data = { 'code': 200, 'type': text_class, 'data': '', 'finished': False, 'isComplete': True } yield f"data: {json.dumps(complete_data, ensure_ascii=False)}\n\n" # 发送换行符 newline_data = { 'code': 200, 'type': 'newline', 'data': '\n\n', 'finished': False, 'isComplete': True } yield f"data: {json.dumps(newline_data, ensure_ascii=False)}\n\n" end_data = { 'code': 200, 'data': '', 'finished': True, 'full_text': "处理结果已发送完毕!" } yield f"data: {json.dumps(end_data, ensure_ascii=False)}\n\n" return Response(stream_with_context(generate_error_response()), mimetype='text/event-stream')