# Notes on LlamaIndex ###### tags: `AGI` :::info :information_source: this note is made from official [documentation](https://gpt-index.readthedocs.io/en/latest/index.html) from llama-index ::: ## Table of Contents [toc] ## Starter Tutorials ### Set-up - run `conda env create -f env.yml` to install python environment and dependencies - import `llamaindex` into your python script ### Building Index ```python from llama_index import SimpleDirectoryReader,GPTSimpleVectorIndex documents = SimpleDirectoryReader('data').load_data() index = GPTSimpleVectorIndex.from_documents(documents) ``` ### Querying Index ```python response = index.query("<query>", response_mode="<mode>") ``` ## Key Components ### Data connectors - #### types of connectors - local file directory: `SimpleDirectoryReader` - Google Docs: `GoogleDocsReader` - else: `NotionPageReader`, `SlackReader`, `DiscordReader` - [community data connectors](https://llamahub.ai) - #### example of built-in connectors ```python from llama_index import GPTSimpleVectorIndex, download_loader GoogleDocsReader = download_loader('GoogleDocsReader') gdoc_ids = ['1wf-y2pd9C878Oh-FmLH7Q_BQkljdm6TQal-c1pUfrec'] loader = GoogleDocsReader() documents = loader.load_data(document_ids=gdoc_ids) index = GPTSimpleVectorIndex.from_documents(documents) index.query('Where did the author go to school?') ``` ### Index Structures - conceptual - index is a sequence of nodes where each node is a chunk of text from documents - `.query` loads all or parts of nodes into Response Synthesis module - types of index - list index: loads all nodes - vector store index: pairs each node with an embedding - tree index: builds a hierachical tree from node set - keyword table index: builds a mapping from keywords to nodes - response synthesis - [setting response mode](https://gpt-index.readthedocs.io/en/latest/guides/primer/usage_pattern.html#setting-response-mode) - create and refine: one node at a time - tree summarize: bottom-up tree traversal - modifying index - creation ```python index = GPTSimpleVectorIndex.from_documents(loader.load_data()) documents = [Document(text, doc_id=f"doc_id_{i}")...] ``` - insertion ```python index.insert(documents[i]) ``` - deletion ```python index.delete("doc_id_0") ``` - update ```python index.update(documents[0]) ``` - [**composing a graph**](https://gpt-index.readthedocs.io/en/latest/how_to/index_structs/composability.html) - compose a graph made up of indices and use query the graph instead ```python doc_i = SimpleDirectoryReader('data_i').load_data() index_i = GPTTreeIndex.from_documents(doc_i) index_i_summary = str(index_i.query("<summary_prompt>", mode="summarize")) graph = ComposableGraph.build_from_indices( GPTListIndex, index_list, index_summaries=index_summaries) graph.save_to_disk("save_path.json") graph = ComposableGraph.load_from_disk("save_path.json") ``` - [query a graph recursively top down](https://gpt-index.readthedocs.io/en/latest/reference/indices/composability_query.html) ### Query Interface - ### [Usage Pattern](https://gpt-index.readthedocs.io/en/latest/guides/primer/usage_pattern.html) - loading documents through data loader or document struct ```python from llama_index import SimpleDirectoryReader documents = SimpleDirectoryReader('data').load_data() from llama_index import Document text_list = [text1, text2, ...] documents = [Document(t) for t in text_list] ``` - parsing documents into nodes ```python from llama_index.node_parser import SimpleNodeParser parser = SimpleNodeParser() nodes = parser.get_nodes_from_documents(documents) from llama_index.data_structs.node_v2 import Node, DocumentRelationship node1 = Node(text="<text_chunk>", doc_id="<node_id>") node2 = Node(text="<text_chunk>", doc_id="<node_id>") node1.relationships[DocumentRelationship.NEXT] = node2.get_doc_id() node2.relationships[DocumentRelationship.PREVIOUS] = node1.get_doc_id() ``` - constructing index from nodes or documnets ```python from llama_index import GPTSimpleVectorIndex index = GPTSimpleVectorIndex.from_documents(documents) from llama_index import GPTSimpleVectorIndex index = GPTSimpleVectorIndex(nodes) ``` - [customizing LLMs](https://gpt-index.readthedocs.io/en/latest/how_to/customization/custom_llms.html) ```python from llama_index import LLMPredictor # defining llm llm_predictor = LLMPredictor(llm=OpenAI(temperature=0, model_name="text-davinci-003")) # define prompt helper # set maximum input size max_input_size = 4096 # set number of output tokens num_output = 256 # set maximum chunk overlap max_chunk_overlap = 20 prompt_helper = PromptHelper( max_input_size, num_output, max_chunk_overlap) # set index configuration service_context = ServiceContext.from_defaults( llm_predictor=llm_predictor, prompt_helper=prompt_helper) # construct index index = GPTSimpleVectorIndex.from_documents( documents, service_context=service_context ) ``` - [customizing prompts](https://gpt-index.readthedocs.io/en/latest/how_to/customization/custom_prompts.html) - [customizing embeddings](https://gpt-index.readthedocs.io/en/latest/how_to/customization/embeddings.html#custom-embeddings) - [building indices on top of other indices](https://gpt-index.readthedocs.io/en/latest/how_to/index_structs/composability.html) ```python from llama_index import GPTSimpleVectorIndex, GPTListIndex index1 = GPTSimpleVectorIndex.from_documents(documents1) index2 = GPTSimpleVectorIndex.from_documents(documents2) index1.set_text("summary1") index2.set_text("summary2") index3 = GPTListIndex([index1, index2]) ``` - [querying the index](https://gpt-index.readthedocs.io/en/latest/reference/query.html) - response_mode - default: querying mode - retrieve - embedding - summarize: hierachical summarization in tree index - simple: keyword extraction - rake: keyword extraction - recursive: recursively query over composed indices ```python index = GPTListIndex.from_documents(documents) # mode="default" response = index.query("<question>", mode="default") # mode="embedding" response = index.query("<question>", mode="embedding") index.query( "<question>", required_keywords=["Combinator"], exclude_keywords=["Italy"] ) ``` - parsing/formating the [response](https://gpt-index.readthedocs.io/en/latest/reference/response.html) ```python response = index.query("<question>", verbose=True) display(Markdown(f"<b>{response}</b>")) ``` - ### [Query Transformation](https://gpt-index.readthedocs.io/en/latest/how_to/query/query_transformations.html) - HypotheticalDocumentEmbedding - [conceptual explaination](http://boston.lti.cs.cmu.edu/luyug/HyDE/HyDE.pdf) - [notebook example](https://github.com/jerryjliu/llama_index/blob/main/examples/query_transformations/HyDEQueryTransformDemo.ipynb) - single-step query decomposition ```python # Setting: a list index composed over multiple vector indices # llm_predictor_chatgpt corresponds to the ChatGPT LLM interface from llama_index.indices.query.query_transform.base import DecomposeQueryTransform decompose_transform = DecomposeQueryTransform( llm_predictor_chatgpt, verbose=True ) # initialize indexes and graph ... # set query config query_configs = [ { "index_struct_type": "simple_dict", "query_mode": "default", "query_kwargs": { "similarity_top_k": 1 }, # NOTE: set query transform for subindices "query_transform": decompose_transform }, { "index_struct_type": "keyword_table", "query_mode": "simple", "query_kwargs": { "response_mode": "tree_summarize", "verbose": True }, }, ] query_str = ( "Compare and contrast the airports in Seattle, Houston, and Toronto. " ) response_chatgpt = graph.query( query_str, query_configs=query_configs, llm_predictor=llm_predictor_chatgpt ) ``` - multi-step query transformation ***coming soon*** ```python from llama_index.indices.query.query_transform.base import StepDecomposeQueryTransform # gpt-4 step_decompose_transform = StepDecomposeQueryTransform( llm_predictor, verbose=True ) response = index.query( "Who was in the first batch of the accelerator program the author started?", query_transform=step_decompose_transform, ) ``` ## Customization - ### [Defining LLMs](https://gpt-index.readthedocs.io/en/latest/how_to/customization/custom_llms.html) - `index` takes `service_context` - `service_context` takes `llm_predictor` and `prompt_helper` - `llm_predictor` defines LLM, i.e. - model_name - temperature - max_token - `prompt_helper` defines chat configurations, i.e. - max_input_size - max_output_size - max_chunk_overlap - example code ```python from llama_index import ( GPTKeywordTableIndex, SimpleDirectoryReader, LLMPredictor, PromptHelper, ServiceContext ) from langchain import OpenAI documents = SimpleDirectoryReader('data').load_data() # define prompt helper max_input_size = 4096 num_output = 256 max_chunk_overlap = 20 prompt_helper = PromptHelper(max_input_size, num_output, max_chunk_overlap) # define LLM llm_predictor = LLMPredictor( llm=OpenAI( temperature=0, model_name="text-davinci-002", max_tokens=num_output) ) service_context = ServiceContext.from_defaults( llm_predictor=llm_predictor, prompt_helper=prompt_helper) # build index index = GPTKeywordTableIndex.from_documents( documents, service_context=service_context) ``` - define [CustomLLM](https://python.langchain.com/en/latest/modules/models/llms/examples/custom_llm.html) using langchain - ### [Defining Prompts](https://gpt-index.readthedocs.io/en/latest/reference/prompts.html) - KeywordExtractPrompt - KnowledgeGraphPrompt - PandasPrompt - QueryKeywordExtractPrompt - QuestionAnswerPrompt - RefinePrompt - RefineTableContextPrompt - SchemaExtractPrompt - SimpleInputPrompt - SummaryPrompt - TableContextPrompt - TextToSQLPrompt - TreeInsertPrompt - TreeSelectMultiplePrompt - TreeSelectPrompt - ### [Output Parsing](https://gpt-index.readthedocs.io/en/latest/how_to/output_parsing.html#langchain) - formatting instructions for any prompt/query (through `output_parser.format`) - “parsing” for LLM outputs (through `output_parser.parse`) - [example code](https://gpt-index.readthedocs.io/en/latest/how_to/output_parsing.html) ## More reads - [Cost Predictor](https://gpt-index.readthedocs.io/en/latest/how_to/analysis/cost_analysis.html) - [Cost Optimizers](https://gpt-index.readthedocs.io/en/latest/how_to/analysis/optimizers.html) - [Combinations Comparison](https://gpt-index.readthedocs.io/en/latest/how_to/analysis/playground.html) - [Using Vector Stores](https://gpt-index.readthedocs.io/en/latest/how_to/integrations/vector_stores.html) - [Using Langchain](https://gpt-index.readthedocs.io/en/latest/how_to/integrations/using_with_langchain.html) - [Using ChatGPT Plugins](https://gpt-index.readthedocs.io/en/latest/how_to/integrations/chatgpt_plugins.html) ## References ### Main information - [LlamaIndex Documentation](https://gpt-index.readthedocs.io/en/latest/index.html) - [LlamaIndex Github](https://github.com/jerryjliu/llama_index) - [langchain Documentation](https://docs.langchain.com/docs/) - [langchain Github](https://github.com/hwchase17/langchain) ### Data Loaders - [Llama Hub for Data Loaders](https://llamahub.ai) - [How to add Data Loaders](https://github.com/emptycrown/llama-hub/tree/main) ### Examples for POC/MVP - [How to build a POC](https://github.com/logan-markewich/llama_index_starter_pack) - [How to build PDF reader](https://github.com/0xmerkle/llama-index-pdf-loader-simple/blob/main/main.py) - [How to build Twitter finder](https://github.com/0xmerkle/llama-index-twitter/blob/main/twitter_main.py) - [How to build a Chatbot](https://gpt-index.readthedocs.io/en/latest/guides/tutorials/building_a_chatbot.html) - [How to build a Web App](https://gpt-index.readthedocs.io/en/latest/guides/tutorials/fullstack_app_guide.html) - [How to augment with Structured Data](https://gpt-index.readthedocs.io/en/latest/guides/tutorials/sql_guide.html) - [How to augment with SEC Filings](https://medium.com/@jerryjliu98/how-unstructured-and-llamaindex-can-help-bring-the-power-of-llms-to-your-own-data-3657d063e30d)https://medium.com/@jerryjliu98/how-unstructured-and-llamaindex-can-help-bring-the-power-of-llms-to-your-own-data-3657d063e30d - [**Example Notebooks**](https://github.com/jerryjliu/llama_index/tree/main/examples) - [**Example WebApps**](https://gpt-index.readthedocs.io/en/latest/gallery/app_showcase.html)