鱼皮AI导航
鱼皮AI导航
  • 主页
  • 社区
  • AI工具
  • AI知识库
  • AI提示词
  • MCP
  • Skills
  • AI学习资源
  • AI资讯
  • GitHub开源
登录/注册
站长:程序员鱼皮 老鱼简历 商务合作 增值电信业务经营许可证
2026 鱼皮AI导航 | 沪ICP备19026706号-6
19
1
13

使用 Cursor 从 0 到 1 开发一个全栈 chatbox 项目

luckySnail
luckySnail
2025-05-23 09:52
阅读 2483
luckySnail
2025-05-23 09:52
阅读 2483

大家好,我是 luckySnail,你肯定用过 AI 聊天工具。例如: Gemini,ChatGPT,claude AI 等产品,我们通过它们的 web 网站或者手机应用提出问题,得到答案。在之前如果你想要构建一个这样的 AI 聊天应用程序,是需要大量时间才能开发出来,但是接下来,我将使用 cursor + vercel 的 Next.js 和 ai-sdk 快速搭建属于你自己的 AI chat 工具,通过这篇文章你可以看到 AI 强大的辅助编程能力和 vercel 家超赞的工具!同时也能了解如何使用 AI 从 0 到 1 构建一个 web 应用,先看一下最终的产品: image.png

如果你想直接看源码: https://github.com/coderPerseus/easyChat 我还使用 deepwiki 生成了对应的项目文档: https://deepwiki.com/coderPerseus/easyChat

环境准备

在正式开发前,你的设备需要有如下环境:

  • Node >= 18.18,pnpm 作为依赖管理工具
  • postgreSQL ,可以是本地或者在线
  • Curosr ,用作 AI 辅助编程
  • chrome 游览器,其他游览器也可

你需要具备的知识:

  • 前端基础
  • 数据库基础
  • 计算机网络基础
  • 熟悉 React 开发 当然,你还需要有良好的软件开发素养,否则你会发现写的代码不好维护,或者不易理解

项目初始化

在真正开发项目之前,让我们先进行需求分析 和 技术选型

需求分析

  • 聊天页面开发(基础能力)
    • 包含提示的输入框和发送 / 停止按钮
    • 实现一个聊天区域来显示对话记录,一个列表展示会话历史
    • 开发 /agent API 来处理请求
    • 确保每个对话的数据都被持久存储
    • 通过流式传输返回所有结果
  • 高级能力
    • 增强聊天组件,支持 markdown 渲染、自动滚动、图片上传等
    • 实现函数调用,例如检索当前时间

技术选型

根据需求,我选择了我喜欢的并且也是主流的技术:

  • Next.js 作为全栈开发基础框架
  • hono.js 作为后端框架,优化在 Next.js 中后端开发体验
  • PostgreSQL 作为数据库存储对话记录
  • DrizzleORM 作为 ORM ,更为便捷和高效的方式与数据库进行交互
  • shadcn/ui 作为 UI 组件库,tailwindcss 作为 css 框架
  • Vercel AI SDK 快速开发 AI 相关的服务,如果你也在开发 AI 相关的服务,强烈推荐使用它,能帮你减少 80% 的工作
  • Biome 进行代码格式化和检测(代替 ESLint + Prettier),需要你安装 Biome 插件哦
  • zod : TypeScript 优先的数据验证库

对了,我们使用 Github 进行版本控制,维护代码。使用 vercel 进行项目部署上线。

初始化

下面进行初始化项目,初始化项目完成后,我们应该就可以进行业务开发

1)根据 Next.js 官方文档我们创建一个 Next.js 项目:

▼
bash
复制代码
npx create-next-app@latest

image.png 2)下面,根据官方文档集成 shadcn/ui:

▼
bash
复制代码
pnpm dlx shadcn@latest init pnpm dlx shadcn@latest add button

image.png 然后尝试使用 Button 按钮,发现集成成功!

注意这里有一个小细节就是我在入口的 layout 组件为 body 标签添加了 suppressHydrationWarning ,作用是:抑制 React 在客户端和服务器端渲染不匹配时产生的警告信息,这在处理动态内容(如日期、时间等)时特别有用,因为这些内容在服务器端和客户端可能会有差异。

image.png 3)下面集成 Biome,保证相关代码风格一致

▼
bash
复制代码
pnpm i @biomejs/biome -D

然后在 package.json 添加对应的脚本:

▼
json
复制代码
{ "scripts": { "lint": "next lint", "format": "biome format --write .", "lint:biome": "biome check --apply.", } }

下面设置编辑器的 Format Document With ,选择 Configure Default Formatter 设置为 Biome。现在你的项目就又了格式化能力,你还可以在 git 提交的链路上进行预先 format 和 lint 等操作,保证提交的代码是格式化的。 4)下面继续集成 hono.js,我参考了文章思路: https://kuizuo.cn/blog/nextjs-with-hono/ 。首先根据官方文档进行安装

▼
bash
复制代码
pnpm i hono # 让 hono 接管所有接口服务 mkdir -p "src/app/api/[[...route]]" && touch "src/app/api/[[...route]]/route.ts"

下面,开发 route.ts 内容,让 hono 来接管接口服务

▼
ts
复制代码
// src/app/api/[[...route]]/route.ts import api from "@/server/api"; import { handle } from "hono/vercel"; const handler = handle(api); export { handler as GET, handler as POST, handler as PUT, handler as DELETE, handler as PATCH, };

因为 Next.js 会自动扫描 app 下的文件夹进行热更新,所以我们可以将服务端代码放在根目录的 server 文件夹下(其实你可以使用任何名称),这里写我们所有的服务端逻辑和接口,下面初始化一下服务端的基础逻辑, 5)创建自定义校验器,它的作用是进行请求数据验证的工具函数,确保数据符合预期的格式和类型规范,并提供类型安全的验证结果

▼
ts
复制代码
// src/server/api/validator.ts import type { Context, MiddlewareHandler, Env, ValidationTargets, TypedResponse, Input, } from "hono"; import { validator } from "hono/validator"; import type { z, ZodSchema, ZodError } from "zod"; export type Hook< T, E extends Env, P extends string, Target extends keyof ValidationTargets = keyof ValidationTargets, // biome-ignore lint/complexity/noBannedTypes: <explanation> O = {} > = ( result: ( | { success: true; data: T } | { success: false; error: ZodError; data: T } ) & { target: Target; }, c: Context<E, P> ) => | Response | void | TypedResponse<O> // biome-ignore lint/suspicious/noConfusingVoidType: <explanation> | Promise<Response | void | TypedResponse<O>>; type HasUndefined<T> = undefined extends T ? true : false; export const zValidator = < T extends ZodSchema, Target extends keyof ValidationTargets, E extends Env, P extends string, In = z.input<T>, Out = z.output<T>, I extends Input = { in: HasUndefined<In> extends true ? { [K in Target]?: K extends "json" ? In : HasUndefined<keyof ValidationTargets[K]> extends true ? { [K2 in keyof In]?: ValidationTargets[K][K2] } : { [K2 in keyof In]: ValidationTargets[K][K2] }; } : { [K in Target]: K extends "json" ? In : HasUndefined<keyof ValidationTargets[K]> extends true ? { [K2 in keyof In]?: ValidationTargets[K][K2] } : { [K2 in keyof In]: ValidationTargets[K][K2] }; }; out: { [K in Target]: Out }; }, V extends I = I >( target: Target, schema: T, hook?: Hook<z.infer<T>, E, P, Target> ): MiddlewareHandler<E, P, V> => // @ts-expect-error not typed well validator(target, async (value, c) => { const result = await schema.safeParseAsync(value); if (hook) { const hookResult = await hook({ data: value, ...result, target }, c); if (hookResult) { if (hookResult instanceof Response) { return hookResult; } if ("response" in hookResult) { return hookResult.response; } } } if (!result.success) { throw result.error; } return result.data as z.infer<T>; });

6)创建错误处理文件,给到客户端更好的错误提示:

▼
ts
复制代码
// src/server/api/error.ts import { z } from "zod"; import type { Context } from "hono"; import { HTTPException } from "hono/http-exception"; import type { ContentfulStatusCode } from "hono/utils/http-status"; export class ApiError extends HTTPException { public readonly code?: ContentfulStatusCode; constructor({ code, message, }: { code?: ContentfulStatusCode; message: string; }) { super(code, { message }); this.code = code; } } export function handleError(err: Error, c: Context): Response { if (err instanceof z.ZodError) { const firstError = err.errors[0]; return c.json( { code: 422, message: `\`${firstError.path}\`: ${firstError.message}` }, 422 ); } /** * This is a generic error, we should log it and return a 500 */ return c.json( { code: 500, message: "服务端错误, 请稍后再试。", }, { status: 500 } ); }

下面我们创建我们的第一个接口,验证 honojs 是否引入成功:

▼
ts
复制代码
// src/server/api/routes/hello.ts import { Hono } from "hono"; const app = new Hono().get("/hello", (c) => c.json({ message: "Hello, luckyChat" }) ); export default app;

7)最后,开发入口文件:

▼
ts
复制代码
// src/server/api/index.ts import { handleError } from "./error"; import { Hono } from "hono"; import helloRoute from "./routes/hello"; const app = new Hono().basePath("/api"); app.onError(handleError); const routes = app.route("/", helloRoute); export default app; export type AppType = typeof routes;

现在我们不仅有了接口,还有了服务端接口的类型声明,我们可以非常方便的在客户端进行类型安全的接口请求,我们不需要写路由,也不需要写类型相关的内容,真的是 amazing,我们赶紧在客户端调用第一个接口吧!在调用接口前, 8)我们先封装一个 fetch 方法:

▼
ts
复制代码
// src/lib/fetch.ts import type { AppType } from "@/server/api"; import { hc } from "hono/client"; import ky from "ky"; const baseUrl = process.env.NODE_ENV === "development" ? "http://localhost:3000" : process.env.NEXT_PUBLIC_APP_URL; export const fetch = ky.extend({ hooks: { afterResponse: [ async (_, __, response: Response) => { if (response.ok) { return response; // biome-ignore lint/style/noUselessElse: <explanation> } else { throw await response.json(); } }, ], }, }); export const client = hc<AppType>(baseUrl as string, { fetch: fetch, });

ky 库是一个基于浏览器原生 Fetch API 的轻量级HTTP客户端库,提供了更简洁友好的接口,使用它更好的与 honojs 集成,这里我们使用 hc 和 AppType 创建了一个安全的接口请求方式:

▼
tsx
复制代码
// src/app/page.tsx import { Button } from "@/components/ui/button"; import { Heart } from "lucide-react"; import { client } from "@/lib/fetch"; async function getData() { try { const res = await client.api.hello.$get(); if (!res.ok) { // This will activate the closest `error.js` Error Boundary throw new Error("Failed to fetch data"); } return res.json(); } catch (error) { console.error("获取数据失败:", error); return { message: "AI 助手" }; } } export default async function Home() { const { message } = await getData(); return ( <div> <div>{message}</div> <Button> <Heart className="mr-2 h-4 w-4" /> lucky Snail </Button> </div> ); }

当我们在使用 client 的时候它会进行代码提示告诉你目前可以使用哪些接口,并且在后面我们可以借助 InferResponseType 和 typeof 等 ts 关键字来使用接口对应的 ts 类型,我们只需要在服务端定义好类型声明,在客户端直接消费即可 👍。

9)下面进行最重要的一步,也就是数据库初始化,有开发经验的应该都知道数据库设计的好,可以大大降低系统复杂度,减少不必要的代码,这么重要的事情肯定是需要 AI 的参与的,我们把需求给到 AI,然后让 AI 帮忙进行初步数据库设计,下面在 cursor 中进行 ask:

▼
text
复制代码
提示词:现在集成 DrizzleORM, and AI SDK.使用 postgreSQL 作为数据库,驱动使用 postgres,数据库名字叫 chatAI ,数据库就一张表,存储 AI 对话记录,设计良好的数据库表结构,最后开发 /agent API 来处理聊天请求,这里使用大模型为 Deepseek ,大模型的 key 存在 环境变量的 DEEPSEEK_API_KEY ,数据库集成参考 @https://orm.drizzle.team/docs/get-started-postgresql ,先梳理需求,然后一步步进行实现

AI 给到的数据库结构如下:

▼
ts
复制代码
// src/lib/db/schema.ts import { pgTable, serial, text, timestamp, varchar } from 'drizzle-orm/pg-core'; // 聊天消息类型 export const chatMessages = pgTable('chat_messages', { id: serial('id').primaryKey(), sessionId: varchar('session_id', { length: 255 }).notNull(), role: varchar('role', { length: 50 }).notNull(), // 'user' 或 'assistant' content: text('content').notNull(), createdAt: timestamp('created_at').defaultNow().notNull(), }); // 会话信息 export const chatSessions = pgTable('chat_sessions', { id: serial('id').primaryKey(), sessionId: varchar('session_id', { length: 255 }).unique().notNull(), title: varchar('title', { length: 255 }), createdAt: timestamp('created_at').defaultNow().notNull(), updatedAt: timestamp('updated_at').defaultNow().notNull(), });

这里 AI 帮我们创建好了数据库的表结构,它能理解需求,并给出合理的数据库设计:

  • chat_sessions 表:存储聊天会话信息
  • chat_messages 表:存储聊天消息 还帮我们在 package.json 添加了生成和运行迁移的脚本,我们在 env 配置到 DATABASE_URL,执行脚本即可初始化数据库

现在我们完成了项目初始化,我们可以使用 cursor 提供的 /generate Cursor Rules 来生成项目开发指导,在后面业务能力开发中,我们每次都携带上这条 rules ,它能帮 AI 更好的生成内容 image.png

现在已经搭建好了前端和后端基础能力,并且生成了项目开发的 rules ,下面就全部交给 AI 来进行业务开发,我们只需要做一个合格的测试和 code review 就好了!

核心能力开发

一个聊天应用最核心的就是输入提示词 => AI 大模型响应内容 => 展示内容 => 继续对话

1)开发 chat,提示词如下

下面 @project-structure.mdc 就是我们生成的项目开发 rules

▼
text
复制代码
@project-structure.mdc 使用 ai-sdk 开发 /agent API 来处理聊天请求,遵循 RESTful API 风格,这里使用大模型为 Deepseek ,大模型的 key 存在 环境变量的 DEEPSEEK_API_KEY ,然后在开发对应的 chat 页面,一个输入框,右侧有发送和暂停按钮,支持接收用户的输入,支持发送和停止能力,这里使用 @ai-sdk/react 快速进行开发,需要流式输出 AI 生成内容。代码组件化,模块化,尽可能使用 shadui/cn 组件开发,先梳理需求,然后一步步进行实现

AI 可能需要比较漫长时间完成工作,在这个过程中,我们可以思考下一个提示词,在 AI 生成完成后,我们需要进行检查和修复 bug,当然你是可以借助 AI 来 fix error。这里需要额外注意的是当我们 chat 中断的时候应该把已经生成的内容进行存储数据库

2)开发创建新会话能力,支持会话缓存到本地

▼
text
复制代码
@project-structure.mdc 支持创建新会话,并且会话 id 存储 localStorage ,在页面刷新的时候会话 id 依然存在,注意点击停止需要把当前会话进行存储

3)开发历史会话列表展示,支持切换会话

▼
text
复制代码
@project-structure.mdc 开发历史对话记录功能,先进行接口开发,这里两个接口:获取所有会话列表和获取指定 id 的会话信息,前端需要将会话列表封装为单独组件,点击会话列表项能进入该对话,数据接口逻辑使用自定义 hooks,保证代码清晰易理解。 注意客户端需要使用封装的 fetch 导出的 client 进行接口请求

4)支持 markdown 渲染 AI 生成的内容,优化页面布局 UI,支持内容自动滚动底部 上面完成后,我们有了基本的 chat 功能页面,但是可能这时候页面比较丑不太美观,现在进行优化

▼
text
复制代码
@project-structure.mdc 你是资深 UI 设计师,现在进行项目优化: 1,实现 markdown 渲染流式内容。添加在对话中自动滚动到底部的能力 2. 优化目前的页面 UI,页面布局为左边的侧边栏,展示历史记录和新对话能力都放在左边,当屏幕宽度小于 tailwindcss 的 lg 的时候就不展示侧边栏,右侧对话框 UI ,也需要进行优化,注意不要新增元素和修改逻辑,仅仅是对元素布局和 UI进行优化,参考优秀的 chatbox UI 设计

5)支持 function call 能力,获取当前时间

▼
text
复制代码
@project-structure.mdc @web 参考文档支持 function call 能力,以获取最新时间为例

优化

如果你做到这里,相信你的项目肯定还有一些 bug 和 UI 细节需要进行优化,你可以和 AI 一起进行优化,给大家看一下我和 AI 的 chat image.png 不断的修复和优化,最终我的 chatbox 就出现啦! image.png 你打几分呢?

总结

  1. AI 目前编程能力已经超过 90% 的工程师了,它在开发功能安全性和兼容性考虑上十分的全面,但是它也有能力边界,在面对复杂系统,奇怪的需求上是不如人的。所以程序员以后更多是做决策,做 AI 与需求的桥梁,通过我们的经验和直觉去选择接受还是拒绝 AI 的生成
  2. 日常 AI 编程开发中,推荐使用方式为 gemini 做设计和文档类工作,写代码部分交给 claude
  3. 需要我们能够合理的进行模块拆分,能够识别 AI 代码是不是合理的
  4. 系统设计是 AI 时代程序员的必须要提升的技能,推荐一本书《软件设计的哲学》第二版
  5. 知识广度,全栈能力对前端有很大的帮助,借助 AI 快速将想法变成现实是程序员的红利
  6. 持续学习,跟进最新的 AI 是保证自己有竞争力的关键
  7. Vibe Coding 必然会成为新的编码方式,纯手工编程必然会像 php 一样成为历史
  8. 目前来看,编程智能体(Agent)真的很成功,让我这种普通人能够快速 开发出产品。

参考:

  1. https://claude.ai/chat/fd4c29a3-3b5c-4965-9670-4380dcc28f98
  2. https://www.youtube.com/watch?v=tlrf4lu8Myc
  3. https://bigbang.easykol.com/search/following?platform=TIKTOK&url=https://www.tiktok.com/@meditationbuddhism
AI
前端
后端
AI编程
19
13
分享
操作
评论
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片

目录

🔥 热门文章
1
离谱,DeepSeek 崩了 5 小时,大家却喊:梁圣恩情还不完??
430
2
DeepSeek 全新模型发布,性价比最高的一集!
390
3
B 站上 DeepSeek 闹鱼灾了,我发起《大肥鱼清除计划》!
380
4
自己学习ai,直接买cursor 的套餐,还是买gpt 或者claude 的套餐?
360
5
又一个国产版 Codex 神器,也来卷办公了!
330
6
day3-如何写出一个高质量的 Skill(组内分享) 高质量 Skill 不是“一个调得很顺的巨型 Prompt”,而是一个可验证、可回归、可维护的能力包。 先定义“什么算好”,再实现“怎么做好”。评估体系先于 Skill 本身成型。 下面用“故障诊断 Markdown 转 YAML”作为例子,但方法是通用的。 --- 一、先想清楚:Skill 到底是什么 一个 Skill 至少包含四部分: 部分 作用 接口 输入什么、输出什么、边界在哪 流程 分几步做,每步的产物是什么 规则 硬约束、经验规则、失败模式 降级策略 不确定时怎么办,而不是硬编一个看似合理的结果 高质量 Skill 的共同点:职责单一、接口清晰、规则可定位、输出可验证。 反例:把几十条经验全塞进一个主 Prompt,改一条规则要重调整个 Prompt,评估时也不知道是哪条规则退化。 --- 二、核心方法:先建评估,再写 Skill 不要先写转换器再补测试。正确顺序是: 1. 定义输出契约:什么算合法、什么算合格; 2. 建金标准集:一小批人工认可“可放行”的样本; 3. 先写评估 Skill:让它在金标准集上跑出基线; 4. 再迭代生成 Skill:每次修改跑同一套评估,无退化且目标维度提升才算正向。 这就是评估驱动开发:评估是 Skill 的单元测试,金标准集是回归锚点。 --- 三、评估 Skill:三层门禁,逐层递进 前一层不过,后一层不跑。每层留可追溯证据。 第 1 层:确定性硬门禁 用解析器、Schema、校验器完成,不消耗模型成本。 · 输出可解析; · 必填字段齐全,类型/枚举合法; · 引用目标存在,无悬空引用、无不可达节点; · 关键路径至少有一条能到达预期出口。 不通过直接打回。 第 2 层:语义断言 用脚本 + 结构遍历检查“逻辑对不对”,仍然保持确定性。 通用检查项: · 覆盖率:源材料里的关键步骤、分支、条件,输出里是否都有对应? · 完整性:每个判断节点是否都有明确出口?有没有死胡同? · 可达性:每条路径是否都能到达预期终点?有没有无出口循环? · 顺序与依赖:有先后依赖的操作,是否保留了顺序?有没有被拍平成无序列表? 例子:故障诊断转换中,检查“每个判断项是否有是/否/异常出口”“每条路径是否能到根因”。 第 3 层:LLM-as-Judge 只处理解析器表达不了的维度:忠实度、完整性、可执行性。 但 Judge 会漂移,不能单独放行,必须建立在第 1、2 层之上。Judge 的 Prompt、rubric、模型版本都要版本化,换模型必须用金标准集重新校准。 通用 Judge 维度: 维度 问什么 忠实度 输出是否忠实源材料意图?有没有自行发明内容? 完整性 关键步骤、条件、证据是否保留?隐式知识有没有被压成空话? 收敛性 输出是否仍指向原目标,而不是发散? 可执行性 下游不依赖源材料能否直接使用? --- 四、金标准集:回归测试的锚点 不需要一开始就标注几百份。用已认可的样本当种子,扩到 15~30 份,覆盖失败模式而非随机抽样: · 完整正例:典型流程; · 边界/异常分支:异常路径、循环、前置失败回退; · 已知易错模式:实际踩过的坑; · 留出集:不参与调优,只用于最终验收,防过拟合。 金标准不需要完美,只需要当前标准下认可可放行。 回归指标:关键路径用 pass^k(k 次全过),稳定性用 pass@k。 --- 五、工程约束:让批量产出可重放 · 幂等:同输入 + 同 Skill 版本 + 同规则 → 输出一致,否则无法判断变好是 Skill 改了还是随机波动; · 隔离不阻断:单份失败进隔离队列,记录失败层和原因,不阻塞其余; · 版本绑定:规则、rubric、金标准集进 Git;每份报告绑定“源版本 + 生成 Skill 版本 + 评估 Skill 版本 + Judge 模型版本”; · 抽样人工复核:Judge 临界样本 + 易错模式,人工抽检结果反过来校准 rubric。 --- 六、Skill 本身怎么写 · SKILL.md 控制篇幅,写清:输入约定、输出契约、分步流程、硬规则、降级策略; · 经验规则放 references/ 或 rules/,按失败模式分类,不要全塞进主 Prompt; · 不确定时标 needs_review: true,不要硬编看似合理的结果; · 迭代由评估报告驱动:报告告诉你哪层挂了、哪类失败模式,你改对应规则文件,而不是漫无目的调 Prompt。 --- 七、落地顺序(不要反过来) 1. 固化输出契约:Schema + 结构约束; 2. 建金标准集:从已认可的 + 最易出错的样本开始; 3. 先写评估 Skill:跑出基线报告; 4. 再迭代生成 Skill:每次修改对比逐项通过率,无退化且目标提升才算正向; 5. 批量运行 + 隔离回放:失败进队列,结束后人工抽检; 6. 评估 Skill 自身版本化:换 Judge 模型必须重新校准。 --- 八、给组员的三条硬要求 1. 不许凭感觉说“变好了”:每次修改必须附评估报告对比,逐项通过率说话。 2. 不许跳过确定性门禁直接看 Judge 分数:前两层挂了,Judge 分数没有意义。 3. 不许把规则堆进主 Prompt:规则按失败模式分文件,评估报告要能定位到具体文件。 --- 一句话收尾 生成 Skill 决定“能不能做”,评估 Skill 决定“敢不敢用”。 先让评估体系站稳,再让生成器迭代。这样交付的不是一堆“看起来还行”的产出,而是一套可证明、可回归、可交接的 Skill 质量体系。
310
7
AI 越强,被它拒绝的代价就越大 我有时候会想:AI 越来越厉害之后,有些事情,会不会反而越来越难做? 这个想法看起来有点矛盾。AI 明明在降低门槛,让不会写代码的人做出软件,让不会画画的人生成图片,让一个人完成过去需要整支团队才能完成的工作。但今天用 Codex 的时候,AI 拒绝帮我编写 SQL 注入的请求体,而那还是我有源码、在本地跑测试的情况。那么,往后是否只会更难? 我们假设某一天,AI 说:「这个请求违规,我不能帮助你。」到那个时候,你还有多少能力,能绕过它,把事情做完? 这里的「违规」需要打个引号。平台的规则、模型的判断、法律的要求,以及一件事实际有没有造成伤害,彼此之间并不总是画得上等号。一个请求可能确实危险,也可能只是缺少上下文被误判,或者恰好落在某家公司的限制范围里。 无论是哪种情况,随着我们越来越依赖 AI,这句拒绝都可能变得越来越贵。 今天,一个程序员让 AI 帮忙写代码,AI 拒绝了,他大概率还有别的办法:查文档、找开源项目、问同行,或者自己写。麻烦一点,慢一点,但路还在。 可如果十年之后,大部分程序都由 AI 完成,情况就不一样了。 很多人从接触编程的第一天起,就习惯了描述需求、等待生成、运行结果、继续迭代。他们能做出相当复杂的产品,却未必经历过独立处理底层问题的训练。平时,这种能力结构完全够用,效率甚至更高。只有 AI 拒绝的时候,他们才会发现:平常被省掉的那段学习过程,恰好是此刻最需要的东西。 到那时,一次拒绝的成本,可能就从「今晚多花两个小时」,变成「先花半年学会这门技术」。 拿 SQL 注入举个稍显极端的例子:往后,连真正理解这类攻击如何发生、能够独立构造测试的人,会不会也越来越少? 这里也包括那些有正当需求的人。一个开发者想检查自己的旧系统,一个经过授权的安全研究员想复现漏洞,假如 AI 识别到危险模式就拒绝,而使用者又只熟悉「让 AI 帮我检查」,这项原本可以独立完成的工作,就这样卡住了。 但是安全专家不会因此消失,但这类技能可能越来越集中在少数人手里。你仍然可以找专家,只是要付出更多的钱、更多的时间,以及更高的沟通成本。 类似的困境,未必只发生在网络安全领域。 你想从一个停止维护的软件里取回自己的数据,需要解析它的旧文件格式。AI 判断这涉及规避保护措施,拒绝继续。你拥有这些数据,却没有能力把它们读出来。 你买了一台设备,厂商停止提供服务。你想修改程序让它继续运转,过程中需要处理某种访问限制。AI 不愿协助,而你所掌握的维修方式,早已只剩下「把报错发给 AI」。 你想给常用的网站写一个辅助工具,减少重复操作。平台将此归入自动化限制,AI 也据此拒绝。过去会写脚本的人可以自己判断、自己处理;未来的使用者,可能连从哪里开始都不知道。 这些例子有一个共同点:当工具同时承担了「执行工作」和「传授知识」的角色,它的拒绝就不只是挡住了一次任务,也挡住了获得这种能力的机会。 更麻烦的是,这种依赖往往是我们主动选择的,而且每一步都很合理。 既然 AI 几秒钟就能做好,为什么还要花几个月学习?既然公司可以采购成熟的 AI 服务,为什么还要养一支负责基础工作的团队?既然市场上已经很少有人手写这些东西,学校为什么还要花大量时间教? 对个人、公司和学校来说,这些选择都有现实依据。但叠加起来,整个社会保留的独立能力就可能越来越少。等到某项能力突然受到限制,我们才发现,备用方案早已在追求效率的过程中被一点点削掉了。 所以,「AI 越强,做事越便宜」可能只描述了未来的一半。 另一半是:被允许的事情越来越便宜,被拒绝的事情依然需要人工完成,却要面对更少的人才、更高的报价,以及越来越难获得的知识。两边的成本差距,会越拉越大。 有人会说,可以换一个模型,或者用本地模型。这确实是重要的选项。只要工具之间还有充分竞争,开放模型还足够可用,限制就未必能形成真正的门槛。 但备用方案也需要维护。它需要硬件、知识、软件生态,以及一群仍然理解这些系统的人。如果大多数人已经习惯了最方便的商业服务,那么「理论上还有别的办法」和「普通人实际用得起、用得明白」,之间仍然可能隔着很远。 我担心的,正是这段距离。 我不指望 AI 对任何请求都照单全收。对明显会伤害他人的行为设置限制,有充分的理由。但我们也需要关心:限制由谁定义,误判有没有申诉渠道,用户能不能换工具,以及脱离这个工具之后,还剩下多少独立行动的能力。 保留这些能力,平时看起来甚至有点低效,明明可以自动生成,还要理解原理;明明可以一键完成,还要知道手动怎么做。 但这些看似多余的知识,会在工具拒绝、失效、涨价或改变规则的那一刻,成为真正的选择权。 AI 越强,我们可能越需要留意它说「不」的那一刻。 因为那句话的分量,最终取决于:它拒绝之后,我们还能做什么。
310
8
什么是LLM
300
9
我的第一个出海产品!7 天 2 万
290
10
WorkBuddy 本地 API 桥 + dsh 插件:把你的 WorkBuddy 额度,变成手边随手可用的模型
290
🔥热门工具
朱雀AI检测朱雀AI检测
朱雀AI检测助手朱雀AI检测助手
LovartLovart
老鱼简历老鱼简历
WritePass官网WritePass官网
面多多面多多
CursorCursor
星月写作星月写作
零感AI零感AI
墨得问题墨得问题