
https://www.youtube.com/watch?v=f32dc5M2Mn0
大家好,我是戴安娜·陈·摩根(Diana Chan Morgan),在 deeplearning.ai 负责所有社区相关事务。今天,我们邀请到了一位非常特别的演讲嘉宾,来探讨开源大型语言模型(LLM)的提示词工程。
正如大家所知,在切换使用任何大型语言模型时,都需要对提示词进行设计优化——即便 OpenAI 在后台更新模型版本,也不例外。这也是为什么人们会困惑:为什么自己的提示词突然失效了?
要想让模型充分发挥性能,完整提示词的**透明度**至关重要。然而,大多数框架都在这一点上存在不足:它们要么试图将所有内容“抽象化处理”,要么故意隐藏提示词,营造出一种“在后台处理复杂事务”的假象。但提示词工程并非软件工程,因此,要想成功做好提示词工程,其工作流程与软件工程截然不同。
所以,在今天的工作坊中,我们将学习以下核心内容:
- 提示词工程与软件工程的区别
- 开源大型语言模型与闭源大型语言模型的差异
- 如何利用提示词透明度提升模型准确性
- 开源大型语言模型提示词工程的最佳实践
- 检索增强生成(RAG)技术,以及如何基于数百万份文档实现检索增强生成
本次工作坊会进行录制,后续我们会将幻灯片分享给大家。本次内容的灵感来源于我们与本次演讲嘉宾合作开发的一门课程——《大型语言模型微调》。
我们今天的活动合作伙伴是 Lamini。Lamini 是一款“一体化开源大型语言模型工具包”,完全由你自主掌控。在 Lamini 平台上,团队正在探索各种方法,帮助你定制可自主拥有的智能模型。
现在,我非常荣幸地向大家介绍我们的演讲嘉宾——莎伦·乔博士(Dr. Sharon Joe)。莎伦是 Lamini 的联合创始人兼首席执行官。在加入企业界之前,她曾是斯坦福大学的教职人员,领导过一个研究团队,并在生成式人工智能领域发表过获奖论文。
莎伦在 Coursera 平台上讲授多门热门课程,其中就包括《大型语言模型微调》,累计覆盖超过 25 万名专业人士。她拥有斯坦福大学人工智能博士学位,师从安德鲁·吴(Dr. Andrew Ng)博士;攻读博士学位前,她曾在谷歌担任机器学习产品经理;本科阶段则毕业于哈佛大学,主修计算机科学与古典学。此外,莎伦还曾在华盛顿特区担任人工智能顾问,并入选《麻省理工科技评论》(MIT Technology Review)“35 岁以下科技创新者”榜单。
莎伦,非常欢迎你今天的到来!你对接下来的分享是否充满期待?
**莎伦**:非常开心能来到这里,感谢再次邀请我!
**戴安娜**:当然啦!我们都很期待你的“小 llama(小骆驼,此处双关 Lamini 相关模型)”登场,为大家提供帮助——其实在部分深度学习短期课程中,它们已经悄悄露过面了,大家可以留意哦!
好的,那我们就正式开始吧!我相信大家都迫不及待想学习莎伦要分享的内容了。如果大家有问题,可以在聊天区看到我们发布的幻灯片链接,通过链接可以为你最想让莎伦解答的问题投票。好了,莎伦,接下来就交给你了!
**莎伦**:太棒了!大家有问题尽管提,我非常乐意解答——尤其是那些“尖锐一点”的问题,我很期待看到这类问题!
大家好,我是莎伦,Lamini 的联合创始人兼首席执行官。今天我要分享的主题是“开源大型语言模型的提示词工程”。正如标题所示,闭源大型语言模型与开源大型语言模型的提示词工程存在差异,接下来我会详细拆解这种差异具体体现在哪些方面。
戴安娜已经对我的背景做了很棒的介绍,但我还想补充一点:今天的分享其实源于我自己的亲身体验,以及我观察到的许多人面临的困境。我不希望其他人再经历同样的挣扎,所以想通过这次分享,梳理我在实践中总结的经验,同时也点出一些我看到的问题——很多聪明的人在这些问题上走了弯路,甚至花费了数月时间却收效甚微。我希望能引导大家走上正确的道路,一条通往成功的道路。
当然,这些都是我的个人经验,其中也会包含一些“大胆的观点”,大家很快就会听到。希望这会是一场有趣的分享!
我的背景戴安娜基本已经介绍过了,但我还是想提一句:我曾是深度学习领域第一位生成式人工智能讲师。我非常热爱生成式模型,觉得它们充满了“魔力”;同时我也热爱与人交流,所以我的人生使命其实是让更多人能够掌握这种“魔力”——这种在我攻读博士期间深深吸引我的魔力。
好的,我们先快速过一下今天的分享大纲,明确我们要覆盖的内容:
1. 无论是调用 API 接口,还是在开始使用某个大型语言模型之前,模型的微调过程、后台的技术细节,都会影响你设计提示词的方式。我会详细说明这些后台因素如何具体影响提示词。
2. 不同的大型语言模型,适用的提示词也不同。我发现很多人会把用于 GPT-4 的提示词直接套用在其他模型上,认为它们具有通用性,但事实并非如此。甚至同一模型的不同版本,也会让人们遇到“提示词失效”的问题——大家都曾为这种“缺乏向后兼容性”的情况感到困扰,毕竟“向后兼容”是软件工程的常规范式,但在大型语言模型领域,情况却并非如此。我会就此展开说明。
3. 我还想强调一点:**提示词工程不是软件工程**。我发现很多人会在这一点上陷入困境,主要是因为它被命名为“工程”。在我看来,这个命名其实不太恰当——它更像是优化谷歌搜索关键词,需要不断迭代调整查询语句。我会分享相关的最佳实践。
4. 最后,提示词本质上就是“字符串”。我希望大家不要把它复杂化,在接下来的分享中,我可能会用比较直接甚至略带调侃的语气强调这一点,但核心就是:提示词只是字符串,而处理字符串对你来说绝对不是难事,我敢保证。
5. 还有一个容易被混淆的点:检索增强生成(RAG)其实是提示词工程的一种形式。很多人会把“提示词工程”“RAG”“微调”看作完全独立的概念,但实际上 RAG 属于提示词工程——因为它本质上是通过拼接字符串来调整提示词。所以, again,不要把事情复杂化,我看到太多人把简单问题搞复杂了。
接下来我们看看,今天的分享是为谁准备的。我之前在 Twitter 上提过,主要面向那些“优秀且聪明的软件工程师”。希望今天在座的很多人都属于这个群体:你们擅长软件工程,同时对开源大型语言模型充满好奇。现在正是探索开源大型语言模型的好时机,它们有很多优势,后续我会结合提示词工程的主题,提及其中一些相关优势。
那谁不适合今天的分享呢?主要是像我这样“训练过数千个生成式模型、提出过新架构并成功训练”的人。因为这类经历会让你天然理解“为什么提示词会有这样的表现”“为什么需要这样设计提示词”,而今天的分享更希望让那些没有这类深度技术背景的人也能理解提示词工程——我认为不需要为了理解这个领域而攻读博士、做大量研究,它应该变得更简单。我会努力通过这次分享,让大家看到它的简洁之处,希望大家能在 30 分钟内(甚至倍速播放的情况下)理解核心内容,同时还能觉得有趣。
## 一个形象的类比:大型语言模型也需要“穿裤子”
我们先从一个容易记住的类比开始,这个类比可能有点“直接”,大家多担待。
假设你每天出门都会穿裤子,所有人都穿裤子,你也被告知“穿裤子是正确的选择”“穿裤子的人才是好人”——总之,穿裤子是一种常态,你会因为穿裤子而表现得很自然。
但如果有一天,你出门时没穿裤子,你还会表现得和平时一样自然吗?
这个类比虽然极端,但想表达的核心是:**大型语言模型也需要“穿裤子”**,而这里的“裤子”就是模型的“提示词设置”(prompt setting)。接下来我会详细解释这一点。同时请记住,提示词本质上就是字符串——字符串的细节对大型语言模型至关重要,尤其是当模型经过特定微调或训练后,字符串的影响会更明显。
即便对我们人类来说,字符串的细微差异也可能带来巨大影响。比如最近杨立昆(Yann LeCun)在推特上提到的“Open Space AI”和“Open AI”——只是几个字母的差异,却是完全不同的概念,编辑距离很小,但含义天差地别。
回到“穿裤子”的类比:“穿裤子”对应模型的“提示词设置”,每一个大型语言模型、每一个模型版本,都有不同的“提示词设置”——可能不是完全不同,但一定会有调整,以适应模型对“常态”的理解。
## 实例:“穿裤子”与“不穿裤子”的模型表现差异
我们用实际例子看看“穿裤子”和“不穿裤子”对模型输出的影响。
第一个例子是开源模型 Mistral。假设我们的提示词是:“请友好地回复一个孩子:‘我真的很讨厌西葫芦,为什么我要吃它呀?’”(注:“我真的很讨厌西葫芦”这句话其实来自我的联合创始人,他虽然是成年人,但很符合孩子的语气)。正常情况下,我们期待模型会以友好的语气回复孩子,对吗?
- **不“穿裤子”时**:模型会用第三人称说话,输出类似“要记住,每个人都有自己的饮食偏好,孩子不喜欢某些蔬菜是很正常的”——这种回复虽然没错,但明显“偏离了目标”,没有直接对孩子说话,感觉很生硬。
- **“穿裤子”后**:模型会直接面向孩子回复,比如“我理解你不喜欢西葫芦,有自己的饮食偏好是很正常的哦!但要记住,吃各种各样的食物对身体健康很重要”——虽然不算完美,但明显更符合预期,输出质量有了显著提升。
第二个例子是 Llama 2。假设提示词是:“你是一个健康饮食爱好者,我正在喝绿色果汁。”我们期待模型会围绕“健康饮食”“绿色果汁”给出相关建议或回应。
- **不“穿裤子”时**:Llama 2 会直接“续写句子”,比如“我正在喝绿色果汁,今天天气很好,我打算去公园散步”——完全偏离了“健康饮食爱好者”的身份设定,输出“跑偏了”。
- **“穿裤子”后**:模型会贴合身份回复,比如“作为健康饮食爱好者,绿色果汁确实是很棒的选择!它富含维生素和膳食纤维,不过也要注意搭配其他食物,保证营养均衡哦”——虽然语气有点活泼(甚至有点搞笑),但完全符合预期,这种差异在大规模使用模型时会带来巨大影响。
## 什么是模型的“裤子”?—— 元标签(Meta-tags)
大家可能会问:到底什么是模型的“裤子”?其实,每一个大型语言模型都有自己对“穿裤子”的定义,你甚至可以控制“裤子的样式”,但首先我们要理解它的基本形态。
对于 Mistral、Llama 2 这类开源模型,“裤子”其实是**元标签(Meta-tags)**。如果你和 OpenAI、Anthropic 的从业者交流,可能会听到他们提到这个术语。元标签是嵌入在提示词中的特殊标签,用于“标记用户输入的属性”——比如明确“这是用户的问题”“这是系统设定”等。
关键在于:**对于开源大型语言模型,元标签是完全公开、透明且可直接使用的**——除非你使用的框架刻意隐藏了它(后续会提到框架的问题)。你可以直接看到这些元标签的格式,然后根据需要调整使用。
比如,Mistral 的元标签格式可能是这样的:<s>[INST] 用户提示词 [/INST]
而 Llama 2 的元标签格式可能是这样的:<s> [SYSTEM] 系统设定 [/SYSTEM] [USER] 用户提示词 [/USER] [ASSISTANT]
这些格式本质上就是“字符串片段”,你只需要用字符串拼接(比如 Python 中的 f-string),就能把它们和你的提示词结合起来——最多只需要增加 30 个左右的字符,非常简单。我实在不理解为什么有人需要用复杂的框架来处理这件事。
## 代码演示:亲手为模型“穿裤子”
接下来我想通过代码,直观展示如何为模型“穿裤子”。这是一个非常基础的开源代码库,只有 50-60 行代码,核心功能是调用 Mistral、Llama 2 等开源模型,对比“穿裤子”和“不穿裤子”的输出差异。
### 代码核心逻辑
1. 定义要测试的提示词:比如前面提到的“西葫芦问题”“绿色果汁问题”,还有一些代码相关的提示词(比如“如何找到 6 个月前提交的代码”)。
2. 迭代测试:
- 首先,直接将“裸提示词”(不添加元标签)输入模型,获取输出。
- 然后,为提示词添加对应模型的元标签(即“穿裤子”),再输入模型,获取输出。
- 对比两次输出的差异。
### 代码片段示例(以 Mistral 为例)
python:
# 导入模型运行类
from model_runner import OpenSourceLLM
# 初始化 Mistral 模型
llm = OpenSourceLLM(model_name="mistral-7b")
# 测试提示词:代码相关问题
prompt = "如何找到代码库中 6 个月前提交的代码?比如超过 6 个月未更新的文件。"
# 1. 不“穿裤子”:直接输入裸提示词
print("=== 不穿裤子的输出 ===")
output_no_pants = llm.generate(prompt=prompt)
print(output_no_pants)
# 2. “穿裤子”:添加 Mistral 的元标签
prompt_with_pants = f"<s>[INST] {prompt} [/INST]"
print("\n=== 穿裤子的输出 ===")
output_with_pants = llm.generate(prompt=prompt_with_pants)
print(output_with_pants)
### 实际运行结果对比
- **不“穿裤子”的输出**:模型会偏离主题,比如“代码库的提交记录通常保存在版本控制系统中,Git 是常用的工具。Git 有很多命令,比如 git log,可以查看提交历史。另外,Git 还支持分支管理……”——虽然提到了 Git,但没有回答“如何找到 6 个月前提交的代码”这个核心问题,输出冗长且无关。
- **“穿裤子”的输出**:模型会直接回答核心问题,比如“在 Git 中,你可以使用以下命令找到 6 个月前提交的代码:\n1. 查看 6 个月前的提交记录:git log --since='6 months ago'\n2. 找到超过 6 个月未更新的文件:git ls-files --modified | xargs -I {} git log -1 --since='6 months ago' {} || echo '{} 超过 6 个月未更新'\n此外,如果你使用 GitHub/GitLab 等平台,也可以在网页端通过‘提交历史’筛选‘6 个月前’的记录……”——完全命中需求,输出简洁且实用。
这个例子充分说明:仅仅添加几个元标签(“穿裤子”),就能让开源模型的输出质量发生质的飞跃。而这一切只需要简单的字符串拼接,不需要复杂的技术。
## 为什么你之前不知道“给模型穿裤子”?
很多人可能会疑惑:既然“穿裤子”这么重要,为什么我之前从来不知道?主要有三个原因:
1. **文档缺失**:模型的元标签格式很少在官方文档中明确说明。我们团队也是花了不少时间,才从非官方但相对可靠的渠道(比如社区讨论、AWS 与 Meta 的合作博客)找到这些格式——甚至有些格式是“半官方”的,让人不确定是否正确。
2. **闭源模型的“隐性处理”**:在闭源模型(如 GPT-4、Claude)中,平台会在后台自动为你的提示词“穿裤子”,你看不到这个过程。比如你在 ChatGPT 中输入“我讨厌西葫芦”,OpenAI 会在后台自动添加类似“[USER] 我讨厌西葫芦 [/USER] [ASSISTANT]”的元标签,但你完全感知不到——这就导致你在切换到开源模型时,不知道需要手动添加元标签。
3. **框架的过度封装**:很多大型语言模型框架(比如 LangChain)会刻意隐藏提示词的细节,用“抽象层”“类型系统”把元标签包装起来。比如你用框架的“ChatPromptTemplate”,可能不知道它在后台拼接了什么元标签——这反而增加了调试难度,因为你看不到最终输入模型的完整提示词。
我自己也犯过类似的错误:我们团队曾经为了“让软件工程师用起来更顺手”,开发了一套基于 Pydantic 的类型系统,把提示词转换成“输入输出类型”,结果导致提示词完全被隐藏,调试时根本不知道问题出在哪里。后来我们花了几个月时间,把这套复杂的系统全部重构掉,回归到“直接操作字符串”的简单方式——这才是最高效的。
## 闭源模型 vs 开源模型:“穿裤子”的差异
接下来我们聊聊“开源模型”和“闭源模型”在“穿裤子”上的区别。比如你用ChatGPT发消息,不需要手动加格式,因为OpenAI在后台帮你“给模型穿了裤子”。从API层面看,你输入的是一段内容字符串(本质上是一个字典结构),但后台会对这段字符串进行处理——我猜可能会添加“角色标签”“消息标签”之类的元信息(当然这只是猜测,实际逻辑可能更复杂)。
不过可以肯定的是,闭源模型的后台会对提示词进行字符串层面的格式处理。而且为了提高“token效率”(减少字符占用),厂商可能会把这些格式标签处理成“单token”(比如类似“句子结束符”的特殊token),这样既能保证格式正确,又不会占用太多token。这就是为什么你用闭源模型时,完全不用考虑“穿裤子”——因为厂商在后台帮你做好了。
如果你自己开发闭源模型,也需要权衡“格式透明度”和“用户体验”:对非工程师用户来说,看到一堆元标签会很困惑,所以需要用友好的界面隐藏这些细节;但从技术角度,让用户理解“格式的存在及作用”,对提升模型使用效果是有实际帮助的。
不过说到底,**“给模型穿裤子”本质上就是添加字符串**——ChatGPT帮你做了,不代表你自己做不到。你只需要额外加30个字符,拼接一下字符串而已。说句实在话,“字符串拼接”是幼儿园水平的编程技能(比如Scratch里就有类似功能),如果你是软件工程师,真的没有理由做不到。
另外还有个误区:80%的框架会把“穿裤子”这件事复杂化。我必须强调:**不要把格式处理搞复杂**,很多框架要么“差几个字符导致格式错误”,要么“把格式藏得太深难以修改”。我就不点名了,但连我自己都踩过这个坑——我们团队曾经为了“让大语言模型支持类型系统”,用Pydantic(Python数据验证库)做了一套复杂的“输入输出类型转换逻辑”,当时很多工程师觉得“很酷”,但现在回头看,完全是画蛇添足。后来我们花了几个月时间,慢慢把这套复杂逻辑删掉了。
我不是说框架的初衷不好——它们是想“用常规软件范式简化大语言模型使用”,这个思路是对的,但很多实现方式都走偏了。其实更好的方式是“让提示词透明可见”:因为只有看到完整的提示词(包括格式),你才能验证“字符是否在正确的位置”,才能最大化模型的性能。
如果想更深入一点,我可以教你“如何调整裤子的样式”(自定义格式),甚至“给模型换条裙子”(完全自定义元标签),但核心原则不变:**对开源模型,一定要让提示词(包括格式)透明可见**。
关于“提示词管理”,我还有几个建议:
第一,**让提示词易于修改**。因为每个新模型、每个模型新版本,格式要求都可能变。比如Hugging Face(开源AI平台)上,很多模型更新时,作者不会通知用户“同一个模型名,内容已经变了”,导致“没有向后兼容性”——这和OpenAI“后台更新模型不改名”是类似的问题。所以,你的工作流里,“提示词”必须是“易修改”的部分。
第二,**理解“提示词的高可变性”**。正因为模型版本、类型不同会导致格式要求不同,所以“提示词透明可见”和“易访问”才至关重要——你需要能随时迭代调整提示词。而且这真的不难,只是字符串而已,不会给你带来太多麻烦,反而能让你更灵活地使用模型。
现在你可能会问:“谁来决定大语言模型该‘穿什么样的裤子’?” 比如OpenAI决定了ChatGPT的格式,Meta决定了Llama的格式,Mraw团队决定了Mraw的格式——但到底该由谁来定?
我个人立场很明确:**最终应该由每个使用者根据自己的需求来决定**。具体来说,取决于你的应用场景,以及你想在“哪个层级”控制格式:是沿用Meta的基础格式,还是在其之上添加自己的格式(比如额外的提示词设置、自定义元标签)?
实现“自定义格式”的标准方法是**微调大语言模型**——我也教这门课,之后会针对软件工程师开设更深入的微调课程。通过微调,你可以让模型“认可”你定义的格式:把你的格式逻辑融入模型的知识和行为中,让模型把你定义的元标签当成“正确的裤子”。
这也解释了为什么闭源模型的提示词“会突然失效”或“不兼容旧版本”——因为厂商在后台调整了“裤子的样式”(格式),而你完全不知情。
另外,“提示词设置”的可能性是无限的,而且都可以通过字符串表示,所以自定义格式其实没那么难。我们之前聊的“聊天格式”,本质上都是“提示词设置”的一种。不同厂商可能会用不同的叫法(比如Mraw团队可能叫“聊天模板”,Hugging Face和Meta可能有其他命名),但核心都是“字符串格式”。只要你能“验证格式正确性”,叫什么名字不重要。
除了“聊天格式”,你还可以自定义“JSON输出格式”“函数调用格式”等——这些都是“提示词设置”,你都可以通过微调让模型认可。比如我们有个客户,为了“从对话中提取菜单信息”(比如快餐店 drive-through 窗口的对话),专门微调了模型,让模型能识别“菜单提取专用格式”——这就是“自定义裤子样式”的实际应用。
最后给大家补充一个进阶技巧:**不用微调也能让模型“以为自己穿了裤子”**——我把这个技巧叫做“皇帝的新衣”(灵感来自那个童话)。我们团队开发了一个自定义推理引擎,能让任何模型在不微调的情况下,100%输出符合要求的JSON格式。简单来说,就是“骗模型穿上你想要的裤子”,虽然不算最完美的方法,但能强制模型输出指定格式,而且结果是“确定性的”(不是概率性的),非常实用。
可能有人会想:“我就是懒得自己弄格式,想让别人帮我处理”——这很正常,我有时也会偷懒。但如果你是为公司或个人项目开发,需要控制模型输出质量,就必须理解“格式的重要性”。通常我的做法是:先用“偷懒模式”快速测试,发现问题后再切换到“精细控制模式”,调整格式优化效果。
好,来说提示词工程(prompting)。有一个关键策略必须强调:迭代。软件工程师怎么才能做好?先设计好方案,再落地实现——大部分时间都花在设计上,对吧?
我发现,80%的开发者在用软件工程的思维做提示词工程,反而有些普通人可能更擅长提示词工程(我不是说真的如此,只是有可能)。
这一点特别有意思,因为提示词工程根本不存在“一次设计到位”的说法。
你没法靠上课学会“照做就能成”的方法——任何课程都教不了你一套放之四海而皆准的流程,因为说到底,它是一个高度迭代的过程。你不能追求“设计完美再落地”,反而应该先给出一个粗糙的版本,
先“懒”一把——就像谷歌搜索时,你有时甚至拼不对词,随便输入几个关键词就行。然后迭代优化:
“哦,谷歌没懂我的意思,连联想推荐都没有,完全误解了我乱按的键盘”——那就在此基础上修改,越改越好。
做提示词工程就要有这种心态,而且不同模型、不同版本的差异很大,你需要掌控这个过程,需要透明化,还得让调整变得简单。所以核心就是“持续迭代提示词”——
我看到很多人会陷入瓶颈,没意识到最佳策略可能只是“限时尝试”:要明白提示词优化存在边际效益递减。而迭代式提示词工程会让你自然领悟这一点——比如设定1小时时限,在这1小时内迭代100次后,再优化的收益就很小了。这和谷歌搜索没什么区别,别花太多时间纠结“设计完美提示词”,也别刷一堆教程——何况提示词的设置还会不断变化,不如掌握“迭代”这个核心技能,让自己轻松应对。所以在代码库中集成模型时,一定要让提示词的修改变得超级简单,不能让它一成不变。当然,如果你自己控制模型、做微调、管理检查点,那就另当别论了——这也是开源模型的一大优势:你能掌控版本升级。
核心结论:
提示词工程既不是软件工程,也不是机器学习(我可以保证它绝对不是机器学习)。尽管有很多人发表相关论文,但它真的不是。当然,你能学到一些实用技巧,比如“让模型逐步推理”,但本质上它不是机器学习。它只是在运行模型、启动机器学习流程之前,对输入的字符串进行处理——说白了就是字符串操作,幼儿园级别的基础操作而已。
接下来讲RAG(检索增强生成)。
很多人会误以为它和提示词工程完全无关,但我认为它是提示词工程的一个子集,是一种特殊的提示词使用方式。RAG本质是搜索,是信息检索——它已经存在几十年了,比ChatGPT早得多。说到搜索,谷歌是这方面的王者,几十年的研究和生产部署积累了很多最佳实践。我要再次强调:别把RAG想得太复杂,它在最基础的层面上,就是给你的提示词字符串“拼接更多字符串”。别过度神化它,它做不到什么神奇的机器学习效果。而且透明化很重要——我见过很多人运行大规模RAG任务,却完全看不到最终的提示词(包括拼接的相关内容),其实他们本可以在这个层面调试,发现很多问题:比如调整数据的呈现方式,给每个文本块加标题、加头部信息,或者补充元数据。所以别复杂化,你完全能做到,根本不需要机器学习博士学位——因为它本来就不是机器学习。
我准备了一个非常简单的代码仓库,目标是“让RAG看起来很简单,而且确实很简单”。我原本说能覆盖80%的场景,现在觉得可能70%左右(还挺自豪的)。代码用的是FAISS库——这是Meta(原Facebook)开发的一个超棒的库,比ChatGPT早很多,专门用于相似度搜索,是处理嵌入向量(embedding)的利器。我还导入了一些标准库,以及嵌入向量API,这样能快速生成嵌入向量,也能在RAG流程的输出阶段运行模型(比如拼接完提示词后,用模型生成最终回答)。
简单走一遍代码逻辑(全程透明,核心代码只有72行):
1. **加载数据(loader)**:
读取文件(比如txt),后面会展示具体效果;
2. **构建索引(build Index)**:
这是核心函数——先把数据分割成文本块(chunking),分批处理以提高效率,然后为每个文本块生成嵌入向量(也就是用数字表示文本块的语义)。嵌入向量并不完美,但能反映语义核心。这里可以用不同的索引类型,它们各自在内存占用、效率和准确性之间做权衡——我们用的是最简单的版本,而很多主流索引算法其实十年前就已经存在了。生成嵌入向量后,把它们存入索引,同时保存对应的原始文本内容,方便后续检索;
3. **嵌入向量生成(vetting)**:
这一步类似调用模型,可能是RAG流程中的最大瓶颈(毕竟模型越来越大),但用小型模型就能应对。这里的吞吐量很重要——比如每秒能处理50个文本块,效率越高越好。有人会用向量数据库,但我觉得除非数据量超过1TB,否则没必要——毕竟模型连整个互联网的信息都能容纳;
4. **查询(query)**:
先把查询语句转换成嵌入向量,然后在索引中搜索最相似的Top 5文本块(K=5)。这里可以用不同策略,比如让结果更具多样性(避免重复),但核心逻辑都很简单;
5. **查询引擎(query engine)**:这是信息检索的最佳实践——先检索索引,再把检索到的文本块传入模型,让模型“整理成自然语言回答用户,并进行推理”。这比以前“只返回检索结果”的方式高级多了,也很令人兴奋;
6. **运行器(runner)**:封装一个类,方便加载数据集、调整K值、构建索引、调用查询引擎。
使用时只需实例化类,指定数据目录,计时构建索引(有些索引需要“训练”,比如寻找聚类中心),然后就能以自然语言交互提问了。
我已经运行过代码了,用的是模拟数据(比如投资相关问题),模型能成功检索相关文本块并生成回答,还能持续接收新问题。关键是这个流程很简单:你可以自己运行,可以替换不同模型、不同嵌入方式、不同索引——FAISS这样的库让这一切变得很容易,再加上一个好用的嵌入模型,你可以尽情尝试。这个仓库是开源的,大家可以随意把玩、修改。
所以核心原则:别把提示词工程(包括RAG)复杂化,它们本质都是字符串操作。
还要验证你的假设:RAG真的能检索到正确信息吗?不一定。谷歌搜索也不是每次都准(这也是大家用ChatGPT的原因之一,开个玩笑)。当然,你可以花大量精力优化检索环节,达到谷歌级别的准确率,
但我个人不推荐——不如把精力放在模型侧:比如让模型在检索结果不佳时依然能生成有效回答,或者直接把数据融入模型权重(模型连互联网都能学,多学几篇甚至几百万篇文档又何妨)。而RAG的最大瓶颈其实是“嵌入向量生成”——提升这一步的吞吐量至关重要。我们也在大力优化这一点,确保大家能高效处理大规模数据。
关于框架:
很多框架会让提示词变得“不透明”(无论是否包含RAG),这不是好事——尤其是在使用开源模型时,或者从闭源模型迁移到开源模型时。比如你觉得“某个模型不如宣传的好”,可能只是因为你没做好RAG,
或者没正确迭代提示词(就像“没穿裤子”一样)。我自己是软件工程师出身,发现很多同行都有这个问题——总觉得是模型的问题,其实是自己的使用方式不对。
### 核心要点总结:
1. **给大语言模型“穿好裤子”**:
现在你知道“裤子”指的是标准化提示词模板(比如Llama的`<s>[INST]`标签),坚持使用这些模板,才能获得符合预期的输出和性能——因为模型就是这么微调或训练的,Meta、Anthropic等厂商会让模型学习这些标签的含义,并按对应的格式输出;
2. **提示词透明化**:
这是你的最大优势。提示词只是字符串,别复杂化。在代码库中确保提示词可查看、可修改、可打印,让团队所有人都能轻松调整;
3. **迭代式方法**:
像谷歌搜索一样,从“懒”和“粗糙”开始,逐步优化,并设定时间限制(避免边际效益递减);
4. **进阶技巧**:
如果觉得字符串操作不够,可以通过微调自定义“提示词规则”,为模型设计专属的“裤子”(标准化模板)。
以上就是我的分享,
非常感谢大家的聆听!
现在可以开始提问了——
#### 问题1:
非英语应用的大语言模型,系统提示词应该用目标语言编写,还是用英语编写并要求模型用目标语言回应?
我的回答还是回到“迭代”——
为什么不两种都试试?之所以强调“不提前设计,靠迭代验证”,是因为我们不完全清楚模型背后的微调细节。这是一个需要实证的问题,我建议你做AB测试:准备20-30个示例,
分别用英语系统提示词和目标语言系统提示词测试,对比效果。大语言模型的表现具有很强的实证性,而且因模型而异——比如Llama在多语言训练上做得更好,可能对目标语言系统提示词的支持更优。
#### 问题2:
对于即将发布的大语言模型,该如何理解其提示词工程?比如分析训练集等。
我认为,模型开发者应该尽可能透明:不仅开源权重,还要公开训练数据相关信息,至少要展示模型的“标准化提示词模板”(也就是“裤子”)。这其实对开发者有利——能让更多人看到模型的优秀性能,
我反而困惑为什么有些厂商不公开这些信息。对于使用者来说,方法还是一样:实证测试。我的框架是为不同用例准备测试集——未来的模型可能会更专业化,针对特定场景的测试集会比通用测试集更有效(毕竟通用模型要应对各种矛盾的需求,测试难度更大)。当然,你也可以用一些进阶技巧,比如分析训练集的主题分布,了解模型的知识覆盖范围。
#### 问题3:
能再举几个不同的“裤子”(标准化提示词模板)示例吗?
非常感谢大家能理解“裤子”这个比喻,给大家上点“虚拟熔岩”作为奖励!(屏幕展示熔岩特效)好,言归正传。
我没提到的一个重要示例是“多轮对话模板”——单轮对话的模板大家已经见过了,多轮对话的模板会更复杂,也有点反直觉(因为是厂商自定义的)。我可以凭记忆大致描述一下,之后也会把示例加到代码仓库里。这些模板大多是我从“半官方/半非官方”渠道找到的,其实如果能看到训练数据,肯定能发现更多。我也试过“诱导模型泄露自身提示词”(没太用力),相信有更专业的方法能做到。另外要说明的是,
有些模型可能没有复杂的多轮模板——厂商可能只训练了单轮模板,这也完全合理。
再补充一点:作为大语言模型开发者,你需要考虑“想给用户多少控制权”。比如Llama的开发者可能觉得“系统提示词很有用,能让模型切换不同身份,而不只是简单对话”,所以他们在微调时纳入了大量不同的系统提示词,让模型能适应各种自定义需求。因此,微调时要确保系统提示词的“分布多样性”,覆盖用户可能的使用场景。
#### 问题4:
如何解决提示词中的歧义、上下文偏移,以及确保提示词的语义准确性?
我得先确认一下我理解对了——你是想问“如何处理提示词本身的歧义、对话上下文的偏移,以及确保提示词传达的语义准确”,对吗?如果能有具体示例会更好,不过我可以基于通用情况回答。核心思路是“让提示词更明确”:比如减少模糊表述,补充必要背景信息,在多轮对话中适时总结上下文(避免偏移),还可以在提示词中明确“要求模型确认歧义点”。但说实话,这个问题有点宽泛,如果能有具体场景(比如某个歧义的提示词案例),我能给出更精准的建议。
好的,那我们今天的问答环节就到这里。非常感谢Sharon的精彩分享,
我们以后肯定还要邀请你回来,带来更多关于大语言模型(比如Llama)的课程。大家可以关注deeplearning.ai的后续活动,我们还有很多课程和分享即将上线。感谢大家的参与,下次再见!