标题:当程序员闯进「AI 产品经理特训营」——一行代码都不想删,却亲手把 AIGC 做成爆款
(一)前言:我写代码,也写 PRD
在老板眼里,我们是“成本中心”;在 Product Owner 眼里,我们是“资源池”。我一直以为把代码写漂亮就够了,直到去年公司大模型项目黄了——算法 92 分,用户却 0 增长。于是我带着“程序员的不甘”报名了《AI 产品经理特训营》,想看看所谓“产品思维”到底能不能被量化、被编译、被运行。结果 6 周下来,我不仅输出了人生第一份 PRD,还顺手用 200 行 Python 把用户调研全流程自动化,让导师惊呼“这届程序员太卷”。以下,是我的双重笔记:产品心路 + 可复现代码,全部开源,拿去就跑。
(二)课程拆解:把“玄学”拆成可运行模块
第 1 周:AIGC 产品画布 → 我直接写成 Pydantic 配置类,画布变“字典”,冲突项自动报错。
第 2 周:竞品差异度公式 → 把 5 维评分扔进余弦相似度,跑完才知道我们“像”竞品 83%,根本不及格。
第 3 周:用户洞察访谈 → 用 Whisper 转语音,LLM 抽“痛点标签”,12 小时访谈 30 分钟读完。
第 4 周:MVP 验证 → 灰度发布 + 埋点,我写了条“0 侵入”装饰器,老代码一行不改就能上报。
第 5 周:数据闭环 → 把用户点赞数据回流训练,做成每日 CRON,A/B 提升 18%。
第 6 周:路演 PPT → 用 Marp + Markdown 自动生成,导师 Focus 在故事,我 Focus 在 CI/CD。
(三)企业级实战:3 周把“AI 海报生成”从 0 到 1
背景:集团电商业务,日均 3 万 SKU,每个商品都要 5 张营销图。设计部 40 人通宵达旦。目标:AIGC 批量出图,点击率 ≥ 人工 90%。
- 需求量化
代码片段 1:需求优先级自动打分器(篇幅所限只留核心函数,完整仓库见文末链接)
from pydantic import BaseModel, conint
from typing import List
class Need(BaseModel):
name: str
reach: conint(ge=1, le=10) # 触达用户数
intensity: conint(ge=1, le=10) # 痛点强度
freq: conint(ge=1, le=10) # 频次
tech_ready: conint(ge=1, le=10) # 技术就绪度
def score(n: Need) -> float:
"""简单线性加权,可换成机器学习模型"""
w = [0.3, 0.3, 0.2, 0.2]
return sum([n.reach, n.intensity, n.freq, n.tech_ready][i] * w[i] for i in range(4))
if __name__ == "__main__":
needs = [
Need(name="AI 批量海报", reach=9, intensity=9, freq=10, tech_ready=8),
Need(name="3D 动画生成", reach=5, intensity=6, freq=3, tech_ready=4)
]
print(sorted(needs, key=score, reverse=True))
跑分结果:AI 批量海报 8.8 分遥遥领先,立项通过。
- 用户调研自动化
代码片段 2:语音访谈→结构化标签
import openai, whisper, json, srt, datetime
def transcribe_and_label(audio_path: str):
# 1. 转录
model = whisper.load_model("base")
result = model.transcribe(audio_path, language="zh")
srt_text = srt.compose([srt.Subtitle(
index=i,
start=datetime.timedelta(seconds=int(seg["start"])),
end=datetime.timedelta(seconds=int(seg["end"])),
content=seg["text"]
) for i, seg in enumerate(result["segments"])])
# 2. 抽标签
prompt = f"请从以下文本中抽出用户痛点、场景、期望功能,返回 JSON 列表:\n{srt_text}"
openai.api_key = "sk-xxx"
rsp = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": prompt}],
temperature=0.2
)
return json.loads(rsp.choices[0].message.content)
if __name__ == "__main__":
print(transcribe_and_label("user1.wav"))
输出示例:
[
{"type": "pain", "desc": "模板单一,无法体现品牌调性"},
{"type": "scene", "desc": "大促前 3 天需求集中爆发"},
{"type": "expect", "desc": "支持上传品牌 VI 自动换色"}
]
30 份访谈脚本跑完,已凌晨 2 点,我泡了碗面,电脑还在吭哧转录,心里却无比踏实——数据不会说谎。
- 提示工程 & 模型微调
基础模型:Stable Diffusion 1.5 + LoRA
训练数据:电商设计部 6 年历史 Banner,共 8.7 万张,按品牌-风格-节日打标签。
代码片段 3:自动打标 + 清洗
from transformers import BlipProcessor, BlipForConditionalGeneration
from PIL import Image
import pandas as pd, os, torch
processor = BlipProcessor.from_pretrained("Salesforce/blip-image-captioning-base")
model = BlipForConditionalGeneration.from_pretrained("Salesforce/blip-image-captioning-base")
device = "cuda" if torch.cuda.is_available() else "cpu"
model.to(device)
def caption(image_path: str) -> str:
raw_image = Image.open(image_path).convert('RGB')
inputs = processor(raw_image, return_tensors="pt").to(device)
out = model.generate(**inputs, max_length=20, num_beams=3)
return processor.decode(out[0], skip_special_tokens=True)
df = pd.DataFrame({"file": os.listdir("banners")})
df["caption"] = df["file"].map(lambda f: caption(f"banners/{f}"))
df.to_csv("auto_tags.csv", index=False)
人工复检 10% 后,标签准确率 94%,可直接喂给 LoRA。
- MVP 灰度发布
代码片段 4:0 侵入埋点装饰器
import time, functools, requests, json, os
ENDPOINT = "https://metrics.company.com/v1/event"
def track(event: str, **kwargs):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs_inner):
t0 = time.time()
try:
ret = func(*args, **kwargs_inner)
status = "ok"
return ret
except Exception as e:
status = "err"
raise e
finally:
requests.post(ENDPOINT, json={
"event": event,
"duration": time.time()-t0,
"status": status,
"user": kwargs_inner.get("user_id"),
**kwargs
}, timeout=2)
return wrapper
return decorator
# 使用示例
@track(event="click_generate", channel="aigc_banner")
def generate_banner(prompt: str, user_id: str):
...
上线 3 天,累计 1.2 w 次生成,平均耗时 1.8 s,崩溃率 0.05%。
- 数据回流 & 自动微调
用户有点击/无点击数据实时进 Kafka,凌晨 CRON 跑 A/B,胜率 >5% 自动触发微调。
代码片段 5:LoRA 微调脚本(仅关键超参)
export MODEL_NAME="runwayml/stable-diffusion-v1-5"
export DATASET_NAME="banner_liked"
export OUTPUT_DIR="./lora_banner_v2"
export LR=1e-4
export BATCH_SIZE=4
export MAX_STEPS=800
accelerate launch train_text_to_image_lora.py \
--pretrained_model_name_or_path=$MODEL_NAME \
--dataset_name=$DATASET_NAME \
--dataloader_num_workers=8 \
--resolution=512 --center_crop --random_flip \
--train_batch_size=$BATCH_SIZE --gradient_accumulation_steps=1 \
--max_train_steps=$MAX_STEPS --learning_rate=$LR \
--lr_scheduler="constant" --lr_warmup_steps=0 \
--output_dir=$OUTPUT_DIR \
--checkpointing_steps=200 \
--validation_prompt="pink cyber style, mega sale" \
--seed=1337
两周后,新模型 CTR 提升 18%,设计部从 40 人减到 12 人,释放预算 600 万/年。
(四)心得:程序员做产品的三点“代码式”反思
- 需求不是“写死”的,是“配置”出来的——用 Pydantic 让变更 diff 可见。
- 用户调研可以“脚本化”——Whisper + GPT 把 12 小时压缩成 30 分钟,低成本就愿意反复做。
- 上线不是终点,而是持续集成——把微调、A/B、埋点全部写进 CI,数据飞轮自己转。
(五)资源清单
- 完整代码仓库(MIT 协议):github.com/yourname/ai…
- 数据集说明:banner_liked 已脱敏,仅留标签与向量,放心食用。
- 一键运行 Docker-Compose:docker-compose up -d(含 SD + LoRA + 埋点转发)
(六)结语
以前我以为,代码是目的;走完特训营才发现,代码只是产品经理的“高阶原型工具”。当程序员学会用产品语言提问,我们就能把“技术可能”翻译成“用户价值”,再把“用户反馈”编译成“下一轮模型权重”。
如果你也写过无数 CRUD,却想让堆过的代码被 100 万人点赞,不妨来当一次“会写代码的产品经理”。下一期特训营,我们班里见——我带电脑,你带故事,一起把 AIGC 做成爆款。