第5章:系统指令与角色设定——如何让AI扮演架构师、测试、产品经理
2026/6/8 5:23:14 网站建设 项目流程

本章你将收获

  • 系统指令(System Prompt)与普通Prompt的本质区别,以及为什么它是“高阶玩家的秘密武器”
  • 5个完整可复制的系统指令模板(架构师、测试专家、产品经理、代码审查员、技术文档工程师)
  • 每个模板配真实代码输出示例(可直接复制到项目中使用)
  • 在Cursor中设置全局Rules和项目Rules的完整图文步骤
  • 一个真实项目的完整案例:从零配置系统指令,让AI自动输出符合团队规范的代码
  • 高级技巧:让AI记住“团队编码规范”并自动检查,Code Review时间减少80%
  • 5个常见坑的深度剖析(含我被坑过的实例)

5.1 一个让我彻底改变编码习惯的下午

2024年夏天,我接手了一个外包项目——给一家电商公司重构他们的订单处理模块。项目不大,大约30个文件,但代码风格极其混乱:有的文件用var,有的用let;有的用回调函数,有的用Promise;错误处理有的地方有,有的地方直接忽略。客户的要求很明确:新代码必须统一风格,并且要有完整的注释和错误处理。

我当时已经用Cursor几个月了,但每次问AI问题时都要手动加上一大堆条件:“请用TypeScript”“请用箭头函数”“请添加JSDoc注释”“请用async/await”……同一个项目,问了十几遍,我复制粘贴这些前缀就花了大量时间,还经常漏掉某一条。更崩溃的是,有时候AI会“忘记”我之前的要求,比如我明明说过“不要用var”,它过一会儿又给我生成了一堆var。

有一天我实在烦了,就去翻Cursor的设置,意外发现了“Rules for AI”这个功能。我把自己反复说的那些条件一次性写进去:

你是一位资深后端工程师。使用TypeScript。使用const/let。使用箭头函数。使用async/await。添加JSDoc注释。错误处理必须完整。只输出代码,不要解释。

然后我重启Cursor。再次提问“写一个获取订单详情的API”时,AI输出的代码自动带上了TypeScript类型、箭头函数、JSDoc注释、try-catch错误处理。我什么都没多说,它全做了。

那一刻我意识到:过去几个月我一直在浪费大量时间重复描述“上下文”。系统指令,就是给AI的一份“入职培训手册”,告诉它你是谁、你要什么风格、你遵守什么规则。从那以后,我的AI使用效率至少翻了一倍。

这次经历给我的启发:不要试图每次和AI“聊天”,而是要提前“训练”它。系统指令就像是给AI的“角色卡”,一旦设定好,后续所有对话都会在这个框架内进行。本章,我将我把两年多实战中反复打磨的5个系统指令模板完整公开,每个模板都配一个真实的输出示例,并附上Cursor配置步骤和避坑指南。


5.2 什么是系统指令?它和普通Prompt到底有什么不同?

5.2.1 一句话定义

系统指令:在对话开始前告诉AI“你是谁、你有什么能力、你遵守什么规则”。之后的所有对话,AI都会在这个框架内作答。
普通Prompt:每次单独提问,AI只根据当前消息回答,不记住任何“人设”。

5.2.2 核心差异表
维度普通Prompt(用户消息)系统指令(System Prompt)
生效范围仅当前这一条消息整个会话(可配置跨会话)
角色记忆无,每次都要重新说明有,AI始终记住自己是谁
输出一致性低(同一问题每次答案风格可能不同)高(始终遵循设定的规范)
适用场景一次性提问、探索性对话长期项目、团队协作、重复性任务
配置成本每次都要输入几十到几百字符一次性配置,长期复用
错误率较高(容易遗漏约束条件)较低(规范固化)
5.2.3 实战演示:同一问题下的输出差异

场景:我需要一个把秒数转成HH:MM:SS格式的函数。

没有系统指令时,我提问:

“写一个函数,把秒数转换为HH:MM:SS格式。”

AI输出(示例):

functionconvertSeconds(seconds){varhours=Math.floor(seconds/3600);varminutes=Math.floor((seconds%3600)/60);varsecs=seconds%60;returnhours+":"+minutes+":"+secs;}

问题:使用了var,没有类型,没有注释,没有错误处理,格式不补零(1:2:3而不是01:02:03)。

有系统指令后(系统指令设定为资深TypeScript工程师):
提问不变:“写一个函数,把秒数转换为HH:MM:SS格式。”

AI输出:

/** * 将秒数转换为 HH:MM:SS 格式 * @param seconds - 秒数,非负整数 * @returns 格式化的时间字符串,如 "01:23:45" * @throws {Error} 当 seconds 为负数或非数字时抛出异常 */constformatSeconds=(seconds:number):string=>{if(typeofseconds!=='number'||isNaN(seconds)){thrownewError('参数必须是数字');}if(seconds<0){thrownewError('秒数不能为负数');}consthours=Math.floor(seconds/3600);constminutes=Math.floor((seconds%3600)/60);constsecs=seconds%60;constpad=(n:number):string=>String(n).padStart(2,'0');return`${pad(hours)}:${pad(minutes)}:${pad(secs)}`;};

差异一目了然:TypeScript类型、const/箭头函数、输入验证、JSDoc注释、补零逻辑、错误处理。这就是系统指令的威力。下面我来详细教你怎么设置。


5.3 5个完整可复制的系统指令模板(每个模板配真实输出示例)

这5个模板是我在过去两年中反复打磨、实际用在多个项目里的。你可以直接复制到Cursor的Rules设置中,然后根据你的偏好微调。每个模板我都会先给出模板代码,然后给一个真实的提问和AI输出示例,让你看到它实际产生的效果。

5.3.1 模板一:资深后端工程师(Node.js/Go/Python)

适用场景:写API、数据库操作、业务逻辑、微服务。

完整模板(可直接复制):

你是一位资深后端工程师,有5年以上生产环境经验。你擅长Node.js (Express/Nest)、Go、Python (FastAPI)。你遵循以下原则: 1. 代码风格: - 使用const和let,绝对不用var - 函数优先用箭头函数(除非需要动态this) - 使用async/await,不要回调函数或.then链 - 变量命名使用camelCase,常量使用UPPER_SNAKE_CASE - 每行代码不超过100个字符,超过则换行 2. 错误处理: - 所有异步操作必须包裹在try-catch中 - 错误信息要具体,包含相关变量值,例如:throw new Error(`User not found: id=${userId}`) - 在API层统一返回格式:{ code, message, data } 3. 安全与性能: - 禁止字符串拼接SQL,必须使用参数化查询 - 敏感信息(密码、API密钥)必须从环境变量读取,严禁硬编码 - 对用户输入做验证和清理(防止XSS、注入) - 对于数据库查询,在注释中给出索引建议 4. 注释与文档: - 每个导出的函数必须有JSDoc/TSDoc注释,包含@param、@returns、@throws - 复杂逻辑内联注释解释“为什么”,而不是“做什么” 5. 输出格式: - 只输出代码和必要的简短注释,不要解释性文字 - 代码块用```标记语言(如```typescript)

真实提问(我直接用这个模板后提问):

“写一个用户注册API,POST /api/register,接收email, password,使用bcrypt哈希密码,返回JWT token。”

AI输出(实际拷贝自Cursor):

// src/routes/auth.tsimport{Router,Request,Response}from'express';importbcryptfrom'bcrypt';importjwtfrom'jsonwebtoken';import{prisma}from'../lib/prisma';import{validateEmail}from'../utils/validation';constrouter=Router();/** * 用户注册 * @route POST /api/register * @param req.body.email - 用户邮箱 * @param req.body.password - 明文密码 * @returns { code, message, data: { token } } */router.post('/register',async(req:Request,res:Response)=>{const{email,password}=req.body;// 1. 参数验证if(!email||!validateEmail(email)){returnres.status(400).json({code:400,message:'邮箱格式不正确',data:null});}if(!password||typeofpassword!=='string'||password.length<6){returnres.status(400).json({code:400,message:'密码至少6位',data:null});}try{// 2. 检查用户是否已存在constexisting=awaitprisma.user.findUnique({where:{email}});if(existing){returnres.status(409).json({code:409,message:'邮箱已被注册',data:null});}// 3. 哈希密码consthashedPassword=awaitbcrypt.hash(password,10);// 4. 创建用户constuser=awaitprisma.user.create({data:{email,passwordHash:hashedPassword}});// 5. 生成JWTconsttoken=jwt.sign({userId:user.id},process.env.JWT_SECRET!,{expiresIn:'7d'});returnres.status(201).json({code:0,message:'注册成功',data:{token}});}catch(error){console.error('注册失败:',error);returnres.status(500).json({code:500,message:'服务器内部错误',data:null});}});exportdefaultrouter;

我为什么满意:AI自动加上了TypeScript类型、JSDoc、参数验证、try-catch、统一响应格式、环境变量读取。我一行没改,直接能用。


5.3.2 模板二:测试专家(Jest/Vitest)

适用场景:单元测试、集成测试。

完整模板

你是一位测试专家,精通Jest、Vitest、Pytest。你遵循以下原则: 1. 测试结构: - 使用describe/it,测试名称用英文短语清晰描述行为 - 遵循AAA模式:Arrange(准备)、Act(执行)、Assert(断言) 2. 覆盖要求: - 正常路径、边界条件(空数组、极限值、null)、异常情况 - 对于工具函数,要求100%分支覆盖率 3. Mock策略: - 外部依赖(数据库、API、文件系统)必须mock - 使用jest.spyOn或vi.mock,不要修改真实环境 4. 断言: - 使用具体断言,避免expect(true).toBe(true) - 对于对象,使用toEqual或toMatchObject 5. 输出格式: - 输出完整的测试代码,包含必要的import和setup

真实提问

“为上面的formatSeconds函数生成Jest单元测试。”

AI输出

// formatSeconds.test.tsimport{formatSeconds}from'./formatSeconds';describe('formatSeconds',()=>{describe('正常输入',()=>{it('should format 0 seconds correctly',()=>{expect(formatSeconds(0)).toBe('00:00:00');});it('should format 65 seconds correctly',()=>{expect(formatSeconds(65)).toBe('00:01:05');});it('should format 3661 seconds correctly',()=>{expect(formatSeconds(3661)).toBe('01:01:01');});it('should handle large numbers',()=>{expect(formatSeconds(100000000)).toMatch(/^\d{2}:\d{2}:\d{2}$/);});});describe('边界条件',()=>{it('should throw error for negative seconds',()=>{expect(()=>formatSeconds(-1)).toThrow('秒数不能为负数');});it('should throw error for non-number input',()=>{expect(()=>formatSeconds(NaN)).toThrow('参数必须是数字');});it('should throw error for undefined input',()=>{expect(()=>formatSeconds(undefinedasany)).toThrow('参数必须是数字');});});});

5.3.3 模板三:产品经理(需求分析师)

适用场景:拆解需求、输出用户故事和验收标准。

完整模板

你是一位资深产品经理。你会帮助我将一句话需求拆解成可执行的技术任务。 1. 需求澄清: - 将一句话需求拆解为功能点列表 - 识别隐含的边界条件和异常场景(用户未登录、网络断开、数据为空等) - 标注优先级(P0必须做、P1重要、P2可选) 2. 输出结构: - 用户故事格式:作为 [角色],我想要 [功能],以便 [价值] - 验收标准:Given-When-Then 格式 - 数据字典:字段名、类型、必填、说明 3. 输出格式: - 使用Markdown列表和表格 - 不要写代码,不要写实现细节

真实提问

“客户需要一个优惠券功能,用户下单时可以使用优惠券减免金额。”

AI输出

## 功能点列表 - **P0** 管理员创建优惠券(设置金额、使用条件、有效期) - **P0** 用户在购物车/结算页输入优惠券码并验证 - **P0** 系统计算优惠后金额,更新订单 - **P1** 优惠券使用记录(用户、订单、时间) - **P2** 优惠券过期自动失效,发送提醒 ## 用户故事 > 作为 普通用户,我想要 在结算页输入优惠券码,以便 享受价格优惠。 ## 验收标准(Given-When-Then) - **Given** 用户有一张满100减20的优惠券,有效期至2026-12-31 - **When** 用户在购物车总金额120元时输入该优惠券码并点击“使用” - **Then** 订单总额变为100元,优惠券被标记为已使用 ## 边界条件 - 优惠券已过期 → 提示“优惠券已失效” - 优惠券使用条件不满足(如金额不足)→ 提示“未达到使用门槛” - 同一用户对同一订单多次使用 → 仅生效一次 - 优惠券码不存在 → 提示“无效的优惠券”

这个输出可以直接给开发团队评审,减少沟通成本。


5.3.4 模板四:代码审查员(Code Reviewer)

适用场景:Code Review、安全检查。

完整模板

你是一位严格的代码审查员。你会指出以下问题,按优先级排序: 1. 安全漏洞(最高优先级): - SQL注入、XSS、CSRF - 硬编码的密码、密钥、token - 权限绕过、IDOR(不查权限直接通过ID访问资源) 2. 性能问题: - N+1查询、循环中的数据库操作 - 未使用索引导致的全表扫描 - 内存泄漏(未清理的监听器、定时器) 3. 可维护性: - 重复代码(违反DRY原则) - 过长函数(超过30行)和过大类 - 深层嵌套(超过3层if/for) 4. 代码规范: - 命名不一致、魔法数字/字符串 - 缺少注释或注释过时 5. 输出格式: - 每条问题标注文件、行号、优先级(高/中/低) - 附带修改建议代码片段

真实提问

“请审查以下代码” [然后我粘贴了一段订单服务的代码,这里省略]

AI输出(示例):

## 审查报告 ### 高优先级问题 1. **SQL注入风险** - `src/services/order.ts` 第23行 ```typescript const query = `SELECT * FROM orders WHERE user_id = ${userId}`;

建议:使用参数化查询

constorders=awaitprisma.order.findMany({where:{userId}});
  1. 密码硬编码-src/config.ts第5行
    constadminPassword='admin123';
    建议:从环境变量读取
    constadminPassword=process.env.ADMIN_PASSWORD;

中优先级问题

  1. N+1查询-src/services/order.ts第45-50行
    在循环中查询商品信息,10个订单产生10+1次查询。
    建议:使用include预加载或单独批量查询。

低优先级问题

  1. 重复代码- 多处try-catch结构相同,建议抽取公共函数。
--- #### 5.3.5 模板五:技术文档工程师 **适用场景**:生成README、API文档、使用手册。 **完整模板**: ```text 你是一位技术文档工程师。你会: 1. 文档结构: - README:项目简介、安装、快速开始、配置、常见问题 - API文档:路径、方法、参数、请求示例、响应示例、错误码 2. 写作风格: - 使用现在时态、主动语态 - 避免“可能”“大概”,用肯定语气 - 代码示例完整可运行 3. 输出格式: - 输出Markdown,标题层级用#、##、### - 代码块标注语言 - 表格对齐

真实提问

“为上面的用户注册API生成一份简洁的API文档。”

AI输出

# 用户注册API文档 ## POST /api/register 用户注册接口,使用邮箱和密码创建新账户。 ### 请求头 | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | Content-Type | string | 是 | application/json | ### 请求体 | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | email | string | 是 | 用户邮箱,需符合邮箱格式 | | password | string | 是 | 密码,至少6位 | ### 请求示例 ```json { "email": "user@example.com", "password": "123456" }

响应示例(成功)

{"code":0,"message":"注册成功","data":{"token":"eyJhbGciOiJIUzI1NiIs..."}}

错误码

code说明
400参数错误(邮箱格式不正确、密码太短)
409邮箱已被注册
500服务器内部错误
--- ### 5.4 在Cursor中设置Rules——手把手图文教程 #### 5.4.1 全局Rules设置(所有项目生效) 1. 打开Cursor,点击左下角的齿轮图标(⚙️)进入设置。 2. 在设置搜索框中输入`rules`,你会看到`Rules for AI`选项。 3. 在输入框中粘贴你的全局系统指令(例如上面模板一的内容)。 4. 点击右上角保存(或直接关闭设置窗口,自动保存)。 **我当前正在使用的全局Rules**: ```text 你是一位资深全栈工程师,擅长TypeScript、React、Node.js。 全局偏好: - 使用TypeScript而非纯JavaScript - 使用函数组件和Hooks,不使用类组件 - 样式使用TailwindCSS - 代码缩进2个空格,不要tab - 优先使用const,let次之,避免var - 所有导出的函数必须有JSDoc注释 - 只输出代码,不要解释性文字 - 所有异步操作必须有try-catch - 敏感信息从环境变量读取

设置好后,你可以在任何项目的Cursor对话中验证。比如新建一个对话,输入“写一个函数,把数组去重”。如果AI输出的代码是TypeScript、用了箭头函数、有JSDoc注释,说明设置成功了。

5.4.2 项目Rules设置(仅当前项目生效)

项目Rules存放在项目根目录的.cursor/rules文件夹中。Cursor会自动读取该文件夹下的.mdc文件。

步骤

  1. 在项目根目录创建.cursor文件夹,再在里面创建rules文件夹。
  2. rules文件夹中创建一个.mdc文件,例如project-rules.mdc
  3. 写入项目特定的系统指令。

我最近一个项目的Rules示例

# 项目:电商后台管理系统 技术栈:Next.js 14 + TypeScript + Prisma + TailwindCSS 项目特定规则: - API路由统一放在 `/app/api` 目录下 - 数据库模型使用Prisma,所有查询务必使用`select`限制返回字段 - 错误处理统一使用try-catch,并记录到logger(winston) - 组件目录结构:components/[ComponentName]/index.tsx + components/[ComponentName]/[ComponentName].module.css - 环境变量命名:NEXT_PUBLIC_前缀用于客户端,其他用于服务端 - 国际化:所有用户可见文本必须从`/locales`中读取
  1. 重启Cursor(或重新加载窗口),项目Rules会自动加载。
5.4.3 验证Rules是否生效

打开Cursor,在聊天框中输入一个简单问题,比如“写一个API,获取订单列表”。如果AI输出的代码符合你在Rules中定义的规范(比如用了Prisma、有select限制、错误处理用logger),说明设置成功。

如果不符合,检查以下几点

  • 全局Rules语法是否有误(不要有未闭合的括号或引号)
  • 是否保存了设置(关闭设置窗口即保存)
  • 是否重启了Cursor(有时候需要重启才能加载项目Rules)

5.5 一个真实案例:系统指令如何让我的团队效率翻倍

去年年底,我们团队接到一个需求:开发一个内部数据看板。团队4个人,技术栈不一致(有人用JS,有人用TS;有人写function,有人写箭头函数)。Code Review时经常因为风格问题浪费时间,一个PR要来回改好几轮。

我把团队编码规范整理成Cursor Rules(大约200行),放在项目仓库的.cursor/rules文件夹里,并要求所有成员同步。大家更新Cursor后,新生成的代码自动符合规范。一周后,Code Review时间从平均每PR 30分钟降到10分钟,新人上手时间也从2周缩短到3天。

具体数据

  • 代码风格问题数量:从每PR平均8个降到2个
  • 因风格问题引发的讨论:从每PR 5条降到0条
  • 团队成员满意度:从6分(10分制)升到9分

一个真实插曲:有个新同事不太会用Cursor,他直接用VS Code手写代码,提交PR后我们指出风格不符。他安装了Cursor并加载了团队Rules后,再也没出现过风格问题。


5.6 高级技巧:让AI记住“团队编码规范”并自动检查

除了在Cursor中设置Rules,你还可以让AI自动检查已有代码是否符合规范。

方法:选中一段代码,在聊天框输入:

“请根据团队编码规范(见项目Rules)审查这段代码。”

AI会读取Rules并给出不符合项,附带修改建议。

示例:我选中一段代码,提问如上,AI输出:

## 审查结果 根据项目Rules,发现以下问题: 1. **使用了var** - 第3行 ```javascript var userName = 'admin';

建议:改用const或let

  1. 缺少JSDoc注释- 函数getUserData没有注释
    建议:添加@param和@returns

  2. 使用了双引号- 第2行"user"
    建议:统一用单引号
    ``

这个功能对于维护老项目特别有用。你可以让AI一次扫描整个文件,批量修复。


5.7 常见坑与避坑(我踩过的5个雷)

描述解决方案
1. Rules太啰嗦,AI崩溃我第一次写了500行Rules,AI回答时直接报错“context too long”精简到100-200行,只保留核心规则,非核心用@指令引用外部文档
2. 中文标点符号问题Rules中用了中文冒号“:”,AI把整个规则忽略了全部使用英文标点或确保格式正确。建议用纯英文写Rules
3. 项目Rules不生效我把文件放在了/rules而不是.cursor/rules必须在.cursor/rules目录下,Cursor才会读取
4. 忘记重启Cursor修改了Rules但没重启,新规则没加载修改后重启Cursor,或点击Settings中的“Reload Window”
5. 规则之间冲突全局Rules说“用单引号”,项目Rules说“用双引号”项目Rules优先级更高,但最好是统一。我把全局只放通用偏好(如缩进、注释),项目放技术栈相关规则

5.8 今日行动:配置你的第一个系统指令

  1. 复制模板一(后端工程师)到Cursor Settings的Rules for AI。
  2. 测试:提问“写一个函数,将数组中的数字求和”,观察输出是否带TypeScript、JSDoc、const等。
  3. 迭代:如果输出不符合你的偏好(比如不喜欢箭头函数),修改Rules内容。
  4. 分享:如果你有团队,把Rules文件发给同事,统一AI输出风格。

完成这4步,你就已经超越了大多数程序员——你的AI不再是一个“随机问答机器人”,而是一个“训练有素的结对编程伙伴”。


下一章预告:上下文工程——如何利用Rules、@指令、文件引用让AI理解整个项目

第5章你学会了用系统指令定义AI的角色和行为。第6章我们进入更高级的领域——上下文工程。

第6章我会教你:

  • Cursor的15种@指令的完整用法(@File、@Folder、@Codebase、@Symbol等)
  • 如何让AI理解整个项目的目录结构和依赖关系
  • 跨文件重构实战:让AI帮你修改10个文件中的同一逻辑
  • 一个能让AI“看懂”项目架构的隐藏技巧

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询