Find answers from the community

Updated 3 months ago

Is there a way to extend the llamaindex

Is there a way to extend the llamaindex document loader or vector builder in a way that it does not add duplicate files, so it filters them on the document loader or vector building step? Are there any example codes for that?
Reason: web scrapers often load 1 page multiple times and content can be duplicated.
A
k
65 comments
@kapa.ai can you help?
Let me check the knowledge base for you. One moment! :books:
----------------------
Of course! I'm here to help. However, I need more specific details about your question or issue. Are you looking for information about LlamaIndex, its functionalities, or how to use it? Please provide more context so I can assist you better.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai Is there a way to extend the llamaindex document loader or vector builder in a way that it does not add duplicate files, so it filters them on the document loader or vector building step? Are there any example codes for that?
Reason: web scrapers often load 1 page multiple times and content can be duplicated.
Let me check the knowledge base for you. One moment! :books:
----------------------
Yes, LlamaIndex provides a way to manage duplicate documents during the ingestion pipeline by attaching a docstore. This feature actively looks for duplicate documents using the document.doc_id or node.ref_doc_id as a grounding point. Here's how it works:

  • It stores a map of doc_id -> document_hash.
  • If a duplicate doc_id is detected, and the hash has changed, the document will be re-processed.
  • If the hash has not changed, the document will be skipped in the pipeline.
If a vector store is not attached, LlamaIndex can only check for and remove duplicate inputs. However, if a vector store is attached, it can also handle upserts (update/insert operations).

Here's an example code snippet on how to attach a docstore to the ingestion pipeline:

Plain Text
from llama_index.core.ingestion import IngestionPipeline
from llama_index.core.storage.docstore import SimpleDocumentStore

pipeline = IngestionPipeline(
    transformations=[...], docstore=SimpleDocumentStore()
)


You can find more details and examples in the LlamaIndex documentation () and GitHub repository ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai Can you actually expand on that - what are the transformations exactly - can you give me example transformations? How do I add the document.doc_id or node.ref_doc_id?
Let me check the knowledge base for you. One moment! :books:
----------------------
Transformations in LlamaIndex are operations that convert documents into nodes. They are a crucial part of the ingestion pipeline. The transformations can include operations like tokenization, named entity recognition, and more. The exact transformations you use can be customized based on your specific use case.

Here's an example of how you might define transformations:

Plain Text
from llama_index.core.transformations import Tokenizer, NamedEntityRecognizer

transformations = [
    Tokenizer(),
    NamedEntityRecognizer(),
    # Add more transformations as needed
]


As for document.doc_id or node.ref_doc_id, these are identifiers used to track and manage documents. When using the SimpleDirectoryReader, you can automatically set the doc_id to be the full path to each document:

Plain Text
from llama_index.core import SimpleDirectoryReader

documents = SimpleDirectoryReader("./data", filename_as_id=True).load_data()


In this example, the filename_as_id=True argument means that the filename of each document in the "./data" directory will be used as its doc_id.

You can also manually set the doc_id of any Document:

Plain Text
document.doc_id = "My new document id!"


For more information, you can refer to the LlamaIndex documentation on loading documents and nodes () and adding metadata ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai Can I use both doc_id as you mentioned and hex of the text content? How would I include that exactly?
Let me check the knowledge base for you. One moment! :books:
----------------------
Yes, you can use both doc_id and a hash of the text content to manage duplicates in LlamaIndex. The doc_id is used as a unique identifier for each document, while the hash of the text content (referred to as document_hash) is used to detect changes in the document content.

When you attach a docstore to the ingestion pipeline, LlamaIndex automatically creates a map of doc_id to document_hash. If a duplicate doc_id is detected and the hash has changed, the document will be re-processed. If the hash has not changed, the document will be skipped.

Here's an example of how you might set up the ingestion pipeline with a docstore:

Plain Text
from llama_index.core.ingestion import IngestionPipeline
from llama_index.core.storage.docstore import SimpleDocumentStore

pipeline = IngestionPipeline(
    transformations=[...], docstore=SimpleDocumentStore()
)


In this example, the SimpleDocumentStore automatically handles the creation of the document_hash for each document. You don't need to manually create or manage these hashes.

For more information, you can refer to the LlamaIndex documentation on document management () and the example code on GitHub ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai How does it work with pdf-s with 50 pages (the doc_id) - since page 5 and page6 are different, but filename is the same?
Let me check the knowledge base for you. One moment! :books:
----------------------
When loading PDFs with LlamaIndex, by default, each page of the PDF is treated as a separate document. This means that if you have a PDF with 50 pages, it will be loaded as 50 separate documents.

If you want to treat the entire PDF as a single document, you can stitch the pages together into one document. Here's an example of how you might do this:

Plain Text
from llama_index.core import Document
from llama_index.readers.file import PyMuPDFReader
from pathlib import Path

# Load the PDF
loader = PyMuPDFReader()
docs0 = loader.load(file_path=Path("./data/llama2.pdf"))

# Stitch the pages together into one document
doc_text = "\n\n".join([d.get_content() for d in docs0])
docs = [Document(text=doc_text)]


In this example, doc_text is a single string that contains the content of all the pages in the PDF, separated by two newline characters. The Document object created from doc_text represents the entire PDF as a single document.

If you want to keep track of which page each piece of content came from, you could modify the code to include the page number in the doc_id for each page:

Plain Text
docs = [Document(text=d.get_content(), id_=f"doc_id_{i}") for i, d in enumerate(docs0)]


In this example, each page gets a unique doc_id that includes the page number.

For more information, you can refer to the LlamaIndex documentation on loading data () and the example code on GitHub ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai So how would I integrate the ingestionpipeline, simple directory reader and pinecone vector index into on complete system?
Let me check the knowledge base for you. One moment! :books:
----------------------
Sure, you can integrate the IngestionPipeline, SimpleDirectoryReader, and PineconeVectorStore into a complete system using LlamaIndex. Here's a step-by-step guide:

  1. Import necessary modules and initialize Pinecone
Plain Text
import os
import pinecone
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, StorageContext
from llama_index.vector_stores.pinecone import PineconeVectorStore


  1. Load documents using SimpleDirectoryReader
Plain Text
documents = SimpleDirectoryReader("./data/paul_graham").load_data()


  1. Initialize PineconeVectorStore and StorageContext
Plain Text
if "OPENAI_API_KEY" not in os.environ:
    raise EnvironmentError(f"Environment variable OPENAI_API_KEY is not set")

vector_store = PineconeVectorStore(pinecone_index=pinecone_index)
storage_context = StorageContext.from_defaults(vector_store=vector_store)


  1. Build the VectorStoreIndex
Plain Text
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)


  1. Define transformations and create the IngestionPipeline
Plain Text
from llama_index.core.ingestion import IngestionPipeline
from llama_index.core.transformations import TextCleaner, TextSplitter, EmbedModel, TitleExtractor

transformations = [
    TextCleaner(),
    TextSplitter(),
    EmbedModel(),
    TitleExtractor(),
]

pipeline = IngestionPipeline(transformations=transformations, vector_store=vector_store)


  1. Run the pipeline
Plain Text
nodes = pipeline.run(documents=documents)


This is a basic example. Depending on your specific use case, you might need to customize the transformations, add a docstore for document management, or make other modifications.
For more information, you can refer to the LlamaIndex documentation () and the example code on GitHub ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai Am I correct in assuming that
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)

And the

transformations = [
OpenAIEmbedding(model="text-embedding-3-large"),]

pipeline = IngestionPipeline(transformations=transformations, vector_store=vector_store)
nodes = pipeline.run(documents=documents)

Would result in identical results?
Let me check the knowledge base for you. One moment! :books:
----------------------
Yes, you are correct. Both methods are used to create a VectorStoreIndex from a set of documents, and both methods apply transformations to the documents as part of the process.

The VectorStoreIndex.from_documents() method is a convenience method that creates an IngestionPipeline under the hood, applies the specified transformations, and then builds the index. It's a quick and easy way to create an index when you don't need fine-grained control over the ingestion process.

On the other hand, creating an IngestionPipeline manually and calling pipeline.run() gives you more control over the ingestion process. You can specify additional options when creating the pipeline, and you can run the pipeline multiple times with different sets of documents if needed.

Here's the equivalent code for both methods:

Method 1: Using VectorStoreIndex.from_documents()

Plain Text
from llama_index.core import VectorStoreIndex, StorageContext
from llama_index.vector_stores.pinecone import PineconeVectorStore

vector_store = PineconeVectorStore(pinecone_index=pinecone_index)
storage_context = StorageContext.from_defaults(vector_store=vector_store)

index = VectorStoreIndex.from_documents(
    documents=documents, 
    storage_context=storage_context, 
    transformations=[OpenAIEmbedding(model="text-embedding-3-large")]
)


Method 2: Using IngestionPipeline

Plain Text
from llama_index.core import IngestionPipeline
from llama_index.vector_stores.pinecone import PineconeVectorStore

vector_store = PineconeVectorStore(pinecone_index=pinecone_index)

pipeline = IngestionPipeline(
    transformations=[OpenAIEmbedding(model="text-embedding-3-large")], 
    vector_store=vector_store
)

nodes = pipeline.run(documents=documents)
index = VectorStoreIndex(nodes)
In both cases, the resulting VectorStoreIndex should be the same, assuming the same set of documents and transformations are used.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai so the embedding tranformatsion aalways has to be the last step in the transformation or how does it know what are the embeddings? Or are they specially marked as "embeddings"?
Let me check the knowledge base for you. One moment! :books:
----------------------
Yes, the embedding transformation typically should be the last step in the transformation pipeline. The reason for this is that the embedding transformation takes the processed text from the previous transformations and converts it into a numerical vector representation. Any transformations that are applied after the embedding transformation would need to be able to operate on these numerical vectors, not on the original text.

In LlamaIndex, the embedding transformation is not specially marked as "embeddings". Instead, it's just another transformation that's included in the list of transformations. The order of the transformations in this list determines the order in which they are applied.

Here's an example of how you might define transformations:

Plain Text
from llama_index.core.transformations import Tokenizer, NamedEntityRecognizer, OpenAIEmbedding

transformations = [
    Tokenizer(),
    NamedEntityRecognizer(),
    OpenAIEmbedding(model="text-embedding-3-large"),
]


In this example, the Tokenizer and NamedEntityRecognizer transformations are applied first to process the text, and then the OpenAIEmbedding transformation is applied to convert the processed text into embeddings.

For more information, you can refer to the LlamaIndex documentation on transformations ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai how would I put a new "filter" in there now, it should be this:

doc_hash = hashlib.sha256(v.text.encode('utf-8')).hexdigest()
Let me check the knowledge base for you. One moment! :books:
----------------------
To add a new filter that computes the SHA256 hash of the document text, you can create a custom transformation. This transformation would take a document as input, compute the hash of the document text, and add it to the document's metadata. Here's an example of how you might do this:

Plain Text
import hashlib
from llama_index.core import Transformation

class HashFilter(Transformation):
    def transform(self, v):
        doc_hash = hashlib.sha256(v.text.encode('utf-8')).hexdigest()
        v.metadata["doc_hash"] = doc_hash
        return v


In this example, HashFilter is a custom transformation that computes the SHA256 hash of the document text and adds it to the document's metadata under the key "doc_hash".

You can then include this transformation in your pipeline like this:

Plain Text
from llama_index.core.transformations import Tokenizer, NamedEntityRecognizer, OpenAIEmbedding

transformations = [
    Tokenizer(),
    NamedEntityRecognizer(),
    OpenAIEmbedding(model="text-embedding-3-large"),
    HashFilter(),
]


In this example, the HashFilter transformation is applied after the OpenAIEmbedding transformation. This means that the hash is computed on the final, processed text of the document.

For more information, you can refer to the LlamaIndex documentation on transformations ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai can i do the hashfilter before asking openai embeddings to make it more cheaper?

Also - how does it actually do filtering - the code just returns hash-code right now - some internal magic?
Let me check the knowledge base for you. One moment! :books:
----------------------
Yes, you can certainly apply the HashFilter before the OpenAIEmbedding transformation. This would allow you to compute the hash of the original, unprocessed text of the document. Here's how you might do this:

Plain Text
from llama_index.core.transformations import Tokenizer, NamedEntityRecognizer, OpenAIEmbedding

transformations = [
    HashFilter(),
    Tokenizer(),
    NamedEntityRecognizer(),
    OpenAIEmbedding(model="text-embedding-3-large"),
]


In this example, the HashFilter transformation is applied first, before any other transformations. This means that the hash is computed on the original, unprocessed text of the document.

As for your second question, the HashFilter transformation itself does not do any filtering. It simply computes the hash of the document text and adds it to the document's metadata. The actual filtering would need to be done later, based on the computed hashes.

For example, you could use the docstore feature of LlamaIndex to manage duplicate documents. When you attach a docstore to the ingestion pipeline, LlamaIndex automatically creates a map of doc_id to document_hash. If a duplicate doc_id is detected and the hash has changed, the document will be re-processed. If the hash has not changed, the document will be skipped.

Here's an example of how you might set up the ingestion pipeline with a docstore:

Plain Text
from llama_index.core.ingestion import IngestionPipeline
from llama_index.core.storage.docstore import SimpleDocumentStore

pipeline = IngestionPipeline(
    transformations=transformations, docstore=SimpleDocumentStore()
)


In this example, the SimpleDocumentStore automatically handles the creation of the document_hash for each document. You don't need to manually create or manage these hashes.
For more information, you can refer to the LlamaIndex documentation on document management () and the example code on GitHub ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai
from llama_index.core import Transformation gives me importerrors - can you confirm for me what llamaindex version it is for?
Let me check the knowledge base for you. One moment! :books:
----------------------
I'm sorry for the confusion, but the Transformation class is not directly importable from llama_index.core in the provided knowledge sources. The knowledge sources do not provide a specific version of LlamaIndex where this would be possible.

However, the knowledge sources do mention several versions of LlamaIndex, including 0.10.11, 0.10.9, and 0.9.5. It's possible that the Transformation class is available in one of these versions, but without more specific information, I can't say for sure.

If you're having trouble with the from llama_index.core import Transformation import, I would recommend checking the LlamaIndex documentation () or the LlamaIndex GitHub repository () for more information. These resources should provide up-to-date information on the available classes and how to import them.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai Is there a way to use the SimpleDirectoryReader to set custom id-s, which would be used by openaiembeddings to be written into pinecone vector db as keys - in other wrods SimpleDirectoryReader defines the keys to be used as id-s?
Let me check the knowledge base for you. One moment! :books:
----------------------
Yes, you can use the SimpleDirectoryReader to set custom IDs for your documents. When you load data using SimpleDirectoryReader, you can set the filename_as_id parameter to True. This will use the filename of each document as its doc_id. Here's an example:

Plain Text
from llama_index.core import SimpleDirectoryReader

documents = SimpleDirectoryReader("./data/paul_graham", filename_as_id=True).load_data()


In this example, the filename of each document in the "./data/paul_graham" directory will be used as its doc_id.

These doc_ids will then be used as keys when the documents are inserted into the Pinecone vector database. When you create a VectorStoreIndex from the documents and persist it to Pinecone, the doc_id of each document will be used as the key for that document's vector in Pinecone.

Here's an example of how you might do this:

Plain Text
from llama_index.core import VectorStoreIndex, StorageContext
from llama_index.vector_stores.pinecone import PineconeVectorStore

# Initialize PineconeVectorStore and StorageContext
vector_store = PineconeVectorStore(pinecone_index=pinecone_index)
storage_context = StorageContext.from_defaults(vector_store=vector_store)

# Build the VectorStoreIndex
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)

# Persist the index to Pinecone
index.storage_context.persist("./storage")


In this example, the VectorStoreIndex.from_documents() method creates an IngestionPipeline under the hood, applies the specified transformations, and then builds the index. The index.storage_context.persist() method then saves the index to Pinecone, using the doc_id of each document as the key for that document's vector.
For more information, you can refer to the LlamaIndex documentation on loading documents () and building a VectorStoreIndex ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai But - how can I extend this filename_as_id to include filename and page or some other way?
Let me check the knowledge base for you. One moment! :books:
----------------------
The SimpleDirectoryReader in LlamaIndex does not directly support using both the filename and page number as the doc_id. However, you can achieve this by using a custom reader that extends the PyMuPDFReader, which is used by SimpleDirectoryReader to read PDF files.

Here's an example of how you might create a custom reader that sets the doc_id to the filename and page number:

Plain Text
from llama_index.core import Document
from llama_index.readers.file import PyMuPDFReader
from pathlib import Path

class CustomPDFReader(PyMuPDFReader):
    def load(self, file_path: Path):
        # Load the PDF
        doc = self._load_pdf(file_path)

        # Create a Document for each page, with doc_id set to filename and page number
        return [
            Document(
                text=page.get_text().encode("utf-8"),
                doc_id=f"{file_path.stem}_page_{i}",
                extra_info={"file_path": str(file_path), "page_number": i}
            )
            for i, page in enumerate(doc)
        ]


In this example, CustomPDFReader is a custom reader that extends PyMuPDFReader. The load() method is overridden to create a Document for each page of the PDF, with the doc_id set to the filename and page number.

You can then use this custom reader to load your documents:

Plain Text
documents = CustomPDFReader().load_data(input_files=["./data/paul_graham"])


In this example, the filename and page number of each document in the "./data/paul_graham" directory will be used as its doc_id.

Please note that this is a custom solution and may require further adjustments based on your specific use case.
For more information, you can refer to the LlamaIndex documentation on PyMuPDFReader () and SimpleDirectoryReader ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai Is there a way to use SentenceSplitter which would use the id-s coming from DocumentLoader?
Let me check the knowledge base for you. One moment! :books:
----------------------
Yes, you can use the SentenceSplitter in conjunction with the doc_ids coming from the DocumentLoader. The SentenceSplitter splits the text of each document into sentences, and each sentence becomes a node. The ref_doc_id of each node is set to the doc_id of the original document.

Here's an example of how you might do this:

Plain Text
from llama_index.core.node_parser import SentenceSplitter

# Initialize the SentenceSplitter
node_parser = SentenceSplitter(chunk_size=1024)

# Get nodes from documents
nodes = node_parser.get_nodes_from_documents(documents)

# Print the ref_doc_id of each node
for node in nodes:
    print(node.ref_doc_id)


In this example, node_parser.get_nodes_from_documents(documents) splits the text of each document into sentences, and each sentence becomes a node. The ref_doc_id of each node is set to the doc_id of the original document.

For more information, you can refer to the LlamaIndex documentation on SentenceSplitter () and the example code on GitHub ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai is there a way to use sentencesplitter inside the ingestionpipeline transformations and also keep the original id-s from document loader?
Let me check the knowledge base for you. One moment! :books:
----------------------
Yes, you can use the SentenceSplitter inside the IngestionPipeline transformations and keep the original doc_ids from the DocumentLoader. The IngestionPipeline applies the transformations to each document in the order they are listed. The SentenceSplitter transformation splits the text of each document into sentences, and each sentence becomes a node. The ref_doc_id of each node is set to the doc_id of the original document.

Here's an example of how you might do this:

Plain Text
from llama_index.core.ingestion import IngestionPipeline
from llama_index.core.node_parser import SentenceSplitter
from llama_index.core.storage.docstore import SimpleDocumentStore

# Define transformations
transformations = [
    SentenceSplitter(chunk_size=1024),
]

# Create the IngestionPipeline
pipeline = IngestionPipeline(
    transformations=transformations,
    docstore=SimpleDocumentStore(),
)

# Run the pipeline
nodes = pipeline.run(documents=documents)


In this example, pipeline.run(documents=documents) applies the transformations to each document, and each sentence in the document becomes a node. The ref_doc_id of each node is set to the doc_id of the original document.

For more information, you can refer to the LlamaIndex documentation on IngestionPipeline () and the example code on GitHub ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai how can I save the documents from pipeline into pinecone with ref_doc_id instead of the normal id
Let me check the knowledge base for you. One moment! :books:
----------------------
When you use the IngestionPipeline in LlamaIndex to process your documents and save them into Pinecone, the doc_id of each document is used as the key in Pinecone. If you want to use the ref_doc_id instead of the doc_id, you would need to modify the doc_id of each document to be the ref_doc_id before saving them into Pinecone.

However, please note that the ref_doc_id is typically used to reference the original document from which a node was created, especially when using transformations like SentenceSplitter that split a document into multiple nodes. If you set the doc_id of each document to be the ref_doc_id, you might lose the ability to reference the original document.

Unfortunately, the provided knowledge sources do not include a specific example of how to do this. For more information, you might want to refer to the LlamaIndex documentation () or the LlamaIndex GitHub repository ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
Let's say I get the nodes like this:
nodes = node_parser.get_nodes_from_documents(documents)

How would I continue with pinecone and creating that index, keeping in mind not to duplicate id-s which share the same id?
@kapa.ai Let's say I get the nodes like this:
nodes = node_parser.get_nodes_from_documents(documents)

How would I continue with pinecone and creating that index, keeping in mind not to duplicate id-s which share the same id?
Let me check the knowledge base for you. One moment! :books:
----------------------
After getting the nodes using node_parser.get_nodes_from_documents(documents), you can create a VectorStoreIndex and insert the nodes into it. The VectorStoreIndex will handle the deduplication of nodes with the same doc_id.

Here's an example of how you might do this:

Plain Text
from llama_index.core import VectorStoreIndex, StorageContext
from llama_index.vector_stores.pinecone import PineconeVectorStore

# Initialize PineconeVectorStore and StorageContext
vector_store = PineconeVectorStore(pinecone_index=pinecone_index)
storage_context = StorageContext.from_defaults(vector_store=vector_store)

# Create the VectorStoreIndex
index = VectorStoreIndex([], storage_context=storage_context)

# Insert nodes into the index
index.insert_nodes(nodes)


In this example, index.insert_nodes(nodes) inserts the nodes into the VectorStoreIndex. If a node with the same doc_id already exists in the index, it will be replaced with the new node.

Please note that this is a basic example and may require further adjustments based on your specific use case.

For more information, you can refer to the LlamaIndex documentation on VectorStoreIndex () and the example code on GitHub ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai can you do the exercise again, but add openai embeddings?
Let me check the knowledge base for you. One moment! :books:
----------------------
Sure, you can add OpenAI embeddings to the nodes before inserting them into the VectorStoreIndex. Here's how you might do this:

Plain Text
from llama_index.core import VectorStoreIndex, StorageContext
from llama_index.vector_stores.pinecone import PineconeVectorStore
from llama_index.embeddings.openai import OpenAIEmbedding

# Initialize PineconeVectorStore and StorageContext
vector_store = PineconeVectorStore(pinecone_index=pinecone_index)
storage_context = StorageContext.from_defaults(vector_store=vector_store)

# Initialize OpenAIEmbedding
embed_model = OpenAIEmbedding(model="text-embedding-3-large")

# Add embeddings to nodes
for node in nodes:
    node.embedding = embed_model.get_text_embedding(node.text)

# Create the VectorStoreIndex
index = VectorStoreIndex([], storage_context=storage_context)

# Insert nodes into the index
index.insert_nodes(nodes)


In this example, embed_model.get_text_embedding(node.text) computes the OpenAI embedding for the text of each node, and node.embedding = ... sets the embedding of the node. index.insert_nodes(nodes) then inserts the nodes, with their embeddings, into the VectorStoreIndex.

Please note that this is a basic example and may require further adjustments based on your specific use case. Also, remember to replace "text-embedding-3-large" with the actual model name you want to use, and pinecone_index with your actual Pinecone index.
For more information, you can refer to the LlamaIndex documentation on OpenAIEmbedding () and the example code on GitHub ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai in your previous "simple" example - does it still do everything in parallel (uses openaiembedding batching or is it 1-by-1? I'd like to process in parallel if all possible
Let me check the knowledge base for you. One moment! :books:
----------------------
The previous example does not process the embeddings in parallel. It computes the embeddings one by one in a for loop. If you want to process the embeddings in parallel, you can use the IngestionPipeline with the OpenAIEmbedding transformation. The IngestionPipeline automatically batches the documents and processes them in parallel.

Here's how you might do this:

Plain Text
from llama_index.core.ingestion import IngestionPipeline
from llama_index.core.node_parser import SentenceSplitter
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.core.storage.docstore import SimpleDocumentStore

# Define transformations
transformations = [
    SentenceSplitter(chunk_size=1024),
    OpenAIEmbedding(model="text-embedding-3-large"),
]

# Create the IngestionPipeline
pipeline = IngestionPipeline(
    transformations=transformations,
    docstore=SimpleDocumentStore(),
)

# Run the pipeline
nodes = pipeline.run(documents=documents)


In this example, pipeline.run(documents=documents) applies the transformations to each document, and each sentence in the document becomes a node. The OpenAIEmbedding transformation computes the embeddings for the nodes in parallel.

Please note that this is a basic example and may require further adjustments based on your specific use case. Also, remember to replace "text-embedding-3-large" with the actual model name you want to use.
For more information, you can refer to the LlamaIndex documentation on IngestionPipeline () and the example code on GitHub ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
Add a reply
Sign up and join the conversation on Discord