LATS:语言代理树搜索

2024年06月17日 由 alex 发表 178 0

简介

众所周知,LLM不能单独用于复杂的、高度细粒度的和上下文感知的实现。


LLM 不仅需要通过外部工具来增强,还需要成为代理框架的支柱。这可以通过利用外部工具和语义反馈来实现。


外部工具可以包括网络搜索、访问特定API、文档搜索等功能。


研究发现,大多数对话式用户界面往往达不到人类水平的深思熟虑决策。此外,许多方法在考虑多种推理路径或提前规划方面也存在不足。


这些方法通常是孤立运行的,缺乏可改善推理的外部反馈。


语言代理树搜索统一了语言模型中的推理、行动和规划。


2


实际工作示例

像 LATS 这样的框架起初可能看起来很不透明,但在本文的后面部分,我将逐步介绍该框架的 LlamaIndex 实现。当我们看到框架的实际运作时,就会对它的神秘性有很大的了解。


返回 LATS


3


初步考虑

  1. 该框架包含了人类对话的基本要素。这就是记忆、上下文意识、类似人类的思维过程以及搜索。
  2. LATS 代理的 LlamaIndex 实现展示了如何根据每个节点下可能探索的子操作的数量以及每次探索搜索的深度来设定代理的范围。
  3. 在考虑这些代理时,人们总是会想到延迟以及运行 LLM 主干网的成本。不过,这些挑战都有解决方案。
  4. 如前所述,可以通过设置 LLM 的预算来降低成本,而在预算已达但仍无最终答案的情况下,可以将对话和上下文转给人工。
  5. LATS 代理会根据样本行动探索并找到最佳轨迹,与反射式提示方法相比,它在解决问题方面更具灵活性和适应性。
  6. 通过整合外部反馈和自我反思,LATS 增强了模型的可感知性,使代理能够从经验中学习,超越了基于推理的搜索方法。
  7. 考虑到 LlamaIndex,LlamaIndex 将自主代理与 RAG 结合称为代理 RAG,这是最佳实践的自然结晶。
  8. 代理所摄取的文件可作为绝佳的上下文参考,并使代理具有特定的使用领域。
  9. 试想一下,如果该代理在一家企业中作为内向型机器人使用。协助员工回答复杂的、往往是雄心勃勃的问题。


实用 LATS 实施


LlamaIndex 实现

笔记本从初始设置开始:


%pip install llama-index-agent-lats
%pip install llama-index-program-openai
%pip install llama-index-llms-openai
%pip install llama-index-embeddings-openai
%pip install llama-index-core llama-index-readers-file


然后定义 OpenAI API 密钥:


import os
os.environ["OPENAI_API_KEY"] = "<Your API Key Goes Here>"
import nest_asyncio
nest_asyncio.apply()


然后定义 LLM 和嵌入模型:


from llama_index.llms.openai import OpenAI
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.core import Settings
# NOTE: a higher temperate will help make the tree-expansion more diverse
llm = OpenAI(model="gpt-4-turbo", temperature=0.6)
embed_model = OpenAIEmbedding(model="text-embedding-3-small")
Settings.llm = llm
Settings.embed_model = embed_model


下载相关数据:


!mkdir -p 'data/10k/''data/10k/'
!wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/10k/uber_2021.pdf' -O 'data/10k/uber_2021.pdf'
!wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/10k/lyft_2021.pdf' -O 'data/10k/lyft_2021.pdf'


索引文档


import os
from llama_index.core import (
    SimpleDirectoryReader,
    VectorStoreIndex,
    load_index_from_storage,
)
from llama_index.core.storage import StorageContext

if not os.path.exists("./storage/lyft"):
    # load data
    lyft_docs = SimpleDirectoryReader(
        input_files=["./data/10k/lyft_2021.pdf"]
    ).load_data()
    uber_docs = SimpleDirectoryReader(
        input_files=["./data/10k/uber_2021.pdf"]
    ).load_data()
    # build index
    lyft_index = VectorStoreIndex.from_documents(lyft_docs)
    uber_index = VectorStoreIndex.from_documents(uber_docs)
    # persist index
    lyft_index.storage_context.persist(persist_dir="./storage/lyft")
    uber_index.storage_context.persist(persist_dir="./storage/uber")
else:
    storage_context = StorageContext.from_defaults(
        persist_dir="./storage/lyft"
    )
    lyft_index = load_index_from_storage(storage_context)
    storage_context = StorageContext.from_defaults(
        persist_dir="./storage/uber"
    )
    uber_index = load_index_from_storage(storage_context)


设置两个工具或引擎:


lyft_engine = lyft_index.as_query_engine(similarity_top_k=3)3)
uber_engine = uber_index.as_query_engine(similarity_top_k=3)


按照典型的代理方式,两个代理工具都有一个说明,这个说明非常重要,因为它可以帮助代理决定何时以及如何使用该工具。


显然,代理可以使用多种工具,代理可以使用的工具越多,代理就越强大。


from llama_index.core.tools import QueryEngineTool, ToolMetadata
query_engine_tools = [
    QueryEngineTool(
        query_engine=lyft_engine,
        metadata=ToolMetadata(
            name="lyft_10k",
            description=(
                "Provides information about Lyft financials for year 2021. "
                "Use a detailed plain text question as input to the tool. "
                "The input is used to power a semantic search engine."
            ),
        ),
    ),
    QueryEngineTool(
        query_engine=uber_engine,
        metadata=ToolMetadata(
            name="uber_10k",
            description=(
                "Provides information about Uber financials for year 2021. "
                "Use a detailed plain text question as input to the tool. "
                "The input is used to power a semantic search engine."
            ),
        ),
    ),
]


这是 LATS 代理的设置...


这里也定义了代理的预算...

  1. num_expansions 指的是在每个节点下要探索的可能子行动的数量。
  2. num_expansions=2表示我们将为每个父节点探索可能的下一个节点。
  3. max_rollouts 是指每次探索搜索空间的深度。
  4. max_rollouts=5 表示在树中探索的最大深度为 5。


你还可以查看 LLM 和工具的参考信息。


from llama_index.agent.lats import LATSAgentWorker

agent_worker = LATSAgentWorker.from_tools(
    query_engine_tools,
    llm=llm,
    num_expansions=2,
    max_rollouts=3,  # using -1 for unlimited rollouts
    verbose=True,
)
agent = agent.as_worker()


下面是向代理人提出的一个问题,注意这个问题是多么模棱两可,有不同的条件和细微差别。


task = agent.create_task(
    "Given the risk factors of Uber and Lyft described in their 10K files, ""Given the risk factors of Uber and Lyft described in their 10K files, "
    "which company is performing better? Please use concrete numbers to inform your decision."
)


文章来源:https://medium.com/@cobusgreyling/language-agent-tree-search-lats-837de73d0672
欢迎关注ATYUN官方公众号
商务合作及内容投稿请联系邮箱:bd@atyun.com
评论 登录
热门职位
Maluuba
20000~40000/月
Cisco
25000~30000/月 深圳市
PilotAILabs
30000~60000/年 深圳市
写评论取消
回复取消