Prompt 到底是什么

很多人第一次接触 LLM 时,会把 Prompt 理解成“提示词”。这个翻译没有错,但很容易让人误会:好像只要找到一句神奇的话,模型就会稳定地产生想要的结果。

在工程里,Prompt 更应该被理解为一次模型请求中的输入协议。它告诉模型当前要做什么、已知什么、应该参考什么、不要做什么,以及输出应该长什么样。

如果用前端工程类比,Prompt 不像一句口号,更像是一次函数调用的参数、组件的 props、接口的 request body,以及页面状态的组合。

Prompt 是什么

Prompt 是你交给模型的上下文。它可以是一句话,也可以是一组结构化消息,还可以包含用户问题、系统规则、业务数据、示例、输出格式、工具说明和安全边界。

一个最简单的 Prompt 可能是:

用三句话解释什么是 TypeScript。

但真实产品里的 Prompt 往往更像这样:

你是一个面向前端工程师的技术写作助手。

任务:
把下面这段接口文档改写成更容易阅读的说明。

要求:
- 使用中文。
- 保留字段名和类型。
- 不要编造接口里没有的信息。
- 输出 Markdown。

接口文档:
GET /api/projects
返回字段:
- id: string
- name: string
- createdAt: string

这已经不只是“提示”了。它包含角色、任务、约束、输入材料和输出格式。

Prompt 和普通输入有什么区别

在传统程序里,输入通常有明确结构。比如一个函数接收对象:

type CreateUserInput = {
  name: string;
  email: string;
  role: 'admin' | 'member';
};

function createUser(input: CreateUserInput) {
  // ...
}

程序会按照确定逻辑处理这个对象。如果字段缺失,TypeScript 或运行时校验可以直接报错。

LLM 的输入更宽松。你可以给它自然语言、代码、表格、日志、JSON、Markdown,甚至几种格式混在一起。模型会根据上下文生成输出,而不是像普通函数那样执行一段确定逻辑。

这带来一个重要变化:Prompt 的质量会影响模型理解任务的方式。

模糊 Prompt:

帮我优化一下这个组件。

更清晰的 Prompt:

请从可读性、状态拆分和渲染性能三个角度 review 下面的 React 组件。
只指出可能造成维护成本或性能问题的地方。
每个问题包含:问题、原因、建议改法。

后者不是因为“话术更高级”,而是因为任务边界更明确。

Prompt 里通常包含什么

一个可用的 Prompt 通常由几类信息组成。

第一类是任务目标。也就是你希望模型完成什么,例如总结、分类、改写、生成代码、抽取字段、判断风险。

第二类是上下文材料。比如用户输入、当前页面状态、接口返回数据、业务规则、文档片段、错误日志。

第三类是约束条件。比如语言、语气、长度、禁止编造、必须引用来源、只能输出 JSON。

第四类是输出格式。比如 Markdown、JSON、表格、列表、代码块,或者某个接口需要的 schema。

第五类是示例。也就是给模型几个输入和输出样例,让它模仿你的格式和判断标准。

这些信息不一定每次都全部需要。越简单的任务,Prompt 越可以短。越接近真实产品,Prompt 越需要像接口协议一样被设计。

前端视角:Prompt 像 props,但不是 props

前端工程师很熟悉组件 props:

<UserCard
  name="Ada"
  role="Frontend Engineer"
  showActions={true}
/>

组件根据 props 渲染 UI。props 是结构化的,组件逻辑也是确定的。

Prompt 也在给模型提供“渲染所需的信息”,但它有三个不同点。

第一,模型不是确定性组件。即使输入相同,也可能因为采样参数、模型版本或服务行为产生细微差异。

第二,模型会解释上下文。它不是简单读取字段,而是尝试理解你的意图、权重和隐含关系。

第三,Prompt 中的不同部分会互相影响。用户问题、系统规则、示例和业务数据不是孤立字段,它们会一起影响输出。

所以,写 Prompt 不是写一句文案,而是在设计模型请求的输入结构。

一个最小 API 示例

下面是一个使用 OpenAI SDK 的最小示例。重点不在模型名,而在如何把 Prompt 当作可组织的输入。

import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

const userQuestion = 'React 中什么时候应该使用 useMemo?';

const response = await client.responses.create({
  model: 'gpt-4.1-mini',
  input: `
你是一个面向前端工程师的技术解释助手。

请回答用户问题。

要求:
- 先给出一句话结论。
- 再给出两个适合使用 useMemo 的场景。
- 再给出两个不应该使用 useMemo 的场景。
- 不要把 useMemo 描述成默认性能优化手段。

用户问题:
${userQuestion}
  `.trim(),
});

console.log(response.output_text);

这里的 Prompt 包含了角色、任务、回答结构、禁止误导的约束和用户问题。

把 Prompt 拆成结构

随着业务变复杂,不建议把所有内容都写在一大段字符串里。可以先在应用层拆成结构,再组装。

type PromptParts = {
  role: string;
  task: string;
  rules: string[];
  input: string;
};

function buildPrompt(parts: PromptParts) {
  return `
${parts.role}

任务:
${parts.task}

要求:
${parts.rules.map((rule) => `- ${rule}`).join('\n')}

用户输入:
${parts.input}
  `.trim();
}

const prompt = buildPrompt({
  role: '你是一个面向前端工程师的技术解释助手。',
  task: '解释一个 React 概念,并给出工程使用建议。',
  rules: [
    '先给结论,再展开解释。',
    '示例使用 TypeScript。',
    '不要制造不存在的 API。',
  ],
  input: '什么时候应该使用 useMemo?',
});

这样做的好处是,Prompt 可以像普通工程代码一样被复用、测试和审查。

Prompt 会影响哪些工程结果

Prompt 不是只影响“回答好不好听”。它会直接影响产品里的工程指标。

它影响准确性。任务描述越模糊,模型越容易猜测。

它影响稳定性。输出格式没有约束,前端解析就容易失败。

它影响成本。上下文越长,token 越多,请求越贵,延迟也越高。

它影响安全边界。如果没有明确说明可用信息和不可泄露信息,模型可能把不该展示的上下文带入回答。

它影响用户体验。比如同样是错误解释,产品可能需要“简短可行动”的回答,而不是一篇百科。

所以,Prompt 是 AI 产品设计的一部分,不是只属于“会写提示词的人”的小技巧。

常见误区

第一个误区:把 Prompt 当成咒语。

很多所谓“万能 Prompt”看起来很长,但真正有效的不是神秘措辞,而是清晰的任务、上下文和约束。

第二个误区:以为 Prompt 越长越好。

Prompt 越长,成本和延迟越高,也越可能混入干扰信息。好的 Prompt 应该包含必要上下文,而不是把所有资料都塞进去。

第三个误区:只调 Prompt,不改产品设计。

有些问题不是 Prompt 能解决的。比如业务数据缺失、权限边界不清、用户意图入口设计不合理,都需要产品和工程一起调整。

第四个误区:忽略输出格式。

如果前端要消费模型结果,就不能只要求“回答得好”。你需要明确字段、格式、错误兜底和解析策略。

第五个误区:把 Prompt 写死在业务代码深处。

Prompt 会迭代。它应该像配置、模板或策略一样有清晰位置,而不是散落在组件事件处理函数里。

小结

Prompt 是提交给模型的任务输入和上下文协议。它可以包含目标、材料、约束、格式和示例。

对前端工程师来说,理解 Prompt 的关键不是背诵某些“神句”,而是把它当作产品和工程之间的一层接口设计:用户想做什么,系统知道什么,模型应该怎样处理,前端又要怎样消费结果。

从这个角度看,Prompt 设计就是 AI 应用工程的起点。