Files

1 line
29 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "adw-19/llmpic", "files": {"doc/README_CN.md": {"584449ccfcd7469408a160c40928141837c00a60": {"t": 1785674664.088481, "n": 20325, "h": "20003f82ce604785", "c": "<p align=\"center\">\n <img src=\"https://img.shields.io/badge/license-MIT-blue.svg\" alt=\"License\">\n <a href=\"https://github.com/ADW-19/llmpic\"><img src=\"https://img.shields.io/badge/github-ADW--19%2Fllmpic-lightgrey.svg\" alt=\"GitHub\"></a>\n <img src=\"https://img.shields.io/badge/python-≥3.10-green.svg\" alt=\"Python\">\n <img src=\"https://img.shields.io/badge/version-0.3.0-orange.svg\" alt=\"Version\">\n <img src=\"https://img.shields.io/badge/pypi-llmpic-blue.svg\" alt=\"PyPI\">\n</p>\n\n<p align=\"center\"><img src=\"../llmpic_logo.png\" alt=\"llmpic logo\" width=\"120\"></p>\n\n<h1 align=\"center\">LLMPIC</h1>\n<p align=\"center\"><strong>自然语言驱动 · 一行代码出图</strong></p>\n\n<p align=\"center\">\n <a href=\"https://github.com/ADW-19/llmpic\">English</a> &nbsp;|&nbsp;\n <a href=\"https://ADW-19.github.io/llmpic/\">文档官网</a> &nbsp;|&nbsp;\n <a href=\"chinese/API_REFERENCE_CN.md\">API 参考</a> &nbsp;|&nbsp;\n <a href=\"chinese/GUIDE_CN.md\">使用指南</a> &nbsp;|&nbsp;\n <a href=\"../notebook_examples/llmpic_demo_cn.ipynb\">Notebook 示例</a>\n</p>\n\n---\n## 💡 为什么选择 llmpic?\n\n传统 Python 画图,你需要死记硬背 matplotlib 那上百个 API —— `plt.subplots()`、`ax.set_xticklabels()`、`fig.tight_layout()` —— 一张图几十行代码,查文档的时间比分析数据的时间还长。\n\n**llmpic** 让 Python 绘图进入**大模型时代**。用中文、英文、日文或韩文描述需求,即刻生成可投入生产的高质量 matplotlib 图表。\n\n| | 传统 matplotlib 画图 | llmpic |\n|---|---|---|\n| 代码量 | 15–40 行 | **1–3 行** |\n| API 门槛 | 100+ 个函数 | **0**(自然语言) |\n| 图表类型 | 手动选择 | **12 种 + 智能推荐** |\n| 修改迭代 | 重写大段代码 | **`result.edit(\"改成红色柱子\")`** |\n| Jupyter | 仅 `plt.show()` | **`result.show()` 内联渲染** |\n| 多格式导出 | 多次 savefig | **一个 `save()` 搞定 PNG/SVG/PDF** |\n| 报错修复 | 人工调试 | **LLM 自动修复(最多2轮)** |\n| 并发处理 | 手动线程管理 | **`AsyncllmPIC.batch()` 并发生成** |\n| 安全防护 | 无 | **双重防护:32 条正则 + 可选 LLM 审查** |\n\n### 同一张图,两种写法\n\n**任务**:分组柱状图 — 3 个产品 × 4 个季度,带数值标签、自定义配色、虚线网格、标题、图例。\n\n<table>\n<tr>\n<td width=\"50%\"><b>传统 matplotlib — 35 行</b></td>\n<td width=\"50%\"><b>llmpic — 2 行</b></td>\n</tr>\n<tr>\n<td>\n\n```python\nimport matplotlib.pyplot as plt\nimport numpy as np\n\nproducts = [\"云服务\", \"AI\", \"安全\"]\nquarters = [\"Q1\",\"Q2\",\"Q3\",\"Q4\"]\ndata = np.array([\n [120,145,160,180],\n [ 95,110,130,155],\n [140,165,180,200],\n])\nx = np.arange(len(quarters))\nw = 0.25\ncolors = [\"#3498DB\",\"#2ECC71\",\"#E74C3C\"]\n\nfig, ax = plt.subplots(figsize=(10,6),dpi=150)\nfor i, p in enumerate(products):\n bars = ax.bar(x+i*w, data[i], w,\n label=p, color=colors[i])\n for bar in bars:\n h = bar.get_height()\n ax.text(bar.get_x()+bar.get_width()/2,\n h+1, f\"{h:.0f}\", ha=\"center\",\n va=\"bottom\", fontsize=9)\nax.set_xticks(x + w)\nax.set_xticklabels(quarters)\nax.set_title(\"各产品季度营收\",\n fontsize=14, pad=12)\nax.set_ylabel(\"营收(万元)\")\nax.legend(loc=\"upper left\")\nax.grid(axis=\"y\", linestyle=\"--\", alpha=0.4)\nfig.tight_layout()\nplt.savefig(\"revenue.png\", dpi=150)\nplt.close()\n```\n\n</td>\n<td>\n\n```python\nfrom llmpic import llmPIC\nlp = llmPIC(api_key=\"sk-...\",\n base_url=\"https://api.openai.com/v1\")\n\nlp.bar(\n \"各产品季度营收:\"\n \"云服务=[120,145,160,180],\"\n \"AI=[95,110,130,155],\"\n \"安全=[140,165,180,200]。\"\n \"分组柱状图,加数值标签,\"\n \"虚线网格,图例。\"\n).style({\n \"figsize\": [10, 6], \"dpi\": 150,\n \"color_scheme\": \"cool\",\n}).save(\"revenue.png\")\n```\n\n</td>\n</tr>\n</table>\n\n---\n\n**以下展示 12 种图表类型中的 6 种**(折线图、散点图、柱状图、饼图、热力图、雷达图),完整列表见 [核心特性](#-核心特性)。\n\n```python\nfrom llmpic import llmPIC\n\nlp = llmPIC(api_key=\"sk-...\", base_url=\"https://api.openai.com/v1\")\n\n# 支持 12 种图表类型 — 一行代码出图,无需 matplotlib 知识\nlp.plot(\"2025年度营收趋势,蓝色填充区域\").data(df).save(\"revenue.png\")\nlp.scatter(\"客户年龄 vs 年消费额,带趋势线\").data(df).save(\"scatter.png\")\nlp.bar(\"Q4产品营收对比,水平柱状图\").data(df).save(\"bar.png\")\nlp.pie(\"市场份额分布,最大扇区突出显示\").data(df).save(\"pie.png\")\nlp.heatmap(\"周活跃用户热力图,Blues主题\").data(df).save(\"heatmap.png\")\nlp.radar(\"产品能力六维评估\").data(df).save(\"radar.png\")\n\n# 地图图表 (v0.3.0) — 支持 cartopy 或纯 matplotlib 回退\nlp.map(\"世界人口分布等值区域图\").data(df).save(\"world.png\")\n```\n\n<p align=\"center\"><i>以上 6 张图表 — 全部为 llmpic V0.3.0 实际输出,非示意图</i></p>\n\n<table>\n<tr>\n <td width=\"50%\" align=\"center\">\n <b>plot — 折线图</b><br>\n <code>lp.plot(\"年度营收趋势,蓝色填充区域\").data(df).save()</code><br>\n <img src=\"../assets/demo_line.png\" width=\"95%\"/>\n </td>\n <td width=\"50%\" align=\"center\">\n <b>scatter — 散点图</b><br>\n <code>lp.scatter(\"年龄 vs 消费额,带趋势线\").data(df).save()</code><br>\n <img src=\"../assets/demo_scatter.png\" width=\"95%\"/>\n </td>\n</tr>\n<tr>\n <td width=\"50%\" align=\"center\">\n <b>bar — 柱状图</b><br>\n <code>lp.bar(\"产品营收对比,水平柱状图\").data(df).save()</code><br>\n <img src=\"../assets/demo_bar.png\" width=\"95%\"/>\n </td>\n <td width=\"50%\" align=\"center\">\n <b>pie — 饼图</b><br>\n <code>lp.pie(\"市场份额分布,最大扇区突出\").data(df).save()</code><br>\n <img src=\"../assets/demo_pie.png\" width=\"95%\"/>\n </td>\n</tr>\n<tr>\n <td width=\"50%\" align=\"center\">\n <b>heatmap — 热力图</b><br>\n <code>lp.heatmap(\"周活跃用户热力图,Blues主题\").data(df).save()</code><br>\n <img src=\"../assets/demo_heatmap.png\" width=\"95%\"/>\n </td>\n <td width=\"50%\" align=\"center\">\n <b>radar — 雷达图</b><br>\n <code>lp.radar(\"产品能力六维评估\").data(df).save()</code><br>\n <img src=\"../assets/demo_radar.png\" width=\"95%\"/>\n </td>\n</tr>\n</table>\n\n---\n\n## ✨ 核心特性\n\n- 🗣️ **自然语言输入** — 支持中文、英文、日文、韩文\n- 📊 **12 种图表类型** — 折线图、散点图、柱状图、饼图、直方图、热力图、箱线图、面积图、雷达图、地图、子图仪表盘、智能推荐\n- 🔗 **流式构建器 API** — 链式调用 `.data()` → `.style()` → `.format()` → `.save()` / `.render()`\n- 📓 **Jupyter 内联显示** — `result.show()` 在 cell 下方直接渲染图表\n- ⚡ **异步批量生成** — `AsyncllmPIC.batch()` 多图表并发生成(总耗时≈最慢那张)\n- 🔧 **自动修复** — 代码执行出错时,LLM 自动修正(最多 2 轮)\n- ✏️ **迭代编辑** — `result.edit(\"改成红色,加网格\")` 用自然语言逐步修改图表\n- 📦 **多格式导出** — 一个 `save()` 搞定 PNG(位图)/ SVG(矢量)/ PDF(打印)\n- 🌍 **多语言标签** — 自动检测查询语言,图表标题/坐标轴自动匹配中文\n- 🛡️ **双重安全** — 32 条预编译正则(~0ms)+ 可选 LLM 语义审查\n- 🗺️ **地图图表** — 基于 cartopy 的地理地图;世界地图、等值区域图、散点标记图、国家/地区视图\n- 💻 **跨平台** — Windows / Linux / macOS 全兼容,中文字体自动配置\n- 🔄 **指数退避重试** — LLM 调用失败自动重试(1s, 2s, 4s)\n- 📊 **JSON 结构化输出** — 使用 JSON mode 稳定提取 LLM 生成的 matplotlib 代码\n\n---\n\n## 📦 安装\n\n```bash\npip install llmpic # 一键安装:matplotlib + numpy + openai + pandas + seaborn + scikit-learn + scipy\n```\n\n**环境要求:**\n- Python ≥ 3.10\n- 任意兼容 OpenAI API 的大模型接口(OpenAI、DeepSeek、Azure、智谱 GLM、Ollama 等)\n- 中文/日文/韩文图表需要系统安装对应字体(首次运行时自动检测)\n\n### 验证安装\n\n```python\nfrom llmpic import llmPIC, AsyncllmPIC, ChartResult, PlotBuilder, AsyncPlotBuilder\nimport llmpic\nprint(llmpic.__version__) # → \"0.3.0\"\n```\n\n---\n\n## 🚀 快速入门\n\n### 1. 初始化 SDK\n\n```python\nfrom llmpic import llmPIC\n\n# OpenAI\nlp = llmPIC(\n api_key=\"sk-your-openai-key\",\n base_url=\"https://api.openai.com/v1\",\n model=\"gpt-4o\",\n)\n\n# DeepSeek(国内推荐,性价比高)\nlp = llmPIC(\n api_key=\"sk-your-deepseek-key\",\n base_url=\"https://api.deepseek.com/v1\",\n model=\"deepseek-chat\",\n)\n\n# 智谱 GLM\nlp = llmPIC(\n api_key=\"your-zhipu-key\",\n base_url=\"https://open.bigmodel.cn/api/paas/v4\",\n model=\"glm-4-plus\",\n)\n\n# 任何兼容 OpenAI 接口的服务都可以\nlp = llmPIC(\n api_key=\"your-key\",\n base_url=\"https://your-endpoint/v1\",\n model=\"your-model\",\n)\n```\n\n### 2. 你的第一张图表\n\n```python\n# 基础用法 — 一句话出图\nlp.plot(\"过去12个月的月度销售趋势\").save(\"sales.png\")\n\n# Jupyter 内联显示\nlp.plot(\"30天内CPU使用率变化\").render().show()\n\n# 默认保存路径(不传参数 → 用户主目录)\nlp.plot(\"温度变化趋势\").save() # → ~/llmpic_charts/chart_20250101_120000.png\n```\n\n### 3. 带真实数据出图\n\n```python\nimport pandas as pd\n\ndf = pd.read_csv(\"sales.csv\")\nlp.bar(\"2024年各地区销售额对比\").data(df).style({\n \"color_scheme\": \"warm\",\n \"figsize\": [12, 7],\n \"title_fontsize\": 16,\n}).save(\"regional_sales.png\")\n```\n\n### 4. 常用代码模板(30秒速查)\n\n```python\n# 折线图 + SVG 输出\nlp.plot(\"CPU使用率趋势\").format('svg').save(\"cpu.svg\")\n\n# 散点图 + DataFrame\nlp.scatter(\"年龄与收入的相关性分析\").data(df).save(\"scatter.png\")\n\n# 饼图 + 内联数据\nlp.pie(\"市场份额: A产品=40%, B产品=25%, C产品=20%, D产品=15%\").save(\"pie.png\")\n\n# 热力图 + 相关性矩阵\nlp.heatmap(\"多特征相关性热力图\").data(corr_df).save(\"heatmap.png\")\n\n# 综合仪表盘\nlp.subplots(\"2x2看板: 趋势折线图, 地区对比柱状图, 客户分布散点图, 增长分布直方图\").save(\"dash.png\")\n\n# 地理地图 (v0.3.0)\nlp.map(\"世界人口分布等值区域图,Blues配色\").data(df).save(\"world.png\")\n\n# 智能推荐图表类型\nlp.custom(\"分析用户留存率变化趋势及影响因素\").data(df).save(\"auto.png\")\n\n# 查看生成的代码\nresult = lp.plot(\"测试图\").render()\nprint(result.code) # LLM 生成的 matplotlib 代码\nprint(result.token_usage) # {'input': 320, 'output': 180}\n\n# 迭代修改\nresult = lp.plot(\"月度销售: 1月=100, 2月=120\").render()\nresult.edit(\"改成柱状图,使用红色系\").edit(\n \"标题改为'第一季度收入',添加网格线\").save(\"final.png\")\n```\n\n---\n\n## 📊 图表类型\n\n| 方法 | 图表类型 | 适用场景 | LLM 提示词 |\n|------|---------|---------|-----------|\n| `.plot()` | 折线图 | 趋势分析、时间序列、连续数据 | `ax.plot()` |\n| `.scatter()` | 散点图 | 相关性分析、聚类可视化 | `ax.scatter()` |\n| `.bar()` | 柱状图 | 分类对比、排名 | `ax.bar()` / `ax.barh()` |\n| `.pie()` | 饼图 | 占比分布、市场份额 | `ax.pie(autopct='%1.1f%%')` |\n| `.hist()` | 直方图 | 数据分布、频率统计 | `ax.hist()` |\n| `.heatmap()` | 热力图 | 相关性矩阵、二维密度 | `ax.imshow()` / `sns.heatmap()` |\n| `.boxplot()` | 箱线图 | 多组数据统计分布对比 | `ax.boxplot()` / `sns.boxplot()` |\n| `.area()` | 面积图 | 堆积趋势、成分变化 | `ax.fill_between()` / `ax.stackplot()` |\n| `.radar()` | 雷达图 | 多维指标对比、能力评估 | 极坐标轴 |\n| `.map()` | 地图 | 地理地图、等值区域图、世界/国家/地区 | `cartopy` 或 `ax.scatter()` |\n| `.subplots()` | 综合仪表盘 | 多图表综合展示 | `plt.subplots(nrows, ncols)` |\n| `.custom()` | 智能推荐 | LLM 自动判断最佳图表类型 | 上下文感知 |\n\n---\n\n## 🔗 核心工作流\n\n```\n sdk.plot(\"需求描述\") ← 用自然语言描述图表需求\n → PlotBuilder 构建器\n .data(df) ← 传入真实数据(可选)\n .style({...}) ← 自定义样式(可选)\n .format('png') ← 选择输出格式(可选)\n .render() ← 触发:LLM 生成 → 安全检查 → 沙箱执行 → ChartResult\n .save(\"路径.png\") ← 触发并保存到文件\n```\n\n### 构建器模式详解\n\n```python\n# 所有图表方法返回 PlotBuilder 对象。构建器是惰性的——\n# 在调用 .render() / .save() 或访问 .image_bytes / .code 之前,什么都不会发生。\n\nbuilder = lp.plot(\"月度销售趋势\") # 返回 PlotBuilder —— 还没有调用 LLM\nbuilder = builder.data(df) # 绑定数据\nbuilder = builder.style({\"figsize\": [12, 6]}) # 设定样式\nbuilder = builder.format('svg') # 设定格式\n\nresult = builder.render() # ← 到这里才执行:LLM生成 → 安全审查 → 沙箱执行\nresult.save(\"chart.svg\") # 保存文件\n```\n\n### ChartResult — 结果对象的完全用法\n\n```python\nresult = lp.plot(\"CPU使用率趋势\").render()\n\n# 基本信息\nresult.success # bool — 是否成功\nresult.code # str — LLM 生成的 matplotlib 代码\nresult.token_usage # dict — {'input': 320, 'output': 180}\nresult.size_kb # float — 图片大小 (KB)\n\n# 保存到文件\nresult.save() # → ~/llmpic_charts/chart_{timestamp}.png\nresult.save(\"out.png\") # PNG\nresult.save(\"out.svg\") # SVG\nresult.save(\"out.pdf\") # PDF\n\n# Jupyter 内联展示\nresult.show()\n\n# Base64 编码(前端嵌入)\nresult.base64() # data:image/png;base64,...\nresult.base64_svg() # data:image/svg+xml;base64,...\n\n# 访问其他格式(懒加载,首次访问时重新渲染并缓存)\nresult.svg_bytes # SVG 字节数据\nresult.pdf_bytes # PDF 字节数据\nresult.svg # SVG 字符串\n\n# 自然语言迭代修改\nv2 = result.edit(\"改成柱状图,使用暖色系\")\nv3 = v2.edit(\"标题字号加大到18\")\n```\n\n---\n\n## ⚡ 异步与批量生成\n\n使用 `AsyncllmPIC` 实现图表并发生成,总耗时接近最慢的那张图表。\n\n```python\nfrom llmpic import AsyncllmPIC\nimport asyncio\n\nasync def main():\n lp = AsyncllmPIC(\n api_key=\"sk-...\",\n base_url=\"https://api.deepseek.com/v1\",\n model=\"deepseek-chat\",\n )\n\n # 批量生成:5 张图表并发执行\n results = await lp.batch([\n (\"plot\", \"过去12个月销售趋势\"),\n (\"bar\", \"各地区销售额对比\"),\n (\"pie\", \"市场份额分布\"),\n (\"scatter\", \"用户年龄与消费金额关系\"),\n (\"heatmap\", \"多维度特征相关性矩阵\"),\n ])\n\n for i, r in enumerate(results):\n if r.success:\n r.save(f\"batch_{i}.png\")\n print(f\"[{i}] 成功 — {r.size_kb:.1f}KB, \"\n f\"Token: 输入={r.token_usage['input']} 输出={r.token_usage['output']}\")\n else:\n print(f\"[{i}] 失败: {r.error_message}\")\n\nasyncio.run(main())\n```\n\n### 手动控制并发\n\n```python\nasync def main():\n lp = AsyncllmPIC(...)\n\n # 精细控制:不同图表使用不同格式\n builders = [\n lp.plot(\"CPU趋势\").format('png'),\n lp.bar(\"销售对比\").data(df).style({\"color_scheme\": \"warm\"}).format('svg'),\n lp.pie(\"市场份额\").format('pdf'),\n ]\n results = await asyncio.gather(*[b.render() for b in builders])\n # 三张图表完全并发生成\n\nasyncio.run(main())\n```\n\n---\n\n## ✏️ 迭代编辑\n\n不需要为小修改重写整个需求 —— 用 `edit()` 逐步打磨图表。\n\n```python\n# 起点\nresult = lp.plot(\"月度销售: 1月=100, 2月=120, 3月=90, 4月=150\").render()\n\n# 逐步修改 —— 每次 .edit() 返回新 ChartResult,不改变原对象\nresult = result.edit(\"换成柱状图\")\nresult = result.edit(\"柱子颜色用红色系,暖色调\")\nresult = result.edit(\"添加网格线,标题字号改大到18\")\nresult = result.edit(\"标题改为'2025年Q1销售报告',Y轴加标签'营收(万元)'\")\n\nresult.save(\"final.png\")\nresult.show()\n```\n\n**原理:** 每次 `edit()` 将当前代码 + 修改描述发给 LLM,LLM 返回修改后的代码,经过安全审查 → 沙箱执行的完整管线,返回新 `ChartResult`。原始 `ChartResult` 始终不变。\n\n---\n\n## 📦 输出格式\n\n| 格式 | 扩展名 | 类型 | 适用场景 |\n|------|-------|------|---------|\n| PNG | `.png` | 位图 | 通用场景、快速预览、嵌入文档 |\n| SVG | `.svg` | 矢量 | 网页嵌入、无限缩放、前端展示 |\n| PDF | `.pdf` | 矢量/打印 | 学术论文、商业报告、印刷输出 |\n\n```python\n# 方式一:渲染前用 .format() 指定格式\nlp.plot(\"趋势\").format('svg').save(\"chart.svg\")\nlp.plot(\"趋势\").format('pdf').save(\"chart.pdf\")\n\n# 方式二:保存时根据扩展名自动切换格式\nresult = lp.plot(\"趋势\").render() # 默认 PNG\nresult.save(\"output.svg\") # → SVG(根据扩展名自动检测)\nresult.save(\"output.pdf\") # → PDF\n\n# 方式三:通过属性访问其他格式(懒加载,首次访问时重新渲染)\nresult = lp.plot(\"趋势\").render() # image_bytes 为 PNG\nsvg_data = result.svg_bytes # 懒加载,重新渲染为 SVG(并缓存)\npdf_data = result.pdf_bytes # 懒加载,重新渲染为 PDF(并缓存)\n```\n\n---\n\n## 🎨 样式定制\n\n### 6 种预设配色方案\n\n```python\nlp.plot(\"趋势\").style({\"color_scheme\": \"blues\"}).save(\"b.png\") # 蓝调\nlp.plot(\"趋势\").style({\"color_scheme\": \"warm\"}).save(\"w.png\") # 暖色\nlp.plot(\"趋势\").style({\"color_scheme\": \"cool\"}).save(\"c.png\") # 冷色\nlp.plot(\"趋势\").style({\"color_scheme\": \"pastel\"}).save(\"p.png\") # 柔和\nlp.plot(\"趋势\").style({\"color_scheme\": \"dark\"}).save(\"d.png\") # 暗色\nlp.plot(\"趋势\").style({\"color_scheme\": \"grayscale\"}).save(\"g.png\") # 灰度\n```\n\n### 所有样式参数\n\n| 参数 | 类型 | 默认值 | 说明 |\n|-----|------|-------|------|\n| `figsize` | `[int, int]` | `[10, 6]` | 图表尺寸(英寸),[宽, 高] |\n| `dpi` | `int` | `150` | 输出分辨率(每英寸像素数) |\n| `color_scheme` | `str` | `\"blues\"` | 配色方案:`blues` `warm` `cool` `pastel` `dark` `grayscale` |\n| `title_fontsize` | `int` | `14` | 标题字号 |\n| `label_fontsize` | `int` | `12` | 坐标轴标签字号 |\n| `tick_fontsize` | `int` | `10` | 刻度标签字号 |\n| `grid` | `bool` | `True` | 是否显示背景网格 |\n| `grid_alpha` | `float` | `0.3` | 网格线透明度(0–1) |\n| `tight_layout` | `bool` | `True` | 是否自动调整布局避免裁剪 |\n| `facecolor` | `str` | `\"white\"` | 图表背景色(支持任意 CSS 颜色) |\n\n### 样式定制示例\n\n```python\n# 学术论文级别\nlp.plot(\"实验结果对比\").style({\n \"figsize\": [8, 5],\n \"dpi\": 300,\n \"color_scheme\": \"dark\",\n \"title_fontsize\": 16,\n \"label_fontsize\": 14,\n}).save(\"paper.png\")\n\n# PPT 汇报专用\nlp.bar(\"Q4营收对比\").data(df).style({\n \"figsize\": [14, 8],\n \"color_scheme\": \"warm\",\n \"title_fontsize\": 22,\n \"label_fontsize\": 16,\n \"tick_fontsize\": 14,\n \"grid\": False,\n \"facecolor\": \"#FAFAFA\",\n \"dpi\": 200,\n}).save(\"ppt.png\")\n\n# 也可以通过 JSON 字符串传入样式\nlp.plot(\"趋势\").style('{\"color_scheme\":\"cool\",\"figsize\":[12,8]}').save(\"trend.png\")\n```\n\n---\n\n## 🛡️ 安全保障\n\nllmpic 在**沙箱环境**中执行 LLM 生成的代码,提供双层防护:\n\n### 第一层:正则模式匹配(~0ms,零延迟)\n\n32 条预编译正则表达式阻止已知危险模式:\n- **系统命令**:`os.system()`, `os.popen()`, `subprocess`\n- **文件操作**:`open()`(LLM 不应直接读写文件)\n- **动态执行**:`exec()`, `eval()`, `compile()`, `__import__()`\n- **网络访问**:`socket`, `urllib`, `requests`, `httpx`\n- **危险模块**:`shutil`, `ctypes`, `pickle`\n- **反射逃逸**:`__subclasses__`, `__bases__`, `__mro__`\n\n### 第二层:沙箱执行\n\n- **受限命名空间**:仅包含安全内置函数 + matplotlib, numpy, pandas, seaborn\n- **Figure.savefig 拦截**:阻止代码直接写文件,由沙箱统一接管渲染\n- **plt.show() / plt.savefig() / plt.close() 阻断**:全部拦截为空操作\n- **超时熔断**:ThreadPoolExecutor + 超时机制终止失控代码\n- **全局互斥锁**:模块级锁防止 matplotlib 全局状态竞争\n\n### 安全级别配置\n\n```python\n# 快速模式(默认,推荐生产环境)\nlp = llmPIC(..., safety_level=\"fast\")\n\n# 完整模式(正则 + LLM 语义审查,每张图额外增加约 1-2 秒)\nlp = llmPIC(..., safety_level=\"full\")\n```\n\n**建议:** 沙箱本身已经阻止所有实际执行路径,`fast` 模式在生产环境中足够安全。`full` 模式适用于对安全性有极高要求的场景。\n\n---\n\n## 🌐 LLM 服务商兼容性\n\nllmpic 兼容**所有提供 OpenAI 兼容接口**的大模型服务(需要支持 `chat/completions` 和 JSON 结构化输出):\n\n| 服务商 | base_url | 模型示例 |\n|--------|----------|---------|\n| OpenAI | `https://api.openai.com/v1` | `gpt-5.5`, `gpt-5.5-mini` |\n| DeepSeek | `https://api.deepseek.com/v1` | `deepseek-v4-pro` |\n| Azure OpenAI | `https://{resource}.openai.azure.com/openai/deployments/{deployment}` | 你的部署名称 |\n| 智谱 GLM | `https://open.bigmodel.cn/api/paas/v5` | `glm-5` |\n| 月之暗面 Moonshot | `https://api.moonshot.cn/v1` | `moonshot-v1-8k` |\n| 阿里通义千问 | `https://dashscope.aliyuncs.com/compatible-mode/v1` | `qwen-plus` |\n| 百度文心一言 | `https://qianfan.baidubce.com/v2` | `ernie-4.0-turbo-8k` |\n| Ollama(本地) | `http://localhost:11434/v1` | `llama3`, `qwen3.5` |\n| vLLM(本地) | `http://localhost:8000/v1` | 你部署的模型 |\n\n> **提示**:图表质量与代码生成能力直接相关。推荐使用 GPT-5.5、DeepSeek-V4、GLM-5 等代码能力强的模型。本地模型可能生成不够可靠的代码——建议增大 `max_retries` 和 `max_fix_attempts` 参数。\n\n---\n\n## 🔧 环境变量配置\n\n推荐将 API 密钥存储在环境变量或 `.env` 文件中:\n\n```bash\n# .env 文件 或 Shell 配置\nexport LLMPIC_API_KEY=\"sk-your-key\"\nexport LLMPIC_BASE_URL=\"https://api.deepseek.com/v1\"\nexport LLMPIC_MODEL=\"deepseek-chat\"\n```\n\n```python\nimport os\nfrom llmpic import llmPIC\n\nlp = llmPIC(\n api_key=os.getenv(\"LLMPIC_API_KEY\"),\n base_url=os.getenv(\"LLMPIC_BASE_URL\"),\n model=os.getenv(\"LLMPIC_MODEL\", \"gpt-4o\"),\n)\n```\n\n---\n\n## 🏗 架构总览\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│ llmPIC / AsyncllmPIC │\n│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │\n│ │ .plot() │ │ .bar() │ │ .pie() │ │.custom() │ │\n│ │.scatter()│ │ .hist() │ │.heatmap()│ │ ...共12种 │ │\n│ │ .map() │ │.boxplot()│ │ .area() │ │ .radar() │ │\n│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │\n│ └──────────────┴──────────────┴──────────────┘ │\n│ │ │\n│ PlotBuilder / AsyncPlotBuilder │\n│ .data() .style() .format() │\n│ │ │\n│ .render() / .save() │\n│ │ │\n│ ┌───────────┴───────────┐ │\n│ │ 1. LLM 代码生成 │ OpenAI 兼容 API │\n│ │ (重试3次+指数退避) │ │\n│ └───────────┬───────────┘ │\n│ │ │\n│ ┌───────────┴───────────┐ │\n│ │ 2. 安全审查 │ CodeSafetyChecker │\n│ │ 32条正则 + 可选LLM│ │\n│ └───────────┬───────────┘ │\n│ │ │\n│ ┌───────────┴───────────┐ │\n│ │ 3. 沙箱执行 │ SandboxExecutor │\n│ │ (自动修复失败代码) │ ThreadPool + 超时 │\n│ └───────────┬───────────┘ │\n│ │ │\n│ ChartResult │\n│ .save() .show() .edit() .base64() .svg .pdf │\n└─────────────────────────────────────────────────────────────┘\n```\n\n**每张图表的生成管线:**\n1. **LLM 代码生成** — 自然语言 → matplotlib Python 代码(JSON 结构化输出,最多重试 3 次)\n2. **安全审查** — 32 条正则模式匹配 + 可选 LLM 语义审查\n3. **沙箱执行** — ThreadPoolExecutor 线程池 + 超时机制 + Figure 猴子补丁 + 受限命名空间\n4. **自动修复** — 执行失败时,将代码+错误信息发回 LLM 修正(最多 2 轮)\n5. **返回结果** — `ChartResult` 包含图像字节、源代码、Token 用量、懒加载格式转换\n\n---\n\n## 📖 文档导航\n\n| 文档 | 语言 | 说明 |\n|------|------|------|\n| [API 参考](chinese/API_REFERENCE_CN.md) | 中文 | 所有类、方法、参数的详细说明 |\n| [API Reference](english/API_REFERENCE_EN.md) | EN | Complete class, method, and parameter reference |\n| [使用指南](chinese/GUIDE_CN.md) | 中文 | 进阶用法、最佳实践、故障排查 |\n| [User Guide](english/GUIDE_EN.md) | EN | Advanced usage, best practices, troubleshooting |\n| [Jupyter 演示](https://github.com/ADW-19/llmpic/tree/main/notebook_examples) | 中/EN | 开箱即用的 Jupyter Notebook |\n| [English README](https://github.com/ADW-19/llmpic) | EN | Full English README |\n\n---\n\n## 📮 官方联系方式\n\n- **小红书**:[ADW_AI](https://xhslink.com/m/AQw13M5WIPc)\n- **GitHub Issues**:[github.com/ADW-19/llmpic/issues](https://github.com/ADW-19/llmpic/issues)\n\n---\n\n## 🙏 致谢\n\nllmpic 站在以下优秀开源项目的肩膀上构建:\n\n- [SciPy](https://scipy.org/) — 科学计算\n- [scikit-learn](https://scikit-learn.org/) — 机器学习工具\n- [pandas](https://pandas.pydata.org/) — 数据分析与 DataFrame\n- [NumPy](https://numpy.org/) — 数值计算\n- [Matplotlib](https://matplotlib.org/) — 图表渲染引擎\n- [seaborn](https://seaborn.pydata.org/) — 统计数据可视化\n\n衷心感谢这些项目的维护者与贡献者。\n\n---\n\n## 📄 开源协议\n\n[MIT](https://github.com/ADW-19/llmpic/blob/main/LICENSE) © 2026 ADW-19\n"}}}}