
Jerry Liu • 2023-08-21
LlamaIndex + Metaphor:借助 LLM 实现知识工作自动化
(由 LlamaIndex 首席执行官 Jerry Liu、Metaphor 联合创始人 Jeffrey Wang 和 Hypotenuse Labs 软件工程师 Adam Hoffman 共同撰写)
我们非常高兴推出 LlamaIndex 与 Metaphor 的集成:将 LlamaIndex 数据代理的功能与作为原生 LLM 搜索工具的 Metaphor 相结合,使知识工作者能够回答任何数据上的任何问题,无论数据有多新或多复杂。
下文将更深入地介绍 Metaphor 和 LlamaIndex 集成。我们还将逐步讲解我们的示例笔记本,展示如何将它们结合使用。
背景/上下文
ChatGPT、GPT-4、Claude 2 等最先进的大型语言模型 (LLM) 具有令人难以置信的推理能力,可以解锁广泛的应用场景——从洞察提取到问答,再到通用工作流程自动化。然而,它们在检索上下文相关信息方面的能力有限。一种流行的技术栈是搭建检索增强生成 (RAG) 系统,该系统将 LLM 与针对静态知识源的外部存储解决方案相结合。LlamaIndex 等框架提供了多种工具来搭建简单和复杂的 RAG 系统。
然而,即使如此,这也不是全貌。理想情况下,LLM 应该能够动态地搜索和检索外部世界的信息,而不仅仅依赖于静态知识源。这将使它们能够完成更通用的任务集,并且不仅执行搜索/检索,还可以执行操作。
要做好这一点,我们需要两个核心组成部分
- 允许 LLM 以“读”和“写”方式智能地对您的数据执行各种任务的通用抽象
- 一个专为 LLM 使用而定制的优秀搜索引擎
LlamaIndex 数据代理抽象有助于满足第一个核心组成部分。一个完整的数据代理既包含一个推理循环,也包含一组工具(Tools)。这些工具可以是搜索/检索的接口,或者更普遍地说,可以是任何外部 API。给定一个查询,代理将执行其推理循环,并动态地确定完成手头任务所需的工具集。
数据代理可以访问 LlamaHub 上提供的丰富工具集——这些工具包括 Gmail API、SQL 数据库 API,以及以 Bing 搜索形式存在的基本工具。我们已经证明它们能够完成端到端任务,从发送电子邮件、安排会议,到自动化客户支持洞察提取。然而,此前还没有专门为 LLM 使用而定制的工具。
Metaphor 概述
Metaphor API 旨在将您的 LLM 连接到互联网。它允许您在互联网上执行完全神经的、高度语义化的搜索,并从结果中获取干净的 HTML 内容。
Metaphor 经过训练,能够根据人们在互联网上讨论事物的方式预测互联网上的链接。例如,有人可能会这样发布他们读到的一篇精彩文章:
发现了一篇关于罗马建筑历史的精彩文章:[链接]
通过训练模型根据人们讨论链接的方式来预测链接,最终结果是一种完全不同的互联网搜索方式——搜索就像你正准备分享你想要的链接一样。虽然起初有点反直觉,但这种搜索方式可以返回极高质量的结果。但就 LlamaIndex 而言,您无需担心这一点,因为默认情况下,查询将被转换为 Metaphor 提示。
为什么选择 Metaphor 搜索而不是 Bing/Google?主要有 3 个原因
- 您可以进行完全语义化的搜索,例如带有情感或复杂描述符的搜索。
- 您可以只搜索您想要的实体类型。公司、文章、人物。
- 您可以找到 Google 不太容易展示的内容,这可能是因为关键词不是合适的工具,或者仅仅是因为 Google 不在意为这类内容返回好的结果。
要了解更多信息,您可以阅读完整的 Metaphor API 博客文章。
集成详情
LlamaHub 中的 Metaphor 工具规范是一个 API 接口,包含代理可以使用的 5 个工具。
- 搜索:Metaphor 的入口点——允许代理传入一个自然语言查询,该查询随后将被传递到 Metaphor 搜索引擎。此端点还包含一些附加参数,例如结果数量、要包含/排除的域以及日期过滤器。
- 检索文档:根据 ID 检索一组文档的内容。这些 ID 作为上述搜索端点的结果的一部分返回。
- 搜索并检索文档:这是一个便捷的端点,结合了 `search` 和 `retrieve_documents` 的功能。
- 查找相似:这直接调用 Metaphor 提供的一个端点,它将返回与给定 URL 相似的文档列表。
- 当前日期:这是一个返回当前日期的便捷函数。它本身与 Metaphor 的 API 无关,但可以在之前调用以确定要传递给 Metaphor 某些端点的正确日期过滤器。
在下一节中,我们将通过各种用例逐步讲解数据代理如何利用这些端点。
示例讲解
让我们逐步讲解示例笔记本,展示如何将 LlamaIndex 数据代理与 Metaphor 结合使用。
测试 Metaphor 工具
第一步是导入 Metaphor 工具规范。
# Set up Metaphor tool
from llama_hub.tools.metaphor.base import MetaphorToolSpec
metaphor_tool = MetaphorToolSpec(
api_key='your-key',
)
# convert tool spec to a list of tools
metaphor_tool_list = metaphor_tool.to_tool_list()
for tool in metaphor_tool_list:
print(tool.metadata.name)
在本讲解中,我们使用了所有工具。但如果您想定义更自定义的工作流程并限制代理操作空间,则可以自由选择使用特定工具。
在定义代理之前,我们可以先使用这些工具。我们所有的 Metaphor 工具都使用了 `AutoPrompt` 选项,其中 Metaphor 会通过 LLM 来细化和改进查询。
示例输入
metaphor_tool.search('machine learning transformers', num_results=3)
示例输出
[{'title': 'On the potential of Transformers in Reinforcement Learning',
'url': 'https://lorenzopieri.com/rl_transformers/',
'id': 'ysJlYSgeGW3l4zyOBoSGcg'},
{'title': 'Transformers: Attention in Disguise',
'url': 'https://www.mihaileric.com/posts/transformers-attention-in-disguise/',
'id': 'iEYMai5rS9k0hN5_BH0VZg'},
{'title': 'Transformers in Computer Vision: Farewell Convolutions!',
'url': 'https://towardsdatascience.com/transformers-in-computer-vision-farewell-convolutions-f083da6ef8ab?gi=a1d0a9a2896c',
'id': 'kX1Z89DdjSvBrH1S1XLvwg'}]
笔记本还包含我们尝试使用其他端点的示例:retrieve_documents
、find_similar
、search_and_retrieve_documents
。
使用 Metaphor 设置 OpenAI 函数调用代理
我们可以创建一个具有上述所有工具访问权限的代理并开始测试
from llama_index.agent import OpenAIAgent
# We don't give the Agent our unwrapped retrieve document tools, instead passing the wrapped tools
agent = OpenAIAgent.from_tools(
metaphor_tool_list,
verbose=True,
)
设置就这么简单!让我们尝试提供一个示例查询
print(agent.chat('What are the best restaurants in toronto?"))
我们将逐步讲解此代理的执行跟踪,看看它如何与 Metaphor 工具交互。
=== Calling Function ===
Calling function: search with args: {
"query": "best restaurants in Toronto"
}
[Metaphor Tool] Autoprompt string: Here's a link to the best restaurant in Toronto:
Got output: [{'title': 'Via Allegro Ristorante - Toronto Fine Dining Restaurant', 'url': 'https://viaallegroristorante.com/', 'id': 'EVlexzJh-lzkVr4tb2y_qw'}, {'title': 'The Senator – Home', 'url': 'https://thesenator.com/', 'id': 'dA3HVr5P8E0Bs7nH2gH7ZQ'}, {'title': 'Home - The Rushton', 'url': 'https://therushton.com/', 'id': '6Je-igG-i-ApqISC5XXmGQ'}, {'title': 'Location', 'url': 'https://osteriagiulia.ca/', 'id': 'HjP5c54vqb3n3UNa3HevSA'}, {'title': 'StockYards | Stockyards Toronto', 'url': 'https://www.thestockyards.ca/', 'id': 'Pffz-DQlOepqVgKQDmW5Ig'}, {'title': 'Select A Restaurant', 'url': 'https://www.torontopho.com/', 'id': 'DiQ1hU1gmrIzpKnOaVvZmw'}, {'title': 'Home | Kit Kat Italian Bar & Grill', 'url': 'http://www.kitkattoronto.com/', 'id': 'kdAcLioBgnwzuHyd0rWS1w'}, {'title': 'La Fenice', 'url': 'https://www.lafenice.ca/', 'id': 'M-LHQZP6V40V81fqLFAQxQ'}, {'title': 'Le Phénix', 'url': 'https://www.lephenixto.com/', 'id': 'spCTcFr0GHlFUTzyngfRVw'}, {'title': 'ITALIAN, INSPIRED.', 'url': 'https://figotoronto.com/', 'id': 'OvBcTqEo1tCSywr4ATptCg'}]
========================
Here are some of the best restaurants in Toronto:
1. [Via Allegro Ristorante](https://viaallegroristorante.com/)
2. [The Senator](https://thesenator.com/)
3. [The Rushton](https://therushton.com/)
4. [Osteria Giulia](https://osteriagiulia.ca/)
5. [Stockyards](https://www.thestockyards.ca/)
6. [Toronto Pho](https://www.torontopho.com/)
7. [Kit Kat Italian Bar & Grill](http://www.kitkattoronto.com/)
8. [La Fenice](https://www.lafenice.ca/)
9. [Le Phénix](https://www.lephenixto.com/)
10. [Figo](https://figotoronto.com/)
You can visit their websites for more information. Enjoy your dining experience in Toronto!
执行跟踪显示代理只是调用了带有“多伦多最好的餐厅”查询的 `search` 端点,并将其作为表示搜索结果的字典列表返回。
请注意,我们也可以提出后续问题
print(agent.chat('tell me more about Osteria Giulia'))
然后我们得到以下结果(注意:我们截断了一些中间输出)
=== Calling Function ===
Calling function: retrieve_documents with args: {
"ids": ["HjP5c54vqb3n3UNa3HevSA"]
}
Got output: […]
========================
Osteria Giulia is a restaurant located at 134 Avenue Road in Toronto, Ontario. You can contact them at 416.964.8686 or via email at info@osteriagiulia.ca (for general inquiries only, no reservation requests via email).
The restaurant's operating hours are from Monday to Saturday, from 5:00pm to 11:00pm. On Sundays, the restaurant is available for private bookings.
Parking is available on Avenue Road and Davenport Road.
You can follow Osteria Giulia on Instagram [@osteriagiulia](https://www.instagram.com/osteriagiulia). They also have a sister restaurant called Giulietta, which you can visit at [giu.ca](https://giu.ca) or on Instagram [@giulietta972](https://www.instagram.com/giulietta972).
Please note that the information provided is based on the available document and may be subject to change. It is recommended to visit their official website or contact them directly for the most up-to-date information.
由于“Osteria Giulia”在代理的对话历史中,代理现在知道调用 `retrieve` 端点来返回有关相关搜索结果的更多信息。
高级:避免上下文窗口问题
使用 retrieve
的一个问题是内容可能很长。如果将内容简单地附加到对话历史并转储到 LLM 上下文窗口中,那么我们可能会遇到上下文窗口限制。
LlamaIndex 提供工具抽象来帮助解决这个问题。我们的 LoadAndSearchToolSpec
封装了任何可能返回大量数据的给定工具,并将其分成两个工具:一个加载工具,它会动态地将数据存储在索引中;以及一个搜索工具,允许在该索引上进行搜索。
在 Metaphor 方面,我们还在 Gist 中定义了一个 search_and_retrieve_documents
端点,该端点结合了 search
和 retrieve
。这使得代理可以执行一次查询来检索大量文档,当与 LoadAndSearchToolSpec
结合使用时,这些文档将直接存储在索引中。如果代理单独调用 search
和 retrieve
,则将搜索结果写入对话历史,然后再将这些结果再次传递到提示中以对所有文档 ID 调用 retrieve
,这将花费更多时间和消耗更多 token。
创建 LoadAndSearchToolSpec
from llama_index.tools.tool_spec.load_and_search.base import LoadAndSearchToolSpec
# The search_and_retrieve_documents tool is the third in the tool list, as seen above
wrapped_retrieve = LoadAndSearchToolSpec.from_defaults(
metaphor_tool_list[2],
)
现在让我们逐步讲解一个完整的执行示例
# Just pass the wrapped tools and the get_date utility
agent = OpenAIAgent.from_tools(
[*wrapped_retrieve.to_tool_list(), metaphor_tool_list[4]],
verbose=True,
)
print(agent.chat('Can you summarize everything published in the last month regarding news on superconductors'))
这里的输出显示代理连续调用了多个工具来获得正确答案。
=== Calling Function ===
Calling function: current_date with args: {}
Got output: 2023-08-20
========================
=== Calling Function ===
Calling function: search_and_retrieve_documents with args: {
"query": "superconductors",
"start_published_date": "2023-07-20",
"end_published_date": "2023-08-20"
}
[Metaphor Tool] Autoprompt: "Here is an interesting article about superconductors:
Got output: Content loaded! You can now search the information using read_search_and_retrieve_documents
========================
=== Calling Function ===
Calling function: read_search_and_retrieve_documents with args: {
"query": "superconductors"
}
Got output:
Superconductors are materials that can perfectly conduct electricity. They are used in a variety of applications, such as particle accelerators, nuclear fusion devices, MRI machines, and maglev trains. However, so far, no superconductor has been proven to work at ambient pressures and temperatures. On July 22, scientists in South Korea published research claiming to have solved this problem with a material called LK-99, which has an electrical resistivity that drops to near zero at 30 degrees Celsius (86 degrees Fahrenheit).
========================
In the last month, there have been developments in the field of superconductors. Scientists in South Korea have published research on a material called LK-99, which has the ability to conduct electricity with near-zero resistance at a temperature of 30 degrees Celsius (86 degrees Fahrenheit). This breakthrough could potentially lead to the development of superconductors that work at ambient pressures and temperatures, opening up new possibilities for various applications such as particle accelerators, nuclear fusion devices, MRI machines, and maglev trains.
代理使用 get_date
工具确定当前月份,然后在调用 search
时根据发布日期在 Metaphor 中应用过滤器。然后,它使用 retrieve_documents
加载文档,并使用 read_retrieve_documents
读取它们。
结论
如上所示,LlamaIndex 数据代理 + Metaphor 搜索的集成有可能绕过 LLM 甚至 RAG 系统的现有局限性。我们很高兴在未来的博客文章中继续深入探讨这一点。
我们鼓励您使用笔记本进行尝试——一定要看看!
资源