LlamaIndex 是一个数据框架,用于基于大型语言模型(LLM)的应用程序来摄取、构建和访问私有或特定领域的数据。
LlamaIndex由以下几个主要能力模块组成:
参考链接:
https://github.com/run-llama/llama_index
大型语言模型(LLMs)为人类与数据之间提供了一种自然语言交互接口。广泛可用的模型已经在大量公开可用的数据上进行了预训练,例如维基百科、邮件列表、教科书、源代码等等。 然而,尽管LLMs在大量数据上进行了训练,它们并没有针对你的数据进行训练,这些数据可能是私有的或者特定于你试图解决的问题。这些数据可能隐藏在API接口后面,存储在SQL数据库中,或者被困在PDF文档和幻灯片中。
LlamaIndex通过连接到这些数据源并将这些数据添加到LLMs已有的数据中来解决这个问题。这通常被称为检索增强生成(Retrieval-Augmented Generation, RAG)。RAG使你能够使用LLMs查询你的数据、转换它,并产生新的洞见。你可以询问有关你数据的问题,创建聊天机器人,构建半自主代理等等。
RAG的五个关键阶段将成为您构建的任何更大应用程序的一部分。这些阶段包括:
加载(Loading):这指的是将您的数据从其所在位置 —— 无论是文本文件、PDF、另一个网站、数据库还是API —— 引入到您的处理流程中。LlamaHub提供了数百种连接器可供选择。
索引(Indexing):这意味着创建一个允许查询数据的数据结构。对于LLM来说,这几乎总是意味着创建向量嵌入(即数据的语义的向量表示),以及许多其他元数据策略,以便于准确地找到上下文相关的数据。
存储(Storing):一旦您的数据被索引,您几乎总是会想要存储您的索引以及其他元数据,以避免必须重新索引。
查询(Querying):对于任何给定的索引策略,您都可以使用多种方式利用LLM和LlamaIndex数据结构进行查询,包括子查询、多步骤查询和混合策略。
评估(Evaluation):任何处理流程中的一个关键步骤是检查其相对于其他策略的有效性,或者当您进行更改时的有效性。评估提供了客观的衡量指标,可以衡量您对查询的响应的准确性、忠实度和速度。
文档(Document)是任何数据源的容器 —— 例如一个PDF文件、一个API输出或者从数据库检索的数据。
节点(Node)是LlamaIndex中数据的原子单位,代表来源文档的一个“chunk”。节点具有元数据,这些元数据将它们与所在的文档以及其他节点相关联。
数据连接器(通常称为Reader)将不同数据源和数据格式的数据摄取到文档和节点中。
检索器(Retrievers)定义了在给定查询时如何从索引中高效地检索相关上下文。您的检索策略对于检索到的数据的相关性以及其效率至关重要。
路由器(Routers)决定使用哪个检索器从知识库中检索相关上下文。更具体地说,RouterRetriever类负责选择一个或多个候选的检索器来执行查询。它们使用选择器根据每个候选者的元数据和查询来选择最佳选项。
节点后处理器(Node Postprocessors)接收一组检索到的节点,并对它们应用转换、过滤或重新排名的逻辑。
响应合成器(Response Synthesizers)使用用户查询和一组给定的检索到的文本块从LLM生成响应。
参考链接:
https://llamahub.ai/l/google_drive https://docs.llamaindex.ai/en/stable/understanding/understanding.html
选择合适的大型语言模型(LLM)是构建任何基于私有数据的LLM应用程序时需要考虑的首要步骤之一。
LLM是LlamaIndex的核心组成部分。它们可以作为独立模块使用,或者插入到其他核心LlamaIndex模块(索引、检索器、查询引擎)中。它们总是在响应合成步骤中使用(例如,在检索之后)。根据所使用的索引类型,LLM可能也会在索引构建、插入和查询遍历过程中被使用。
LlamaIndex为定义LLM模块提供了统一的接口,无论是来自OpenAI、Hugging Face还是LangChain,这样您就不必自己编写定义LLM接口的样板代码。这个接口包括以下内容:
下面的代码片段展示了如何在llama-index中使用大型语言模型。
使用openai大模型,
from llama_index.llms import OpenAI # non-streaming resp = OpenAI().complete("Paul Graham is ") print(resp)
使用hugeface托管大模型,
# -- coding: utf-8 --** from llama_index.prompts import PromptTemplate import torch from llama_index.llms import HuggingFaceLLM if __name__ == "__main__": system_prompt = """<|SYSTEM|># StableLM Tuned (Alpha version) - StableLM is a helpful and harmless open-source AI language model developed by StabilityAI. - StableLM is excited to be able to help the user, but will refuse to do anything that could be considered harmful to the user. - StableLM is more than just an information source, StableLM is also able to write poetry, short stories, and make jokes. - StableLM will refuse to participate in anything that could harm a human. """ # This will wrap the default prompts that are internal to llama-index query_wrapper_prompt = PromptTemplate("<|USER|>{query_str}<|ASSISTANT|>") llm = HuggingFaceLLM( context_window=4096, max_new_tokens=256, generate_kwargs={"temperature": 0.7, "do_sample": False}, system_prompt=system_prompt, query_wrapper_prompt=query_wrapper_prompt, tokenizer_name="StabilityAI/stablelm-tuned-alpha-3b", model_name="StabilityAI/stablelm-tuned-alpha-3b", device_map="auto", stopping_ids=[50278, 50279, 50277, 1, 0], tokenizer_kwargs={"max_length": 4096}, # uncomment this if using CUDA to reduce memory usage # model_kwargs={"torch_dtype": torch.float16} ) service_context = ServiceContext.from_defaults( chunk_size=1024, llm=llm, )
如果要使用自定义的本地大型语言模型(LLM),您仅需实现 LLM 类(或为了简化接口实现 CustomLLM 类)。您将负责将文本传递给模型并返回新生成的token。 这种实现可以是某个本地模型,甚至是围绕您自己的API的封装。
# -- coding: utf-8 --** from typing import Optional, List, Mapping, Any from llama_index import ServiceContext, SimpleDirectoryReader, SummaryIndex from llama_index.callbacks import CallbackManager from llama_index.llms import ( CustomLLM, CompletionResponse, CompletionResponseGen, LLMMetadata, ) from llama_index.llms.base import llm_completion_callback class OurLLM(CustomLLM): context_window: int = 3900 num_output: int = 256 model_name: str = "custom" dummy_response: str = "My response" @property def metadata(self) -> LLMMetadata: """Get LLM metadata.""" return LLMMetadata( context_window=self.context_window, num_output=self.num_output, model_name=self.model_name, ) @llm_completion_callback() def complete(self, prompt: str, **kwargs: Any) -> CompletionResponse: return CompletionResponse(text=self.dummy_response) @llm_completion_callback() def stream_complete( self, prompt: str, **kwargs: Any ) -> CompletionResponseGen: response = "" for token in self.dummy_response: response += token yield CompletionResponse(text=response, delta=token) # define our LLM llm = OurLLM() service_context = ServiceContext.from_defaults( llm=llm, embed_model="local:BAAI/bge-base-en-v1.5" ) # Load the your data documents = SimpleDirectoryReader("./data").load_data() index = SummaryIndex.from_documents(documents, service_context=service_context) # Query and print response query_engine = index.as_query_engine() response = query_engine.query("<query_text>") print(response)
使用这种方法,您可以使用任何LLM。也许您有在本地运行的,或者在您自己的服务器上运行的LLM。只要类被实现并且返回了生成的token,它就应该可以正常工作。
请注意,我们需要使用prompt helper来定制提示的大小,因为每个模型的上下文长度略有不同。
decorator是可选的,但它通过在LLM调用上的回调上提供了可观察性。
请注意,您可能需要调整内部提示(internal prompts)才能获得良好的性能。即便如此,您应该使用足够大的LLM来确保它能够处理LlamaIndex内部使用的复杂查询,所以您的实际效果可能会有所不同。
在LlamaIndex中,嵌入(Embeddings)用于使用复杂的数值向量表示来表示您的文档。
这些嵌入模型已经经过海量语料无监督训练过,嵌入模型将文本作为输入,并返回一长串数字(向量表示),这些数字被用来捕捉文本的语义。
举个例子,从高层次上讲,如果用户提出有关狗的问题,那么该问题的嵌入将与谈论狗的文本的嵌入高度相似。
在计算嵌入之间的相似性时,有许多方法可以使用(点积、余弦相似度等)。默认情况下,LlamaIndex在比较嵌入时使用余弦相似度。
有许多嵌入模型可以选择。默认情况下,LlamaIndex使用OpenAI的text-embedding-ada-002。llama-index还支持Langchain提供的任何嵌入模型,以及提供一个易于扩展的基类,用于实现您自己的嵌入。
在LlamaIndex中,最常见的是在ServiceContext对象中指定嵌入模型,然后在向量索引中使用。在索引构建过程中,将使用嵌入模型来嵌入文档,以及稍后使用查询引擎进行的任何查询。
from llama_index import ServiceContext from llama_index.embeddings import OpenAIEmbedding embed_model = OpenAIEmbedding() service_context = ServiceContext.from_defaults(embed_model=embed_model)
嵌入模型最常见的用途是在服务上下文对象中设置它,然后使用它来构建索引和查询。输入文档将被拆分成节点,嵌入模型将为每个节点生成一个嵌入。
默认情况下,LlamaIndex会使用text-embedding-ada-002,
from llama_index import ServiceContext, VectorStoreIndex, SimpleDirectoryReader from llama_index.embeddings import OpenAIEmbedding embed_model = OpenAIEmbedding() service_context = ServiceContext.from_defaults(embed_model=embed_model) # optionally set a global service context to avoid passing it into other objects every time from llama_index import set_global_service_context set_global_service_context(service_context) documents = SimpleDirectoryReader("./data").load_data() index = VectorStoreIndex.from_documents(documents)
然后,在查询时,嵌入模型将再次被用来嵌入查询文本。
query_engine = index.as_query_engine() response = query_engine.query("query string")
参考链接:
https://huggingface.co/stabilityai/stablelm-tuned-alpha-3b https://docs.llamaindex.ai/en/stable/api_reference/llms/huggingface.html https://github.com/run-llama/llama_index/blob/main/llama_index/prompts/default_prompts.py https://github.com/run-llama/llama_index/blob/main/llama_index/prompts/chat_prompts.py https://docs.llamaindex.ai/en/stable/module_guides/models/llms/usage_custom.html https://docs.llamaindex.ai/en/stable/module_guides/models/embeddings.html https://docs.llamaindex.ai/en/stable/module_guides/models/llms.html
mkdir -p 'data/paul_graham/' wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/examples/data/paul_graham/paul_graham_essay.txt' -O 'data/paul_graham/paul_graham_essay.txt'
将海量、高维的语料库提取出嵌入向量,形成一个向量知识库。
from llama_index import VectorStoreIndex, SimpleDirectoryReader, ServiceContext from llama_index.llms import HuggingFaceLLM # load documents documents = SimpleDirectoryReader("./data/paul_graham").load_data() # setup prompts - specific to StableLM from llama_index.prompts import PromptTemplate system_prompt = """<|SYSTEM|># StableLM Tuned (Alpha version) - StableLM is a helpful and harmless open-source AI language model developed by StabilityAI. - StableLM is excited to be able to help the user, but will refuse to do anything that could be considered harmful to the user. - StableLM is more than just an information source, StableLM is also able to write poetry, short stories, and make jokes. - StableLM will refuse to participate in anything that could harm a human. """ # This will wrap the default prompts that are internal to llama-index query_wrapper_prompt = PromptTemplate("<|USER|>{query_str}<|ASSISTANT|>") import torch llm = HuggingFaceLLM( context_window=4096, max_new_tokens=256, generate_kwargs={"temperature": 0.7, "do_sample": False}, system_prompt=system_prompt, query_wrapper_prompt=query_wrapper_prompt, tokenizer_name="StabilityAI/stablelm-tuned-alpha-3b", model_name="StabilityAI/stablelm-tuned-alpha-3b", device_map="auto", stopping_ids=[50278, 50279, 50277, 1, 0], tokenizer_kwargs={"max_length": 4096}, # uncomment this if using CUDA to reduce memory usage # model_kwargs={"torch_dtype": torch.float16} ) service_context = ServiceContext.from_defaults(chunk_size=1024, llm=llm, embed_model="local:BAAI/bge-large-en") index = VectorStoreIndex.from_documents( documents, service_context=service_context )
将输入query通过embedding大模型生成嵌入空间向量,然后通过向量相似度搜索算法,在向量知识库里搜索近似的embedding chunk nodes。
from llama_index import VectorStoreIndex, SimpleDirectoryReader, ServiceContext from llama_index.llms import HuggingFaceLLM # load documents documents = SimpleDirectoryReader("./data/paul_graham").load_data() # setup prompts - specific to StableLM from llama_index.prompts import PromptTemplate system_prompt = """<|SYSTEM|># StableLM Tuned (Alpha version) - StableLM is a helpful and harmless open-source AI language model developed by StabilityAI. - StableLM is excited to be able to help the user, but will refuse to do anything that could be considered harmful to the user. - StableLM is more than just an information source, StableLM is also able to write poetry, short stories, and make jokes. - StableLM will refuse to participate in anything that could harm a human. """ # This will wrap the default prompts that are internal to llama-index query_wrapper_prompt = PromptTemplate("<|USER|>{query_str}<|ASSISTANT|>") import torch llm = HuggingFaceLLM( context_window=4096, max_new_tokens=256, generate_kwargs={"temperature": 0.7, "do_sample": False}, system_prompt=system_prompt, query_wrapper_prompt=query_wrapper_prompt, tokenizer_name="StabilityAI/stablelm-tuned-alpha-3b", model_name="StabilityAI/stablelm-tuned-alpha-3b", device_map="auto", stopping_ids=[50278, 50279, 50277, 1, 0], tokenizer_kwargs={"max_length": 4096}, # uncomment this if using CUDA to reduce memory usage # model_kwargs={"torch_dtype": torch.float16} ) service_context = ServiceContext.from_defaults(chunk_size=1024, llm=llm, embed_model="local:BAAI/bge-large-en") index = VectorStoreIndex.from_documents( documents, service_context=service_context ) query_engine = index.as_query_engine() response = query_engine.query("what is The worst thing about leaving YC?") print(response)
默认情况下,您刚刚加载的数据以一系列向量嵌入的形式存储在内存中。您可以通过将嵌入保存到磁盘来节省时间(以及对大模型的请求)。
from llama_index import VectorStoreIndex, SimpleDirectoryReader, ServiceContext, StorageContext, load_index_from_storage from llama_index.llms import HuggingFaceLLM # setup prompts - specific to StableLM from llama_index.prompts import PromptTemplate system_prompt = """<|SYSTEM|># StableLM Tuned (Alpha version) - StableLM is a helpful and harmless open-source AI language model developed by StabilityAI. - StableLM is excited to be able to help the user, but will refuse to do anything that could be considered harmful to the user. - StableLM is more than just an information source, StableLM is also able to write poetry, short stories, and make jokes. - StableLM will refuse to participate in anything that could harm a human. """ # This will wrap the default prompts that are internal to llama-index query_wrapper_prompt = PromptTemplate("<|USER|>{query_str}<|ASSISTANT|>") import torch llm = HuggingFaceLLM( context_window=4096, max_new_tokens=256, generate_kwargs={"temperature": 0.7, "do_sample": False}, system_prompt=system_prompt, query_wrapper_prompt=query_wrapper_prompt, tokenizer_name="StabilityAI/stablelm-tuned-alpha-3b", model_name="StabilityAI/stablelm-tuned-alpha-3b", device_map="auto", stopping_ids=[50278, 50279, 50277, 1, 0], tokenizer_kwargs={"max_length": 4096}, # uncomment this if using CUDA to reduce memory usage # model_kwargs={"torch_dtype": torch.float16} ) service_context = ServiceContext.from_defaults(chunk_size=1024, llm=llm, embed_model="local:BAAI/bge-large-en") import os.path # check if storage already exists if not os.path.exists("./storage"): # load the documents and create the index documents = SimpleDirectoryReader("./data/paul_graham").load_data() index = VectorStoreIndex.from_documents( documents, service_context=service_context ) # store it for later index.storage_context.persist() else: # load the existing index storage_context = StorageContext.from_defaults(persist_dir="./storage") index = load_index_from_storage(storage_context) query_engine = index.as_query_engine() response = query_engine.query("what is The worst thing about leaving YC?") print(response)
from llama_index import VectorStoreIndex, SimpleDirectoryReader, ServiceContext from llama_index.llms import HuggingFaceLLM # load documents documents = SimpleDirectoryReader("./data/paul_graham").load_data() # setup prompts - specific to StableLM from llama_index.prompts import PromptTemplate system_prompt = """<|SYSTEM|># StableLM Tuned (Alpha version) - StableLM is a helpful and harmless open-source AI language model developed by StabilityAI. - StableLM is excited to be able to help the user, but will refuse to do anything that could be considered harmful to the user. - StableLM is more than just an information source, StableLM is also able to write poetry, short stories, and make jokes. - StableLM will refuse to participate in anything that could harm a human. """ # This will wrap the default prompts that are internal to llama-index query_wrapper_prompt = PromptTemplate("<|USER|>{query_str}<|ASSISTANT|>") import torch llm = HuggingFaceLLM( context_window=4096, max_new_tokens=256, generate_kwargs={"temperature": 0.7, "do_sample": False}, system_prompt=system_prompt, query_wrapper_prompt=query_wrapper_prompt, tokenizer_name="StabilityAI/stablelm-tuned-alpha-3b", model_name="StabilityAI/stablelm-tuned-alpha-3b", device_map="auto", stopping_ids=[50278, 50279, 50277, 1, 0], tokenizer_kwargs={"max_length": 4096}, # uncomment this if using CUDA to reduce memory usage # model_kwargs={"torch_dtype": torch.float16} ) service_context = ServiceContext.from_defaults(chunk_size=1024, llm=llm, embed_model="local:BAAI/bge-large-en") index = VectorStoreIndex.from_documents( documents, service_context=service_context ) query_engine = index.as_query_engine() response = query_engine.query("what is The worst thing about leaving YC?") print(response) chat_engine = index.as_chat_engine() response = chat_engine.chat("Oh interesting, tell me more.") print(response)
参考链接:
https://docs.llamaindex.ai/en/stable/module_guides/models/embeddings.html#modules https://docs.llamaindex.ai/en/stable/examples/customization/llms/SimpleIndexDemo-Huggingface_stablelm.html https://docs.llamaindex.ai/en/stable/examples/vector_stores/SimpleIndexDemoLlama-Local.html
LLM 最常见的应用之一是回答有关一组文档内容的问题。 LlamaIndex 对多种形式的问答提供了丰富的支持。
参考链接:
https://docs.llamaindex.ai/en/stable/use_cases/q_and_a.html
聊天机器人是LLM极其流行的另一个典型场景。与单一的问题和回答不同,聊天机器人可以处理多个来回的查询和回答,获取澄清或回答后续问题。
LlamaIndex为您提供了构建知识增强型聊天机器人和代理的工具。
参考链接:
https://docs.llamaindex.ai/en/stable/use_cases/chatbots.html https://docs.llamaindex.ai/en/stable/understanding/putting_it_all_together/chatbots/building_a_chatbot.html