纯小白第一次接触用 AI 做系统,最常见的心态是:把需求往对话框里一贴,AI 把代码吐出来,复制到本地,保存,运行,系统就成了。真正做过一次就会知道,这个流程少了两个关键环节:一是你不清楚应该让 AI 生成什么,二是代码生成之后,你还没有能力把文件、环境、数据库和运行方式串起来。这篇文章就用一个待办清单管理系统为例,把从需求到运行的完整链路拆开,告诉你怎么用大白话和 AI 对话,怎么判断它生成的内容,遇到报错又该怎么回喂给它。目标不是让某一种语言变成你的强项,而是建立一条可复用的 AI 辅助开发路径。
1. 先理解 AI 写系统的逻辑:它给你的是素材,不是成品
很多教程喜欢说“让 AI 帮你写系统”,但“写系统”这件事本身是模糊的。系统不是一段代码,也不是一个文件,而是一组文件、依赖、数据和行为规则,最终组合成一个能通过浏览器访问、能保存数据、能处理用户操作的服务。
1.1 为什么“一句话生成系统”在小项目里并不是天方夜谭
大语言模型的训练数据里包含大量代码仓库、技术文档、问答和开源项目,所以对于常见的增删改查类系统,模型确实能生成非常接近可用的代码。待办清单、博客、笔记、留言板、库存管理等,都属于这类模式。
问题在于,模型生成的是“代码片段”,不是“文件夹”。同一个系统,AI 可能只给你一个app.py,但实际运行还需要模板文件、依赖清单、初始化表结构、启动命令。如果只复制主文件,第一次运行大概率会报错。
1.2 一套可用系统等于代码 + 环境 + 数据 + 运行路径
把 AI 生成的代码当成素材,再手动补全其他部分,问题就清晰多了。一个最小可运行的系统,至少包含四块内容:
| 组成部分 | 说明 | 小白容易忽略的地方 |
|---|---|---|
| 代码 | 主程序、页面模板、样式文件 | 只复制一个文件,缺少目录结构 |
| 环境 | Python、依赖包、虚拟环境 | 不装依赖,启动直接报No module named |
| 数据 | 数据库文件、表结构 | 第一次访问没初始化表,报No such table |
| 运行路径 | 启动命令、访问地址、端口 | 不知道在哪里打开浏览器确认效果 |
后面所有步骤都围绕这四块展开。理解了这一点,就不会再指望 AI 一次性给你一个“成品系统”,而是学会和 AI 一起把一个空目录变成可运行项目。
2. 从最小目标开始:把“待办清单系统”拆成 AI 能理解的需求
AI 编程最怕的不是需求复杂,而是需求没说清楚。你丢一句“帮我做一个系统”,它只能猜。你丢一组“需求、技术栈、页面行为、运行要求”,它才能生成接近可用的代码。
2.1 为什么选择“待办清单”作为入门项目
待办清单包含一个系统最常见的完整闭环:数据建模、新增、读取、修改、删除。它没有复杂的业务规则,也没有支付、权限、弹窗流,很适合第一次体验“从 0 到 1”。
用 AI 做这个项目时,你可以把注意力放在方法论上,而不是被业务逻辑带偏。后面换成记账本、读书笔记,流程完全一样。
2.2 用大白话给 AI 写第一版任务描述
推荐的提示词结构是:说明身份、指定技术栈、列出功能、说明页面形式、要求输出文件结构和运行命令。
我是一个没写过代码的新手。请帮我用 Python Flask 做一个待办清单系统。 功能要求: 1. 能新增待办事项。 2. 能标记为已完成,也能取消完成。 3. 能删除待办事项。 4. 使用 SQLite 保存数据,数据库文件放在项目目录下。 页面要求: 1. 只有一个页面,展示所有待办。 2. 页面顶部是输入框和“新增”按钮。 3. 每一条待办后面有“完成”和“删除”按钮。 4. 已完成的待办文字显示删除线。 文件结构要求: 1. 请把主程序放在 app.py,页面模板放在 templates/index.html。 2. 提供 requirements.txt。 3. 提供 Windows 下的启动命令。为什么这样写?因为每一句话都在限制 AI 的发挥空间。指定Flask是限制技术栈,指定SQLite是限制数据存储方式,指定templates/index.html是限制文件结构,指定Windows是让命令更匹配当前环境。
2.3 AI 会返回什么:先学会读结果
AI 大概率会给你一个app.py、一个index.html、一个requirements.txt,同时附上运行说明。这套结果已经接近可用。
但不要直接信任。重点检查三处:
- 有没有初始化数据库表的逻辑。
- 模板文件里的表单路径和主程序路由是否一致。
- 依赖是否被完整写进
requirements.txt。
如果发现它把模板直接写在app.py里,也没关系,后续可以再问一句“请把页面模板拆到 templates/index.html”。
3. 让 AI 生成代码,然后用本地环境把它跑起来
纯小白最容易卡在“代码有了,项目跑不起来”。这不是笨,而是环境没有对齐。
3.1 环境准备:Python、编辑器和虚拟环境
先确认电脑上有没有 Python。Windows 下打开 PowerShell,输入:
python --version如果提示找不到命令,可以再试:
py --version推荐环境如下:
| 工具 | 版本建议 | 说明 |
|---|---|---|
| Python | 3.10 以上 | Flask 和 sqlite3 都能兼容 |
| Flask | 3.x 系列 | 安装时用 pip,不需要手动下载 |
| 数据库 | SQLite | Python 内置 sqlite3,不需要额外安装 |
| 编辑器 | VS Code 或任意文本编辑器 | 方便查看文件结构 |
建议使用虚拟环境,避免依赖被装进全局 Python。Windows 下创建和激活虚拟环境的命令:
python -m venv venv venv\Scripts\activate如果 PowerShell 提示“因为在此系统上禁止运行脚本”,不是项目出错。执行下面命令,只修改当前用户策略,然后重新激活:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser如果以后运行 npm 命令也遇到类似提示,通常是同一类 PowerShell 执行策略问题,可以先检查当前策略,再决定是否需要放开。
3.2 先让 AI 输出文件结构,再创建项目目录
项目目录最好提前创建好。可以按这样的结构准备:
todo-system/ app.py requirements.txt templates/ index.html不要把所有文件都放在一个深层次桌面路径里。路径带中文、空格太多,有时会让新手分不清当前终端在哪一层。
3.3 生成主程序 app.py
把下面内容保存为app.py。这段代码由 AI 生成后,经过整理变成了最小可用版本。
from flask import Flask, request, redirect, url_for, render_template import sqlite3 from datetime import datetime app = Flask(__name__) DATABASE = 'todos.db' def get_db(): conn = sqlite3.connect(DATABASE) conn.row_factory = sqlite3.Row return conn def init_db(): with get_db() as db: db.execute(''' CREATE TABLE IF NOT EXISTS todos ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, done INTEGER DEFAULT 0, created_at TEXT NOT NULL ) ''') @app.route('/') def index(): db = get_db() todos = db.execute('SELECT * FROM todos ORDER BY created_at DESC').fetchall() db.close() return render_template('index.html', todos=todos) @app.route('/add', methods=['POST']) def add(): title = request.form.get('title', '').strip() if title: with get_db() as db: db.execute( 'INSERT INTO todos (title, created_at) VALUES (?, ?)', (title, datetime.now().strftime('%Y-%m-%d %H:%M:%S')) ) return redirect(url_for('index')) @app.route('/toggle/<int:todo_id>') def toggle(todo_id): with get_db() as db: db.execute( 'UPDATE todos SET done = 1 - done WHERE id = ?', (todo_id,) ) return redirect(url_for('index')) @app.route('/delete/<int:todo_id>') def delete(todo_id): with get_db() as db: db.execute('DELETE FROM todos WHERE id = ?', (todo_id,)) return redirect(url_for('index')) if __name__ == '__main__': init_db() app.run(debug=True)关键点有两个。
一是init_db()一定要在app.run()前执行,否则第一次访问页面时,数据库里根本没有todos表,会直接报sqlite3.OperationalError: no such table: todos。
二是所有 SQL 操作都用了?占位符,而不是把title直接拼进 SQL 字符串。这是安全的做法,能避免 SQL 注入风险。
3.4 生成页面模板 templates/index.html
在templates目录下新建index.html,写入:
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title>我的待办清单</title> <style> body { font-family: sans-serif; max-width: 600px; margin: 40px auto; } .done { text-decoration: line-through; color: gray; } </style> </head> <body> <h1>我的待办清单</h1> <form action="/add" method="post"> <input type="text" name="title" placeholder="输入新待办" required> <button type="submit">新增</button> </form> <ul> {% for todo in todos %} <li class="{{ 'done' if todo.done else '' }}"> <a href="/toggle/{{ todo.id }}"> {{ '取消完成' if todo.done else '完成' }} </a> <span>{{ todo.title }}</span> <a href="/delete/{{ todo.id }}">删除</a> </li> {% else %} <li>还没有待办,先加一条吧。</li> {% endfor %} </ul> </body> </html>这里用到了 Flask 自带的 Jinja2 模板语法。{% for todo in todos %}是在循环渲染列表,{{ todo.title }}是输出当前待办的标题。模板文件必须放在templates目录里,目录名不能写错,否则 Flask 会报TemplateNotFound。
4. 运行、验证和把报错回喂给 AI
代码文件写好后,进入第一次运行。这一步要有心理准备:不报错是幸运,报错是常态。重点不是追求一次成功,而是学会从错误里找到信息。
4.1 第一次启动:从终端到浏览器
在项目目录下创建依赖清单requirements.txt:
flask然后依次执行:
pip install -r requirements.txt python app.py如果python不行,试py app.py。正常启动后,终端会输出类似Running on http://127.0.0.1:5000。
打开浏览器,访问http://127.0.0.1:5000,就能看到待办清单页面。
如果看到端口被占用,说明 5000 端口已经被其他程序使用。可以把启动命令改成:
python app.py --port 5001更简单的方式是在代码最后改成:
app.run(debug=True, port=5001)4.2 功能验证清单:别只验证“能打开”
很多新手看到页面打开就认为系统完成了。真正要验证的是操作链路。按下面表格逐项点一遍:
| 功能 | 操作 | 预期结果 |
|---|---|---|
| 新增待办 | 输入内容,点击新增 | 页面刷新后列表出现新待办 |
| 标记完成 | 点击“完成” | 文字出现删除线,颜色变灰 |
| 取消完成 | 点击“取消完成” | 删除线消失,颜色恢复正常 |
| 删除待办 | 点击“删除” | 该条记录从列表消失 |
| 数据持久化 | 关闭终端,重新python app.py | 之前加的待办还在 |
如果最后一条不通过,说明数据库没有真正持久化,可能是代码连接了内存数据库,或者数据库文件路径不对。
4.3 报错了不要重新生成,把错误信息喂给 AI
代码运行出问题时,最错误的做法是清空对话重新让 AI 生成一遍。这样做会丢失上下文,AI 又会给你一份看似全新但同问题的代码。
正确做法是把错误信息、执行过的命令、项目结构一起丢给 AI:
我运行 python app.py 后出现这段报错: [在这里粘贴完整报错,不要只粘贴最后一行] 我的环境是 Windows 10,Python 3.11,已经执行过 pip install -r requirements.txt。 项目目录结构如下: todo-system/ app.py requirements.txt templates/ index.html 请帮我解释原因,并给出修改后的最小代码片段。为什么要给完整报错?因为很多新手只复制最后一行No such table: todos,AI 看不出是没建表,还是建表失败。给完整 Traceback 和项目结构后,AI 才能定位问题在哪一层。
5. 常见坑:AI 写系统最容易翻车的地方
用 AI 做系统,翻车点往往不是 AI 能力不够,而是使用方式不对。下面几个坑几乎每个人都会遇到。
5.1 坑一:把 AI 输出的代码当成整个项目
AI 给你一个app.py,你就只建一个文件。运行时报TemplateNotFound,因为你还没建templates目录,也没写index.html。
解决方案是:在提示词里明确要求“按文件结构输出”,并且在本地创建对应的目录。代码只是项目的一部分,文件位置、依赖清单、数据库初始化都是项目成员。
5.2 坑二:提示词太宽泛,AI 反复猜需求
“帮我做一个系统”这类提示词,AI 只能靠猜。猜偏了,你让它改,它改完可能又偏了。
更高效的方式是先花两分钟把需求拆成列表。页面有哪些按钮,数据保存到哪里,用哪个框架,启动命令是什么,这些信息越具体,生成结果的可用性越高。这不是你不会表达,而是你要学会把一个模糊目标变成可执行任务。
5.3 坑三:遇到报错就清空对话重新生成
重新生成会带来新的问题。比如数据库初始化代码和旧版本不一致,导致老数据读不出来;或者模板语法变了,页面样式全乱。
推荐做法是保留对话上下文,直接在后面追加提问。AI 能记录前面的代码,减少重复解释成本。只有当前对话已经彻底混乱,或者你换了一个完全不同的技术方案,才值得开新对话。
5.4 坑四:不检查文件路径和启动目录
很多报错看起来是代码问题,其实是路径问题。
例如你在C:\Users\你\Desktop\todo-system下执行python app.py,但代码里读取的是相对路径todos.db,那么这个数据库文件就会生成在当前目录。如果没先切换目录就直接运行,项目找不到模板,数据库也不知道建在哪里。
检查方式很简单。启动前先确认终端当前路径在项目根目录,再执行命令。Windows 下可以这样查看:
pwd如果路径不对,用cd切换到项目目录,再执行启动命令。
6. 从“能跑”到“可用”:生产环境还要补什么
文章到这里,项目已经在本地跑通了。但“本地能跑”和“生产环境可用”之间还有距离。用 AI 做系统时,不要满足于能打开页面,还要知道一套可用系统在生产环境还需要补哪些东西。
6.1 功能层面至少还要补四件事
学习环境里,代码可以只考虑正常路径。生产环境必须考虑异常和资源限制。
一是输入校验。现在新增待办时只做了空字符串判断,生产环境还要限制长度、过滤危险内容、防止重复提交。
二是异常处理。数据库写入失败、磁盘空间不足、用户频繁点击,都需要有兜底逻辑,而不是直接抛出一个带技术细节的错误页。
三是日志。至少记录启动时间、每次新增或删除操作的时间、关键报错的堆栈。以后排查问题才不会靠回忆。
四是权限。单用户待办系统不需要登录,但一旦多人使用,就必须区分用户身份。AI 能帮你生成登录页面,但你要理解登录背后的会话、密码存储和权限控制。
6.2 部署层面还要注意这些差距
Flask 自带的app.run(debug=True)只适合开发调试。生产环境不能直接这样跑,因为性能差,而且debug=True会暴露详细报错信息,安全风险很高。
常见做法是使用waitress或gunicorn这样更稳定的 WSGI 服务器,再加一层反向代理处理静态资源和请求转发。同时需要配置环境变量,把数据库路径、密钥等敏感信息外置,不能写死在代码里。
对于刚开始练习的人,可以先不考虑完整部署。但至少要知道:生产环境还需要进程守护、日志切割、数据库备份和回滚方案。
6.3 给小白的三条进阶练习建议
第一,把待办清单改成“带登录功能的个人笔记系统”。这一步会让你理解用户体系和权限控制。
第二,让 AI 帮你生成测试用例。不要只让 AI 写功能代码,还可以让它根据当前代码生成pytest测试,然后人工验证这些测试是否合理。
第三,把项目提交到git仓库,每次改动前先确认代码能运行,再提交新版本。这样 AI 改坏时,至少还能回到上一个可用状态。
真正有价值的能力,不是背下 Flask 语法,也不是记住 SQLite 命令,而是能判断 AI 给出的代码离“可用”还差多少,知道下一步该问什么,知道报错从哪里开始查。这条能力一旦建立,后面做成任何系统都会快很多。