Files
ai-startup/gen_pptx.py
T
2026-08-05 17:25:15 +08:00

523 lines
30 KiB
Python
Raw 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.
# -*- coding: utf-8 -*-
"""
生成《销售型生产企业 AI 数字化建设方案》策划案 PPT (.pptx)
- 两张图示(architecture.png / dataflow.png) 用 matplotlib 渲染
- 正文用【占位符】当可复用模板;演讲者备注含"示例填充 + 讲解话术"
- 成本页仅含硬件/云成本,不含服务费报价
"""
import os
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.patches import FancyBboxPatch
import matplotlib.font_manager as fm
# ---------- 路径 ----------
BASE = r"C:\Users\Administrator\Desktop\AI落地公司企划项目"
ASSETS = os.path.join(BASE, "assets")
os.makedirs(ASSETS, exist_ok=True)
ARCH_PNG = os.path.join(ASSETS, "architecture.png")
FLOW_PNG = os.path.join(ASSETS, "dataflow.png")
OUT_PPTX = os.path.join(BASE, "销售型生产企业AI数字化建设方案.pptx")
# ---------- matplotlib 中文字体 ----------
def setup_cjk_font():
for p in [r"C:/Windows/Fonts/msyh.ttc", r"C:/Windows/Fonts/simhei.ttf",
r"C:/Windows/Fonts/simsun.ttc", r"C:/Windows/Fonts/msyhbd.ttc"]:
if os.path.exists(p):
try:
fm.fontManager.addfont(p)
except Exception:
pass
cands = ["Microsoft YaHei", "SimHei", "SimSun", "Noto Sans CJK SC",
"WenQuanYi Micro Hei", "Source Han Sans SC"]
avail = {f.name for f in fm.fontManager.ttflist}
chosen = next((c for c in cands if c in avail), None)
if chosen:
plt.rcParams["font.sans-serif"] = [chosen]
plt.rcParams["axes.unicode_minus"] = False
setup_cjk_font()
# ---------- 图1:四层技术架构栈 ----------
def draw_architecture(path):
fig, ax = plt.subplots(figsize=(12.5, 9))
ax.set_xlim(0, 12.2)
ax.set_ylim(0, 9.2)
ax.axis("off")
bands = [
("触达层", "第四层", "#2E93F7", ["Web 看板 (Streamlit)", "微信/钉钉/飞书推送", "经营简报(图文)"]),
("智能调度层", "第三层", "#1E6FB8", ["Hermes Agent", "Web 管理面板", "工具调用·消息网关"]),
("模型层", "第二层", "#15538C", ["Qwen3.6-35B (Ollama)", "DeepSeek V4 Flash 备用", "bge-m3 向量嵌入"]),
("数据层", "第一层", "#0E3D66", ["SQLite 数据库", "Python 清洗脚本", "Chroma 向量知识库"]),
("硬件与系统", "底层", "#0B2545", ["EVO-X2 128GB", "Ubuntu 24.04 LTS", "2×2TB NVMe·Tailscale"]),
]
n = len(bands)
bh, gap, bottom = 1.45, 0.22, 0.55
for i, (name, tag, color, chips) in enumerate(bands):
y = bottom + i * (bh + gap)
band = FancyBboxPatch((0.4, y), 11.4, bh,
boxstyle="round,pad=0.02,rounding_size=0.12",
linewidth=0, facecolor=color, alpha=0.95)
ax.add_patch(band)
ax.text(0.7, y + bh/2 + 0.18, name, color="white", fontsize=17,
fontweight="bold", va="center", ha="left")
ax.text(0.7, y + bh/2 - 0.32, tag, color="#BBD6F2", fontsize=10,
va="center", ha="left")
cx, cw, sp = 3.3, 2.55, 0.16
for j, c in enumerate(chips):
x = cx + j * (cw + sp)
chip = FancyBboxPatch((x, y + 0.30), cw, bh - 0.60,
boxstyle="round,pad=0.02,rounding_size=0.08",
linewidth=0, facecolor="white", alpha=0.94)
ax.add_patch(chip)
ax.text(x + cw/2, y + bh/2, c, color="#0B2545", fontsize=10.5,
fontweight="bold", va="center", ha="center")
ax.annotate("", xy=(0.4, bottom + n*(bh+gap) - 0.15), xytext=(0.4, bottom + 0.15),
arrowprops=dict(arrowstyle="-|>", color="#9FB6CE", lw=2))
ax.text(0.2, bottom + n*(bh+gap)/2, "数据流\n自下而上", color="#9FB6CE",
fontsize=9, va="center", ha="center", rotation=90)
ax.text(6.1, 9.0, "整体技术架构(四层 + 底层硬件)", color="#0B2545",
fontsize=14, fontweight="bold", va="center", ha="center")
plt.tight_layout()
fig.savefig(path, dpi=200, bbox_inches="tight", facecolor="white")
plt.close(fig)
# ---------- 图2:数据流转全链路 ----------
def draw_dataflow(path):
fig, ax = plt.subplots(figsize=(14, 7))
ax.set_xlim(0, 14)
ax.set_ylim(0, 7)
ax.axis("off")
nodes = [
(1.0, 4.4, "每月原始数据\n(Excel/CSV)", "#0E3D66"),
(3.3, 4.4, "清洗脚本\n(pandas)", "#15538C"),
(5.6, 4.4, "SQLite\n数据库", "#1E6FB8"),
(8.0, 4.4, "Hermes Agent\n调度", "#2E93F7"),
(10.4, 4.4, "看板 / 报表", "#2E93F7"),
(12.6, 4.4, "微信推送\n→ 老板决策", "#FF8A3D"),
]
models = [
(7.0, 1.7, "本地 Ollama\nQwen3.6", "#FF8A3D"),
(8.6, 1.7, "DeepSeek API\n(备用)", "#FF8A3D"),
(10.2, 1.7, "向量知识库\nChroma", "#FF8A3D"),
]
def box(x, y, text, color, w=1.7, h=1.0):
b = FancyBboxPatch((x - w/2, y - h/2), w, h,
boxstyle="round,pad=0.02,rounding_size=0.12",
linewidth=0, facecolor=color, alpha=0.96)
ax.add_patch(b)
ax.text(x, y, text, color="white", fontsize=10.5, fontweight="bold",
va="center", ha="center")
for x, y, t, c in nodes:
box(x, y, t, c)
for x, y, t, c in models:
box(x, y, t, c, w=1.7, h=0.95)
acolor = "#7A94B0"
for i in range(len(nodes) - 1):
x1, x2 = nodes[i][0], nodes[i+1][0]
ax.annotate("", xy=(x2 - 0.85, 4.4), xytext=(x1 + 0.85, 4.4),
arrowprops=dict(arrowstyle="-|>", color=acolor, lw=2))
for mx, _, _, _ in models:
ax.annotate("", xy=(8.0, 3.9), xytext=(mx, 2.17),
arrowprops=dict(arrowstyle="-|>", color="#FF8A3D", lw=1.8))
ax.text(8.6, 2.6, "模型层支撑", color="#FF8A3D", fontsize=9,
va="center", ha="center")
ax.text(7.0, 6.5, "数据流转全链路:只出不进,分析结果闭环到老板手机",
color="#0B2545", fontsize=14, fontweight="bold", va="center", ha="center")
plt.tight_layout()
fig.savefig(path, dpi=200, bbox_inches="tight", facecolor="white")
plt.close(fig)
draw_architecture(ARCH_PNG)
draw_dataflow(FLOW_PNG)
print("diagrams done")
# ============ PPTX ============
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
BG_DARK = RGBColor(0x0B, 0x25, 0x45)
PRIMARY = RGBColor(0x13, 0x31, 0x5C)
ACCENT = RGBColor(0x2E, 0x93, 0xF7)
HIGHLIGHT = RGBColor(0xFF, 0x8A, 0x3D)
LIGHT = RGBColor(0xF4, 0xF7, 0xFB)
GRAY = RGBColor(0x6B, 0x7A, 0x8F)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
TEXTDARK = RGBColor(0x1A, 0x24, 0x33)
prs = Presentation()
SW = Inches(13.333)
SH = Inches(7.5)
prs.slide_width = SW
prs.slide_height = SH
BLANK = prs.slide_layouts[6]
def add_bg(slide, color=BG_DARK):
s = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, 0, SW, SH)
s.fill.solid(); s.fill.fore_color.rgb = color
s.line.fill.background(); s.shadow.inherit = False
return s
def add_title(slide, title, page=None, subtitle=None):
bar = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, 0, SW, Inches(1.15))
bar.fill.solid(); bar.fill.fore_color.rgb = PRIMARY
bar.line.fill.background(); bar.shadow.inherit = False
stripe = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, Inches(1.15), SW, Inches(0.06))
stripe.fill.solid(); stripe.fill.fore_color.rgb = ACCENT
stripe.line.fill.background(); stripe.shadow.inherit = False
tb = slide.shapes.add_textbox(Inches(0.55), Inches(0.16), SW - Inches(1.1), Inches(0.95))
tf = tb.text_frame; tf.word_wrap = True
p = tf.paragraphs[0]; r = p.add_run(); r.text = title
r.font.size = Pt(25); r.font.bold = True; r.font.color.rgb = WHITE
if subtitle:
p2 = tf.add_paragraph(); r2 = p2.add_run(); r2.text = subtitle
r2.font.size = Pt(12); r2.font.color.rgb = RGBColor(0xBB, 0xD6, 0xF2)
if page is not None:
ft = slide.shapes.add_textbox(Inches(0.55), SH - Inches(0.4), SW - Inches(1.6), Inches(0.3))
fp = ft.text_frame.paragraphs[0]; fr = fp.add_run()
fr.text = "销售型生产企业 AI 数字化建设方案 · 【客户名称】"
fr.font.size = Pt(9); fr.font.color.rgb = GRAY
pg = slide.shapes.add_textbox(SW - Inches(1.05), SH - Inches(0.4), Inches(0.6), Inches(0.3))
pp = pg.text_frame.paragraphs[0]; pr = pp.add_run(); pr.text = str(page)
pr.font.size = Pt(9); pr.font.color.rgb = GRAY; pp.alignment = PP_ALIGN.RIGHT
def add_bullets(slide, items, left, top, width, height, size=15, color=TEXTDARK):
tb = slide.shapes.add_textbox(left, top, width, height)
tf = tb.text_frame; tf.word_wrap = True
first = True
for it in items:
text, lvl = it if isinstance(it, tuple) else (it, 0)
p = tf.paragraphs[0] if first else tf.add_paragraph()
first = False
p.level = lvl
p.space_after = Pt(9)
prefix = "• " if lvl == 0 else " "
r = p.add_run(); r.text = prefix + text
r.font.size = Pt(size if lvl == 0 else size - 2)
r.font.color.rgb = color
return tb
def add_table(slide, data, left, top, width, height, col_widths=None):
rows = len(data); cols = len(data[0])
gtbl = slide.shapes.add_table(rows, cols, left, top, width, height)
table = gtbl.table
if col_widths:
tot = sum(col_widths)
for i, cw in enumerate(col_widths):
table.columns[i].width = Emu(int(width * cw / tot))
for ri, row in enumerate(data):
for ci, val in enumerate(row):
cell = table.cell(ri, ci)
cell.margin_left = Inches(0.08); cell.margin_right = Inches(0.08)
cell.margin_top = Inches(0.04); cell.margin_bottom = Inches(0.04)
cell.vertical_anchor = MSO_ANCHOR.MIDDLE
tf = cell.text_frame; tf.word_wrap = True
p = tf.paragraphs[0]; r = p.add_run(); r.text = val
r.font.size = Pt(11)
if ri == 0:
cell.fill.solid(); cell.fill.fore_color.rgb = PRIMARY
r.font.color.rgb = WHITE; r.font.bold = True
else:
cell.fill.solid()
cell.fill.fore_color.rgb = WHITE if ri % 2 else LIGHT
r.font.color.rgb = TEXTDARK
if ci == 0:
r.font.bold = True
return table
def add_image(slide, path, left, top, width):
slide.shapes.add_picture(path, left, top, width=width)
def set_notes(slide, text):
slide.notes_slide.notes_text_frame.text = text
def new_content(title, page, subtitle=None):
s = prs.slides.add_slide(BLANK)
add_bg(s, LIGHT)
add_title(s, title, page=page, subtitle=subtitle)
return s
# ---------- 1. 封面 ----------
cov = prs.slides.add_slide(BLANK)
add_bg(cov, BG_DARK)
# 左侧强调条
acc = cov.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, 0, Inches(0.22), SH)
acc.fill.solid(); acc.fill.fore_color.rgb = ACCENT; acc.line.fill.background(); acc.shadow.inherit = False
# 主标题
t = cov.shapes.add_textbox(Inches(0.9), Inches(1.9), Inches(11.5), Inches(1.6))
tf = t.text_frame; tf.word_wrap = True
p = tf.paragraphs[0]; r = p.add_run(); r.text = "销售型生产企业"
r.font.size = Pt(46); r.font.bold = True; r.font.color.rgb = WHITE
p2 = tf.add_paragraph(); r2 = p2.add_run(); r2.text = "AI 数字化建设方案"
r2.font.size = Pt(46); r2.font.bold = True; r2.font.color.rgb = ACCENT
# 副标题
st = cov.shapes.add_textbox(Inches(0.9), Inches(3.7), Inches(11.5), Inches(0.6))
sp = st.text_frame.paragraphs[0]; sr = sp.add_run()
sr.text = "软硬件一体化 · 私有本地部署 · 数据不出厂"
sr.font.size = Pt(18); sr.font.color.rgb = RGBColor(0xBB, 0xD6, 0xF2)
# 一句话价值
vt = cov.shapes.add_textbox(Inches(0.9), Inches(4.5), Inches(11.5), Inches(0.6))
vp = vt.text_frame.paragraphs[0]; vr = vp.add_run()
vr.text = "把“脏数据”变成“干净资产”,让 AI 替你看盘、盯异常、做决策"
vr.font.size = Pt(15); vr.font.color.rgb = WHITE
# 底部占位信息
info = cov.shapes.add_textbox(Inches(0.9), Inches(6.0), Inches(11.5), Inches(1.0))
ip = info.text_frame; ip.word_wrap = True
for i, line in enumerate([
"客户:【客户名称】 行业:【如 母婴/食品/五金 网店工厂】",
"服务商:【您的公司 / 顾问姓名】 日期:【提交日期】"]):
pp = ip.paragraphs[0] if i == 0 else ip.add_paragraph()
rr = pp.add_run(); rr.text = line
rr.font.size = Pt(13); rr.font.color.rgb = RGBColor(0x9F, 0xB6, 0xCE)
set_notes(cov,
"【示例填充】客户:杭州某母婴用品网店工厂;行业:母婴用品;服务商:XX 数字化工作室;日期:2026-09-01\n"
"【讲解话术】老板您好,这份方案不卖您系统、不碰您现有进销存,只在您办公室放一台小主机,"
"把散落各处的销售数据收拢成'一本账',再用本地 AI 帮您看盘、盯异常、给决策。数据全在您自己厂里,不出门。")
# ---------- 2. 目录 ----------
s = new_content("目录", 1)
add_bullets(s, [
"一、为什么现在要做(痛点与现状)",
"二、方案定位与整体技术架构",
"三、四层技术架构详解(硬件 / 数据 / 模型 / 调度 / 触达)",
"四、数据流转全链路",
"五、三期建设路线(资产化 → 智能化 → 自动化)",
"六、成本估算与客户配合事项",
"七、服务价值与下一步行动",
], Inches(0.9), Inches(1.6), Inches(11.5), Inches(5.0), size=18)
set_notes(s, "【讲解话术】我按'先理清家底→再发现问题→最后自动决策'三步走,今天重点讲清每一步给您带来什么、要投多少。")
# ---------- 3. 执行摘要 ----------
s = new_content("执行摘要", 2)
add_bullets(s, [
"一期(打基础,1–2 月):把分散数据收拢成“一本账”,让老板看明白去年赚在哪、亏在哪。",
"二期(提效率,2–3 月):本地 AI 自动出周/月报、盯异常,释放人力。",
"三期(增利润,3–6 月):AI 预测备货与资金,真正帮老板省钱。",
"零风险落地:不碰客户现有 ERP/进销存,旁路部署,数据只出不进。",
"数据不出厂:全部模型跑在客户内网 EVO-X2 主机,敏感数据不离开办公室。",
"一期一付、做一期看一期效果,老板决策压力小、回款节奏稳。",
], Inches(0.9), Inches(1.6), Inches(11.5), Inches(5.0), size=15)
set_notes(s,
"【示例填充】以母婴客户为例:一期后老板能随时看'去年 11 月双11 哪个 SKU 最赚'"
"二期后每周一手机收到经营简报;三期后 AI 建议'年后少备 A 款、多备 B 款'。\n"
"【讲解话术】您不用一次性投很多,先做一期看效果,满意再继续。")
# ---------- 4. 客户痛点与现状 ----------
s = new_content("一、为什么现在要做:客户痛点与现状", 3)
add_bullets(s, [
"数据散落各处:网店后台、Excel 台账、微信记录各管各的,对不上账。",
"看不清赚亏:想看“去年哪月卖得好、哪个 SKU 最赚”要人工拼表,慢且易错。",
"人力耗在重复劳动:财务/运营每周手动导出、透视、做图,没空做分析。",
"库存与现金流焦虑:缺货断供、积压占资金,老板心里没底。",
"想用 AI 但不会用:担心数据上云泄露、怕采购昂贵系统、怕折腾业务。",
], Inches(0.9), Inches(1.6), Inches(11.5), Inches(5.0), size=15)
set_notes(s,
"【示例填充】某母婴用品网店工厂,年销约 3000 万,3 个平台店铺,SKU 200+"
"老板最关心库存周转和回款,财务每周花 1.5 天做表。\n"
"【讲解话术】这些痛点您是不是都有?这套方案就是专门冲着'看不清、做表累、心里没底'来的。")
# ---------- 5. 方案定位 ----------
s = new_content("二、方案定位:旁路部署,零风险落地", 4)
add_bullets(s, [
"旁路部署:在原有业务系统“旁边”独立搭一套 AI 数据分析与自动化辅助系统。",
"数据只出不进:从原系统(网店/进销存)只读导出,分析结果不回写,不影响现有流程。",
"私有本地运行:模型与数据库部署在客户内网主机,敏感经营数据不出厂。",
"轻量可演进:不强制替换 ERP,先见效再扩展,风险可控、投入可控。",
"管理层触达:看板 + 微信推送,老板手机即可看报告、收预警。",
], Inches(0.9), Inches(1.6), Inches(11.5), Inches(5.0), size=15)
set_notes(s,
"【讲解话术】一句话:我不在您现有系统上动刀,只在旁边加一台'AI 数据助理'"
"您原来的进销存该怎么用还怎么用,零风险。")
# ---------- 6. 四层技术架构总览 ----------
s = new_content("三、整体技术架构(四层 + 底层硬件)", 5)
add_image(s, ARCH_PNG, Inches(2.0), Inches(1.35), Inches(9.3))
set_notes(s,
"【讲解话术】从下往上看:最底下是您办公室一台 EVO-X2 小主机;往上是数据层、模型层、"
"调度层,最上面是您手机能看到的看板和微信推送。数据从原系统只进到最底层,结果从最上层出来。\n"
"注:具体型号(EVO-X2 / Qwen3.6 / DeepSeek 等)以交付时主流为准。")
# ---------- 7. 底层:硬件与系统 ----------
s = new_content("底层:硬件与系统部署方案", 6, subtitle="核心逻辑:2 万预算内本地流畅跑 30B 级模型,功耗约 100W,适合 24h 开机")
add_table(s, [
["项目", "配置", "说明"],
["主机", "GMKtec EVO-X2128GB 版)", "迷你主机,不占空间、静音,适合办公室"],
["内存", "128GB LPDDR5X 统一内存(可分 96GB 给 GPU", "本地跑 35B MoE + 向量库 + 数据库够用"],
["存储", "2TB NVMe SSD ×2(系统盘/数据盘分离)", "系统装系统模型,数据盘存库与日志"],
["操作系统", "Ubuntu 24.04 LTS", "对 AMD ROCm 支持好,AI 性能高 2030%"],
["网络", "内网固定 IP + Tailscale", "远程巡检与系统更新"],
["备用方案", "DeepSeek V4 Flash API", "复杂任务自动 fallback 到云端"],
], Inches(0.7), Inches(1.7), Inches(11.9), Inches(4.6), col_widths=[1.3, 3.6, 4.0])
set_notes(s,
"【示例填充】以母婴客户为例:一台 EVO-X2 放财务室,插网线,固定内网 IP,我用 Tailscale 远程维护。\n"
"【讲解话术】这台机器比一台台式机还小,静音不发热,24 小时开着电费忽略不计,但能本地跑大模型。")
# ---------- 8. 第一层:数据层 ----------
s = new_content("第一层:数据层方案", 7, subtitle="核心逻辑:SQLite 单文件易备份;Markdown 是 AI 理解准确率最高的文本格式")
add_bullets(s, [
"数据库:SQLite 3,轻量零配置,单文件易备份迁移。",
"清洗脚本:Pythonpandas + openpyxl),每月定时运行 Excel→清洗→入库。",
"中间格式:Markdown 表格,AI 理解准确率最高的文本格式,便于人工核对。",
"向量知识库:Chroma(轻量),存产品手册/会议纪要,供 RAG 检索。",
"定时任务:cron(Linux 自带),每月 1 号自动清洗,无需人工干预。",
], Inches(0.9), Inches(1.7), Inches(11.5), Inches(4.8), size=15)
set_notes(s,
"【讲解话术】您每月把网店导出的 Excel 丢进一个文件夹,系统自己洗好存进数据库,"
"不用您再手动拼表。")
# ---------- 9. 第二层:模型层 ----------
s = new_content("第二层:模型层方案", 8, subtitle="核心逻辑:Qwen3.6 为 MoE,激活仅 3B,在 EVO-X2 上 2535 Token/s,数据不出厂")
add_table(s, [
["组件", "技术选型", "说明"],
["本地推理引擎", "Ollama", "一行命令部署,兼容 OpenAI API,管理方便"],
["主模型", "Qwen3.6-35B-A3B4bit 量化)", "智商≈Claude 3.5 Sonnet,约 20GB,速度 2535 Token/s"],
["备用云端模型", "DeepSeek V4 Flash API", "复杂推理按量付费,月均 < 200 元"],
["嵌入模型", "bge-m3(本地)", "知识库向量化,纯本地不依赖外网"],
["模型格式", "GGUFllama.cpp 兼容)", "CPU+GPU 混合推理,显存不足可 fallback 内存"],
], Inches(0.7), Inches(1.7), Inches(11.9), Inches(4.6), col_widths=[1.8, 3.2, 4.0])
set_notes(s,
"【讲解话术】95% 的分析都在您这台机器上本地算,只有极少量复杂任务才花几块钱走云端,"
"您的客户名单和金额永远不会出办公室。")
# ---------- 10. 第三层:智能调度层 ----------
s = new_content("第三层:智能调度层方案", 9, subtitle="核心逻辑:Hermes Agent 国产开源,原生支持微信接入与工具调用,适合 ToB")
add_bullets(s, [
"智能体框架:Hermes Agent,连接模型/工具/消息平台,系统“大脑”。",
"Web 管理面板:可视化配置模型、工具、知识库,查看 Token 消耗与日志。",
"工具定义:Python 函数注册为 Tools,让 AI 能查库、跑脚本、发报告。",
"消息网关:iLink Bot API(微信),AI 主动推送报告、接收指令。",
"国产开源、部署简单,适合 ToB 场景。",
], Inches(0.9), Inches(1.7), Inches(11.5), Inches(4.8), size=15)
set_notes(s,
"【讲解话术】这一层就是让 AI '会干活':它能自己查数据库、自己生成报告、自己发到您微信上。")
# ---------- 11. 第四层:触达层 ----------
s = new_content("第四层:触达层方案", 10, subtitle="核心逻辑:Streamlit 快速搭看板;微信推送让老板手机收报告,无需装 APP")
add_bullets(s, [
"数据看板:StreamlitPython),展示销售趋势、SKU 排行、区域分布、异常预警。",
"报表推送:Hermes Agent + 微信 Bot,每周一自动推送《经营简报》图文。",
"多通道:飞书/钉钉/企业微信可选,走同一消息通道。",
"人工巡检:每月 2 次远程巡检,查日志、备份库、确认推送正常。",
], Inches(0.9), Inches(1.7), Inches(11.5), Inches(4.8), size=15)
set_notes(s,
"【示例填充】母婴客户用微信:每周一早 9 点,老板微信收到上周经营简报,含销量异动和库存预警。\n"
"【讲解话术】您不用学新软件,报告直接发您微信,像收一条工作消息一样简单。")
# ---------- 12. 数据流转全链路 ----------
s = new_content("四、数据流转全链路", 11)
add_image(s, FLOW_PNG, Inches(1.1), Inches(1.35), Inches(11.1))
set_notes(s,
"【讲解话术】整条链路是'只进不出':原始数据进来,洗干净存库,AI 分析完把结论推到您手机,"
"结论不回写您的业务系统,所以绝对不影响您现有流程。")
# ---------- 13. 第一期 ----------
s = new_content("五之一、第一期:数据资产化(1–2 个月)", 12, subtitle="核心任务:打通数据孤岛,建立统一数据看板")
add_bullets(s, [
"数据清洗与入库:导出近 1–2 年网店销售(订单/SKU/区域/金额),清洗入 SQLite。",
"建立核心指标:固定口径(销售额、退货率、客单价、库存周转天数)。",
"搭建基础看板:Web 看板展示月度趋势、SKU 排行、区域分布。",
("交付物:数据表结构文档、在线看板、《公司数据资产盘点报告》", 0),
("验收:老板随时登录查任意月份数据且准确", 0),
], Inches(0.9), Inches(1.7), Inches(11.5), Inches(4.8), size=15)
set_notes(s,
"【示例填充】母婴客户一期交付:一张看板,能点开看'2025 各月销售额''TOP20 SKU''华东/华南占比'。\n"
"【讲解话术】一期结束,您就拥有了全公司统一的'一本账'。")
# ---------- 14. 第二期 ----------
s = new_content("五之二、第二期:分析智能化(2–3 个月)", 13, subtitle="核心任务:接入 AI,实现自动化分析与预警")
add_bullets(s, [
"本地模型部署:EVO-X2 内部署 Qwen3.6 等小模型,数据不出厂。",
"自动化周/月报:AI 读库,每周一生成《经营简报》推送微信。",
"异常归因:SKU 销量暴跌时,AI 关联缺货/竞品跟价,给“可能原因”。",
("交付物:本地推理服务、推送机器人、异常预警配置文档", 0),
("验收:每月初手机收到完整经营分析,重点异常清晰标注", 0),
], Inches(0.9), Inches(1.7), Inches(11.5), Inches(4.8), size=15)
set_notes(s,
"【示例填充】母婴客户二期:某 SKU 周销量跌 40%,AI 简报标注'疑似断货+竞品降价',并附建议。\n"
"【讲解话术】这期相当于给您配了个 24 小时不休息的数据分析师。")
# ---------- 15. 第三期 ----------
s = new_content("五之三、第三期:决策自动化(3–6 个月)", 14, subtitle="核心任务:从“发现问题”升级到“给出方案”并介入业务")
add_bullets(s, [
"库存预测与补货:按历史+季节因子预测需求,自动生成采购建议单。",
"现金流模拟:输入支出与回款周期,模拟健康度、预警资金缺口。",
"选品与定价:结合外部大盘,输出《SKU 优化建议》(淘汰/主推/清仓)。",
("交付物:智能库存预警采购系统、现金流压力测试看板、SKU 生命周期报告", 0),
("验收:参考 AI 建议做至少一次库存调整,产生可量化资金占用下降", 0),
], Inches(0.9), Inches(1.7), Inches(11.5), Inches(4.8), size=15)
set_notes(s,
"【示例填充】母婴客户三期:AI 预测年后 B 款需求涨,建议提前备货;同时提示 C 款滞销建议清仓,"
"释放占用资金约 30 万。\n"
"【讲解话术】这期是'商业大脑',不仅告诉您哪有问题,还告诉您怎么办、办了会怎样。")
# ---------- 16. 三期节奏总览 ----------
s = new_content("五、三期节奏与投入对比总览", 15)
add_table(s, [
["阶段", "周期", "核心目标", "关键交付", "老板获得感"],
["一期 数据资产化", "12 月", "理清家底", "统一看板 + 数据资产报告", "看明白赚亏"],
["二期 分析智能化", "23 月", "提效率", "本地 AI + 自动周报 + 预警", "AI 分析师盯盘"],
["三期 决策自动化", "36 月", "增利润", "预测补货 + 现金流模拟", "商业大脑给方案"],
], Inches(0.7), Inches(1.8), Inches(11.9), Inches(3.6), col_widths=[2.0, 1.2, 1.8, 3.6, 2.3])
set_notes(s,
"【讲解话术】三步走、每一步都有明确交付和验收,您随时可以停在任意一期,风险完全可控。")
# ---------- 17. 成本估算(仅硬件/云) ----------
s = new_content("六之一、总体成本估算(仅硬件 / 云,不含服务费)", 16)
add_table(s, [
["项目", "预估金额(人民币)", "备注"],
["主机硬件(EVO-X2 128GB", "15,000 18,000 元", "一次投入,含 2TB SSD"],
["备用配件(额外 SSD 等)", "1,000 2,000 元", "数据备份与冗余"],
["云端 APIDeepSeek Flash", "100 200 元/月", "仅复杂任务触发,日常用本地"],
["网络/域名(如需公网)", "0 500 元/年", "可选项,非必需"],
], Inches(0.7), Inches(1.8), Inches(11.9), Inches(3.6), col_widths=[3.2, 3.0, 3.7])
set_notes(s,
"【示例填充】母婴客户一次性硬件约 1.7–2.0 万,之后每月云端 API 不到 200 元。\n"
"【讲解话术】这是您要承担的'材料费',一次性投入小、月费可忽略;我的实施服务费咱们线下另谈,"
"按一期一付、验收后付。")
# ---------- 18. 客户需配合准备 ----------
s = new_content("六之二、客户需配合准备清单", 17)
add_table(s, [
["序号", "内容", "说明"],
["1", "近 12 年网店销售数据(Excel/CSV", "用于清洗和导入数据库"],
["2", "产品手册/商品台账(Excel", "补充 SKU 维度(品类/成本/建议售价)"],
["3", "一台能联网的电脑 / 一个不用的手机号", "微信 Bot 登录 + 远程维护通道"],
["4", "内网 WiFi 或有线网络", "固定内网 IP 或 Tailscale 替代"],
], Inches(0.7), Inches(1.8), Inches(11.9), Inches(3.8), col_widths=[0.8, 4.2, 4.0])
set_notes(s,
"【讲解话术】您这边要做的事很简单:把数据导出给我、准备一个不用的手机号和能联网,"
"其余安装部署都是我来做。")
# ---------- 19. 服务价值卖点 + 复制扩张 ----------
s = new_content("七之一、服务价值卖点(三句话)", 18)
add_bullets(s, [
"第一期:我把你家散落各处的数据收拢成“一本账”,让你看明白钱花哪去了。",
"第二期:我给你配个“AI 数据分析师”,24 小时盯着数据,出问题第一时间告诉你。",
"第三期:我给你装上“AI 商业大脑”,不仅告诉哪有问题,还告诉你怎么办、模拟办了会怎样。",
"复制扩张:样板跑通后,同一套架构可快速复制到同类销售型生产企业。",
"商务模式:一期一付、做一期看一期效果,决策压力小、回款稳。",
], Inches(0.9), Inches(1.7), Inches(11.5), Inches(4.8), size=15)
set_notes(s,
"【讲解话术】您跟同行聊的时候,就这三句话,谁都听得懂、谁都想要。样板跑通,"
"后面复制给其他厂非常快。")
# ---------- 20. 下一步行动 / CTA ----------
s = new_content("七之二、下一步行动", 19)
add_bullets(s, [
"建议从一期起步:先交付“一本账”看板,2 个月内见效。",
"我方接下来:① 拉取贵司近 1–2 年销售数据做样例清洗;② 部署 EVO-X2 演示环境;③ 输出首版看板。",
"贵司配合:提供销售数据/台账、准备一台不用的手机、确认内网接入。",
"确认即启动:签订一期合作,按里程碑验收付款。",
"联系人:【您的姓名 / 微信】",
], Inches(0.9), Inches(1.7), Inches(11.5), Inches(4.8), size=15)
set_notes(s,
"【讲解话术】今天聊完,如果您认可,咱们就先签一期。两周内您能看到第一版看板demo,"
"觉得有用再继续二期、三期。")
prs.save(OUT_PPTX)
print("PPTX saved:", OUT_PPTX, "slides:", len(prs.slides._sldIdLst))