samlax12's picture
Upload 23 files
1625bb7 verified
# modules/visualization/routes.py
from flask import Blueprint, request, jsonify, send_file
import os
import time
import re
import requests
import plotly.graph_objects as go
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from io import BytesIO
import matplotlib
import json
matplotlib.use('Agg') # 非交互式后端
visualization_bp = Blueprint('visualization', __name__)
# 确保存储目录存在
os.makedirs('static', exist_ok=True)
@visualization_bp.route('/mindmap', methods=['POST'])
def generate_mindmap():
"""生成思维导图"""
try:
data = request.json
content = data.get('content', '')
if not content:
return jsonify({
"success": False,
"message": "思维导图内容不能为空"
}), 400
# 提取@startmindmap和@endmindmap之间的内容
pattern = r'@startmindmap\n([\s\S]*?)@endmindmap'
match = re.search(pattern, content)
if match:
processed_content = f"@startmindmap\n{match.group(1)}\n@endmindmap"
else:
# 如果内容中没有正确格式,直接使用原始内容
processed_content = content
# 确保内容有开始和结束标记
if '@startmindmap' not in processed_content:
processed_content = "@startmindmap\n" + processed_content
if '@endmindmap' not in processed_content:
processed_content += "\n@endmindmap"
# 使用HuggingFace Space API生成图像
response = requests.post(
'https://mistpe-flask.hf.space/v1/images/generations',
headers={
'Authorization': 'Bearer sk-xxx', # 实际应用中应从配置中获取
'Content-Type': 'application/json'
},
json={
'model': 'dall-e-3',
'prompt': processed_content,
'n': 1,
'size': '1024x1024'
}
)
if response.status_code != 200:
return jsonify({
"success": False,
"message": "生成思维导图图像失败",
"status_code": response.status_code
}), 500
response_data = response.json()
if not response_data.get('data') or not response_data['data'][0].get('url'):
return jsonify({
"success": False,
"message": "API返回的数据中没有图像URL"
}), 500
image_url = response_data['data'][0]['url']
# 下载图像并保存到本地
img_response = requests.get(image_url)
if img_response.status_code != 200:
return jsonify({
"success": False,
"message": "下载生成的图像失败"
}), 500
# 保存图像到本地
img_filename = f'mindmap_{int(time.time())}.png'
img_path = os.path.join('static', img_filename)
with open(img_path, 'wb') as f:
f.write(img_response.content)
# 构建URL
local_img_url = f'/static/{img_filename}'
return jsonify({
"success": True,
"url": local_img_url,
"original_url": image_url,
"message": "思维导图生成成功"
})
except Exception as e:
import traceback
traceback.print_exc()
return jsonify({
"success": False,
"message": str(e)
}), 500
@visualization_bp.route('/3d-surface', methods=['POST'])
def generate_3d_surface():
"""生成3D表面图并返回嵌入式HTML"""
try:
data = request.json
code = data.get('code', '')
if not code:
return jsonify({
"success": False,
"message": "请提供函数代码"
}), 400
# 清理代码(移除可能的Markdown标记)
code = re.sub(r'```python\n', '', code)
code = re.sub(r'```', '', code)
# 在安全环境中执行代码
local_vars = {}
try:
# 仅提供numpy库
exec(code, {"__builtins__": __builtins__, "np": np, "numpy": np}, local_vars)
# 检查是否有create_3d_plot函数
if 'create_3d_plot' not in local_vars:
return jsonify({
"success": False,
"message": "提供的代码未包含create_3d_plot函数"
}), 500
# 执行函数获取数据
plot_data = local_vars['create_3d_plot']()
if not isinstance(plot_data, dict) or not all(k in plot_data for k in ['x', 'y', 'z']):
return jsonify({
"success": False,
"message": "函数未返回有效的3D数据"
}), 500
# 创建Plotly图形
fig = go.Figure()
# 根据类型添加跟踪
if plot_data.get('type') == 'scatter3d':
fig.add_trace(go.Scatter3d(
x=plot_data['x'],
y=plot_data['y'],
z=plot_data['z'],
mode='markers',
marker=dict(
size=4,
color=plot_data.get('color', plot_data['z']),
colorscale='Viridis',
opacity=0.8
)
))
else: # 默认为surface
# 处理数据格式
try:
x = np.array(plot_data['x'])
y = np.array(plot_data['y'])
z = np.array(plot_data['z'])
if len(x.shape) == 1 and len(y.shape) == 1:
X, Y = np.meshgrid(x, y)
if len(z.shape) == 1:
Z = z.reshape(len(y), len(x))
else:
Z = z
else:
X = x
Y = y
Z = z
fig.add_trace(go.Surface(
z=Z,
x=X,
y=Y,
colorscale='Viridis'
))
except Exception as data_error:
return jsonify({
"success": False,
"message": f"处理3D数据时出错: {str(data_error)}"
}), 500
# 设置图形布局
fig.update_layout(
title=plot_data.get('title', '3D 可视化'),
scene=dict(
xaxis_title='X',
yaxis_title='Y',
zaxis_title='Z'
),
width=800,
height=600,
margin=dict(l=0, r=0, b=0, t=30) # 减小边距,使图形更紧凑
)
# 直接生成HTML
html_content = fig.to_html(include_plotlyjs=True, full_html=True)
# 保存为文件
html_filename = f'3d_plot_{int(time.time())}.html'
html_path = os.path.join('static', html_filename)
with open(html_path, 'w', encoding='utf-8') as f:
f.write(html_content)
return jsonify({
"success": True,
"html_url": f'/static/{html_filename}',
"message": "3D图形生成成功"
})
except Exception as e:
import traceback
error_traceback = traceback.format_exc()
print(f"3D可视化执行错误: {error_traceback}")
return jsonify({
"success": False,
"message": f"执行代码时出错: {str(e)}"
}), 500
except Exception as e:
import traceback
traceback.print_exc()
return jsonify({
"success": False,
"message": str(e)
}), 500