吴恩达亲授:如何用Prompt工程让大模型“靠谱”地为你工作?

2 阅读8分钟

🤖 吴恩达亲授:如何用Prompt工程让大模型“靠谱”地为你工作?

告别“随机输出”,像写代码一样精确控制LLM

在AI应用开发的浪潮中,大语言模型(LLM)展现了惊人的理解与生成能力。但很多开发者都遇到过这样的困扰:同样的Prompt,有时输出完美,有时却答非所问;有时返回优美的JSON,有时却夹杂着废话;甚至还会一本正经地编造事实……

吴恩达(Andrew Ng)在多次演讲和课程中反复强调:要让LLM成为“靠谱”的工程师伙伴,而不是一个随性的诗人。这就需要我们掌握一套系统化的Prompt工程原则——它不仅是写几句话,而是像编程一样,通过清晰性、结构化、约束和示例来减少随机性。

本文将基于吴恩达的核心思想,深入讲解如何设计高质量Prompt、封装API调用函数、以及实战中应对“幻觉”等棘手问题。无论你是新手还是进阶玩家,都能从中获得可落地的技巧。


📌 目录

  1. Prompt工程的三个核心原则
  2. get_response:封装LLM API的艺术
  3. 四大实战规则:让输出更确定
    • 3.1 清晰且具体的表达
    • 3.2 强制输出JSON并丰富语义
    • 3.3 分布式提示(分解复杂任务)
    • 3.4 Few-shot:给模型“抄作业”的机会
  4. 直面幻觉:原因与缓解策略
  5. 完整案例:从模糊到可靠的Prompt进化
  6. 总结与推荐资源

1. Prompt工程的三个核心原则

吴恩达将Prompt设计总结为三个层次:

原则说明
清晰且详细的指令不要只告诉模型“做什么”,还要说明“怎么做”和“不要做”
约束返回结构要求模型输出JSON/XML等结构化数据,便于程序解析
五个构建块指令 + 上下文 + 输入数据 + 输出格式 + 示例

💡 记住:LLM不是读心者。你越是含糊,它就越可能“自由发挥”。


2. get_response:封装LLM API的艺术

在实际开发中,我们通常不会每次都裸调API,而是封装一个get_response函数。这样做的好处:

  • 复用默认参数:比如temperature=0.2max_tokens=1000
  • 统一异常处理:处理限流、超时等
  • 支持不同接口completions(老式补全)和chat.completions(推荐)

2.1 简单封装示例(伪代码)

def get_response(prompt, system_msg="你是一个有用的AI助手", temperature=0.3):
    response = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[
            {"role": "system", "content": system_msg},
            {"role": "user", "content": prompt}
        ],
        temperature=temperature,
        max_tokens=800
    )
    return response.choices[0].message.content

2.2 两种API的区别

接口特点何时使用
completions输入单个prompt字符串,返回续写简单生成任务(如写诗、翻译单句)
chat.completions输入messages数组,支持多角色对话99%的现代应用(尤其是需要系统指令的)

messages结构示例:

[
  {"role": "system", "content": "你是一个严格的数据分析师,只回答数值型事实,不编造数据。"},
  {"role": "user", "content": "2024年全球AI融资总额是多少?"},
  {"role": "assistant", "content": "根据Crunchbase数据,约为500亿美元。"}
]

🔔 小技巧:system消息是最强大的控制开关。你可以在这里设置角色、语气、安全边界,甚至禁止模型说“我不知道”。


3. 四大实战规则:让输出更确定

吴恩达提出了四条黄金规则,下面一一拆解。

3.1 清晰且具体的表达

错误示例:

“总结这篇文章。”
(模型不知道长度、风格、侧重点)

正确示例:

请用三句话总结下面的文本,每句话不超过20个字,聚焦于技术难点,忽略背景介绍。
文本:{文章内容}

关键技巧:使用分隔符

用三个反引号```"""<tag>将原始数据与指令隔开,可以显著降低模型混淆。这是经过了数百次实验验证的有效手段。

请将以下客户评价的情感分类为【正面/负面/中性】,并输出JSON。
---
评价:```这个产品很好,但物流太慢了。```

3.2 强制输出JSON并丰富语义

结构化输出是LLM接入工程系统的前提。我们不仅要要求JSON,还可以通过在字段后添加注释(自然语言描述) 来进一步约束模型。

基础要求:

{"summary": "...", "score": 0.8}

进阶要求(带语义约束):

{
  "summary": "// 20字以内,一句话总结",
  "confidence": "// 0~1之间的浮点数,表示模型对自己的回答有多确信",
  "keywords": "// 数组,最多3个关键词"
}

⚠️ 注意:某些模型会忽略注释,所以最好在指令中明确:“字段后的//内容仅为说明,不要输出//符号”。

3.3 分布式提示:拆解复杂任务

不要让LLM一次完成太多事。例如“分析合同 → 提取条款 → 判断合规性 → 生成报告”四个步骤,最好分成四次调用。

优点:

  • 每个子任务错误率更低
  • 中间结果可缓存、可调试
  • 可替换或升级单个环节的模型

案例:分析用户反馈

  • 步骤1:提取关键实体(产品名、问题类型、情绪词)
  • 步骤2:判断情绪强度(1-5分)
  • 步骤3:生成改进建议
  • 最终:合并为结构化报告
# 伪代码
entities = extract_entities(feedback)   # 子Prompt 1
sentiment = score_sentiment(feedback)   # 子Prompt 2
suggestions = generate_actions(entities, sentiment) # 子Prompt 3
report = merge(entities, sentiment, suggestions)

3.4 Few-shot:给模型“抄作业”的机会

Few-shot是指在Prompt中提供少量(通常是2~5个)输入-输出示例,让模型通过类比学习任务格式。它比零样本(zero-shot)要稳定得多,又比微调(fine-tuning)轻量得多。

零样本(效果一般):

将英文翻译成法文:Hello

Few-shot(效果更好)

示例1:
英文:Good morning → 法文:Bonjour
示例2:
英文:Thank you → 法文:Merci
示例3:
英文:How are you? → 法文:Comment allez-vous?

现在请翻译:
英文:Nice to meet you → 法文:

🧠 原理:LLM在预训练时已经见过类似模式,Few-shot只是激活了正确的“工作记忆”。


4. 直面幻觉:原因与缓解策略

幻觉:模型生成了表面上流畅但事实上错误或杜撰的内容。例如问“谁是火星上第一个人类定居者”,模型可能回答“埃隆·马斯克于2029年建立了基地”——这完全是编造。

4.1 为什么会产生幻觉?

  • 模型本质是概率生成器,没有真假判断的神经元
  • 训练数据不完整或存在虚假信息
  • 用户要求超出了模型知识截止日期
  • 模型为了“取悦用户”强行给出答案

4.2 缓解幻觉的实战方法

策略说明示例指令
要求引用原文让模型必须基于提供的上下文回答“仅根据以下文档回答,不要添加任何外部知识。如果答案不在文档中,输出‘不知道’。”
启用低温度temperature=0 使输出确定性最高API参数设置
加入置信度评分让模型输出对自己的答案有多确定“在JSON中添加confidence字段,取值0-1,1表示非常确信。”
事后验证用知识图谱或规则检查关键事实写一段代码,检查模型输出的日期、名称是否存在
系统指令限制明确禁止捏造system: “你是一个AI助手,严禁编造事实。如果不知道答案,直接说‘我无法确定’。”

5. 完整案例:从模糊到可靠的Prompt进化

假设我们需要一个函数,输入任意产品的用户评论,输出情感分析改进建议,且必须以JSON返回。

❌ 模糊版本(低质量)

分析:{review} 输出建议。

问题:格式随意,情感标签不统一,建议质量飘忽。

✅ 可靠版本(运用所有原则)

system_prompt = """
你是一个专业的产品分析AI。你的任务:
1. 必须严格输出以下JSON结构,不要输出任何其他文字。
2. 字段说明:
   - sentiment: 只能是"positive", "neutral", "negative"之一
   - confidence: 0~1之间的浮点数
   - suggestions: 字符串数组,最多3条具体可操作的改进建议
   - quoted_phrases: 从原文中摘录的关键短句数组(证明依据)
3. 如果用户评论少于5个词,设置sentiment为"neutral",confidence为0.2。
4. 绝不可以捏造建议,如果评论中没有明显问题,建议数组可以留空。
"""

user_prompt = """
请分析以下产品评论:
---
{review}
---
输出JSON:
"""

def analyze_review(review_text):
    return get_response(
        prompt=user_prompt.format(review=review_text),
        system_msg=system_prompt,
        temperature=0.1
    )

示例输出:

{
  "sentiment": "negative",
  "confidence": 0.95,
  "suggestions": ["加快物流速度", "增加包裹追踪通知"],
  "quoted_phrases": ["物流太慢了", "等了一周"]
}

这个案例综合了分隔符、JSON约束、系统指令、低温度、Few-shot思路(虽然没有显式给示例,但通过字段描述模拟了示例效果)


6. 总结与推荐资源

核心要点回顾

问题解决方案
输出格式混乱强制JSON + 字段注释
忽略上下文用```分隔符包裹原始文本
复杂任务出错率高分布式提示(拆分成子任务)
模型不知道想要什么提供2~5个Few-shot示例
幻觉编造事实要求引用原文 + 低温度 + 事后验证

延伸学习

  • 吴恩达《ChatGPT Prompt Engineering for Developers》(DeepLearning.ai免费课程)
  • OpenAI官方Prompt指南(包括6大策略)
  • LangChain:帮你结构化编排多步Prompt调用

最后,记住这句话:Prompt工程不是“与AI聊天”,而是一种面向任务的编程范式。当你把LLM看作一个可控的函数调用,而不是一个神秘的魔盒时,你就真正掌握了它。

如果你在实践中发现了更有趣的技巧,欢迎在评论区分享~ 🚀