路由器查询引擎¶
在本教程中,我们将定义一个自定义路由器查询引擎,用于从多个候选查询引擎中选择一个来执行查询。
配置¶
如果您在colab上打开这个笔记本,您可能需要安装LlamaIndex 🦙。
In [ ]:
Copied!
%pip install llama-index-embeddings-openai
%pip install llama-index-llms-openai
%pip install llama-index-embeddings-openai
%pip install llama-index-llms-openai
In [ ]:
Copied!
!pip install llama-index
!pip install llama-index
In [ ]:
Copied!
# 注意:这仅在jupyter笔记本中是必需的。
# 详情:Jupyter在后台运行一个事件循环。
# 当我们启动一个事件循环来进行异步查询时,会导致嵌套的事件循环。
# 通常情况下是不允许这样做的,我们使用nest_asyncio来允许这样做以方便操作。
import nest_asyncio
nest_asyncio.apply()
# 注意:这仅在jupyter笔记本中是必需的。
# 详情:Jupyter在后台运行一个事件循环。
# 当我们启动一个事件循环来进行异步查询时,会导致嵌套的事件循环。
# 通常情况下是不允许这样做的,我们使用nest_asyncio来允许这样做以方便操作。
import nest_asyncio
nest_asyncio.apply()
全局模型¶
In [ ]:
Copied!
import os
os.environ["OPENAI_API_KEY"] = "sk-..."
import os
os.environ["OPENAI_API_KEY"] = "sk-..."
In [ ]:
Copied!
from llama_index.llms.openai import OpenAI
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.core import Settings
Settings.llm = OpenAI(model="gpt-3.5-turbo-1106", temperature=0.2)
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")
from llama_index.llms.openai import OpenAI
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.core import Settings
Settings.llm = OpenAI(model="gpt-3.5-turbo-1106", temperature=0.2)
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")
加载数据¶
我们首先展示如何将一个文档转换为一组节点,并插入到文档存储中。
In [ ]:
Copied!
from llama_index.core import SimpleDirectoryReader
# 加载文档
documents = SimpleDirectoryReader("../data/paul_graham").load_data()
from llama_index.core import SimpleDirectoryReader
# 加载文档
documents = SimpleDirectoryReader("../data/paul_graham").load_data()
In [ ]:
Copied!
from llama_index.core import Settings
# 初始化设置(设置块大小)
Settings.chunk_size = 1024
nodes = Settings.node_parser.get_nodes_from_documents(documents)
from llama_index.core import Settings
# 初始化设置(设置块大小)
Settings.chunk_size = 1024
nodes = Settings.node_parser.get_nodes_from_documents(documents)
In [ ]:
Copied!
from llama_index.core import StorageContext
# 初始化存储上下文(默认情况下是内存中的)
storage_context = StorageContext.from_defaults()
storage_context.docstore.add_documents(nodes)
from llama_index.core import StorageContext
# 初始化存储上下文(默认情况下是内存中的)
storage_context = StorageContext.from_defaults()
storage_context.docstore.add_documents(nodes)
定义相同数据的摘要索引和向量索引¶
In [ ]:
Copied!
from llama_index.core import SummaryIndex
from llama_index.core import VectorStoreIndex
summary_index = SummaryIndex(nodes, storage_context=storage_context)
vector_index = VectorStoreIndex(nodes, storage_context=storage_context)
from llama_index.core import SummaryIndex
from llama_index.core import VectorStoreIndex
summary_index = SummaryIndex(nodes, storage_context=storage_context)
vector_index = VectorStoreIndex(nodes, storage_context=storage_context)
定义查询引擎并设置元数据¶
In [ ]:
Copied!
list_query_engine = summary_index.as_query_engine(
response_mode="tree_summarize",
use_async=True,
)
vector_query_engine = vector_index.as_query_engine()
list_query_engine = summary_index.as_query_engine(
response_mode="tree_summarize",
use_async=True,
)
vector_query_engine = vector_index.as_query_engine()
In [ ]:
Copied!
from llama_index.core.tools import QueryEngineTool
list_tool = QueryEngineTool.from_defaults(
query_engine=list_query_engine,
description=(
"Useful for summarization questions related to Paul Graham eassy on"
" What I Worked On."
),
)
vector_tool = QueryEngineTool.from_defaults(
query_engine=vector_query_engine,
description=(
"Useful for retrieving specific context from Paul Graham essay on What"
" I Worked On."
),
)
from llama_index.core.tools import QueryEngineTool
list_tool = QueryEngineTool.from_defaults(
query_engine=list_query_engine,
description=(
"Useful for summarization questions related to Paul Graham eassy on"
" What I Worked On."
),
)
vector_tool = QueryEngineTool.from_defaults(
query_engine=vector_query_engine,
description=(
"Useful for retrieving specific context from Paul Graham essay on What"
" I Worked On."
),
)
In [ ]:
Copied!
from llama_index.core.query_engine import RouterQueryEngine
from llama_index.core.selectors import LLMSingleSelector, LLMMultiSelector
from llama_index.core.selectors import (
PydanticMultiSelector,
PydanticSingleSelector,
)
query_engine = RouterQueryEngine(
selector=PydanticSingleSelector.from_defaults(),
query_engine_tools=[
list_tool,
vector_tool,
],
)
from llama_index.core.query_engine import RouterQueryEngine
from llama_index.core.selectors import LLMSingleSelector, LLMMultiSelector
from llama_index.core.selectors import (
PydanticMultiSelector,
PydanticSingleSelector,
)
query_engine = RouterQueryEngine(
selector=PydanticSingleSelector.from_defaults(),
query_engine_tools=[
list_tool,
vector_tool,
],
)
In [ ]:
Copied!
response = query_engine.query("What is the summary of the document?")
print(str(response))
response = query_engine.query("What is the summary of the document?")
print(str(response))
The document provides a comprehensive account of the author's diverse experiences, including writing, programming, founding and running startups, and investing in early-stage companies. It covers the challenges, successes, and lessons learned in these ventures, as well as the author's personal and professional growth, interactions with colleagues, and evolving interests and priorities over time.
In [ ]:
Copied!
response = query_engine.query("What did Paul Graham do after RICS?")
print(str(response))
response = query_engine.query("What did Paul Graham do after RICS?")
print(str(response))
Paul Graham started painting after leaving Y Combinator. He wanted to see how good he could get if he really focused on it. After spending most of 2014 painting, he eventually ran out of steam and stopped working on it. He then started writing essays again and wrote a bunch of new ones over the next few months. Later, in March 2015, he started working on Lisp again.
LLMSingleSelector¶
使用OpenAI(或任何其他LLM)在内部解析生成的JSON,以选择用于路由的子索引。
In [ ]:
Copied!
query_engine = RouterQueryEngine(
selector=LLMSingleSelector.from_defaults(),
query_engine_tools=[
list_tool,
vector_tool,
],
)
query_engine = RouterQueryEngine(
selector=LLMSingleSelector.from_defaults(),
query_engine_tools=[
list_tool,
vector_tool,
],
)
In [ ]:
Copied!
response = query_engine.query("What is the summary of the document?")
print(str(response))
response = query_engine.query("What is the summary of the document?")
print(str(response))
The document provides a comprehensive account of the author's professional journey, covering his involvement in various projects such as Viaweb, Y Combinator, and Hacker News, as well as his transition to focusing on writing essays and working on Y Combinator. It also delves into his experiences with the Summer Founders Program, the growth and challenges of Y Combinator, personal struggles, and his return to working on Lisp. The author reflects on the challenges and successes encountered throughout his career, including funding startups, developing a new version of Arc, and the impact of Hacker News. Additionally, the document touches on the author's interactions with colleagues, his time in Italy, experiences with painting, and the completion of a new Lisp called Bel. Throughout, the author shares insights and lessons learned from his diverse experiences.
In [ ]:
Copied!
response = query_engine.query("What did Paul Graham do after RICS?")
print(str(response))
response = query_engine.query("What did Paul Graham do after RICS?")
print(str(response))
Paul Graham started painting after leaving Y Combinator. He wanted to see how good he could get if he really focused on it. After spending most of 2014 painting, he eventually ran out of steam and stopped working on it. He then started writing essays again and wrote a bunch of new ones over the next few months. In March 2015, he started working on Lisp again.
In [ ]:
Copied!
# [可选] 查看所选结果
print(str(response.metadata["selector_result"]))
# [可选] 查看所选结果
print(str(response.metadata["selector_result"]))
selections=[SingleSelection(index=1, reason='The question is asking for specific context about what Paul Graham did after RICS, which would require retrieving specific information from his essay.')]
PydanticMultiSelector¶
如果你期望查询被路由到多个索引,你应该使用多选择器。多选择器将查询发送到多个子索引,然后使用汇总索引聚合所有响应,形成完整的答案。
In [ ]:
Copied!
from llama_index.core import SimpleKeywordTableIndex
keyword_index = SimpleKeywordTableIndex(nodes, storage_context=storage_context)
keyword_tool = QueryEngineTool.from_defaults(
query_engine=vector_query_engine,
description=(
"Useful for retrieving specific context using keywords from Paul"
" Graham essay on What I Worked On."
),
)
from llama_index.core import SimpleKeywordTableIndex
keyword_index = SimpleKeywordTableIndex(nodes, storage_context=storage_context)
keyword_tool = QueryEngineTool.from_defaults(
query_engine=vector_query_engine,
description=(
"Useful for retrieving specific context using keywords from Paul"
" Graham essay on What I Worked On."
),
)
In [ ]:
Copied!
query_engine = RouterQueryEngine(
selector=PydanticMultiSelector.from_defaults(),
query_engine_tools=[
list_tool,
vector_tool,
keyword_tool,
],
)
query_engine = RouterQueryEngine(
selector=PydanticMultiSelector.from_defaults(),
query_engine_tools=[
list_tool,
vector_tool,
keyword_tool,
],
)
In [ ]:
Copied!
# 这个查询可以使用关键字查询引擎或向量查询引擎,因此它将合并两者的响应
response = query_engine.query(
"作者在Interleaf和YC的时代有哪些值得注意的事件和人物?"
)
print(str(response))
# 这个查询可以使用关键字查询引擎或向量查询引擎,因此它将合并两者的响应
response = query_engine.query(
"作者在Interleaf和YC的时代有哪些值得注意的事件和人物?"
)
print(str(response))
The author's time at Interleaf involved working on software for creating documents and learning valuable lessons about what not to do. Notable individuals associated with Y Combinator during the author's time there include Jessica Livingston, Robert Morris, and Sam Altman, who eventually became the second president of YC. The author's time at Y Combinator included notable events such as the creation of the Summer Founders Program, which attracted impressive individuals like Reddit, Justin Kan, Emmett Shear, Aaron Swartz, and Sam Altman.
In [ ]:
Copied!
# [可选] 查看选定的结果
print(str(response.metadata["selector_result"]))
# [可选] 查看选定的结果
print(str(response.metadata["selector_result"]))
selections=[SingleSelection(index=0, reason='Summarization questions related to Paul Graham essay on What I Worked On.'), SingleSelection(index=2, reason='Retrieving specific context using keywords from Paul Graham essay on What I Worked On.')]