前言

今天,让我们从最基本,最初始的地方开始,探讨一个完整,专业的项目到底该如何完成。

思维起手势

第一步:把需求还原成“人话故事”,而不是功能列表

用户给的需求往往是模糊的,比如“我想做一个能自动回答客户问题的系统”或者“我想用AI分析报表”。这个时候,你第一个要做的,不是想“我要用哪个模型”,而是把自己当成用户,走完一整条业务流程。问自己三个问题:

  • 谁在用? 是内部员工、外部客户,还是系统管理员?
  • 在什么场景下用? 是上班时查数据,还是购物时咨询售后?
  • 他最终得到了什么? 是一段回答、一份表格,还是一个操作指令?

你会把这些答案,浓缩成一句极其通俗的“核心用户故事”。比如:

“我们公司的销售总监,每天早上想对着一个对话框说‘给我导出昨天华南区销量前三的产品’,系统就能跑出一份分析简报,并把原始数据留底。”

这句话,就是整个项目的北极星。你之后所有技术决策,都要回来问自己:我这么做,能让这个销售总监更爽吗?如果偏了,就拉回来。

第二步:给AI大模型“定角色”,别让它当万能的神

我们现在要做的是“Python + AI大模型”项目。很多新手最容易犯的错,就是把大模型当成一个全知全能的魔法盒子,什么东西都往里扔。

你要清醒地认识到:在我们这个以FastAPI为骨架的系统里,大模型只是一个“智商极高,但需要精确调度的特殊员工”。

拿到需求后,你必须明确大模型到底扮演哪个角色,这直接决定了你的架构。常见角色有这三种,你辨认一下你的需求属于哪种:

在这里插入图片描述

怎么定角色?

很简单,你就看用户要达到目的,核心的“智力劳动”是谁干的。如果核心是需要理解千奇百怪的自然语言,那大模型是大脑;如果用户指令很明确,只是想让AI帮忙省掉打字和点菜单的麻烦,它就是翻译官。

第三步:画“数据河流图”,在纸上就跑通系统

你现在有了“北极星故事”和“大模型角色”,接下来就是用数据把这两个东西串起来。拿出一张白纸,横着画三道线,分别代表:

  • 用户端(前端界面)
  • 你的FastAPI服务(中间层)
  • 数据与模型(MySQL + 大模型API/本地模型)

然后开始画一个完整的请求循环,比如“用户问:‘上个月哪些产品退货最多?’”:

  1. 用户端 → FastAPI:发了一个POST请求给 /chat 接口,带了这句话和用户I
  2. FastAPI内部(路由→服务层):服务层接到活儿,先想:“这事儿得查数据库,但我不知道该怎么查,需要翻译官”。
  3. FastAPI →大模型(翻译官):把用户的自然语言,连同你预设好的数据库表结构Prompt,一起发给大模型。大模型返回一个结构化的“查询计划”,比如
    {“intent”: “top_returned_products”, “month”: “2026-04”}
  4. FastAPI → MySQL:服务层拿到这个计划,组装出SQL,去MySQL里把退货最多的Top 5产品查出来。
  5. FastAPI →大模型(工匠):把查回来的冰冷数据,甩给大模型:“请把下面这堆数据,用友好的、给老板汇报的口吻写成一段话。数据:[……]”。
  6. FastAPI → 用户端:把大模型生成的分析报告,返回给用户。

落到具体行动上,你的第一个产出应该是一份“一页纸架构”

到现在为止,你没写一行代码,但思路比谁都清晰。把你的思考固化下来,形成一份只有一页纸的文档,它至少要包含:

  • 项目一句话定义:就是上面那个“核心用户故事”。
  • AI角色定义:一句话说清大模型在本项目里的角色(大脑/翻译官/工匠)。
  • 核心API端点:先列最重要的,比如:
    • POST /api/v1/chat (对话接口)
    • GET /api/v1/reports/latest (获取最新报告)
    • POST /api/v1/auth/login (登录)
  • 核心数据表:只列最关键的,比如 users, conversations, sales_data。先不用画满所有的字段
  • 关键流程草图:就是上面那种“数据河流图”的文字简版。

新手容易犯的错误

  1. “我要用最牛的模型!” → 先跑通再优化。模型再牛,一个糟糕的Prompt就能让它变傻子。先用能调用的、成本最低的模型把整个链路跑起来。

  2. “MySQL表我要设计得无比完美!” → 为时过早。根据上面设计的三四个核心表,直接用SQLAlchemy定义好Model,跑起来再说。数据结构的优化,源于真实数据的淬炼,不是凭空想出来的。

  3. “我要学完所有FastAPI知识再动手” → 别。先会用 FastAPI(), @app.post, async def, Pydantic BaseModel 定义请求体和响应体,就足够你完成第一个MVP了。【Minimum Viable Product(最小可行产品)]

举例

我现在要做一个关于健康瘦身管理的网页端项目FitTrack,我们先确定他的的需求和业务流程为

① 用户注册/登录
       ↓
② 进入"健康概览"仪表盘
       ↓
③ 记录今日饮食(摄入多少卡路里)
④ 记录运动(消耗多少卡路里)  
⑤ 记录体重
       ↓
⑥ AI自动生成每日健康评估(基于①②③的数据)
       ↓
⑦ 月底生成月度总结报告
       ↓
⑧ 根据报告定制下个月计划
       ↓
⑨ 循环往复,直到达到目标体重

定故事:给 FitTrack 一个一句话灵魂

“一个关心自己体重的普通人,每天花两分钟记录吃了什么、动了多久、体重多少,系统就自动帮他生成‘今日健康评价’和‘月度总结’,并且告诉他下个月怎么调整能更快达到目标体重。”
这个故事的潜台词是:用户不想懂营养学,不想自己算热量,更不想盯着Excel。所以你的系统,本质上是一个自动化的私人健康顾问。

定角色:AI大模型在这个故事里是谁?

我们对照之前的三角色表,来看 FitTrack 的每一步:

  1. 用户记录饮食/运动/体重:这是数据录入,不需要AI。

  2. AI自动生成每日健康评估:基于今天的数据,给出评价和建议。比如“你今天碳水偏高,但运动消耗不错,继续保持,明天建议多吃点蔬菜”。这里需要理解营养学常识,并生成自然语言。

  3. 月底生成月度总结报告:需要分析一个月的数据趋势,发现规律,并用通俗的语言写出来。

  4. 定制下个月计划:基于月度总结和目标,生成一个可执行的饮食运动计划。

结论很明确:FitTrack里的AI大模型,扮演的是“资深营养师+健身教练”的角色。它是大脑,而且是“基于结构化数据进行推理和表达”的大脑。

更精确地说,它是一个 “架构师型大脑” :它的核心输入不是千奇百怪的开放问题,而是固定结构的用户健康数据。这比开放域聊天好做得多,也更容易控制质量。

因此,AI的角色定位一句话:“利用结构化健康数据,产出个性化评估、总结与计划的智能健康顾问。”

画流程:最重要的“数据河流图”

我们来画一条最核心的业务链路:用户请求生成“今日健康评估”。

在脑子里想像三个泳道:前端、FastAPI服务端、数据与模型层。

[前端] 
  │  用户点击“生成今日评估”
  │  POST /api/v1/assessments/daily
  ▼
[FastAPI 服务端] 
  │  1. 鉴权中间件,拿到 user_id
  │  2. 路由 → 每日评估服务(DailyAssessmentService)
  │
  │  3. 服务先问自己:我要拿哪些原始数据?
  │       - 今日饮食记录 (从MySQL food_logs表)
  │       - 今日运动记录 (从MySQL exercise_logs表)
  │       - 最新体重记录 (从MySQL weight_logs表)
  │       - 用户基础信息与目标 (从MySQL users/profiles表)
  │
  │  4. 拿到四条数据后,组装成一个结构化的上下文对象
  │     例如:{ "user_name":"小明", "goal":"减重5kg", "calories_in":1800, 
  │              "calories_out":400, "weight_trend":"较昨日+0.3kg", 
  │              "food_detail":[{...}], "exercise_detail":[{...}] }
  │
  │  5. 调用大模型服务(ModelService),把上面的上下文 + 精心设计的提示词模板
  │     发给大模型(这里大模型是“大脑”)
  │
  │  6. 收到大模型生成的评估文本,做一层安全/质量过滤
  │     然后把评估结果存入数据库 assessment_reports 表
  │
  │  7. 返回评估结果给前端
  ▼
[数据与模型层]
  MySQL: 提供原始数据,存储生成的报告
  大模型API: 执行自然语言生成任务

定架构:从数据流图画出一页纸架构

  1. 项目一句话定义
    FitTrack 是一个帮助用户通过简单记录饮食、运动、体重,自动获得AI驱动的每日评估、月度总结和下月计划的健康管理平台。

  2. AI角色定义
    AI大模型是“基于用户结构化健康数据的个性化健康顾问大脑”。

  3. 核心API端点(初版)

POST /api/v1/auth/register 用户注册

POST /api/v1/auth/login 用户登录

GET /api/v1/dashboard 获取健康概览仪表盘数据

POST /api/v1/logs/food 记录饮食

POST /api/v1/logs/exercise 记录运动

POST /api/v1/logs/weight 记录体重

POST /api/v1/assessments/daily 生成今日评估

GET /api/v1/assessments/daily 查看历史评估

POST /api/v1/reports/monthly 生成月度总结报告

POST /api/v1/plans/monthly 生成下月计划

GET /api/v1/plans/current 查看当前计划

  1. 核心数据表(极其精简版,只列核心)

users : id, email, password_hash, created_at

profiles : user_id, height, target_weight, weekly_goal, …

food_logs : id, user_id, date, meal_type, food_name, calories, …

exercise_logs : id, user_id, date, exercise_type, duration, calories_burned, …

weight_logs : id, user_id, date, weight

assessments : id, user_id, date, content (AI生成的文本)

monthly_reports : id, user_id, year_month, content

monthly_plans : id, user_id, year_month, content

  1. 关键流程草图
    见上方的“数据河流图”,重点就是:路由→服务层→数据聚合→Prompt组装→调用模型→存储结果→返回。

总结

你拿到需求后,第一个想的不应该是代码,而是:

定故事 → 定角色 → 画流程 → 写一页纸。

文件夹该怎么建

心法

项目结构不是银弹,是“分类收纳箱”。
我们的原则只有一个:当你想找一个东西时,3秒内能知道它大概在哪个文件里。 这就够了。

确认“地基” (.venv)和依赖

  1. 打开 PyCharm,右下角应该能看到 Python 3.11 (fittrack) … 之类,代表虚拟环境已激活。如果没有,手动点一下,选你项目里的 .venv 下的 python。
  2. 打开 PyCharm 底部的 Terminal 标签,你应该能看到命令行前面有 (fittrack) 字样。输入 pip list,确保 fastapi 和 uvicorn 已经躺在里面了。

一些常见文件名到底是装什么的

在这里插入图片描述
作者友情(血泪)提示:一定要学好英语

架构心法

一切架构的本质,是“分层”和“边界”
一个合格健康的项目,不管是后端还是前端,其核心思想只有一个:把不同职责的代码,物理隔离在不同的文件和文件夹里。修改一个功能时,改动的范围尽可能小。 这就是“高内聚,低耦合”的人话解释。
我们分为两个独立王国:后端帝国 和 前端帝国。它们通过 HTTP 协议(JSON 格式)互相派遣使者。

前后端分离 + SPA (单页应用)

fittrack-fullstack/   (你的总项目名)
├── backend/         ← 纯 API,不碰任何 HTML
└── frontend/        ← 纯前端 Vue/React 项目,用 npm run dev 跑

它的特征是:
前端和后端跑在不同的端口(比如前端 localhost:5173,后端 localhost:8000)。
前端通过 fetch/axios 跨域调用后端 API。
前端负责所有的页面渲染和路由跳转,后端只管 JSON 数据。
这也是现代互联网公司99%的项目形态。

第一帝国:FastAPI 后端(纯 API 服务)

它的唯一使命:接收 HTTP 请求,经过一系列处理,返回 JSON 数据。绝不直接碰 HTML 模板。

下面这个结构,是我们从今以后新建任何 FastAPI 项目的万金油模板。只要遵循心法,就能“随心所欲,而不逾矩”。

backend/
├── .env                          # 环境变量,存密钥,永不提交Git
├── requirements.txt              # Python依赖
├── alembic.ini                   # 数据库迁移工具配置
├── alembic/                      # 迁移脚本
│   └── versions/
│
└── app/                          # 主应用包
    ├── main.py                   # 总入口:创建FastAPI实例,挂载路由,注册中间件
    │
    ├── core/                     # [地基层] 与业务无关的全局基础设施
    │   ├── config.py             # Pydantic Settings类,从.env读取所有配置
    │   ├── security.py           # 与安全相关:JWT生成校验、密码哈希
    │   └── database.py           # 异步引擎、会话工厂、get_db依赖
    │
    ├── models/                   # [数据层] SQLAlchemy 模型,纯表结构定义
    │   ├── base.py               # Base = declarative_base()
    │   ├── user.py
    │   └── ...                   # 其他表:product.py, order.py 等
    │
    ├── schemas/                  # [接口层] Pydantic 模型,定义进出数据的形状
    │   ├── user.py               # UserCreate, UserResponse, Token
    │   └── ...                   # 其他:product.py, order.py
    │
    ├── api/                      # [路由层] 接待员,只做参数提取和调用下层,不写业务逻辑
    │   ├── v1/
    │   │   ├── __init__.py
    │   │   ├── router.py         # 聚合所有子路由,统一加 /api/v1 前缀
    │   │   └── endpoints/
    │   │       ├── auth.py       # 登录注册
    │   │       ├── users.py      # 用户CRUD
    │   │       └── ...
    │   └── deps.py               # 共享依赖项:如 get_current_user
    │
    ├── crud/                     # [数据访问层] 只与数据库交互,不关心HTTP
    │   ├── user.py
    │   └── ...
    │
    ├── services/                 # [业务逻辑层] 核心业务、算法、第三方API调用
    │   ├── ai_service.py
    │   └── ...
    │
    └── utils/                    # [工具层] 与业务无关的通用函数
        ├── pagination.py
        └── exceptions.py
后端帝国的铁律:数据流向是单向的

这是依赖倒置原则(Dependency Inversion Principle)的体现:高层模块不依赖低层模块,都依赖抽象

Controller → Service → DAO/CRUD → Database

作者小常识:
什么是"高层"和"底层"?

不是指代码的物理位置,而是指"业务抽象程度"
高层模块 = 接近业务逻辑的代码
底层模块 = 接近基础设施的代码

一个请求的生命周期,必须严格遵循这个链条:
api/endpoints (取参数)
→ 需要鉴权时,调用 api/deps.py 的依赖注入
→ 参数校验后,交给 services/ (处理业务逻辑)
→ 需要数据库时,services/ 调用 crud/
→ crud/ 操作 models/ 定义的表
→ 结果一层层返回到 api/endpoints,用 schemas/ 模型格式化后返回
数据流向:

api/endpoints → deps.py → services → crud → models

铁律:

  • api 绝不直接操作数据库,必须通过 crud。
    【关注点分离(Separation of Concerns)原则】
  • crud 绝不包含业务逻辑,只做增删改查。
  • services 是唯一可以调用多个crud 和外部的服务的地方。
第二帝国:Vue3 前端(纯客户端应用)

它的唯一使命:从后端拿 JSON 数据,经过一系列处理,渲染成用户可以交互的网页。

当你用 npm create vue@latest 创建项目后,把它放在后端旁边,形成我之前说的总项目文件夹:

fittrack-fullstack/          (或用你的项目名)
├── backend/
└── frontend/

以下是frontend/ 里的万金油结构,不管你走到哪一步,谨记心法:

frontend/
├── index.html                 # 单页面应用的HTML挂载点
├── vite.config.js             # Vite 构建配置
├── package.json               # 项目依赖
│
└── src/
    ├── main.js                # 应用入口:创建Vue实例,挂载路由、状态管理
    ├── App.vue                # 根组件
    │
    ├── router/                # [路由] 控制URL与页面组件的映射
    │   └── index.js
    │
    ├── api/                   # [通信层] 对所有后端接口的封装,前端其他部分只能通过这里与后端交互
    │   ├── client.js          # Axios实例,配置 baseURL、拦截器、自动带JWT令牌
    │   ├── auth.js            # 调用 /auth/register, /auth/login 等
    │   ├── users.js
    │   └── ...
    │
    ├── stores/                # [状态层] Pinia/Vuex 全局状态管理
    │   ├── auth.js            # 用户登录状态、JWT令牌
    │   └── ...
    │
    ├── views/                 # [页面层] 与路由一一对应的页面级组件
    │   ├── LoginView.vue
    │   ├── HomeView.vue
    │   ├── UserProfileView.vue
    │   └── ...
    │
    ├── components/            # [组件层] 可复用的UI组件,不包含页面级逻辑
    │   ├── common/            # 通用组件:Navbar.vue, Footer.vue, Loading.vue
    │   └── ...
    │
    ├── composables/           # [逻辑复用] Vue3 组合式函数的封装 (自定义hooks)
    │   └── useAuth.js         # 封装登入登出逻辑
    │
    └── assets/                # [静态资源] 图片、字体、全局样式
        ├── styles/
        └── images/
前端帝国的铁律:数据是单向向下流动的

views/ 页面组件通过调用 stores/ 里的 action 获取数据,或直接调用 api/。
api/ 通过 client.js 里配置好的 axios 实例与后端通信。
获取到的数据在 stores/ 中存储,或直接在组件本地存储。
components/ 只通过 props 接收数据,通过 emits 事件通知父组件,自己不直接操作全局状态或发起 API 请求。
composables/ 将可复用的有状态逻辑抽取出来,让 views 和 components 保持简洁。

需要注意的小tips

一、Git 是什么(通俗版)

Git 是目前全球最主流的代码版本管理工具,简单理解:

给你的代码做「时光机 + 多人协作盘」。

核心两大作用

  1. 版本回溯(时光机)
    每一次代码改动都会记录快照,改错了、功能崩了,可以一键切回之前正常的版本;也能查看每一行代码是谁、什么时候改的。
  2. 多人协作
    团队多人开发同一个项目,所有人基于同一套代码拉取、修改、合并,不会互相覆盖文件。

配套平台(你常听到的)

  • GitHub / Gitee / GitLab:云端代码仓库(线上服务器)
    本地代码 → 推送(Push)到云端仓库 → 队友拉取(Pull)代码。
    日常说「把代码传上去」,就是指推送到云端 Git 仓库

二、核心问题:为什么密码、密钥、.env 绝对不能提交到 Git?

先看你项目里的敏感内容:
数据库账号密码、JWT 签名密钥、API Key(DeepSeek/OpenAI 密钥)、内网地址等。
一旦提交到 Git(尤其是公开仓库),风险极大

1. 一旦上传,永久留痕,删不掉

Git 不是普通网盘:

  • 普通文件:删掉 → 网盘里就没了;
  • Git:所有历史提交记录永久保存

哪怕你后来在代码里删掉密码、重新提交,历史提交快照里依然能完整查到原始密码
任何人拿到你的代码仓库,翻历史记录就能扒出所有明文密钥。

2. 仓库分「公开/私有」,风险等级不同

① 公开仓库(GitHub 公开项目)

任何人都能搜索、下载、查看你的代码。
密码、密钥泄露后:

  • 别人用你的数据库账号登录,篡改/盗取数据;
  • 盗用你的 AI API Key 疯狂调用接口,产生高额账单;
  • 接管你的 JWT 密钥,伪造登录 Token,入侵后台。
② 私有仓库(仅团队可见)

哪怕仓库设为私密,也不建议传:

  • 团队人员流动、账号泄露、仓库意外外泄,都会导致敏感信息流出;
  • 违反安全规范,正规企业开发一律禁止硬编码/提交密钥。

3. 多环境冲突

你的本地数据库密码、测试库密码、线上库密码完全不一样
如果把本地 .env 提交上去,队友拉取代码后,配置和自己本地环境冲突,直接项目启动失败。


三、标准避坑做法

1. 第一步:新建 .gitignore 文件(关键)

项目根目录创建文件,文件名就叫 .gitignore(无后缀)。
作用:告诉 Git:这些文件/文件夹,一律忽略,不要提交、不要上传

你的项目 .gitignore 标准内容
# 忽略环境变量文件(核心!禁止上传 .env)
.env
.env.local
.env.dev
.env.prod

# Python 缓存、虚拟环境、日志、编译文件
__pycache__/
*.pyc
venv/
logs/
*.log

# 编辑器配置(可选)
.idea/
.vscode/

只要写了 /.env,Git 就会彻底无视这个文件,永远不会把它传到云端仓库。

2. 第二步:提供示例模板(队友怎么用?)

因为 .env 被忽略了,队友拉完代码是空的,启动会报错。
解决方案:
新建一份 .env.example 示例文件,这个可以正常提交到 Git。

示例文件 .env.example
# 数据库配置
DB_HOST=127.0.0.1
DB_USER=root
DB_PASSWORD=你的数据库密码

# JWT 配置
SECRET_KEY=你的JWT密钥

# AI 接口
DEEPSEEK_API_KEY=你的API密钥

3. 使用流程(团队统一规范)

  1. 代码仓库里只保留:.env.example(模板,可上传)
  2. 每个人本地:复制一份 cp .env.example .env
  3. 自己修改本地 .env 填入自己的真实密码/密钥
  4. 本地 .env.gitignore 忽略,不会上传

四、区分 3 个容易混淆的文件(你项目必记)

文件 作用 能不能提交到 Git
.env 存放真实密码、密钥、本地配置 ❌ 绝对不能提交(.gitignore 忽略)
.env.example 配置模板、字段说明、占位符 ✅ 必须提交,给队友参考
config.py 配置加载代码(BaseSettings ✅ 正常提交(只是代码,无明文密码)

五、补充:再回头串你整套流程(完整闭环)

  1. 本地开发:
    .env → 存放数据库密码、JWT密钥
  2. config.py
    pydantic-settings 自动读取 .env,业务代码导入使用
  3. Git 控制:
    配置 .gitignore 忽略 .env
  4. 协作/上传:
    只上传代码 + .env.example真实密码留在每个人本地

六、一句话总结

  1. Git = 代码版本管理工具,用来存代码、回溯版本、团队协作;
  2. 密码/密钥不能传 Git:因为 Git 历史记录删不掉,一旦泄露会被盗用、拖垮服务;
  3. 标准解决方案
    真实配置放 .env + 用 .gitignore 禁止上传 + 提交 .env.example 模板给他人使用。
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐