| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- 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')
-
|