概述
先上演示应用 https://www.snowpeak.org/math_question/ChatPyplot.htm
演示运行的截图:
项目源码已开源 https://github.com/xfsnow/xfsnow.github.io/blob/master/math_question/ChatPyplot.htm
谁适合看此文档?
本文深入讲解了一个结合 Python Matplotlib 库与 AI 对话功能的智能工具——ChatPyplot 的开发过程和实现原理。适用于对前端开发、AI 集成和数据可视化感兴趣的朋友,了解 JavaScript、HTML/CSS 基本语法,有一定的前端开发经验。
此文档有什么用?
此文档介绍的内容适用于较大规模的前端开发项目,尤其是涉及 AI 集成、数据可视化和用户交互设计的场景。通过详细介绍 ChatPyplot 项目的架构和实现细节,帮助开发者理解如何将 AI 技术与 Python 数据可视化库结合,创造出实用的教育工具。
意义
在教育和数据分析领域,可视化是一个非常重要的工具。传统的数据可视化需要用户掌握特定的编程语言和库的使用方法,而将 AI 与 Python Matplotlib 结合可以大大降低使用门槛,使用户能够通过自然语言与系统交互,自动生成和执行绘图代码。这不仅提高了用户体验,也拓展了数据可视化的应用场景。
ChatPyplot 项目的意义在于: 1. 提供了一种全新的数据分析和可视化方式 2. 展示了如何将多种 AI 模型集成到一个统一的界面中 3. 实现了 AI 与 Python 数据可视化库的无缝连接 4. 为教育技术的发展提供了新的思路
项目背景与需求场景
项目背景
Python Matplotlib 是一款优秀的数据可视化库,广泛应用于数据分析和科研领域。然而,使用 Matplotlib 需要掌握其特定的 API 和编程语法,这对初学者来说是一个门槛。同时,随着 AI 技术的发展,特别是大语言模型在理解和生成代码方面的能力不断提升,将 AI 与 Python 数据可视化库结合成为可能。
ChatPyplot 项目应运而生,旨在通过自然语言交互降低 Python Matplotlib 的使用门槛,让用户能够通过简单的语言描述来生成和执行绘图代码。
解决的需求场景
- 降低学习门槛:用户无需掌握复杂的 Python 和 Matplotlib 语法,只需用自然语言描述需求
- 提高效率:快速生成和执行绘图代码,节省手动编写时间
- 多模型支持:集成多种 AI 模型,满足不同用户的需求
- 图像理解:支持上传图片,结合图像内容进行分析和绘图
- 教育应用:为数据分析教学和学习提供直观的可视化工具
代码架构设计
整体架构
ChatPyplot 项目采用纯前端架构,主要由以下几个部分组成:
- 用户界面层:HTML/CSS 实现的用户界面
- 控制逻辑层:JavaScript 实现的业务逻辑
- AI 接口层:与不同 AI 模型的接口实现
- Python 运行环境层:Pyodide 运行环境,用于在浏览器中执行 Python 代码
核心类设计
项目采用了面向对象的设计方法,主要包含以下几个核心类:
AiBase 基类
AiBase 是所有 AI 模型类的基类,封装了通用的逻辑,包括: - 消息历史管理 - 系统提示语处理 - 图片文件转 Base64 编码 - AI 响应格式化 - Python 代码提取
具体 AI 模型类
项目支持三种主要的 AI 模型,每种模型都有对应的实现类,继承自 AiBase 基类:
- AiDeepSeek - DeepSeek AI 类
- AiQwen - 通义千问 AI 类
- AiAzureOpenAI - Azure OpenAI AI 类
每个子类根据各自模型的 API 规范实现了特定的调用逻辑。
PyodideManager 类
这是项目的核心管理类,负责在浏览器中运行 Python 代码,主要功能包括: - 初始化 Pyodide 运行环境 - 加载必要的 Python 包(如 numpy、matplotlib) - 加载并配置中文字体 - 执行 Python 代码并生成图像 - 管理 Python 环境状态
Pyodide 在浏览器中运行的基本原理
什么是 Pyodide?
Pyodide 是一个 Python 发行版,它被编译为 WebAssembly 并在浏览器中运行。它使得在浏览器中直接运行 Python 代码成为可能,无需服务器端支持。
工作原理
加载 Pyodide:首次访问时,浏览器会从 CDN 下载 Pyodide 环境(约 10-20MB),其中包括 Python 解释器和标准库。
安装依赖包:根据需要加载额外的 Python 包,如 numpy、matplotlib 等科学计算库。这些包也被编译为 WebAssembly 格式。
执行 Python 代码:用户生成的 Python 代码在浏览器中的 Pyodide 环境中执行,无需与服务器通信。
结果可视化:使用 Matplotlib 生成的图表被转换为图像数据(base64 编码),然后显示在网页上。
技术优势
- 隐私保护:所有代码都在本地浏览器中执行,无需上传到服务器
- 实时响应:无需网络往返,代码执行响应速度快
- 离线可用:一旦加载完成,即使断网也能继续使用
- 丰富的生态系统:支持大多数常用的 Python 科学计算库
中文字体加载与显示方案
问题背景
在数据可视化中,正确显示中文标签、标题和图例是一个重要需求。然而,浏览器中的 Pyodide 环境无法访问系统字体,因此需要特殊处理才能正确显示中文。
解决方案
ChatPyplot 采用了一种有效的中文字体加载和配置方案:
字体文件获取:从 Google Fonts CDN 获取思源黑体(Noto Sans SC)字体文件。
字体文件加载:使用 fetch API 下载字体文件,并将其写入 Pyodide 的虚拟文件系统中。
字体注册:在 Python 环境中使用 matplotlib 的字体管理功能注册并加载中文字体。
字体配置:设置 matplotlib 的默认字体为加载的中文字体。
实现细节
// 加载字体文件
const fontResponse = await fetch(this.fontUrl);
if (fontResponse.ok) {
const fontArrayBuffer = await fontResponse.arrayBuffer();
const fontData = new Uint8Array(fontArrayBuffer);
this.pyodide.FS.writeFile(fontPath, fontData);
}
// 在 Python 环境中配置字体
this.pyodide.runPython(`
try:
# 检查字体文件是否存在于Pyodide的虚拟文件系统中
if os.path.exists('${fontPath}'):
# 加载字体文件
fm.fontManager.addfont('${fontPath}')
font_name = fm.FontProperties(fname='${fontPath}').get_name()
# 设置为默认字体
plt.rcParams['font.family'] = font_name
except Exception as e:
# 备用字体方案
plt.rcParams['font.sans-serif'] = ['DejaVu Sans', 'Bitstream Vera Sans', 'Arial Unicode MS', 'sans-serif']
`);
技术要点
- 使用思源黑体(Noto Sans SC)作为主要中文字体,它是一款开源、高质量的字体
- 通过 Pyodide 的 FS 模块将字体文件写入虚拟文件系统
- 使用 matplotlib 的 fontManager 注册字体
- 设置合理的字体回退机制,确保在字体加载失败时仍能显示基本内容
- 配置负号显示,解决中文负号显示异常问题
系统提示语设计
系统提示语是引导 AI 行为的关键部分,在 ChatPyplot 项目中具有特殊的重要性。它不仅需要指导 AI 如何回答数学相关问题,还需要明确如何生成 Python 代码。
系统提示语的核心内容
系统提示语主要包括以下几个方面:
- 角色定义:明确 AI 作为数据可视化助手的身份
- 行为规范:要求 AI 在回答时提供友好的解释和清晰的 Python 代码
- 代码格式:规定 Python 代码必须放在特定的代码块中(
python
) - 数学公式格式:要求数学公式使用 $$ 包裹
- 代码规范:生成的代码应能直接运行并生成可视化图表
系统提示语的共享机制
在 ChatPyplot 中,系统提示语作为全局配置,对所有 AI 模型都有效。用户只需设置一次,即可应用于所有模型,这大大简化了配置过程。
对话交互方式
ChatPyplot 支持多种对话交互方式,满足不同场景的需求:
纯文本对话
用户可以直接输入文本问题,如"画一个正弦函数图像",AI 会解析问题并生成相应的 Python 代码。
文本加图片对话
对于更复杂的场景,用户可以上传图片并结合文本描述进行提问。这特别适用于以下场景: - 上传数据图表图片,询问数据分析方法并重新绘制 - 上传函数图像,要求分析函数性质并绘制相似图形 - 上传实际场景照片,要求抽象为数据模型并绘制
这一功能主要由支持视觉理解的模型实现,如 Azure OpenAI 的 gpt-4o 和通义千问的 qwen3-vl-plus。
图片处理与接口调用
本地图片处理流程
当用户选择上传图片时,系统会执行以下步骤:
- 文件选择:用户通过文件选择器选择本地图片
- 格式校验:检查文件类型(JPG/PNG/GIF/WEBP)和大小(不超过10MB)
- 转换编码:使用 FileReader 将图片文件转换为 Base64 编码
- 预览显示:在界面中显示图片预览
- 数据存储:将 Base64 编码存储在共享状态中
图片参数组织
在调用支持视觉理解的 AI 模型时,需要将图片和文本组织成特定的参数格式:
// 构造包含图片和文本的用户消息
const userContent = [
{ type: "text", text: "请分析这张图片中的数据图表并重新绘制" },
{
type: "image_url",
image_url: {
url: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ..."
}
}
];
这种结构化的方式允许 AI 同时处理文本和图像信息,提供更丰富的交互体验。
调用大模型的主要原理
统一接口设计
项目通过继承 AiBase 基类,为不同的 AI 模型实现了统一的接口。这样做的好处是: 1. 代码结构清晰,易于维护和扩展 2. 新增 AI 模型只需继承基类并实现特定方法 3. 上层调用逻辑无需关心具体模型的实现细节
流式传输处理
为了提供更好的用户体验,项目采用了流式传输技术,实时显示 AI 的思考过程。这种方式让用户能够看到 AI 逐步生成的响应,而不是等待完整响应后再显示。
多模型支持机制
项目通过模型选择机制支持多种 AI 模型,用户可以根据需求选择合适的模型。每种模型都有独立的配置项,但共享系统提示语等全局设置。
项目特点与优势
多模型支持
ChatPyplot 支持多种主流 AI 模型:
- DeepSeek:适合中文场景的开源大模型
- 通义千问:阿里巴巴的千问系列模型,支持图像理解
- Azure OpenAI:微软 Azure 平台的 OpenAI 服务
图像理解能力
项目支持上传图片并与 AI 进行结合分析,这是通过 Azure OpenAI 的 gpt-4o 模型和通义千问的 qwen3-vl-plus 模型实现的。这些模型具备强大的视觉理解能力,能够分析图片中的数据内容并生成相应的 Python 代码。
本地存储配置
用户的配置信息通过 localStorage 进行持久化存储,包括各模型的 API 密钥和系统提示语等。这样用户在下次访问时无需重新配置。
浏览器内代码执行
与传统的需要服务器执行代码的方案不同,ChatPyplot 使用 Pyodide 在浏览器中直接执行 Python 代码,具有更好的隐私保护和响应速度。
中文支持完善
通过精心设计的中文字体加载和配置方案,确保图表中的中文标签、标题和图例能够正确显示。
总结
ChatPyplot 项目通过将 AI 技术与 Python Matplotlib 库相结合,为用户提供了一种全新的数据分析和可视化方式。项目采用模块化设计,具有良好的扩展性和维护性,支持多种 AI 模型和图像理解功能。
通过这个项目,我们可以看到:
- AI 技术在数据分析领域的巨大潜力
- 前端技术在实现复杂交互方面的强大能力
- WebAssembly 技术在浏览器中运行复杂应用的可能性
- 开源技术在推动教育创新中的重要作用
未来,该项目还可以进一步扩展,例如:
- 增加更多的 AI 模型支持
- 提供更丰富的可视化效果和图表类型
- 增强交互性和用户体验
- 和数据分析系统集成,实现数据的智能分析和可视化