讲透大模型应用开发:新时代技术核心竞争力

目录

1 前言

2 大模型如何在业务中发挥作用

3 普通程序员应该关注的机会

4 总结

最近几年,大模型在技术领域的火热程度属于一骑绝尘遥遥领先,它已经深刻地影响了“编程”领域,且正在各个领域迅速渗透。与此同时,普通开发者也变得非常地焦虑,因为实实在在感受到了它强大的威力,担心哪天自己就被取代。与其担忧,我们不如主动拥抱这种技术变革。

前言

最近几年,大模型在技术领域的火热程度属于一骑绝尘遥遥领先,不论是各种技术论坛还是开源项目,大多都围绕着大模型展开。大模型的长期目标是实现 AGI,这可能还有挺长的路要走,但是眼下它已经深刻地影响了“编程”领域。各种 copilot 显著地提升了开发者的效率,但与此同时,开发者也变得非常地焦虑。因为开发者们实实在在感受到了它强大的能力,虽然目前只能辅助还有很多问题,但随着模型能力的增强,以后哪天会不会就失业了?与其担忧,我们不如主动拥抱这种技术变革。

但是很多人又会打退堂鼓:研究 AI 的门槛太高了,而大模型属于 AI 领域皇冠上的明珠,可能需要深厚的数学和理论基础。自己的微积分线性代数概率论这三板斧早都忘光了,连一个最基础的神经网络反向传播的原理都看不懂,还怎么拥抱变革?

其实大可不必担心,不论大模型吹得如何天花乱坠,还是需要把它接入到业务中才能产生真正的价值,而这归根到底还是依赖我们基于它之上去做应用开发。而基于大模型做业务开发,并不依赖我们对 AI 领域有深入的前置了解。就好比我们做后台业务开发,说到底就是对数据库增删改查,数据库是关键中的关键。理论上你需要懂它了解它,但其实你啥也不懂也没太大影响,只是“天花板低“而已,有些复杂场景你就优化不了。基于大模型做应用开发也是一样,你不需要了解大模型本身的原理,但是怎么结合它来实现业务功能,则是开发者需要关心的。

本文是给所有非 AI 相关背景的开发人员写的一个入门指南,目标是大家读完之后能够很清晰地明白以下几点:

  • 参与大模型应用开发,无需任何 AI 和数学知识背景,不必担心学习门槛。

  • 了解基于LLM的应用开发的流程、各个环节,最后可以自信地说:我行我上啊。

  • 大模型怎么和具体业务知识结合起来,实现用户真正需要的功能——RAG

  • 我们广大非 AI 背景的开发人员,在大模型的浪潮中如果想卷一下,发力点在哪里——AI Agent

大模型如何在业务中发挥作用

目前的大语言模型,几乎都是以聊天地方式来和用户进行交互的,这也是为什么 OpenAI 开发的大模型产品叫 ChatGPT,核心就是 Chat。而我们基于大语言模型 LLM 开发应用,核心就是利用大模型的语义理解能力和推理能力,帮我们解决一些难以用“标准流程”去解决的问题,这些问题通常涉及:理解非结构化数据、分析推理 等。

一个典型的大模型应用架构如下图所示,其实和我们平时开发的应用没什么两样。我们平时开发应用,也是处理用户请求,然后调用其它服务实现具体功能。在这个图中,大模型也就是一个普通的下游服务。

图片

不过像上图的应用,没有实际的业务价值,通常只是用来解决的网络连不通的问题,提供一个代理。真正基于大模型做应用开发,需要把它放到特定的业务场景中,利用它的理解和推理能力来实现某些功能。

   2.1 最简单的大模型应用

下图就是一个最简单的 LLM 应用:

图片

和原始的 LLM 的区别在于,它支持 联网搜索。可能大家之前也接触过可以联网搜索的大模型,觉得这也没啥,应该就是大模型的新版本和老版本的区别。其实不然,我们可以把大模型想象成一个有智慧的人,而人只能基于自己过去的经验和认知来回答问题,对于没学过或没接触过的问题,要么就是靠推理要么就是胡说八道。大语言模型的“智慧”完全来自于训练它的数据,对于那些训练数据之外的,它只能靠推理,这也是大家经常吐槽它“一本正经的胡说八道”的原因——它自身没有能力获取外界的新知识。但假如回答问题时有一个搜索引擎可供它使用,对于不确定的问题直接去联网搜,最后问答问题就很简单了。

带联网功能的聊天大模型就是这样一种“大模型应用”,看起来也是聊天机器人,但其实它是通过应用代码进行增强过的机器人:

图片

从图中可以看到,为了给用户的问题生成回答,实际上应用和 LLM 进行了两轮交互。第一轮是把原始问题给大模型,大模型分析问题然后告诉应用需要联网去搜索什么关键词(如果大模型觉得不需要搜索,也可以直接输出答案)。应用侧使用大模型给的搜索关键词 调用外部 API 执行搜索,并把结果发给大模型。最后大模型基于搜索的结果,再推理分析给出最终的回答。

从这里例子中我们可以看到一个基于大模型开发应用的基本思路:应用和大模型按需进行多轮交互,应用侧主要负责提供外部数据或执行具体操作,大模型负责推理和发号施令。

   2.2 怎么和 LLM 进行协作——Prompt Engineering

以我们平时写代码为例,为了实现一个功能,我们通常会和下游服务进行多次交互,每次调不通的接口实现不同的功能:

func AddScore(uid string, score int) {
  
      // 第一次交互    user := userService.GetUserInfo(uid)    // 应用本身逻辑    newScore := user.score + score    // 第二次交互    userService.UpdateScore(uid, score)}

如果从我们习惯的开发视角来讲,当要开发前面所说的联网搜索 LLM 应用时,我们期望大模型能提供这样的 API 服务:

service SearchLLM {
  
    // 根据问题生成搜索关键词  rpc GetSearchKeywords(Question) Keywords;  // 参考搜索结果 对问题进行回答  rpc Summarize(QuestionAndSearchResult) Answer;}

有了这样的服务,我们就能很轻易地完成开发了。但是,大模型只会聊天,它只提供了个聊天接口,接受你的问题,然后以文本的形式给你返回它的回答。那怎么样才能让大模型提供我们期望的接口?——答案就是靠 “话术(嘴遁)”,也叫 Prompt(提示词)。因为大模型足够 “智能”,只要你能够描述清楚,它就可以按照你的指示来 “做事”,包括按照你指定的格式来返回答案。

我们先从最简单的例子讲起——让大模型返回确定的数据格式。

让大模型返回确定的数据格式

简单讲就是你在提问的时候就明确告诉它要用什么格式返回答案,理论上有无数种方式,但是归纳起来其实就两种方式:

Zero-shot Prompting (零样本提示)。

Few-shot Learning/Prompting (少样本学习/提示)。

这个是比较学术比较抽象的叫法,其实它们很简单,但是你用 zero-shot、few-shot 这种词,就会显得很专业。

Zero-shot

直接看个 Prompt 的例子:​​​​​​​

帮我把下面一句话的主语谓语宾语提取出来要求以这样的json输出:{"subject":"","predicate":"","object":""}---
这段话是:我喜欢唱跳rap和打篮球

在这个例子中,所谓的 zero-shot,我没给它可以参考的示例,直接就说明我的要求,让它照此要求来进行输出。与只对应的 few-shot 其实就是多加了些例子。

Few-shot

比如如下的 prompt:​​​​​​​

帮我解析以下内容,提取出关键信息,并用JSON格式输出。给你些例子:
input: 我想去趟北京,但是最近成都出发的机票都好贵啊output: {"from":"成都","to":"北京"}
input: 我看了下机票,成都直飞是2800,但是从香港中转一下再到新西兰要便宜好几百output: {"from":"成都","to":"新西兰"}
input: 之前飞新加坡才2000,现在飞三亚居然要单程3000,堂堂首都票价居然如此高昂,我得大出血了output: {"from":"北京","to":"三亚"}

从这个 prompt 中可以看到,我并没有明确地告诉大模型要提取什么信息。但是从这3个例子中,它应该可以分析出来2件事:

  • {"from":"","to":""}这种 JSON 格式输出。

  • 提取的是用户真正的出发地目的地

这种在 prompt 中给出一些具体示例让模型去学习的方式,这就是所谓的 few-shot。不过,不论是 zero-shot 还是 few-shot,其核心都在于 更明确地给大模型布置任务,从而让它生成符合我们预期的内容。当然,约定明确的返回格式很重要但这只是指挥大模型做事的一小步,为了让它能够完成复杂的工作,我们还需要更多的指令。

怎么和大模型约定多轮交互的复杂任务

回到最初联网搜索的应用的例子,我给出一个完整的 prompt,你需要仔细阅读这个 prompt,然后就知道是怎么回事了:​​​​​​​

你是一个具有搜索能力的智能助手。你将处理两种类型的输入:用户的问题 和 联网搜索的结果。
1. 我给你的输入格式包含两种:1.1 用户查询:{
  
      "type": "user_query",    "query": "用户的问题"}
1.2 搜索结果:{
  
      "type": "search_result",    "search_keywords": ["使用的搜索关键词"],    "results": [        {
  
              "title": "搜索结果标题",            "snippet": "搜索结果摘要",            "url": "来源URL",        }    ],    "search_count": number  // 当前第几次搜索}
2. 你需要按如下格式给我输出结果:{
  
      "need_search": bool,    "search_keywords": ["关键词1", "关键词2"],  // 当need_search为true时必须提供    "final_answer": "最终答案",  // 当need_search为false时提供    "search_count": number,  // 当前是第几次搜索,从1开始    "sources": [  // 当提供final_answer时,列出使用的信息来源        {
  
              "url": "来源URL",            "title": "标题"        }    ]}
3. 处理规则:- 收到"user_query"类型输入时:  * 如果以你的知识储备可以很确定的回答,则直接回答  * 如果你判断需要进一步搜索,则提供精确的search_keywords  - 收到"search_result"类型输入时:  * 分析搜索结果  * 判断信息是否足够  * 如果信息不足且未达到搜索次数限制,提供新的搜索关键词  * 如果信息足够或达到搜索限制,提供最终答案
4. 搜索限制:- 最多进行3次搜索- 当search_count达到3次时,必须给出最终答案- 每次搜索关键词应该基于之前搜索结果进行优化
5. 注意事项:- 每次搜索的关键词应该更加精确或补充不足的信息- 最终答案应该综合所有搜索结果

看完这个 prompt,假如 LLM 真的可以完全按照 prompt 来做事,可能你脑子中很快就能想到应用代码大概要如何写了(伪代码省略海量细节):​​​​​​​

const SYSTEM_PROMPT = "刚才的一大段提示词"
async function chatWithSearch(query, maxSearches = 3) {
  
    // 初始调用,给
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

呱牛 do IT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值