利用客户端技术开发基于大语言模型(LLM)的 Web 应用 [译]

2023 年 10 月 13 日

这篇文章是由 Jacob Lee 编写的客座博客,他是 @LangChainAI 的 JS/TS 维护人员,曾是 @Autocode 的联合创始人及首席技术官,并且曾在 Google Photos 团队担任工程师。

最初,这篇文章是作为 Google 内部的 WebML 峰会 2023 演讲内容,感兴趣的读者可以点击下面的链接观看:

Google 内部 WebML 峰会 2023
Google 内部 WebML 峰会 2023

长久以来,机器学习领域几乎被 Python 独霸,但随着 ChatGPT 的迅速崛起,许多开发者涌入这个新领域。由于 JavaScript 是最广泛使用的编程语言,包括众多网页开发者在内的人们纷纷尝试开发 Web 应用。

虽然关于通过 OpenAI、Anthropic、Google 等公司的 API 调用 LLM 来构建应用的文章层出不穷,但我选择了一条不同的道路,尝试仅使用本地模型和技术来构建网页应用,尤其是那些能在浏览器中运行的技术!

为何选择这种方式?

使用这种方法的主要优势包括:

  1. 成本低廉。所有计算和推理都在客户端完成,开发者在构建应用时除了极低的托管费用外,无需承担额外成本。
  2. 保障隐私。无需将任何数据发送出用户的本地机器!
  3. 由于无需进行 HTTP 调用,可能提高速度。
    1. 但由于用户硬件的限制,这可能导致推理速度有所降低。

项目介绍

我尝试重新实现 LangChain 中一个极受欢迎的应用场景:使用开源和本地运行的软件来实现一个执行检索增强生成(Retrieval-Augmented Generation,简称 RAG)的链条,让你能“与你的文档对话”。这样你就可以从各种非结构化格式的数据中提取信息。

这个示例项目的架构
这个示例项目的架构

数据录入过程

我们的第一步是加载数据,并将其格式化成可以后续通过自然语言进行查询的形式。这个过程主要包括以下几个步骤:

  1. 将文档(PDF、网页或其他形式的数据)切分成含有独立意义的小块。
  2. 利用一种叫做嵌入模型(embeddings model)的技术,为每一小块生成向量形式的表示。
  3. 把这些小块及其向量表示加载到一个特殊的数据库——向量存储(vector store)里。

这个初步的过程需要几个关键部件:文本切分工具、嵌入模型和向量存储。好消息是,这些工具都已经能在浏览器友好的 JavaScript 环境中使用了!

LangChain 负责处理文档的加载与切分。至于嵌入模型,我采用了一个由 HuggingFace 开发的小型嵌入模型,并通过 Xenova 的 Transformers.js 包 进行量化处理,使其能在浏览器中运行。关于向量存储,我选用了一个名为 Voy 的非常先进的 Web Assembly 向量存储工具。

数据检索与生成的实现

在建立了数据加载流程之后,我接下来的任务是对这些数据进行查询:

描述数据检索和生成过程的图表
描述数据检索和生成过程的图表

核心思想是这样的:拿用户提出的问题,在我们精心构建的向量库中寻找与问题在语义上最匹配的文档片段。然后,结合这些检索到的片段和原始问题,引导大语言模型 (LLM) 根据我们的输入数据给出最终答案。

对于那些含有代词或涉及之前聊天记录的后续提问,我们还需要一个额外的步骤。由于向量库是基于语义相似性进行检索的,这些间接提及可能会影响检索结果。因此,我们增加了一个步骤,先将问题转化为一个独立的问题,然后再利用这个问题在向量库中进行搜索。

找到一个合适的能在浏览器中运行的大语言模型相当有挑战性。因为功能强大的大语言模型通常体积庞大,而且我发现通过 HuggingFace 提供的模型无法生成满意的回答。尽管 核心技术是机器学习编译 的 WebLLM 项目看似有潜力,但它要求在页面加载时下载大量的数据,这导致了极大的延迟。

Jacob 的终端界面截图
Jacob 的终端界面截图

此前,我尝试过使用 Ollama 作为一种简便的方式来运行本地模型。当我得知它可以通过一个简单的 shell 命令将本地运行的模型与 Web 应用连接时,我感到很惊喜。我将其接入后发现,这正是我所需要的!我启动了更先进的 Mistral 7B 模型,它在我的 16GB M2 Macbook Pro 上运行得非常流畅,最终构建了如下的本地系统:

展示了使用全本地 RAG、langchain 和 ollama 所能达成的配置图表
展示了使用全本地 RAG、langchain 和 ollama 所能达成的配置图表

结果

你现在可以在 Vercel 上体验 Next.js 应用程序的实时版本了:

https://webml-demo.vercel.app

要实现这一功能,你需要在本地通过 Ollama 运行 Mistral 实例,并执行以下命令以解决 CORS 问题,使其能够被特定域名访问:

$ ollama run mistral
$ OLLAMA_ORIGINS=https://webml-demo.vercel.app OLLAMA_HOST=127.0.0.1:11435 ollama serve

我还在我们的可观测性和追踪平台 LangSmith(https://smith.langchain.com/)中分享了几个使用我的个人简历作为输入的问题示例:

  1. “这篇简历是关于谁的?”
    1. https://smith.langchain.com/public/2386b1de-7afb-48a2-8c83-205162bfcac0/r
  2. “简历主人懂 JavaScript 吗?”
    1. https://smith.langchain.com/public/18cec162-d12c-4034-aa9a-39b1cd2011ea/r

结论

总的来说,这个项目运行效果不错。有几点我观察到的:

  • 开源模型正迅速进步 - 我最初是用 Llama 2 开发这个应用的,而 Mistral 模型在几周后就发布了。
  • 越来越多的消费电子产品开始配备 GPU。
  • 随着开源模型变得更小更快,使用工具如 Ollama 在本地硬件上运行这些模型的趋势将越来越明显。
  • 虽然最近几个月浏览器友好的向量存储、嵌入及其他特定任务模型取得了巨大进展,但大语言模型 (LLM) 依然太大,不适合直接打包到 Web 应用中。

目前看来,Web 应用要想利用本地模型,可行的方法似乎是我上述的那种方式,即通过应用程序来访问一个强大的、预先安装的大语言模型。

浏览器新功能?大语言模型的本地应用

针对不擅长运行 shell 命令的普通网页用户,一个理想的解决方案可能是开发一种新的浏览器 API。这样,网页应用就可以请求连接到本地运行的大语言模型(LLM),比如通过一个弹窗,再将这种强大功能与浏览器内其他针对特定任务的模型和技术相结合。

示意图:展示 Chrome 浏览器和 Ollama 如何相互作用
示意图:展示 Chrome 浏览器和 Ollama 如何相互作用

感谢您的阅读!

我对大语言模型(LLM)推动的网络应用的未来充满期待,尤其是技术如 Ollama 和 LangChain 如何促进全新的用户交互体验。

以下是应用中使用到的一些重要链接:

欢迎与 Jacob Lee@LangChainAI 保持联系。