matplotlib 中文乱码方框怎么办?MathModelAgent 黑体字体渲染完整方案
【免费下载链接】MathModelAgent🤖📐专为数学建模设计的 Agent & skills ,自动完成数学建模,生成一份完整的可以直接提交的论文。 An Agent Designed for Mathematical Modeling ,Automatically complete mathmodel and generate a complete paper ready for submission.项目地址: https://gitcode.com/GitHub_Trending/ma/MathModelAgent
MathModelAgent 是一个专为数学建模设计的开源 Agent 项目,能自动完成问题分析、建模、写代码、绘图并生成可直接提交的论文。其中"图表中文变成豆腐块(□□□)"是建模同学在用 matplotlib 绘图时几乎必然踩的坑,本项目通过内置黑体字体 + kernel 启动自动注册 + 提示词约束三管齐下,让 Agent 生成的每一张图表都稳定显示中文。本文带你拆解这套完整方案。
一、为什么 matplotlib 中文会变成方框?
matplotlib 默认只加载系统字体的一个缓存列表,而 Linux 服务器、Docker 容器、云端沙箱(E2B)这类环境通常没有安装中文字体。一旦字体缺失:
- 中文标签、图例全部渲染成
□□□方框; - 负号
-也可能显示异常(axes.unicode_minus未处理); - 手动
addfont之后,旧字体缓存不失效,字体依然"找不到"。
所以一个可靠方案必须同时解决三件事:字体文件就位、清缓存注册字体、固定 rcParams 配置。MathModelAgent 正是按这个思路设计的。
二、第一步:黑体字体文件随任务就位
项目在仓库里内置了思源黑体文件:
- 字体文件:backend/fonts/simhei.ttf
- 复制逻辑:backend/app/utils/common_utils.py
每当创建一个新任务工作目录(backend/project/work_dir/<task_id>/)时,create_work_dir()会自动把backend/fonts/下的全部.ttf/.otf/.ttc字体复制到工作目录。这样无论代码跑在本地还是云端,字体都"跟着数据走",不依赖宿主机的系统字体。
💡 这是整个方案的地基:不假设任何系统环境,把字体当数据文件分发。
三、第二步:kernel 启动时一键注册中文字体
核心代码在 backend/app/tools/matplotlib_setup.py,build_matplotlib_init_code()会生成一段在 Jupyter / E2B kernel 启动时最先执行的初始化代码,逻辑分三步:
- 清字体缓存:删除
matplotlib.get_cachedir()下的fontlist*.json,再调用font_manager.fontManager.__init__()重建字体列表——这解决了"手动加字体不生效"的经典坑; - 注册黑体:遍历字体目录,对每个
.ttf/.otf/.ttc调用font_manager.fontManager.addfont(),并记录真实字体名; - 设置 rcParams:把已注册的黑体名放到
font.sans-serif最前面,再依次兜底Heiti SC、PingFang SC、Noto Sans CJK SC、Microsoft YaHei等常见中文字体,同时设置axes.unicode_minus = False修复负号显示。
本地执行器在 backend/app/tools/local_interpreter.py 的initialize()中调用这段初始化代码,并把"中文字体已加载:SimHei(共 1 个)"这样的结论通过 WebSocket 推给前端;如果没找到字体,也会给出明确的 warning,方便排查。
另外,初始化代码还必须先os.path.abspath()解析绝对路径再os.chdir()——这是一个隐蔽但关键的细节,否则会因相对路径失效导致addfont静默失败(源码注释中有专门说明,见 matplotlib_setup.py 第 43-48 行)。
四、第三步:统一注入学术图表样式
中文字体只是"能显示",论文级图表还需要统一观感。同一份初始化代码还注入了:
COLORS竞赛向配色(主色#2E5B88、辅色#E85D4C等 5 色);FIG_SINGLE / FIG_DOUBLE / FIG_WIDE / FIG_SQUARE四种论文适配的画布尺寸;- 300dpi 保存、去掉上右边框、图例去边框、标题加粗等
rcParams。
Agent 写绘图代码时直接引用这些预置变量即可,产出风格高度一致:
五、第四步:用提示词约束 Agent 别"好心办坏事"
字体注册完就万事大吉了吗?不一定——如果模型在代码里随手写一句sns.set_theme()或重新改font.sans-serif,前面的配置全被覆盖,中文立刻变回方框。
因此项目在 Coder 的提示词里做了硬性约束(见 backend/app/core/prompts/coder.py):
执行环境已预配置
CJK_FONT、COLORS、FIG_*等变量,严格禁止在代码中调用sns.set_theme()或修改font.*/font.sans-serif/axes.unicode_minus(否则会覆盖中文字体导致方框)。
这是很多"环境配置 + 提示词护栏"双保险设计的缩影:环境层保证字体可用,提示词层保证字体不被破坏。
六、Docker 与云端沙箱的字体双保险
方案对三种运行环境都有覆盖:
| 运行环境 | 字体来源 | 说明 |
|---|---|---|
| 本地 Jupyter kernel | backend/fonts/simhei.ttf复制到工作目录 | 见 common_utils.py |
| Docker 容器 | 系统级fonts-noto-cjk+ 内置黑体 | backend/Dockerfile 第 5 行安装 Noto CJK |
| E2B 云端沙箱 | 工作目录里的字体文件上传到/home/user后注册 | e2b_interpreter.py 第 64-111 行 |
云端沙箱的初始化代码同样包含"清缓存 →addfont→ 设置font.sans-serif兜底链"三步,逻辑与本地保持一致,只是字体目录换成了/home/user。
七、小结:可复用的 4 步方法论
如果你自己也要在服务器/容器里用 matplotlib 画中文图表,可以直接套用 MathModelAgent 的四步方案:
- 字体当数据分发:把
simhei.ttf放进项目仓库(参考 backend/fonts/simhei.ttf),运行前复制到代码执行目录; - 先清缓存再注册:删除
fontlist*.json→fontManager.__init__()→addfont(); - rcParams 固定中文字体链 +
axes.unicode_minus=False,兜底多平台常见字体名; - 在代码生成侧加约束,禁止后写入覆盖字体配置。
配合项目内置的 17 套论文模板与图表规范(见 skills/mathmodel-figure-templates/SKILL.md),从中文图表到整篇论文都能一次跑通。想快速体验完整效果,可以运行docker-compose up启动项目,在 WebUI 中提交一个建模任务,即可看到 CoderAgent 全程无方框的中文图表产出。
【免费下载链接】MathModelAgent🤖📐专为数学建模设计的 Agent & skills ,自动完成数学建模,生成一份完整的可以直接提交的论文。 An Agent Designed for Mathematical Modeling ,Automatically complete mathmodel and generate a complete paper ready for submission.项目地址: https://gitcode.com/GitHub_Trending/ma/MathModelAgent
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考