聊聊最近被不少 AI 产品经理同行问爆的一个组合:Vibe Coding + ChatBI。圈子里好像一夜之间都在聊“用嘴写代码”“让 AI 自己搭数据分析系统”。很多朋友想把这套东西做成作品集,写进简历,但又不知道从哪儿开始下手,更不知道简历上到底该怎么写才不虚。
先说结论:Vibe Coding 不是歪门邪道,也不是“偷懒不写代码”,它是 AI 时代产品经理快速验证想法的一种新的工作方式。而 ChatBI(对话式数据智能)是目前最适合拿来当作品集落地场景的 AI 应用之一——需求清晰、价值明显、技术链路完整,面试官一看就懂,问起来也有话聊。
这篇文章我会从一个 AI 产品经理的实际视角出发,拆解三件事:Vibe Coding 到底是什么、怎么用它把一个 ChatBI 从想法变成能跑的原型,以及最后怎么把这个作品集专业地写进简历里。全程给可复用的提示词、代码思路和简历模板,不是那种只讲概念的空文章。
1. 背景与核心概念
1.1 为什么 AI 产品经理需要“作品集”
传统产品经理找工作靠的是 PRD、原型图、数据报告和讲项目故事的能力。但 AI 产品经理面临的情况不太一样:面试官尤其是一线技术负责人,很难通过文档判断你是否真的理解 AI 能力边界。你说你设计过一个智能客服,问你 Prompt 怎么调优、模型幻觉怎么处理、召回率怎么测,答不上来就露馅了。
作品集的核心作用,是证明“我不光会画图写文档,我真的动手把一个 AI 应用从概念推到了可用状态”。
而 AI 产品经理的作品集和程序员的作品集有一个本质区别:重点不是代码写得多漂亮,而是你如何定义问题、拆解功能、评估效果、迭代优化。所以作品集不要求你有高级工程师的编码水平,但要求你能用最低成本把想法落地成可体验、可演示、可分析的产品。
1.2 Vibe Coding 是什么,解决什么问题
Vibe Coding 这个词最早流行起来,源于大家发现用自然语言给 AI 编程助手(比如 Cursor、Claude、GPT 的 Artifacts、DeepSeek、通义灵码等)下达指令,已经能完成相当一部分实际开发工作。它不强调手写每一行代码,而是强调用清晰的意图描述驱动 AI 生成代码,自己负责判断、组合、调试和验证。
对 AI 产品经理来说,Vibe Coding 的意义不是替代工程师,而是:
- 快速做原型:把想法直接跟 AI 说,几分钟拿到一个可点击、可交互、可演示的页面。
- 验证技术可行性:不确定某个功能能不能做,直接让 AI 写一版试试,比争论半天都有效。
- 降低沟通成本:你手上有个能跑的 Demo,和技术团队沟通需求时,大家对着真实系统讨论,而不是对着文字想象。
- 补齐产品 Sense 到技术理解之间的空档:通过亲手调试 Prompt、修改参数、观察错误日志,你能真正理解模型的能力边界。
有人可能会担心,这是不是在鼓励产品经理抢工程师的活?我个人的观点是:Vibe Coding 产出的是“原型”“样板”和“作品集”,不是高并发高可用的商业系统。你的目标是用它来验证和表达,而不是用它替代专业研发流程。
1.3 ChatBI 是什么,为什么适合做成作品集
ChatBI 是 Chat Business Intelligence 的缩写,指通过自然语言对话的方式来查询、分析和理解业务数据。
你可以把它理解成一个“能聊天”的数据分析助手。传统 BI 工具要求用户会拖拽报表、懂维度指标、能自己写 SQL;ChatBI 做的事情是让用户直接问:“上个月华东区域的销售额环比增长了多少?哪个品类贡献最大?”系统自动理解问题,生成查询逻辑,返回结果,甚至自动生成图表。
ChatBI 作为 AI 产品经理的作品集,有几个天然优势:
- 需求场景普及:几乎每个公司都有数据分析需求,面试官完全能理解这个产品解决什么问题。
- 技术链路完整:涉及 NL2SQL、意图识别、Prompt 工程、可视化、数据权限、效果评估,这些都是 AI 产品经理面试的高频话题。
- 可量化效果好:你可以给出“SQL 生成准确率”“查询响应时间”“端到端任务完成率”等指标,这些都是作品集里的硬通货。
- 能独立完成:借助 Vibe Coding,一个人就能搭出可演示的版本,不需要依赖后端团队、数据团队和测试资源。
1.4 容易混淆的概念澄清
很多初学者会把几个相关概念搞混:
| 概念 | 核心能力 | 与 ChatBI 的区别 |
|---|---|---|
| 传统 BI(Tableau、Power BI) | 可视化报表、拖拽分析 | 需要用户手动配置图表和指标,学习成本高 |
| Chatbot(智能客服) | 对话问答、任务办理 | 偏向服务交互,不一定涉及数据库查询 |
| ChatBI | 自然语言 → 数据查询 → 分析与展示 | 强调“对话即分析”,核心是理解和查询数据 |
| Copilot(编程助手) | 在 IDE 里辅助写代码 | 面向研发场景,不是面向业务分析场景 |
搞清楚这些边界,写简历时才能精确表达自己作品集的定位。
2. 环境准备与工具选型
做作品集不需要企业级技术架构,我们的原则是:够用、开源、免费、演示顺畅。
2.1 我选择的工具链
下面是我个人的方案,你可以根据手头资源调整:
| 用途 | 工具选择 | 选型理由 |
|---|---|---|
| Vibe Coding 主环境 | Cursor 或 Claude / DeepSeek 对话窗口 | Cursor 适合边聊边改代码;对话式工具适合快速生成完整脚本 |
| 编程语言 | Python 3.10+ | AI 生成代码最容易稳定运行的语言,生态完善 |
| 前后端框架 | Streamlit | 纯 Python 写 Web 应用,几百行代码就能做出像样的界面 |
| 数据库 | SQLite | 无需安装数据库服务,单文件存储,作品集演示零成本 |
| 向量数据库 | ChromaDB | 用于存放样例问题和 SQL 模板,提升 NL2SQL 准确率 |
| LLM API | OpenAI GPT-4o / DeepSeek / Qwen | 任选其一即可,取决于你的预算和可用性 |
| 依赖管理 | requirements.txt + pip | 保持环境简单,方便他人复现 |
2.2 需要确认的版本说明
我必须先声明:大模型相关 API 和工具版本变化非常快,下面给出的版本号只是说明我在写这篇文章时的常见选择。你实际使用时,请以官方最新文档为准,不要照搬。
# 建议使用 Python 3.10 或 3.11 python --version # 安装核心依赖(注意:版本可能随时间更新) pip install streamlit pip install openai pip install langchain pip install chromadb pip install pandas pip install sqlite3 # 一般内置,无需单独安装如果你所在的网络环境不方便直接访问部分外部服务,可以选择国内可用的模型服务商,或者通过代理方式访问,这里不展开。
2.3 示例项目结构
我在做这个作品集时,项目目录如下:
chatbi-mvp/ ├── app.py # Streamlit 入口页面 ├── nl2sql.py # 核心模块:自然语言转 SQL ├── database/ │ ├── init_db.py # 初始化数据库和样例数据 │ └── sales.db # SQLite 数据库文件 ├── prompts/ │ └── sql_prompt.py # Prompt 模板 ├── examples/ │ └── few_shot_examples.py # 少样本示例,用于提升准确率 ├── requirements.txt └── README.md这个结构够清晰,面试官一眼能看出你对项目有工程化思维,而不是把代码堆在一个文件里。
3. Vibe Coding 实操方法论:从想法到原型
这一节是整篇文章最关键的部分。我不会直接给你一堆代码,而是先讲 Vibe Coding 的操作方法。因为只有掌握了这套方法,你以后才能快速做出不同主题的作品集。
3.1 第一轮:用自然语言让 AI 生成脚手架
我第一次做 ChatBI 原型时,没有先写架构文档,而是直接打开 Cursor,输入了这样一段 Prompt:
你是一名 Python 开发工程师,请帮我搭建一个 ChatBI MVP 项目的骨架。 要求如下: 1. 使用 Streamlit 作为 Web 界面框架; 2. 用户输入中文问题,系统返回 SQL 查询语句、执行结果和图表; 3. 数据库使用 SQLite,提前生成一个销售订单表,包含 100 条左右的测试数据,字段包括: - order_id - order_date - region - product_category - sales_amount - quantity 4. 先别写完整功能,只生成项目目录结构和每个文件的占位代码。 请直接输出每个文件的完整代码。这段 Prompt 的关键信息非常明确:技术栈、数据表结构、输出格式要求。AI 生成的代码一开始当然不完美,但不重要。第一轮的目标是拿到一个能跑起来的骨架。
3.2 第二轮:逐模块迭代,而不是一次到位
拿到骨架后,不要急着让 AI 一次性把所有功能全部补齐,那样很容易生成一大堆互相不兼容的代码。
我的建议是把完整需求拆成下面几个模块,分别对话解决:
- 模块一:数据初始化(让 SQLite 有数据可查)
- 模块二:LLM 调用封装(让程序可以请求大模型接口)
- 模块三:NL2SQL 核心逻辑(自然语言转成 SQL 语句)
- 模块四:结果解析与可视化(把查询结果渲染成图表)
- 模块五:异常处理(SQL 生成错误时给出兜底方案)
每次对 AI 只提一个小需求。比如:
请给 nl2sql.py 写一个函数,输入是用户问题(中文),输出是一条 SQL 查询语句。 要求: 1. 先获取数据表的 schema,也就是表名、字段名、字段类型和主键信息; 2. 把 schema 和 few-shot 示例一起放进 Prompt; 3. 解析 LLM 返回的 SQL,去掉 markdown 格式代码块标记; 4. 如果生成失败,返回空字符串。这样做的优势是:每个模块的代码都短小、逻辑清晰,即使出现 Bug 也容易定位。这就是 Vibe Coding 和传统开发的典型差异——我们通过“对话 + 小步迭代”替代了“一次性编码”。
3.3 第三轮:运行、报错、反馈、优化
Vibe Coding 的本质不只是让 AI 写代码,还包括让 AI 帮你改代码。运行报错时,直接把错误信息复制回对话窗口:
运行 app.py 时出现以下报错,请分析原因并给出修复后的代码。 Streamlit run app.py 报错信息: sqlite3.OperationalError: table sales_orders has no column named order_dateAI 能根据报错信息迅速定位问题,通常是因为我们初始化数据库时字段名不一致。它会把相关代码段重新生成一遍,你复制覆盖即可。
这个“运行-报错-反馈-修复”的循环,就是 Vibe Coding 的核心工作流。你要习惯把自己当成项目经理和测试人员,而不是“打字员”。
3.4 关于“避免幻觉功能”的提醒
使用 Vibe Coding 时,最大的风险是让 AI 生成了它“以为自己能做”但实际运行不了的功能。比如让它接入一些并不存在的第三方 API,或者编造不存在的 Python 库。
我的规避方法有两条:
- 在 Prompt 里明确要求使用主流、成熟、真实存在的库;
- 拿到 AI 给的代码后,先看它 import 了哪些库,逐个确认这些库是否真实存在、是否能正常安装。
如果 AI 给出的某个库你从来没听说过,不要直接相信,先去 PyPI 或 GitHub 搜一下再决定。这是 AI 产品经理应该养成的技术敬畏心。
4. 实战:用 Vibe Coding 从零构建 ChatBI 最小可行版本
下面进入完整实战环节。我尽量把每一步写清楚,让你可以照着做出来。
4.1 初始化数据库与样例数据
首先准备好数据。在项目根目录创建database/init_db.py。
# 文件路径:database/init_db.py import sqlite3 import random from datetime import datetime, timedelta def create_database(db_path="database/sales.db"): conn = sqlite3.connect(db_path) cursor = conn.cursor() # 创建销售订单表 cursor.execute(""" CREATE TABLE IF NOT EXISTS sales_orders ( order_id INTEGER PRIMARY KEY AUTOINCREMENT, order_date TEXT NOT NULL, region TEXT NOT NULL, product_category TEXT NOT NULL, sales_amount REAL NOT NULL, quantity INTEGER NOT NULL ) """) # 生成测试数据 regions = ["华东", "华南", "华北", "西南"] categories = ["数码产品", "家用电器", "服饰鞋包", "食品饮料"] start_date = datetime(2024, 1, 1) random.seed(42) # 固定随机种子,保证数据可复现 for i in range(200): order_date = start_date + timedelta(days=random.randint(0, 365)) region = random.choice(regions) category = random.choice(categories) amount = round(random.uniform(50, 2000), 2) quantity = random.randint(1, 10) cursor.execute( "INSERT INTO sales_orders " "(order_date, region, product_category, sales_amount, quantity) " "VALUES (?, ?, ?, ?, ?)", (order_date.strftime("%Y-%m-%d"), region, category, amount, quantity) ) conn.commit() conn.close() print("数据库初始化完成,共插入 200 条销售订单。") if __name__ == "__main__": create_database()运行初始化脚本:
python database/init_db.py预期输出:
数据库初始化完成,共插入 200 条销售订单。这个脚本有三个教学点值得你在简历里提到:字段设计、随机种子保证数据可复现、SQLite 轻量化的选型理由。
4.2 编写 Prompt 模板与少样本示例
NL2SQL 的核心是 Prompt 设计。我们要让模型知道:有哪些表、哪些字段、用户的问题是什么意思、应该生成什么 SQL。
先创建prompts/sql_prompt.py:
# 文件路径:prompts/sql_prompt.py def build_sql_prompt(schema_text: str, examples_text: str, user_question: str) -> str: prompt = f""" 你是一个数据分析师,负责把用户的中文问题转换成 SQL 查询语句。 请严格遵循以下规则: 1. 只能根据给定的表结构生成 SQL,不能臆造不存在的字段; 2. 只输出 SQL 语句本身,不要输出解释、不要使用 Markdown 代码块标记; 3. 查询结果必须是聚合后的汇总数据,不允许返回明细行; 4. 如果用户问题中指定了时间范围,要使用 WHERE 条件进行过滤; 5. 金额相关字段需要输出保留两位小数; 6. 如果问题无法用给定表结构回答,请输出: ERROR: 无法生成查询 数据库表结构如下: {schema_text} 参考示例: {examples_text} 用户问题:{user_question} SQL: """ return prompt再创建examples/few_shot_examples.py,这里放了几个典型问题,用来引导模型生成风格统一的 SQL:
# 文件路径:examples/few_shot_examples.py FEW_SHOT_EXAMPLES = [ { "question": "上个月华东区域的销售额是多少?", "sql": "SELECT region, ROUND(SUM(sales_amount), 2) AS total_sales " "FROM sales_orders " "WHERE region = '华东' " "AND order_date BETWEEN '2024-11-01' AND '2024-11-30' " "GROUP BY region" }, { "question": "哪个产品类别累计销售额最高?", "sql": "SELECT product_category, ROUND(SUM(sales_amount), 2) AS total_sales " "FROM sales_orders " "GROUP BY product_category " "ORDER BY total_sales DESC " "LIMIT 1" }, { "question": "西南区域今年第一季度各个月份的订单数量趋势如何?", "sql": "SELECT strftime('%Y-%m', order_date) AS month, COUNT(*) AS order_cnt " "FROM sales_orders " "WHERE region = '西南' " "AND order_date BETWEEN '2024-01-01' AND '2024-03-31' " "GROUP BY month " "ORDER BY month" }, { "question": "华南区域销量最高的商品类别是哪一类?", "sql": "SELECT product_category, SUM(quantity) AS total_quantity " "FROM sales_orders " "WHERE region = '华南' " "GROUP BY product_category " "ORDER BY total_quantity DESC " "LIMIT 1" }, { "question": "最近一个月平均每笔订单的金额是多少?", "sql": "SELECT ROUND(AVG(sales_amount), 2) AS avg_order_amount " "FROM sales_orders " "WHERE order_date >= '2024-11-30' - INTERVAL 30 DAY" }, ]需要说明的是,最后一个示例里的INTERVAL语法在 SQLite 中不一定直接生效,实际使用时应统一用字符串日期比较。这里保留原样是想提醒你:AI 生成的 SQL 并不总是和数据库方言匹配,审查 SQL 是产品经理必须具备的能力。
因此,我们在运行时会对生成的 SQL 做两层校验,下面会讲到。
4.3 编写获取 Schema 的工具函数
要让模型写出正确 SQL,必须把数据库结构告诉它。写一个工具函数,用 SQLite 的系统表查询字段信息:
# 文件路径:nl2sql.py(部分代码) import sqlite3 def get_schema(db_path: str = "database/sales.db") -> str: conn = sqlite3.connect(db_path) cursor = conn.cursor() cursor.execute("SELECT name FROM sqlite_master WHERE type='table'") tables = [row[0] for row in cursor.fetchall()] schema_parts = [] for table in tables: cursor.execute(f"PRAGMA table_info({table})") columns = cursor.fetchall() col_desc = ", ".join([f"{col[1]} {col[2]}" for col in columns]) schema_parts.append(f"表名: {table}, 字段: {col_desc}") conn.close() return "\n".join(schema_parts)这里用PRAGMA table_info获取字段名和类型,信息足够简洁,适合放进 Prompt。需要说明的是,这里的f"PRAGMA table_info({table})"属于内部信任场景,因为表名来自系统表,不是直接拼接用户输入,因此在演示场景下风险可控。如果对接真实业务库,不能直接这样写,应该使用参数化查询方式获取元数据。
4.4 编写 NC2SQL 主流程
下面来写nl2sql.py的完整核心逻辑。它负责四件事:获取 Schema、调用模型生成 SQL、校验 SQL、执行 SQL。
# 文件路径:nl2sql.py import re import sqlite3 from openai import OpenAI from prompts.sql_prompt import build_sql_prompt from examples.few_shot_examples import FEW_SHOT_EXAMPLES client = OpenAI(api_key="your-api-key", base_url="your-base-url") # 取决于你的模型服务商 def get_schema(db_path: str = "database/sales.db") -> str: # 省略,同上文 get_schema 函数 def extract_sql(text: str) -> str: """从模型输出中提取纯 SQL,去掉可能的 markdown 标记""" # 去掉代码块标记 text = re.sub(r"```sql|```", "", text).strip() return text def validate_sql(sql: str) -> bool: """简单校验 SQL 是否包含风险或异常语法""" blacklist = ["INSERT", "UPDATE", "DELETE", "DROP", "ALTER", "CREATE"] for word in blacklist: if re.search(r"\b" + word + r"\b", sql.upper()): return False return True def execute_sql(sql: str, db_path: str = "database/sales.db"): conn = sqlite3.connect(db_path) try: cursor = conn.cursor() cursor.execute(sql) columns = [desc[0] for desc in cursor.description] if cursor.description else [] rows = cursor.fetchall() return columns, rows except Exception as e: return None, f"执行错误: {e}" finally: conn.close() def nl2sql(user_question: str) -> dict: schema = get_schema() examples_text = "" for item in FEW_SHOT_EXAMPLES: examples_text += f"问题: {item['question']}\nSQL: {item['sql']}\n\n" prompt = build_sql_prompt(schema, examples_text, user_question) response = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": prompt}], temperature=0.1, ) raw_sql = response.choices[0].message.content sql = extract_sql(raw_sql) # 判断是否生成失败 if sql.startswith("ERROR") or sql == "": return {"error": "无法理解该问题,请尝试换个说法。"} # 判断是否包含非法 SQL if not validate_sql(sql): return {"error": "生成的 SQL 存在安全风险,已阻止执行。"} # 执行 SQL columns, rows = execute_sql(sql) if columns is None: return {"error": rows} return {"columns": columns, "rows": rows, "sql": sql}关键步骤说明:
temperature=0.1让模型输出更稳定,减少随意生成。extract_sql是为了兼容不同模型输出格式,有的模型喜欢带 markdown 代码块。validate_sql是安全兜底,避免模型生成非查询语句。这很重要,正式做 ChatBI 时不能直接执行模型生成的 SQL。execute_sql捕获执行异常,保证至少不会让整个 Web 应用崩溃。
4.5 编写图表可视化逻辑
为了让作品集看起来更完整,我们在拿到查询结果后,尝试根据字段特征自动判断是否适合画图。
# 文件路径:app.py(部分代码) import pandas as pd import streamlit as st from nl2sql import nl2sql import matplotlib.pyplot as plt plt.rcParams["font.sans-serif"] = ["SimHei", "Arial Unicode MS", "PingFang SC"] plt.rcParams["axes.unicode_minus"] = False def auto_visualize(columns, rows): """ 根据返回的字段做简单的可视化判断。 如果只有一个维度字段和一个数值字段,输出柱状图或折线图。 """ df = pd.DataFrame(rows, columns=columns) if len(df.columns) >= 2: first_col = df.columns[0] second_col = df.columns[1] if pd.api.types.is_numeric_dtype(df[second_col]): fig, ax = plt.subplots(figsize=(10, 5)) ax.bar(df[first_col].astype(str), df[second_col]) ax.set_xlabel(first_col) ax.set_ylabel(second_col) ax.set_title(f"{first_col} vs {second_col}") plt.xticks(rotation=45, ha="right") st.pyplot(fig)这一步不用太复杂,关键是让面试官和用户直观感受到“系统不仅能问答,还能自动给出图表”。
4.6 编写 Streamlit 界面
最后是 Web 界面层。我们希望用户输入一个问题,点击按钮,看到三个东西:生成的 SQL、查询结果表格、对应图表。
# 文件路径:app.py import streamlit as st import pandas as pd from nl2sql import nl2sql def auto_visualize(columns, rows): # 省略,同上文 def main(): st.set_page_config(page_title="ChatBI 数据问答助手", layout="wide") st.title("📊 ChatBI 数据问答助手") st.caption("输入你的业务问题,系统将自动完成 SQL 生成、执行与可视化展示。") user_question = st.text_input("请输入你的问题", placeholder="比如:华东区域销售额最高的商品类别是什么?") if st.button("开始分析", type="primary"): if not user_question.strip(): st.warning("请先输入问题。") return with st.spinner("正在理解和生成查询..."): result = nl2sql(user_question) if "error" in result: st.error(result["error"]) return st.subheader("生成的 SQL") st.code(result["sql"], language="sql") st.subheader("查询结果") columns = result["columns"] rows = result["rows"] df = pd.DataFrame(rows, columns=columns) st.dataframe(df, use_container_width=True) st.subheader("可视化分析") auto_visualize(columns, rows) if __name__ == "__main__": main()运行方式:
streamlit run app.py浏览器会自动打开http://localhost:8501。输入中文问题,就能看到完整的问答分析过程。
4.7 运行效果预期
当你输入“华东区域销售额最高的商品类别是什么?”时,预期输出大致是:
- 生成的 SQL:
SELECT product_category, ROUND(SUM(sales_amount), 2) AS total_sales FROM sales_orders WHERE region = '华东' GROUP BY product_category ORDER BY total_sales DESC LIMIT 1- 数据表格:一列是商品类别,一列是累计销售额,按降序排列。
- 可视化图表:因为第一列是字符串、第二列是数值,系统自动绘制柱状图。
虽然这个 MVP 还不够智能,但它已经是一个完整的 ChatBI 闭环,足够放进作品集里讲清楚产品逻辑。
5. 进阶提升:让 ChatBI 更接近真实产品
只跑通一个简单 Demo 是不够的,AI 产品经理的作品集一定要体现“思考深度”。下面这几个方向,你可以选 1 到 2 个在作品集里展示。
5.1 加入语义缓存机制
在很多 ChatBI 场景中,用户会反复问类似的问题。如果每次都调用大模型生成 SQL,成本高、响应慢。一个简单有效的优化是引入语义缓存。
思路:先把用户问题转成 embedding 向量,然后在 ChromaDB 里查找最相似的历史问题。如果相似度超过一个阈值(比如 0.85),直接返回历史 SQL 和结果。
# 思路示例:语义缓存 from chromadb import Client # 1. 初始化 Chroma 集合 # 2. 将每个历史问题写入 collection,同时存储 SQL 和结果 # 3. 用户提问时,先用 embedding 搜索相似记录 # 4. 相似度高直接返回,否则走 NL2SQL 主链路这个机制进简历非常加分,因为它体现你考虑了成本、性能和产品体验的平衡。
5.2 加入多轮对话能力
上面的 MVP 只支持单轮对话。真实产品中,用户会追问:“那华北呢?”“占比是多少?”这些问题依赖上下文。
优化思路有两种:
- 简单法:把历史对话记录拼进 Prompt,让模型自己理解当前问题是否依赖上文。
- 结构法:在对话历史中抽取实体和条件(区域、时间、品类),填充一个“查询条件槽位”。
作为作品集,建议先实现简单法,后说明结构法的演进方向。
5.3 加入数据权限控制
真实 ChatBI 最重要的工程问题之一,是数据权限。不是所有用户都有权限查看所有区域的数据。
你可以在作品集里加上一个简单的角色权限模型:
# 思路示例:权限控制 # 1. 定义用户角色,比如 admin、analyst、visitor # 2. 根据角色生成不同的 SQL 过滤条件 # 3. 例如 visitor 只在 WHERE 条件中强制追加 user_region = '华东' # 4. 在原型中通过侧边栏切换角色,演示不同身份看到的数据范围不同这个功能不用写得很复杂,但一定要在 README 和简历里说明,因为这直接展示了你作为 AI 产品经理对“安全边界”的理解。
6. 如何把 ChatBI 作品集写进简历
作品集做出来了,最关键的一步来了:怎么在简历里展示它。
6.1 简历项目描述通用框架
我建议参考 STAR 法则,但写简历时不需要严格写成四段。核心是让面试官在 30 秒内看懂三个信息:背景、动作、结果。
| 信息项 | 内容建议 |
|---|---|
| 项目背景 | 一句话说明为什么做这个 ChatBI |
| 时间跨度 | 写清楚周期,最好在 2-4 周内 |
| 你的角色 | 独立完成,或作为 AI 产品经理主导 |
| 核心动作 | Vibe Coding、Prompt 工程、NL2SQL、可视化、安全机制 |
| 量化结果 | SQL 生成准确率、响应时间、功能覆盖率 |
| 技术栈 | Python、Streamlit、SQLite、LLM API |
6.2 简历项目描述示例
下面给一个可以直接参考的写法,注意替换为你的实际数据和指标:
ChatBI 对话式数据分析助手(独立开发 / 2025.03 - 2025.04) 项目背景: 企业内部运营人员日常取数依赖数据团队,大量常见问题通过即时通讯工具纸质传递,查询效率低、口径不一致。 项目动作: - 基于 Vibe Coding 方法论,使用 Python + Streamlit 完成 ChatBI MVP 从需求拆解到可运行原型; - 设计 NL2SQL 核心链路:通过 LLM 将中文问题转换为 SQL,结合 sqlite schema 注入、few-shot 示例增强生成准确率; - 设计结果可视化模块,根据字段类型自动选择柱状图、折线图或明细表展示; - 加入语义缓存、多轮对话扩展方案,降低接口调用成本; - 设计用户角色与数据权限控制逻辑,确保不同角色只能查看授权范围内的数据。 量化结果: - 在 200 条销售订单数据上,常见业务问题的 SQL 生成准确率达到约 92%; - 将语义缓存命中后的查询响应从平均 8 秒降低至 1 秒以内; - MVP 从需求确定到可演示版本交付耗时 2 周,全程独立完成; - 沉淀了一套可复用的 NL2SQL 提示词模板和 SQL 安全校验规则。 技术栈:Python、Streamlit、SQLite、ChromaDB、OpenAI API / DeepSeek API需要提醒的是,准确率 92% 这种数字不能拍脑袋乱写。我的建议是自己在测试集上跑一遍,记录真实结果后填进去。哪怕准确率只有 75%,只要说明测试条件和改进路径,也比虚标数字更有说服力。
6.3 面试时如何讲解这个作品集
面试官通常会从三个角度追问:
- 技术理解类:NL2SQL 的难点是什么?幻觉问题怎么处理?
- 产品判断类:为什么选 ChatBI 这个场景?目标用户是谁?
- 工程落地类:模型返回错误 SQL 怎么办?如何防止用户越权查数?
建议在本地留一个可运行的 Demo 包,面试时直接打开 Streamlit 现场演示。这比任何口头描述都有说服力。你需要准备好一段 3 分钟的演示脚本,讲清楚“用户输入问题 → 生成 SQL → 执行 → 可视化”的完整流程。
7. 常见问题与排查思路
7.1 常见问题汇总
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 输入问题后长时间无响应 | LLM API 响应慢或网络不稳定 | 检查 API 服务状态;设置超时时间;落地语义缓存 |
| 模型生成的 SQL 执行报错 | 字段名与 schema 不一致 | 在 Prompt 中强调只使用给定字段;查看报错信息反馈给 AI 修复 |
| SQL 能执行但结果明显不对 | 缺少 WHERE 条件或聚合方式错误 | 补充 few-shot 示例;降低 temperature |
| 中文图表乱码 | matplotlib 缺少中文字体 | 设置字体为 SimHei 或 PingFang SC |
| Streamlit 页面打不开 | 端口被占用或依赖未装齐 | 检查streamlit run app.py的启动日志;尝试换端口 |
| 数据库大量重复数据 | 重复运行 init_db.py | 在脚本里增加删除旧表或判断是否已存在的逻辑 |
7.2 排查优先级清单
如果系统跑不通,不要慌,按下面的顺序排查:
- 数据库是否有数据:打开
database/sales.db,确认sales_orders表非空; - API 是否可用:在 Python 里单独测试一次
client.chat.completions.create,看能否返回内容; - Prompt 是否正确拼接:打印出
build_sql_prompt的完整输出,检查 schema 和 examples 是否有语法问题; - SQL 校验是否过严:确认没有误杀合法的 SELECT 语句;
- 页面渲染是否出错:查看 Streamlit 终端的完整 traceback,定位到具体行号。
8. 最佳实践与工程建议
8.1 Vibe Coding 过程的工程素养
Vibe Coding 不等于“没有工程素养”。恰恰相反,AI 产品经理更应该具备工程思维,否则很容易被 AI 生成的一堆花哨代码带偏。
几点建议:
- 版本控制必须有:哪怕是小项目,也建议用 Git 管理,否则改坏了无法回退。
- 每个版本“能跑即提交”:不要等技术债积累太多才想起保存。
- 记录 Prompt 迭代过程:你每次怎么修改 Prompt 才让模型输出变好,这是 AI 产品经理作品集里的隐形资产。
- 保持项目结构整洁:即使代码是 AI 写的,也要坚持模块化拆分,不要一个文件写 800 行。
8.2 安全边界
这是 ChatBI 类作品最重要的部分:
- 绝不能让模型生成的 SQL 直接在生产库上执行,必须加白名单机制、SQL 校验和资源限制;
- 明确定义安全边界:作品集演示可以用 SQLite,但简历里一定要写清楚“正式方案中需要接入查询网关、数据脱敏、行级权限”;
- 提示词注入风险:不要在业务数据中直接拼接用户输入到 Prompt 之外的部分;涉及真实数据时,必须经过授权和脱敏处理。
8.3 效果评估方法
ChatBI 不是“能跑就行”。一个合格的数据分析助手,必须有一套评估维度:
| 评估维度 | 说明 | 评估方式 |
|---|---|---|
| 查询生成准确率 | 生成的 SQL 是否与预期结果一致 | 构建测试集,人工标注 |
| 端到端成功率 | 用户提问后是否成功返回结果 | 日志统计 |
| 响应时间 | 从提问到结果展示的总耗时 | 日志统计 |
| 用户满意率 | 用户对回答是否满意 | 问卷或反馈按钮 |
| 兜底率 | 无法回答时是否有友好提示 | 日志统计 |
建议在作品集 README 里写清楚评估方式和测试结果,这比“Demo 做得很炫”更有专业深度。
9. 总结与下一步行动路线
9.1 你已经掌握了什么
通过这篇文章,你已经了解到:
- Vibe Coding 的核心工作流:自然语言 → 生成代码 → 运行报错 → 反馈修复 → 迭代优化;
- 从零构建 ChatBI MVP 的完整链路:数据准备、Prompt 设计、NL2SQL、业务校验、可视化展示;
- ChatBI 产品在真实落地时需要关注的进阶能力:语义缓存、多轮对话、数据权限控制;
- 如何把一个作品集项目专业地写进简历,并准备好面试讲解路径。
9.2 下一步推荐做什么
我一直强调,AI 产品经理最重要的不是堆代码量,而是形成“定义问题 - 快速验证 - 量化评估 - 持续迭代”的闭环。基于这个思路,建议你接下来做以下增强:
- 把自己测试的真实业务数据替换掉样例数据,让作品集更有业务说服力;
- 尝试接入一个国内可用的模型服务,比如 DeepSeek,验证不同模型在 NL2SQL 场景下的表现差异;
- 增加 10 条真实测试用例,记录准确率变化,形成一份简短的效果评估报告;
- 把整个项目放进 GitHub,顺便把 README 写完整,让别人可以复现。
当你完成上面这些动作之后,这个作品集就不只是一个“AI 生成的 Demo”,而是一个能证明你具备 AI 产品经理核心能力的完整项目。
9.3 作品集的长期意义
最后说一点真心话。Vibe Coding 必然会继续进化,模型能力也会越来越强,也许未来会出现更轻量的方式直接构建数据问答系统。但无论工具怎么变,作为 AI 产品经理,真正稀缺的能力始终是:
- 判断什么场景值得做;
- 知道怎么把模糊想法拆成可落地的功能边界;
- 能评估模型和产品的效果差距在哪里;
- 能推动一个 AI 功能从“能跑”走向“好用”。
ChatBI 只是切入点。通过这个作品集,你证明的不是“我会用 AI 写代码”,而是“我能用 AI 把一个产品想法变成可体验、可评估、可演进的原型”。
接下来就动手打开 Cursor 或任意一个 AI 编程工具,把上面第 4 节的代码结构跑通。遇到问题也不用怕,报错信息直接贴给 AI,改就完了。Vibe Coding 的乐趣,恰恰就在这个“边聊边改、不断逼近可用状态”的过程里。
如果这篇文章对你有帮助,可以收藏备用。要是你想了解 ChatBI 更进阶的语义缓存实现,或者想看更复杂的简历案例,可以在评论区留言,我来安排。