ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

WorkBuddy+Python+LLM:季度销售复盘与汇报PPT自动化实战

WorkBuddy+Python+LLM:季度销售复盘与汇报PPT自动化实战 季度末把销售明细整理成复盘报告再顺手出一版能直接上会的汇报 PPT这件事听起来像是两个独立任务实际上是一条完整的数据加工链路。我过去几个季度都是用 WorkBuddy 配合 Python 和 LLM 来跑这套流程从最初手工复制粘贴到后来全流程半自动化中间踩过的坑足够写满一个笔记本。这篇内容就是把这套链路完整拆开讲清楚每一步为什么这么做、参数怎么定、哪些地方最容易翻车。不管你是刚接触 WorkBuddy 的新手还是已经用过一段时间但总觉得输出不够稳定的老用户都能从里面找到可以直接抄作业的部分。核心关键词就三个WorkBuddy 做任务编排、Python 做数据处理、LLM 做文本生成三者串起来才能把一张季度销售表变成有观点、有结构、能汇报的成品。1. 为什么季度销售表不能直接丢给 LLM 出报告1.1 原始表格的数据噪声远比想象中多很多人第一反应是既然有 LLM直接把 Excel 文件传进去让它写复盘报告不就行了。我最初也是这么干的结果输出质量惨不忍睹。原因很简单季度销售表里塞满了 LLM 不擅长处理的东西。比如合并单元格导致的空值、多级表头、隐藏列、批注、条件格式产生的颜色标记还有各种手工填写的备注字段。这些东西在人眼里是上下文在 LLM 眼里就是噪声。我拿一份真实的季度销售表做过测试原始文件 3800 行、27 列直接喂给 LLM 后它把华东大区和华东区域当成两个不同的区域来统计因为表格里这两种写法混用。还有一次某列的数值被存成了文本格式LLM 读出来是字符串做同比计算时直接算错。这类问题不是 LLM 能力不够而是输入数据本身没有经过清洗和结构化。所以正确的做法是先用 Python 把表格清洗成规整的二维结构再交给 LLM 做语义层面的分析和写作。WorkBuddy 在这里的角色是编排整个流程把清洗、统计、生成、导出这几个环节串起来而不是让 LLM 直接面对原始表格。1.2 复盘报告需要的是观点而不是数据罗列另一个常见误区是把复盘报告写成数据汇总。我见过太多季度复盘通篇都是本季度销售额 X 万同比增长 Y%读完不知道重点在哪。真正的复盘报告需要有判断、有归因、有建议。比如华东大区虽然完成了目标但增长主要来自一次性大客户订单可持续性存疑这种话才是管理层想看的。这就决定了流程设计Python 负责算出客观数据同比、环比、目标完成率、集中度等LLM 负责基于这些数据生成有观点的叙述。两者分工明确不能混。如果让 LLM 自己去算数它大概率会算错如果让 Python 去写观点它写不出来。WorkBuddy 的价值就在于把这两类能力按正确的顺序编排起来。1.3 WorkBuddy 在这条链路里的真实定位WorkBuddy 不是数据处理工具也不是写作工具它是任务编排层。你可以把它理解成一个流程调度员什么时候调用 Python 脚本、什么时候把中间结果传给 LLM、什么时候触发 PPT 生成、输出文件存到哪里这些都由 WorkBuddy 来管。我目前的配置是WorkBuddy 里定义三个核心 skill分别对应数据清洗与统计复盘文本生成PPT 组装。每个 skill 内部可以调用 Python 脚本或 LLM 接口。这样设计的好处是每个环节可以独立调试出问题容易定位。如果全部塞进一个大流程里一旦输出不对你根本不知道是清洗错了、统计错了还是 LLM 写偏了。提示WorkBuddy 的 skill 划分粒度建议按输入输出边界清晰的原则来定。一个 skill 的输入应该是一份明确的数据或文本输出也应该是明确的产物中间不要有模糊的处理一下这种步骤。2. 用 Python 把销售表洗成 LLM 能吃的格式2.1 读取阶段就要处理的三个坑用 pandas 读 Excel 看起来是一行代码的事但实际项目里这一步就能卡住很多人。我总结下来有三个高频问题。第一个是表头行数不固定。有些销售表的标题占了两三行真正的列名在第四行。这时候pd.read_excel的header参数要设对或者干脆用headerNone读进来再手动指定列名。我一般会先读前 10 行看看结构确认列名在第几行。第二个是数据类型自动推断错误。pandas 会把看起来像数字的列读成 int 或 float但销售表里经常有1,234这种带千分位的写法读进来就变成字符串了。解决办法是读的时候统一用dtypestr后续再逐列转换。这样虽然多一步但可控性强很多。第三个是隐藏行和筛选状态。Excel 里被隐藏的行pandas 默认还是会读进来。如果业务方在表里做了筛选你读到的可能是全量数据而不是他看到的那些。这个必须在流程开始前跟业务方确认清楚到底要处理全量还是筛选后的数据。import pandas as pd # 先探查结构 raw pd.read_excel(sales_q3.xlsx, headerNone, nrows10) print(raw.head(10)) # 确认列名在第 3 行后正式读取 df pd.read_excel(sales_q3.xlsx, header2, dtypestr) df.columns df.columns.str.strip() # 去掉列名前后空格2.2 清洗规则要写成可复用的配置清洗规则不要硬编码在脚本里我吃过这个亏。上季度写的清洗逻辑这季度表格结构微调了一下脚本直接报错改了半天。后来我把清洗规则抽成一个 YAML 配置文件包括哪些列需要去空格、哪些列需要做同义词映射、哪些列需要转数值、空值怎么填充。这样换一份表格只需要改配置不用动代码。同义词映射是重点。销售表里区域名、产品名、渠道名的写法经常不统一。我一般会先跑一遍value_counts()把出现频次低的写法挑出来人工确认后加到映射表里。比如华东华东区华东大区East China统一映射成华东大区。# clean_config.yaml strip_columns: [客户名称, 销售员, 备注] synonym_map: 区域: 华东: 华东大区 华东区: 华东大区 East China: 华东大区 numeric_columns: [销售额, 数量, 成本] fillna: 备注: 销售员: 未知2.3 统计口径必须在代码里显式定义这一步是最容易被忽略但最影响报告质量的。什么叫同比增长是跟去年同期比还是跟上季度比目标完成率的分母是季度目标还是年度目标按比例拆分这些口径如果不显式定义不同人算出来的数不一样报告就没法用。我的做法是在 Python 脚本里把每个指标的计算逻辑写成独立函数并且加上注释说明口径。比如def yoy_growth(current, last_year_same_period): 同比增长率 (本期 - 去年同期) / 去年同期 注意去年同期为 0 时返回 None不返回 inf if last_year_same_period 0: return None return (current - last_year_same_period) / last_year_same_period这样即使后面换人维护也能一眼看懂口径。而且 LLM 拿到这些带注释的统计结果后写出来的报告口径也更准确。2.4 输出给 LLM 的中间格式选择清洗统计完之后要把结果传给 LLM。这里有个关键选择传什么格式。我试过三种直接传 DataFrame 的字符串表示、传 JSON、传 Markdown 表格。直接传 DataFrame 字符串最省事但 LLM 解析时容易把列对齐搞错。JSON 结构最清晰但 LLM 读大段 JSON 时容易丢失层级关系。最后我固定用Markdown 表格 关键指标 JSON的组合明细数据用 Markdown 表格LLM 对表格理解很好汇总指标用 JSON结构清晰方便 LLM 引用具体数值。# 明细转 Markdown detail_md df_summary.to_markdown(indexFalse) # 关键指标转 JSON metrics { total_sales: 12500000, yoy_growth: 0.18, target_completion: 1.05, top_region: 华东大区, top_region_share: 0.42 }注意传给 LLM 的数值一定要保留原始精度不要在 Python 里提前四舍五入。让 LLM 决定在报告里显示几位小数这样更灵活。3. 让 LLM 写出有观点的复盘而不是流水账3.1 Prompt 结构决定了输出质量的上限我调了几十版 prompt 才找到比较稳定的结构。核心思路是把 LLM 当成一个刚拿到数据、需要向老板汇报的分析师而不是一个写作机器。Prompt 里要明确四件事角色、数据、任务、输出格式。角色部分要具体不要写你是一个数据分析师而是写你是一个负责华东区销售的资深分析师需要向销售总监汇报本季度情况。越具体LLM 的输出越有针对性。数据部分就是我前面说的 Markdown 表格加 JSON。任务部分要拆成几个明确的小任务先总结整体表现再分析各区域差异然后指出异常点最后给建议。输出格式要规定好章节结构但不要规定得太死留一点发挥空间。prompt 你是一位负责季度销售复盘的高级分析师需要向销售总监提交一份复盘报告。 以下是本季度销售数据 {detail_md} 关键指标 {metrics_json} 请按以下结构撰写复盘报告 1. 整体表现概述200字以内给出核心结论 2. 区域表现分析重点分析 Top3 和 Bottom3 区域说明差异原因 3. 异常点识别找出数据中值得警惕的信号 4. 下季度建议3条以内要具体可执行 要求 - 所有结论必须基于给定数据不要编造 - 涉及具体数值时保留原始精度 - 语言简洁避免套话 3.2 用 few-shot 示例锚定输出风格光靠指令LLM 的输出风格还是不稳定。有时候写得很官方有时候又太口语。我的解决办法是在 prompt 里塞一两个 few-shot 示例展示我想要的风格。示例不用长一段话就够。比如我会给一个这样的示例华东大区本季度完成销售额 520 万目标完成率 112%但增长主要来自 3 月的一笔大客户订单剔除后实际增长仅 4%可持续性需要关注。这段话的特点是先给数据再给判断最后给风险提示。LLM 看到这个模式后输出会明显更接近。3.3 数值校验环节不能省LLM 有个毛病它会顺手改数字。比如你给它 12500000它可能写成 1250 万这没问题但它也可能写成 1200 万这就出错了。所以 LLM 输出后必须做数值校验。我的做法是写一个校验函数把 LLM 输出里所有数字提取出来跟原始数据比对。如果发现对不上的标记出来人工确认。这个环节用 Python 做很快但能避免很多尴尬。import re def extract_numbers(text): return re.findall(r\d\.?\d*, text) def validate_numbers(llm_output, source_metrics): output_nums set(extract_numbers(llm_output)) source_nums set(str(v) for v in source_metrics.values()) # 找出输出里有但源数据里没有的数字 suspicious output_nums - source_nums return suspicious3.4 处理 LLM 的过度自信问题LLM 写报告时经常给出过于肯定的判断比如该区域业绩下滑是因为销售团队能力不足。这种归因没有数据支撑写进报告里很危险。我在 prompt 里加了一条约束对于无法从数据直接得出的结论使用可能需要进一步确认等措辞不要做确定性归因。另外我会在报告末尾加一个数据局限性说明章节让 LLM 自己列出本次分析的数据盲区。比如本次分析未包含退货数据实际净销售额可能低于报告数值。这个章节看起来是减分项实际上大大提升了报告的可信度。4. 从复盘文本到汇报 PPT 的转换逻辑4.1 PPT 不是报告的搬运而是重新组织很多人做汇报 PPT 就是把报告内容复制粘贴到幻灯片里结果每页都是大段文字没人看。正确的做法是PPT 是报告的提纯版只保留最核心的结论和支撑数据细节留在报告里备查。我一般会把复盘报告拆成 8 到 12 页 PPT结构大致是封面、核心结论1页、整体数据1页、区域分析2到3页、异常点1页、建议1页、附录数据1到2页。每页只讲一件事标题就是结论本身比如华东大区完成目标但增长质量存疑而不是华东大区分析。4.2 用 WorkBuddy 编排 PPT 生成流程PPT 生成我用的是 python-pptx 库配合一个预定义的模板文件。WorkBuddy 在这里负责把 LLM 生成的文本按页拆分然后调用 python-pptx 填充到模板里。关键点是模板要提前设计好版式。我做了三种版式标题加正文、标题加图表、标题加表格。LLM 输出时会给每页标注用哪种版式WorkBuddy 根据标注选择对应的填充逻辑。这样既保证了风格统一又不用每次重新排版。from pptx import Presentation from pptx.util import Inches def add_content_slide(prs, title, bullets): slide prs.slides.add_slide(prs.slide_layouts[1]) slide.shapes.title.text title body slide.placeholders[1].text_frame for i, bullet in enumerate(bullets): if i 0: body.text bullet else: p body.add_paragraph() p.text bullet return slide4.3 图表生成要跟 PPT 同步做复盘 PPT 里少不了图表。我的做法是在 Python 阶段就把图表生成好存成 PNG然后插入 PPT。图表类型根据数据特点选趋势用折线图区域对比用条形图占比用饼图或环形图。这里有个细节图表的配色要跟 PPT 模板一致。我一开始没注意生成的图表是 matplotlib 默认配色插到 PPT 里跟模板的蓝色系完全不搭。后来我把模板的主色提取出来在 matplotlib 里设置成全局配色看起来就协调多了。import matplotlib.pyplot as plt plt.rcParams[axes.prop_cycle] plt.cycler( color[#1F4E79, #2E75B6, #9DC3E6, #BDD7EE] ) plt.rcParams[font.sans-serif] [SimHei] # 中文显示4.4 导出环节的格式兼容问题PPT 导出看起来简单但实际会遇到字体丢失、图片模糊、动画错乱等问题。我的经验是字体用系统自带的中文字体比如微软雅黑、黑体不要用特殊字体否则换台电脑打开就变形。图片导出时设置 DPI 为 150 以上保证投影清晰。还有一个坑是 python-pptx 对某些模板的兼容性。如果模板里有复杂的 SmartArt 或组合图形python-pptx 可能无法正确填充。解决办法是模板尽量用简单的占位符结构复杂图形提前在模板里做好代码只负责填文字。5. 整条链路串起来之后的实测效果与调优5.1 一次完整运行的耗时分布我把整条链路跑通后记录了几次运行的耗时。清洗统计阶段大概 15 到 30 秒取决于数据量LLM 生成报告 20 到 40 秒PPT 组装 10 到 20 秒整体下来 1 到 2 分钟。相比手工做效率提升是数量级的。但这里有个隐藏成本首次配置的时间。清洗规则、prompt、PPT 模板这些都需要根据具体业务调整第一次做可能要花半天到一天。不过一旦配好后续每个季度只需要微调边际成本很低。阶段首次配置耗时后续运行耗时数据清洗规则2-3 小时15-30 秒Prompt 调优3-4 小时20-40 秒PPT 模板设计2-3 小时10-20 秒整体联调1-2 小时-5.2 输出质量不稳定的三个常见原因跑多了之后会发现有时候输出很好有时候又不行。我总结下来主要是三个原因。第一是输入数据波动。如果某季度数据里出现了之前没见过的值比如新区域、新产品线清洗规则没覆盖到就会出问题。解决办法是每次运行前先跑一遍数据探查看看有没有异常值。第二是LLM 的随机性。同样的 prompt不同次运行输出会有差异。如果对稳定性要求高可以把 temperature 调低比如 0.3牺牲一点创造性换稳定性。第三是模板与内容的匹配度。如果 LLM 生成的某页内容特别长模板的文本框装不下就会溢出。我的做法是在代码里加一个长度检查超过阈值就自动拆分或精简。5.3 给 WorkBuddy 定几条长期生效的规则用 WorkBuddy 一段时间后我发现有些规则是每次都要遵守的与其每次重复交代不如直接写进 WorkBuddy 的全局规则里。我目前定了这么几条所有涉及数值的输出必须经过 Python 校验后才能进入下一步所有 LLM 生成的文本必须保留原始版本和校验后版本方便回溯所有输出文件按日期_项目名_版本号命名避免覆盖任何环节报错先输出中间结果再终止不要静默失败这几条规则写进去之后整个流程的稳定性明显提升。特别是最后一条以前出错了什么线索都没有现在至少能看到卡在哪一步。5.4 后续可以扩展的方向这套链路目前跑得比较顺但我还在想几个扩展点。一个是多季度对比把过去四个季度的数据都跑一遍生成趋势分析。另一个是自动生成汇报讲稿在 PPT 基础上再生成一份逐页讲稿汇报时直接照着念。还有一个是异常自动预警如果某区域数据偏离历史均值超过阈值自动在报告里高亮。这些扩展都不难核心链路已经通了剩下的就是加环节。我的建议是先把基础链路跑稳再考虑扩展不要一上来就追求大而全。提示扩展功能时每加一个环节都要单独测试确认它不会影响已有环节的输出。我吃过这个亏加了个自动预警功能结果把原来的统计逻辑搞乱了排查了半天。6. 几个容易翻车的细节和我的处理方式6.1 中文编码问题贯穿始终从 Excel 读取到 LLM 输出到 PPT 写入中文编码问题几乎每个环节都会遇到。最常见的是乱码根源通常是某个环节用了默认编码而不是 UTF-8。我的做法是在所有文件读写操作里显式指定encodingutf-8包括读 Excel、写 JSON、写文本文件。还有一个隐蔽的坑是全角和半角字符。销售表里经常混用比如华东和(华东)。这会导致同义词映射失效。我在清洗阶段加了一步字符规范化把所有全角括号、逗号、空格统一转成半角。def normalize_chars(text): if not isinstance(text, str): return text # 全角转半角 text text.replace(, ().replace(, )) text text.replace(, ,).replace( , ) return text.strip()6.2 LLM 输出格式不稳定的应对即使 prompt 里规定了输出格式LLM 有时候还是会跑偏。比如要求用 Markdown 标题它可能用加粗代替要求分四点它可能写成三段。我的应对方式是在 prompt 里给一个严格的输出模板并且要求严格按照以下格式输出不要添加额外说明。如果还是不稳定就在 Python 侧加一个格式修正层。比如检测到 LLM 用了加粗而不是标题自动转换成标题格式。这个修正层不用太复杂覆盖最常见的几种偏差就行。6.3 PPT 文字溢出的预防PPT 文字溢出是最影响观感的问题。我的预防措施有三层第一层是在 prompt 里限制每页 bullet 数量和每条字数第二层是在代码里检查文本长度超过阈值自动截断或拆分第三层是在模板设计时留足空间宁可页面空一点也不要挤。具体阈值我设的是每页最多 5 条 bullet每条不超过 40 个字。超过的话要么拆成两页要么精简表述。这个标准是根据实际投影效果定的40 个字在 16:9 的幻灯片上大约占两行看起来比较舒服。6.4 版本管理和回溯这套流程涉及多个环节一旦最终输出有问题需要能快速定位是哪一步出的错。我的做法是每个环节的输出都单独存文件按运行时间戳建文件夹。比如2024Q3_20241015_143022/下面存01_cleaned_data.csv、02_metrics.json、03_report.md、04_report_checked.md、05_slides.pptx。这样出问题可以逐环节比对。这个习惯看起来麻烦但实际省了很多时间。有一次报告里某个数字不对我直接对比02_metrics.json和03_report.md发现是 LLM 引用错了五分钟就定位了。如果没有中间文件可能要重新跑一遍才能发现。6.5 跟业务方确认口径的时机技术上的坑好解决业务上的坑才麻烦。我遇到过一次报告都生成好了业务方说我们这个季度的目标口径变了你用的还是老口径。结果整个报告重做。后来我定了个规矩每次运行前先跟业务方确认三个问题——数据范围是什么、统计口径有没有变化、报告重点想看什么。这三个问题确认清楚后面基本不会返工。确认方式可以很简单发个消息问一下就行但一定要问。7. 写在最后的一点个人体会这套流程我跑了四个季度从最初的手忙脚乱到现在基本可以一键出报告中间最大的体会是工具的价值不在于替代人而在于把人从重复劳动里解放出来去做真正需要判断的事。Python 负责算得准LLM 负责写得快WorkBuddy 负责串得稳但最终报告里的观点、建议、风险提示还是需要人来把关。我现在的工作模式是流程自动跑出初稿我花 20 分钟审一遍重点看结论是否合理、数值是否准确、建议是否可执行。这 20 分钟的投入换来的是以前半天的工作量。省下来的时间可以用来做更深入的业务分析而不是耗在复制粘贴和排版上。如果你也想搭这套流程我的建议是从最小可用版本开始先跑通Excel 到 Markdown 表格这一步再加 LLM 生成最后加 PPT。每步都跑稳了再往下走不要一上来就追求全自动。踩坑是必然的但只要每个环节都有中间产物可以检查排查起来就不会太痛苦。
返回列表