Contents Menu Expand Light mode Dark mode Auto light/dark mode
LlamaIndex 🦙 0.6.18
LlamaIndex 🦙 0.6.18

Getting Started

  • 安装和设置
  • 从Pip安装
  • 从源代码安装
  • 环境设置

Guides

  • LlamaIndex使用指南
    • 1.加载文档
    • 2.将文档解析为节点
    • 3.索引构建
    • 列表索引
    • 向量存储索引
    • 树索引
    • 关键字表索引
    • 架构概述
  • 教程
    • 上下文
    • 摄取数据
    • 为每年设置向量索引
    • 测试代理
    • Flask后端
    • 结论
    • 我们要建造什么
    • 架构概述
    • 系统要求
    • Django后端
    • 推断结构数据点
    • Text-to-SQL(基本)
    • 注入上下文
    • 将表上下文存储在索引中
    • 最后总结
    • 上传文本
    • LLM设置
    • 保存提取的术语
    • 干预测试
    • 改进#1 - 创建一个起点索引
    • 改进#2 -(细化)更好的提示
    • 设置
    • 定义索引集
    • 设置
    • 定义索引集
    • 查询我们的统一接口
    • SEC 10k分析
    • 使用LlamaIndex与本地模型

Use Cases

  • 语义搜索
  • 摘要
  • 对结构化数据的查询
  • 跨异构数据源的路由
  • 比较/对比查询
  • 多文档查询
  • 聊天机器人
  • 全栈Web应用程序

Key Components

  • DeepLake Reader
  • Qdrant Reader
  • Discord Reader
  • MongoDB Reader
  • Chroma Reader
  • MyScale Reader
  • Faiss Reader
  • Obsidian Reader
  • Slack Reader
  • Web Page Reader
  • Pinecone Reader
  • Mbox Reader
  • MilvusReader
  • Notion Reader
  • Github Repo Reader
  • Google Docs Reader
  • Database Reader
  • Twitter Reader
  • Weaviate Reader
  • Make Reader
  • 🗃️索引结构
    • 列表索引
    • 向量存储索引
    • 树索引
    • 关键字表索引
    • 插入
    • 删除
    • 更新
    • 您可以根据您的知识库的层次结构堆叠指数,尽可能多地堆叠指数! [可选]持久化图 图也可以持久化到存储,然后在需要时再次加载。请注意,您需要设置根索引的ID,或者跟踪默认值。 我们可以看一下代码示例。我们首先构建两个树索引,一个是维基百科的纽约市页面,另一个是保罗·格雷厄姆的文章。然后,我们定义一个关键字提取索引,覆盖这两个树索引。 这里有一个示例笔记本--- 标题:示例 最大深度:1
    • Knowledge Graph Index
    • Pandas Index
    • SQL Index Guide (Core)
    • Document Summary Index
  • 设计哲学:逐步披露复杂性
  • 资源
  • 🛠️定制
    • 示例:更改底层LLM
    • 示例:更改输出令牌数(用于OpenAI,Cohere,AI21)
    • 定义自定义提示
    • 将自定义提示传递到管道中
    • 完整示例
    • 将嵌入添加到Document对象
    • 使用向量存储作为底层索引
    • 在列表/树索引中使用嵌入查询模式
    • 全局ServiceContext
    • 低级API
    • 设置
    • 流式响应
  • 🔬 Evaluation
    • Response Evaluator
    • Query Response Evaluator
    • Question Generation
  • 使用向量存储作为索引
  • 使用数据连接器从向量存储加载数据
  • ChatGPT插件集成
  • Llama Tool abstractions
  • Llama Demo Notebook:Tool + Memory module
  • 💾存储
    • 持久化数据
    • 加载数据
    • 使用远程后端
    • 低级API
    • 简单文档存储
    • MongoDB文档存储
    • 简单索引存储
    • MongoDB索引存储
    • 简单向量存储
    • 第三方向量存储集成

Reference

  • 索引
  • 查询索引
    • 检索器
      • 空索引检索器
      • 知识图检索器
      • 列表检索器
      • 关键词表检索器
      • 树检索器
      • 向量存储检索器
      • 变换检索器
    • 响应合成器
    • 查询引擎
      • 图查询引擎
      • 多步查询引擎
      • 检索查询引擎
      • 变换查询引擎
      • 路由器查询引擎
      • 子问题查询引擎
      • SQL查询引擎
      • Pandas查询引擎
    • Chat Engines
      • 简单聊天引擎
      • 紧缩问题聊天引擎
      • ReAct聊天引擎
    • 查询包
    • 查询转换
  • 节点
  • 节点后处理器
  • 存储上下文
    • 文档存储
    • 索引存储
    • Vector Store
    • 向量存储
    • KV存储
    • 加载索引
  • 可组合性
  • 数据连接器
  • Prompt Templates
  • 优化器
  • 回调
  • 结构化索引配置
  • 响应
  • 游乐场
  • 节点解析器
  • 示例笔记本
  • Langchain集成

Gallery

  • Meru - 密集数据检索API
  • Algovera
  • ChatGPT LlamaIndex
  • AgentHQ
  • PapersGPT
  • VideoQues + DocsQues
  • PaperBrain
  • CACTUS
  • 个人笔记聊天机器人
  • RHOBH AMA
  • Mynd
  • Al-X by OpenExO
  • AnySummary:
  • Blackmaria:
Back to top
Edit this page

Retriever Query Engine with Custom Retrievers - Simple Hybrid Search

In this tutorial, we show you how to define a very simple version of hybrid search!

Combine keyword lookup retrieval with vector retrieval using "AND" and "OR" conditions.

Setup

import logging
import sys

logging.basicConfig(stream=sys.stdout, level=logging.INFO)
logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))

from llama_index import (
    GPTVectorStoreIndex, 
    GPTSimpleKeywordTableIndex, 
    SimpleDirectoryReader,
    ServiceContext,
    StorageContext
)
from IPython.display import Markdown, display

Load Data

We first show how to convert a Document into a set of Nodes, and insert into a DocumentStore.

# load documents
documents = SimpleDirectoryReader('../paul_graham_essay/data').load_data()
# initialize service context (set chunk size)
service_context = ServiceContext.from_defaults(chunk_size_limit=1024)
node_parser = service_context.node_parser

nodes = node_parser.get_nodes_from_documents(documents)
# initialize storage context (by default it's in-memory)
storage_context = StorageContext.from_defaults()
storage_context.docstore.add_documents(nodes)

Define Vector Index and Keyword Table Index over Same Data

We build a vector index and keyword index over the same DocumentStore

vector_index = GPTVectorStoreIndex(nodes, storage_context=storage_context)
keyword_index = GPTSimpleKeywordTableIndex(nodes, storage_context=storage_context)

Define Custom Retriever

We now define a custom retriever class that can implement basic hybrid search with both keyword lookup and semantic search.

  • setting "AND" means we take the intersection of the two retrieved sets

  • setting "OR" means we take the union

# import QueryBundle
from llama_index import QueryBundle
# import NodeWithScore
from llama_index.data_structs import NodeWithScore
# Retrievers 
from llama_index.retrievers import BaseRetriever, VectorIndexRetriever, KeywordTableSimpleRetriever

from typing import List
class CustomRetriever(BaseRetriever):
    """Custom retriever that performs both semantic search and hybrid search."""
    
    def __init__(
        self,
        vector_retriever: VectorIndexRetriever,
        keyword_retriever: KeywordTableSimpleRetriever,
        mode: str = "AND"
    ) -> None:
        """Init params."""
        
        self._vector_retriever = vector_retriever
        self._keyword_retriever = keyword_retriever
        if mode not in ("AND", "OR"):
            raise ValueError("Invalid mode.")
        self._mode = mode
        
    def _retrieve(self, query_bundle: QueryBundle) -> List[NodeWithScore]: 
        """Retrieve nodes given query."""
        
        vector_nodes = self._vector_retriever.retrieve(query_bundle)
        keyword_nodes = self._keyword_retriever.retrieve(query_bundle)
        
        vector_ids = {n.node.get_doc_id() for n in vector_nodes}
        keyword_ids = {n.node.get_doc_id() for n in keyword_nodes}
        
        combined_dict = {n.node.get_doc_id(): n for n in vector_nodes}
        combined_dict.update({n.node.get_doc_id(): n for n in keyword_nodes})
        
        if self._mode == "AND":
            retrieve_ids = vector_ids.intersection(keyword_ids)
        else:
            retrieve_ids = vector_ids.union(keyword_ids)
            
        retrieve_nodes = [combined_dict[rid] for rid in retrieve_ids]
        return retrieve_nodes
        
        

Plugin Retriever into Query Engine

Plugin retriever into a query engine, and run some queries

from llama_index import ResponseSynthesizer
from llama_index.query_engine import RetrieverQueryEngine

# define custom retriever
vector_retriever = VectorIndexRetriever(index=vector_index, similarity_top_k=2)
keyword_retriever = KeywordTableSimpleRetriever(index=keyword_index)
custom_retriever = CustomRetriever(vector_retriever, keyword_retriever)

# define response synthesizer
response_synthesizer = ResponseSynthesizer.from_args()

# assemble query engine
custom_query_engine = RetrieverQueryEngine(
    retriever=custom_retriever,
    response_synthesizer=response_synthesizer,
)

# vector query engine
vector_query_engine = RetrieverQueryEngine(
    retriever=vector_retriever,
    response_synthesizer=response_synthesizer,
)
# keyword query engine
keyword_query_engine = RetrieverQueryEngine(
    retriever=keyword_retriever,
    response_synthesizer=response_synthesizer,
)
response = custom_query_engine.query("What did the author do during his time at YC?")
INFO:llama_index.token_counter.token_counter:> [retrieve] Total LLM token usage: 0 tokens
> [retrieve] Total LLM token usage: 0 tokens
> [retrieve] Total LLM token usage: 0 tokens
INFO:llama_index.token_counter.token_counter:> [retrieve] Total embedding token usage: 12 tokens
> [retrieve] Total embedding token usage: 12 tokens
> [retrieve] Total embedding token usage: 12 tokens
INFO:llama_index.indices.keyword_table.retrievers:> Starting query: What did the author do during his time at YC?
> Starting query: What did the author do during his time at YC?
> Starting query: What did the author do during his time at YC?
INFO:llama_index.indices.keyword_table.retrievers:query keywords: ['time', 'yc', 'author']
query keywords: ['time', 'yc', 'author']
query keywords: ['time', 'yc', 'author']
INFO:llama_index.indices.keyword_table.retrievers:> Extracted keywords: ['time', 'yc']
> Extracted keywords: ['time', 'yc']
> Extracted keywords: ['time', 'yc']
INFO:llama_index.token_counter.token_counter:> [get_response] Total LLM token usage: 2250 tokens
> [get_response] Total LLM token usage: 2250 tokens
> [get_response] Total LLM token usage: 2250 tokens
INFO:llama_index.token_counter.token_counter:> [get_response] Total embedding token usage: 0 tokens
> [get_response] Total embedding token usage: 0 tokens
> [get_response] Total embedding token usage: 0 tokens
print(response) 
The author worked on YC, wrote essays, hacked, and worked on a new version of Arc with Robert. He also organized a summer program for undergrads to start startups, funded a batch of 8 startups, and provided free air conditioners to the founders. He also noticed the advantages of funding startups in batches, such as the tight alumni community and the startups becoming each other's customers.
# hybrid search can allow us to not retrieve nodes that are irrelevant
# Yale is never mentioned in the essay
response = custom_query_engine.query("What did the author do during his time at Yale?")
print(str(response))
len(response.source_nodes)
None
0
# in contrast, vector search will return an answer
response = vector_query_engine.query("What did the author do during his time at Yale?")
print(str(response))
len(response.source_nodes)
The author attended Harvard for his PhD program in computer science and took art classes there. He then applied to the Rhode Island School of Design (RISD) for a Bachelor of Fine Arts (BFA) program and the Accademia di Belli Arti in Florence for an entrance exam. He eventually went to RISD and passed the entrance exam in Florence. During his time at Harvard, he also co-founded the Summer Founders Program, which invited undergrads to apply to start their own startups. He also worked on a new version of Arc with Robert Morris and wrote essays to promote the program.
2
Copyright © 2023, Jerry Liu
Made with Sphinx and @pradyunsg's Furo
On this page
  • Retriever Query Engine with Custom Retrievers - Simple Hybrid Search
    • Setup
    • Load Data
    • Define Vector Index and Keyword Table Index over Same Data
    • Define Custom Retriever
    • Plugin Retriever into Query Engine