大模型上层工具链调研 - langchain, llama-index

langchain 基于 0.0.109 版本

一个基于LLMs的应用程序开发框架, 通过可组合性来使用LLM构建应用程序. 其重点在于"可组合性"

大型语言模型 (LLM) 正在作为一种变革性技术出现,使开发人员能够构建他们以前无法构建的应用程序。但是单独使用这些 LLM 通常不足以创建真正强大的应用程序,当可以将它们与其他计算或知识来源相结合时,就有真的价值了。LangChain 旨在协助开发这些类型的应用程序.

其主要包含六个部分:

  1. LLMs和prompt, 对所有大模型的通用交互接口, 以及prompt管理,优化等等
  2. chains, 一系列的调用(LLMs或者其他, 如网络, 操作系统), chains提供了标准的接口和设置来组合这些调用.
  3. data augmented generation 基于特定数据的内容生成, 一种特殊的chain, 提供了一种能力: 先从外部的源获取信息, 然后喂给LLMs
  4. agents, 代理, 非常重要的一环, 关于对LLMs做何种action, 如何做
  5. memory 标准的接口, 在chains/call之间保存状态
  6. Evaluation 提供了一些prompts/chains来利用模型来评估自身

prompt templates

ChatGPT 提供了通过 prompts 来进行提示的方法,也就是在发起请求时,可以带上一段信息。由于是一个聊天接口,因此可以包含多个聊天的内容。其中包括来自系统的提示:例如用来描述一下 ChatGPT 现在是什么角色,应该具有什么样的语言风格等。另外还可以包含一些用户的历史聊天记录,就像背景知识一类的,都可以作为用户的输入带进去,这样可以使得 ChatGPT 在本次聊天中具有了领域知识与上下文信息。通过这种 prompts 的方式,可以对 ChatGPT 有一定的定制能力,并使用其大模型的自然语言能力来组织回答信息。

prompt template是简化和用户的交互, 用户提出核心问题, template 渲染问题, 增加上下文信息, 历史聊天信息, 背景知识等等.

chains

简单应用可能对LLM进行一次调用即可, 而复杂应用往往需要串联LLMs(相互连接或者和其他的专家系统). langchain为此提供了一套标准的接口和通用的实现.

chain还细分为两类: 通用任务chain 和 专有工具chain ,前者更多用来组织任务顺序, 后者则专注在对某个工具的调用上.

  • LLMChain: 简单接受template和用户输入, 调用LLM, 返回输出
  • SequentialChain: 组合chains, 发起一系列且有顺序的调用请求
    SimpleSequentialChain(chains=[chain, chain_two], verbose=True)
  • BashChain: 使用LLMs 以及 调用bash命令
  • LLMRequestsChain: 发起调用, 之后将结果输送给后来的chain.
  • .........
  • 自定义chain:
    • 继承Chain
    • 实现input_keys和output_keys (前者接收先前chains的输出, 后者给到后来chains作为输入)
    • 补全调用实现_call ( _call是chain运行会调用的方法)

chain可以很简单地理解为 过程的抽象, chains的可组合性, 就是过程的组合.

agents

use LLM to determine which actions to take and in what order. An action can either be using a tool and observing its output, or returning to the user.

搭配上能理解用户输入的大模型, agents接受大模型输出的指令, 可以打造强大的个人助理程序.

concepts

Tool : A function that performs a specific duty. This can be things like: Google Search, Database lookup, Python REPL, other chains. The interface for a tool is currently a function that is expected to have a string as an input, with a string as an output.
工具, 可以执行某种特定任务. 当下, 可以理解为一个 string => string的函数. 内置的工具:
https://langchain.readthedocs.io/en/latest/modules/agents/tools.html
可以: 发起调用, http请求, 搜索内容, 执行代码(python), etc.

LLM : The language model powering the agent.

Agent : The agent to use. This should be a string that references a support agent class. Because this notebook focuses on the simplest, highest level API, this only covers using the standard supported agents. If you want to implement a custom agent, see the documentation for custom agents (coming soon).
用来调用工具的代理, 如果标准库里没有合适的工具代理, 可以自定义.
内置代理类型:

  • zero-shot-react-description 根据工具的描述, 和请求的string 来决定使用哪个工具
  • react-docstore 使用react框架, 和docstore交互, 使用SearchLookup 工具, 前者用来搜, 后者寻找term, 举例: Wipipedia工具
  • self-ask-with-search 此代理只使用一个工具: Intermediate Answer, 它会为问题寻找事实答案(指的非gpt生成的答案, 而是在网络中,文本中已存在的), 如 Google search API 工具
  • conversational-react-description 为会话设置而设计的代理, 它的prompt会被设计的具有会话性, 且还是会使用 ReAct框架来决定使用来个工具, 并且将过往的会话交互存入内存.

https://langchain.readthedocs.io/en/latest/modules/agents/agents.html

举例

与向量数据库交互

希望应用程序, 在使用LLM的过程中, 和向量数据库交互(其实, 不用langchain库, 自己编写很简单的代码就可以做到) 只是langchain库在多数向量库之上, 包装了一层统一的交互接口.
https://langchain.readthedocs.io/en/latest/modules/agents/examples/agent_vectorstore.html

如下代码所示 , 两个tool被创建, 组合成工具包, 两个工具, 分别是"SOU的qa"和 "Ruff的qa", 他们会分别阅读SOU和Ruff网站的内容, 并且调用LLM的向量接口, 生成向量, 存于本地数据库. 然后使用特定种类的agent作为某种路由, 可以按工具描述使用他们.

tools = [
    Tool(
        name = "State of Union QA System",
        func=state_of_union.run,
        description="useful for when you need to answer questions about the most recent state of the union address. Input should be a fully formed question."
    ),
    Tool(
        name = "Ruff QA System",
        func=ruff.run,
        description="useful for when you need to answer questions about ruff (a python linter). Input should be a fully formed question."
    ),
]

agent = initialize_agent(tools, llm, agent="zero-shot-react-description", verbose=True)
agent.run("What did biden say about ketanji brown jackson is the state of the union address?")
先搜再问 - data agumented generation

对于某些大模型没有的信息或者知识, 如果要补充这些信息, 需要重新训练模型, 成本比较高, 但是可以通过prompt的方式给到它, langchain为了方便上层开发应用, 设计了self-ask-with-search代理, 即先到某个知识库去获取相关的信息和知识, 然后利用LLM来理解这些知识和信息,然后回答用户的问题.

memory

chain和agent是无状态的, LLM模型也是, 所以需要prompt来进行历史提示.
Chains and Agents are stateless, meaning that they treat each incoming query independently (as are the underlying LLMs and chat models).
memory模块提供了两种能力:

  1. 模块化管理和操作先前的对话的工具
  2. 将这些工具集成到chain里的设施

示例

https://langchain.readthedocs.io/en/latest/modules/memory/types/buffer.html
从示例中可以看出, langchain将对话保存在模块化的memory中, 并且在predict的时候, 自动带上历史会话, 作为prompt.

总结

关于agent和chains的差异,尤其是utils chain
agent是关于对LLM做何种action, 怎么做action, 在于挑选工具. chain重点是对输入做处理 , 并且组织各个过程的顺序.

data augemented generation

LLMs是基于大量非结构化的语料训练的, 所以对通用的nlp任务有很好的的效果, 然而很多时候, 我们需要的不是在利用通用数据来生成结果, 而是基于特定的数据来产生结果.

  • Summarization of a specific piece of text (a website, a private document, etc.)
  • Question answering over a specific piece of text (a website, a private document, etc.)
  • Question answering over multiple pieces of text (multiple websites, multiple private documents, etc.)
  • Using the results of some external call to an API (results from a SQL query, etc.)
    即, 不希望模型仅仅通过其训练的数据来生成文本, 而要把某些外部的数据也结合进去, 所以步骤可以拆解为两步:
  1. fetching: 取回
  2. user provided
  3. document retrival
  4. api querying
  5. augmenting: 传递给LLM

fetching

在fetching过程中, 比较重要的是取回的文档不能太大, 因为目前的模型都对输入的长度有限制, 所以 langchain提供了各种工具来split文档成一片一片, 并且控制每片中的内容重叠(保持上下文). 另外一个是, 不能取回太多的文档, 最好只选取和问题相关的文档, 即相关度要高, 有比较多的方式来做这件事, 当下比较流行的是:
在语义搜索和Q&A系统中, 将语料的doc切分成chunk, 将chunk向量化, 然后存储, 之后用户的输入到来后, 首先进行向量化的相关性搜索, 将搜索的结果以及用户数据一起作为prompt作为输入喂给LLM, 这是目前常见的做法, 但业界也在考虑转为大模型设计的数据结构和索引技术, 详见 LlamaIndex

几个开源项目:

LlamaIndex -> 专注在数据层

对于私有数据, 受限于LLM的无状态, 训练代价大, token个数限制, 甚至fine-tune的接口不开放等等, 对于私有数据上的内容生成, 现在常见的做法是embedding文档, 先搜后问, 也即上文提到的langchain的一个核心模块: data augementing generation. 与此同时, LlamaIndex在考虑为LLM设计的数据结构和索引.

现在想要增强LLM在私有数据上的表现能力, 有两种方式: fine-tune 和 in-context learning (即将上下文放入输入的prompt中) .
为了更好地(高效,便宜)进行data augmentation, 想要解决: 数据摄取和索引. LlamaIndex提供的工具:

  • data connectors : 连接到数据源, 和不同的数据格式
  • 利用LLM来给结构化,非结构化数据做索引. 简化了in-context learning过程中繁琐的细节: prompt长度, 文本拆分,etc
  • 用户优化的索引query 接口 和 模型调用接口的结合
  • 一个权衡成本和性能的全面的工具集

不同于langchain的全面开发, 均衡发展策略, llama-index更像是专注在data augmentation generation, 围绕它来开发周边对应的能力. 即丰富的数据源和数据格式的读取器, 统一的index表示, 花式的index读取, 写入.

smart agents -> 专注在agents

https://www.fixie.ai/

Build natural language agents that connect to your data, talk to APIs, and solve complex problems.

和Llama-index类似, 不过专注在agents, 准备构建一个agents market, 在大模型之上构建一个软件系统, 可以和其它系统交互, 完成复杂任务.

目前资料较少

总结

GPT Index vs LangChain 的区别:

根本上是因为 大语言模型支持的context有限,比如ChatGPT的Davinci model只有 4096 tokens,对应中文,可能只有2000

“A big limitation of LLMs is context size (e.g. Davinci's limit is 4096 tokens. Large, but not infinite).”

  1. 如果单纯的跟GPT模型对接,那直接用 GPT 的 Davinci 模型直接对话就行;ChatGPT 只是 GPT 其中一个 chat-model 而已

  2. 如果需要借助GPT语言模型+私有数据,那就需要突破 4096 tokens 的限制,也就是 feed "knowledge" to LLMs,所以需要用上 GPT Index

与此同时,在用 ChatGPT 时,单次输入的 prompt 也有限制,所以 GPT Index 可以简化这个 feed 喂数据的过程。

  1. 如果 GPT 直接就满足要求,可以用 GPT Index,就够了。

那为什么还有用上 LangChain 呢?就是因为 LLMs 不止 OpenAI 的 GPT 模型,LangChain 可以对接多种模型,即 Lang

而 Chain 的意思就是把多个 LLM 调用,而且是调用序列,标准化,集成等工作,最后串起来

  1. LangChain 还做了很多框架层面的工作:Prompt、Loader、Chain、Agent、Memory

比如 Loader 部分,它也推出了跟 https://llamahub.ai 类似的 https://github.com/hwchase17/langchain-hub,用来集成外部数据。区别就在于 GPT Index 能用的,LangChain 都能用,LangChain 的 Loader 能加载其他语言模型,是 GPT 的超集。

再比如 Memory 部分,就是用来持久化 内存 状态,所以能实现 ChatGPT 聊天机器人这样的功能,记住以前的交互非常重要,无论是短期的还是长期的。

Agent 部分就更有趣了,可以根据用户输入,再来决定调用这些工具中的哪一个,比如 LangChain 的 GPT+WolframAlpha 示例,甚至还可以根据输入去调用 WolframAlpha,解答你的数学提问,弥补GPT 数学弱智的问题。

当然,它也可以去做 Google 搜索、数据库查找 等操作,通过需要跟 Document Loader 结合起来用,你可以找到类似 https://llamahub.ai/l/file-pdf 等不少例子。

应用

  • chatpdf : 和书籍对话, 也是类似llama index的做法, 将内容embedding, 利用LLM进行提炼总结.
  • chatexcel: https://chatexcel.com/convert, 上传excel, 利用自然语言描述需求, 自动改表, 总结内容. (私人表格助手)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容