
2025年初,Andrej Karpathy 提出了“Vibe Coding”——一种完全沉浸于 AI 节奏、忽视代码细节、依靠直觉与上下文驱动开发的编程模式。当上下文窗口突破百万Token,传统“逐行调试”的工程模式正在被“意图表达+AI实现”的范式所颠覆。 本文不讲空话。我将通过一个完整的实时数据看板重构项目,带你深入 Vibe Coding 的技术内核,拆解其底层的上下文工程、工具链矩阵,以及最重要的一点:在全面拥抱“氛围”的同时,如何用工程化手段兜底“失控”。
Vibe Coding 常被误解为“随意的、不严谨的瞎写”。但在技术层面,它的本质是 “基于超大上下文的模式匹配与意图推理”。
传统编程是 “指令式” 的:开发者告诉计算机“如何做”(How)。 Vibe Coding 是 “声明式 + 生成式” 的:开发者告诉 AI“要什么”(What)和“为什么”(Why),由模型根据海量开源代码的潜在分布,补全“如何做”。
要实现高效的 Vibe Coding,必须满足三个技术前提:
mypy)和测试用例将其“锁定”为确定性产物。我们以一个典型的 React + FastAPI 实时监控看板为例。传统开发预估工时:40 小时。在纯 Vibe Coding 模式下,实际有效工时:6.5 小时(但后续 Debug 花了 4 小时,共 10.5 小时)。
我没有写任何 package.json 或 requirements.txt,而是直接在 Cursor Composer 中输入:
Prompt 1(初始上下文设定): “我要构建一个实时数据监控看板,技术栈使用 FastAPI 后端 + React + ECharts 前端。后端需要模拟 WebSocket 推送股票/日志数据。请帮我生成完整的项目目录结构、依赖清单,并给出 docker-compose 用于本地一键启动。要求前后端分离,且前端必须支持 Dark Mode。”
AI 的产出(耗时 30 秒):
backend/ 与 frontend/ 完整骨架。docker-compose.yml 挂载热更新卷。技术深潜点: 在这个阶段,AI 调用了系统内置的“最佳实践模板”。关键代码在于 FastAPI 的 WebSocket 管理器,AI 默认使用了 asyncio.Queue 来广播消息,这为后续的背压问题埋下了伏笔。
# AI 初始生成的 WebSocket 核心 (backend/app/ws/manager.py)
class ConnectionManager:
def __init__(self):
self.active_connections: List[WebSocket] = []
self.send_queue = asyncio.Queue()
async def broadcast(self, message: str):
# 简单实现,直接将消息放入队列
await self.send_queue.put(message)
async def _send_loop(self):
while True:
message = await self.send_queue.get()
# 遍历连接发送——此处存在潜在的性能陷阱
for connection in self.active_connections:
await connection.send_text(message)Vibe 模式的关键在于“不提具体文件名,只提感受”。
Prompt 2(发现问题与演进): “现在的数据推送频率很高,我看前端渲染有明显卡顿。你能不能分析一下后端和前端代码,找到瓶颈并自动加上节流/缓存机制?”
AI 的推理过程(Chain of Thought):
_send_loop 中的 for 循环是串行的,如果一个客户端接收慢,会阻塞整个广播队列(Head-of-Line blocking)。useEffect 中 setState 导致了高频重绘。AI 产出的优化代码(技术核心):
# AI 重构后的广播机制 - 使用 asyncio.gather 并发发送
async def broadcast(self, message: str):
# 1. 使用列表推导式创建并发任务
tasks = [
connection.send_text(message)
for connection in self.active_connections
]
# 2. 增加错误隔离,避免一个连接断开影响全局
results = await asyncio.gather(*tasks, return_exceptions=True)
# 3. 自动清理断开的连接 (Vibe 模式下 AI 主动加入的鲁棒性逻辑)
for i, result in enumerate(results):
if isinstance(result, Exception):
self.active_connections.pop(i)// AI 重构后的前端 - 使用 requestAnimationFrame 聚合更新
// 这是 Vibe 模式下“意图驱动”的典型产物,我没有提 RAF,AI 自行补充了
const useThrottledData = (data: any) => {
const [displayData, setDisplayData] = useState(data);
const rafRef = useRef<number | null>(null);
useEffect(() => {
if (rafRef.current) return;
rafRef.current = requestAnimationFrame(() => {
setDisplayData(data);
rafRef.current = null;
});
return () => {
if (rafRef.current) cancelAnimationFrame(rafRef.current);
};
}, [data]);
return displayData;
};在开发进入第 4 小时时,项目开始变得混乱。这恰恰是 Vibe Coding 最考验工程师内功的地方。
场景还原:
我要求 AI“增加用户认证(JWT)并接入 Redis 缓存”。由于之前的 WebSocket 和 HTTP 路由代码分散在不同文件中,AI 在修改时出现了“幻觉延续”——它在 auth.py 中引入了一个并不存在的 websocket_dependency,导致整个项目无法启动。
传统方案: 我手动修改引用。 Vibe 方案(更高阶的 Prompt 工程):
Prompt 3(注入确定性约束): “启动报错
ImportError: cannot import name 'websocket_dependency'。请不要直接修改auth.py,请先画出当前项目的依赖关系图(Mermaid),找出循环引用点,然后设计一个独立的dependencies.py统一管理所有 DI,最后再重构代码。”
AI 的产出:
它不仅修复了错误,还生成了一个 dependencies.py,并利用 Python 的 functools.lru_cache 实现了依赖的单例模式。
# backend/app/core/dependencies.py
from functools import lru_cache
from fastapi import Depends
from .config import Settings
from .redis_client import RedisClient
from .auth_handler import AuthHandler
@lru_cache()
def get_settings() -> Settings:
return Settings()
def get_redis(settings: Settings = Depends(get_settings)) -> RedisClient:
return RedisClient(settings.redis_url)
def get_auth_handler(
settings: Settings = Depends(get_settings),
redis: RedisClient = Depends(get_redis)
) -> AuthHandler:
# 显式的依赖注入,解决了循环引用问题
return AuthHandler(settings, redis)Vibe Coding 最怕的不是 Bug,而是“你不知道 AI 刚才改了什么”。为了让思否的读者能真正落地这套方案,我整理了一套 “.vibe 工程规范”。
在项目根目录放置一个 .vibe/rules.md 文件。这类似于 .cursorrules,但更侧重于架构。
策略:每次对话开始时,强制要求 AI 读取该文件。
# .vibe/rules.md (强制架构约束)
1. **数据流向**:所有数据必须经过 Service -> DTO -> ViewModel 转换,严禁直接将 ORM Model 返回给前端。
2. **异步隔离**:WebSocket 和 HTTP 路由必须使用不同的 `APIRouter` 前缀。
3. **类型优先**:所有 Python 函数必须包含完整的 Type Hints,所有 React Props 必须定义 Interface。
4. **测试锁定**:对于 `utils/` 目录下的纯函数,AI 在生成代码后必须自动生成对应的 `pytest` 单元测试。Vibe Coding 会生成大量代码。必须要求 AI 使用 Conventional Commits 规范,并且每次只做一件事。
Prompt 4(提交控制): “请帮我实现日志持久化功能。要求:完成该功能后,请使用
git add . && git commit -m "feat(logging): add structured JSON logging with rotation"进行提交,并在终端输出 diff 摘要。”
技术价值:这让每个“Vibe 瞬间”都变成了可回滚的原子操作。当你发现 AI 进入幻觉循环时,可以直接 git reset --hard HEAD~1,回到稳定状态。
现代 Vibe Coding 工具链(如 Continue.dev 或 Cursor)支持 MCP(模型上下文协议)。我们可以开启一个 “LSP 服务端” 的 MCP。
实操逻辑: AI 写完代码 -> LSP 服务端检测到语法错误 -> 错误信息通过 MCP 回传给 AI -> AI 自动修正代码。
这项技术彻底解放了双手。在测试中,AI 自己生成了一个错误的 TypeError,然后 LSP 捕获到 pylint 报错,AI 读取报错后自我修正,整个过程无需人工干预,耗时仅 45 秒。
当项目规模超过 3000 行代码时,AI 的上下文开始“稀释”,经常忘记文件头部的 import。
高阶技巧:使用 Tree-sitter 结构化摘要 不要直接把整个文件发给 AI,而是利用 AST(抽象语法树)提取函数签名。
# 自定义脚本 - 生成 AI 友好的项目索引
import ast
import os
def generate_ai_index(filepath):
with open(filepath, 'r') as f:
tree = ast.parse(f.read())
# 提取所有 FunctionDef 和 ClassDef 的名称及行号
return {
"functions": [n.name for n in tree.body if isinstance(n, ast.FunctionDef)],
"classes": [n.name for n in tree.body if isinstance(n, ast.ClassDef)]
}
# 将这个索引作为系统前缀放在每次 Prompt 的 System Message 中
# 告诉 AI:“当前项目包含这些函数,如果你需要具体实现,请询问我读取对应文件。”通过这种方式,即使上下文窗口有限,AI 也能保持对全局架构的“方位感”。
维度 | 传统编码 | Vibe Coding (无工程化) | Vibe Coding + 工程化兜底 |
|---|---|---|---|
原型产出速度 | 基准 | +400% | +350% |
运行时 Bugs | 基准 | +200% (指数增长) | +20% (线性可控) |
代码可维护性 | 高 | 极低(垃圾代码) | 高(AI 遵循 Rules.md) |
开发者疲劳度 | 极高(体力活) | 极高(Debug 脑力活) | 极低(专注架构决策) |
Vibe Coding 不是去工程化,而是将“工程化思维”前置到了 Prompt 设计阶段。
.vibe/rules.md 和 MCP 配置来组织 AI 的思维。未来的顶级开发者,不再是打字最快的人,而是 “上下文架构师” 。他们懂得如何用自然语言构建高约束性的“思维栅栏”,让 AI 在栅栏内肆意狂奔,却始终无法跑出安全的边界。
如果你正在尝试 Vibe Coding,请记住我今天分享的这条铁律: “永远不要问 AI '你怎么实现的',而要告诉 AI '我们的架构约定是什么'。”
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。