通过 LLMs 实现需求的背后逻辑
date
Jun 27, 2023
slug
the-logic-behind-building-applications-with-LLMs
status
Published
summary
大型语言模型(LLMs)是目前最热门的人工智能领域。在这个领域中,已经逐渐形成了一个初具规模的生态系统。本文希望说清楚 AI 构建一个应用背后的逻辑,以此希望对后续产品思考和设计有所帮助,
tags
AI
LLMs
GPT
权限设计
物流
面试
type
Post
前言
大型语言模型(LLMs)是目前最热门的人工智能领域。在这个领域中,已经逐渐形成了一个初具规模的生态系统。本文并不是手把手教你如何通过 AI 构建一个应用,而是希望说清楚 AI 构建一个应用背后的逻辑,以此希望对后续产品思考和设计有所帮助,当然文中也包含代码,如果感兴趣也可以点击链接查看源代码了解更多内容。
如何通过 LangChain 构建应用
LangChain 是目前最热门的 LLMs 应用框架,甚至没有之一,如果想要深入了解 LLMs 构建应用,那么这一个框架是绕不开的,所幸这个框架入门非常简单,我下面会结合一些实际场景来说明一下。
LangChain 是什么?和大语言模型(LLMs)有什么关系?
LangChain 是一个基于大语言模型(LLMs)的应用框架,它本身不是大语言模型(LLMs),其主要作用是降低通过 LLMs 实现功能的开发成本,因此它可以对接多个 LLMs,对于产品来说可以降低被某一个 LLMs 影响整个产品的风险:
- ……
以上场景可能在产品中被使用,因此作为产品团队,我们可以通过了解 LangChain 的实现底层逻辑、可行性和限制来预先规划,并帮助未来的产品设计工作。以下将以通过 LangChain 实现文档问答机器人为例。
通过 LangChain 实现文档问答机器人
首先需要做的还是数据清洗+存储
这里涉及到一个知识点是向量,关于向量的具体原理可以去网上查找,资料很多,如果不想找的话可以暂时只记住向量计算主要是计算内容之间的相似程度即可。
而向量在这里主要是降低 AI 使用费用的,因为如果要将所有文档都告诉 AI,一个是很多模型的上下文长度不够,另外一方面是由于成本实在太高了。因此当我们将文档交给 LLMs 转化成向量后,如果有一个地方进行存储,这就是向量数据库了。
目前比较火热的向量数据库有很多:付费的有Pincone,免费的有 Redis、Chroma、PostgreSQL 等,具体区别和差异就是另外一个话题了。
接下来我们来模拟一下真实的用户使用流程,看看如何利用这些向量并结合 LLMs 优化用户问答体验:
下面我将通过 LangChain 实现上面的流程:https://github.com/xukecheng/APITable-LLMs-Enhancement-Experiments/blob/main/apitable_devbook_vector_db_qa_with_sources.ipynb
当然这里还有一份 OpenAI 官方的实例可以参考:https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_embeddings.ipynb。
通过上述流程,可以方便快捷地实现一个文档问答系统,甚至可初步投入使用。然而,我们也需要了解该模式的缺点。因为得失常并存,例如采用向量数据库降低 LLMs 使用费用时,会失去聊天上下文的便利性:通过上面对于整体的流程说明后,可以知道我们主要工作是需要根据用户问题获取相关文档内容,那么假如实现聊天上下文,用户首先问如何实现表格内快速查找替换,然后我们返回了相关文档,再然后用户又问了一个关于如何合并单元格的问题,此时的 Prompt = 第一个问题 + 第一个问题的相关文档 + 第二个问题,如果此时将 Prompt 直接发送给 LLMs 获取向量必定是不准确的,因此就需要做更精细的 Prompt 管理,例如说只将第二个问题单独发给 LLMs 获取向量再进行对比获取相关文档,然后组成新的 Prompt = 第一个问题 + 第一个问题的相关文档 + 第二个问题 + 第二个问题的相关文档,以此组成聊天上下文发送给 LLMs 获取最终答案。
在市场上,文档 + AI 这一需求在市面上也催生出了一些 SaaS 产品,有些甚至已经有了不少的用户,比如说 LangChain 官方文档网站中使用的产品:https://www.mendable.ai/。
Fine-tuning(微调)
上面主要是关于 AI 技术中关于向量(Embeddings)相关的应用,向量是一种很强大的工具可以用在很多其他方面:内容推荐、文本比较、数据分析等。而另外一个需要厘清的技术是微调(Fine-tuning)。在 OpenAI 开放 API 的初期,绝大部分人以为微调就是可以让 GPT 按照自己提供的数据集回答问题,但其实微调并不是做这个的,相反向量计算才是做这个,从上面的示例中也能看到。
官方也有提到:Although fine-tuning can feel like the more natural option—training on data is how GPT learned all of its other knowledge, after all—we generally do not recommend it as a way to teach the model knowledge. Fine-tuning is better suited to teaching specialized tasks or styles, and is less reliable for factual recall.
那么微调到底是做什么的呢?从目前网上的实践经验来看,我发现微调主要是可以让 GPT 模型对于特定领域的内容有着更好的理解能力和更适当的表达方式:比如说可以通过一定的语料加强模型对于中文的理解,例如去识别评论里的阴阳怪气、反问并准确地做出情感分析。
而要实现这一点,也需要准备海量的优质训练文本,训练文本越多,微调的价格也越高,根据我在网上看到的实践来看,要达到一定的效果需要数百到数千美元不等,且不含购买或准备训练文本的费用。
因此,很多时候 Embeddings 或 Prompt Engineering 才是性价比更高的选择。
OpenAI Function Calling 对于构建应用的影响
LLMs 目前的领头羊 OpenAI 在本月进行了一次 API 方面的更新,更新内容包含新增 mode、降价等等,但是其中对于构建产品来说最重要的更新是支持 16K 上下文和 Chat Completions API 新增函数调用功能,前者支持了更多上下文,后者则有可能改变使用 AI 构建产品的方式。
函数调用并不是指 GPT 会直接帮你调用功能或接口,而是需要你告诉 GPT 有哪些函数以及每个函数的具体信息。然后输入用户问题,GPT 能够根据用户问题准确匹配出应该使用哪个函数,并为你准备好相应的入参。然后,你只需将入参发送给对应的函数执行,完成后将结果返回给 GPT,它就会自动匹配相应结果并呈现给用户。
有什么用呢?
这个可以大大的降低通过 AI 构建应用成本,比如说我之前想实现 AI 通过操作 APITable Fusion API 实现语义化查询表格,我应该怎么做?
说实话,这个在 Function Calling 出来之前也是成功通过 LangChain 实现了的,且基本逻辑和 Function Calling 较为类似,首先是定义一组工具,包括获取空间站、获取表格、获取记录、获取字段等,然后基本 ReAct 原理设计 Prompt,并且将工具说明注入到 Prompt 中,然后就是交给 LLMs 自行循环推理+本地执行了。但是最终实现的效果不算理想,一个是不够稳定,另一方面是由于 ReAct 和工具的原因导致耗费的 token 过多,同时在很多时候总是需要几轮会话下来 AI 才能成功解决一个问题(gpt-3.5-turbo),一个问题往往可能需要几个回合,其中不成功的原因主要包括返回数据不是 JSON 需要告知并让其重新组织数据、经常出现人工智能幻觉等等:https://github.com/xukecheng/APITable-LLMs-Enhancement-Experiments/blob/main/apitable_langchain_toolkit.ipynb。
而使用 Function Calling 就不一样了,由于是 OpenAI 官方推出的能力,理应有着更好的问题→方法的推理能力,如果顺利的话,理想的用户流程应该如下:
- 准备方法:获取空间站、获取表格、获取记录、获取字段
- 用户问题:我想要 XX 空间站中 XX 表的最新数据。
- APITable:把用户问题和上述函数定义传给 GPT
- GPT:根据用户问题判断是否应用使用函数,应该用哪个?怎么用?然后把结果发过来
- APITable:根据 GPT 的结果本地(服务端)调用对应的函数,然后获取到结果并发送给 GPT
- GPT:获取调用结果,返回最终回复
- APITable:发送最终回复给用户
下面这两个是我的一些实践过程:
我分别使用了 OpenAI API 和 LangChain 两种形式去实现,发现最终效果还算符合预期,一个是对问题的理解很准确,能够准确地调用对应的方法,另外一个就是 token 的消耗比之前少很多。
当然也存在一些问题:
- 使用 OpenAI 提供的 API 来实现复杂问题(通常需要多个方法联合解决)时无法判断 AI 返回的结果是否完成,因此有可能还需要继续调用才能得出最终结果,但是 API 中并不能给出任何标记说明是否需要继续请求 API,此时就需要使用结合了 ReAct 的 LangChain。
- LangChain 定义方法的方式和官方不太一样,需要通过定义 LangChain 中的 Tool 类型,再由 LangChain 自行转换传给 OpenAI,但是过程中发现转换似乎有些问题
总结
需要着重说明的是上面的应用其实仅仅停留在 Demo 阶段。如果我们想进一步将其打造成一个可用的产品,就需要考虑到许多其他问题。例如:
- 文本的检索直接影响问答的质量,我们应该如何对其进行优化,优化向量检索?提高文本质量?
- 不同的 Prompt 对结果有很大影响,如何进行有效的效果评估也很重要。
- 从成本上来说,自己训练一个 LLM 的成本目前来说不太现实,因此暂时只能优先考虑使用 OpenAI 一类的 LLMs 服务提供商,但是他们基本都是按照用量付费,也就是说随着产品的用量增加,计算和存储的成本也会逐渐增加,如何保证入能敷出也是一个问题。
- 现在虽然已经有国内的产品接入了 GPT,但是这可能处于监管灰色地带,暂无确定的条例允许这一行为,这也是一个高风险事项。
- 目前绝大部分能力都是通过 API 实现,并不存在任何实质上的壁垒,因此和产品的结合才是更加重要的思考点
总的来说,根据我的实践经验,将人工智能应用到实际场景并不像传闻中那么简单。无论市面上声称只需几百行代码搭建一个应用还是我今天演示的只是个玩具,要开发出可用的产品仍需要做更多的工作。