You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将SHAP forceplot通过emit推送到HTML的iframe中展示

问题根因

SHAP生成的force plot HTML源码中自带{{obj}}、{{#each}}这类Mustache模板语法标记,和Flask默认使用的Jinja2模板语法(同样使用{{ }}作为变量占位符)完全冲突。
原有render_template方案正常是因为你给传递的SHAP HTML变量加了|safe过滤器,直接输出转义后的内容,不会触发Jinja2的二次解析;改为SocketIO推送后触发报错,是因为SHAP HTML里的{{obj}}标记被Jinja2识别为模板变量,尝试在当前渲染上下文查找obj变量失败,因此抛出未定义错误。

解决方法

1. 后端预处理SHAP HTML,避免Jinja2解析标记

生成SHAP force plot HTML后,先对特殊标记做转义处理,再通过SocketIO推送:

import shap
from jinja2 import escape

# 生成SHAP force plot HTML
force_plot = shap.force_plot(explainer.expected_value, shap_values[0], X.iloc[0], show=False)
shap_html = shap.getjs() + shap.html(force_plot)
# 转义双大括号标记,避免被Jinja2识别为模板变量
processed_html = shap_html.replace("{{", r"{{ '{{' }}").replace("}}", r"{{ '}}' }}")
# 也可直接用escape函数全量转义
# processed_html = str(escape(shap_html))

# 推送处理后的内容
socketio.emit("update_shap", {"html": processed_html})

2. 前端直接赋值,不要经过Jinja2渲染

前端接收SocketIO推送的内容时,直接用原生JS操作DOM,不要把返回内容放在{{ }}等Jinja2模板标记中:

// iframe赋值方案
socket.on('update_shap', function(data) {
  const iframe = document.getElementById('shap-iframe');
  // 先解码再赋值
  iframe.srcdoc = decodeURIComponent(data.html);
  // 开放必要权限保证SHAP脚本正常执行
  iframe.sandbox = "allow-scripts allow-same-origin";
});

// 兜底DIV插入方案(无需iframe)
// socket.on('update_shap', function(data) {
//   document.getElementById('shap-container').innerHTML = decodeURIComponent(data.html);
// });

内容的提问来源于stack exchange,提问作者Sade

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 18:09:02