# RAG 程式筆記 這一行就代表了全部 RAG 的過程 ```python index = VectorStoreIndex.from_documents(documents,show_progress=True) ``` 會先進到 from_documents ` llama_index\core\indices\base.py\BaseIndex\from_documents ` 然後會直接到此處建立儲存上下文的物件 **storage_context** storage_context 現在是 **None** (預設), 如果之前有儲存此資料時才會需要在.from_documents()中添加 storage_context ```python # 建立 storage_context 物件 storage_context = storage_context or StorageContext.from_defaults() ``` StorageContext.from_defaults() 位於 `llama_index\core\storage` 此物件可以放的參數是: ``` docstore:文件存儲 index_store:索引存儲 vector_store:向量存儲 graph_store:圖形存儲 image_store:映像存儲 persist_dir:持久目錄 (之前儲存的 index) ``` 以上如果沒有放 都會是 None。 當 persist_dir 為 None , 其他存儲格式會是預設值 這邊先看 index_store 跟 vector_store ``` index_store = index_store or SimpleIndexStore() ``` SimpleIndexStore() 其實就是 simple key-value store 簡單鍵值存儲 `llama_index\core\storage\index_store\SimpleIndexStore()` ``` vector_stores = vector_stores or {DEFAULT_VECTOR_STORE: SimpleVectorStore()} ``` storage_context 最後回傳的資料為一個類別的實例 ``` return cls( docstore=docstore, index_store=index_store, vector_stores=vector_stores, # type: ignore graph_store=graph_store, ) ``` 接著設定 transformation 物件, 這是用來判斷要使用哪一種方式將文件切割成結點 ```python= transformations = transformations or transformations_from_settings_or_context( Settings, service_context ) ``` transformations 初始值為 None。 service_context 初始值也為 None。 接著執行 transformations_from_settings_or_context(), 我們有放入 service_comtext 參數, 所以最終會回傳預設的設定: ```python return settings.transformations ``` 而 settings.transformations 的由來是: ```python self._transformations = [self.node_parser] ``` node_parser 是 SentenceSplitter 物件 ```python self._node_parser = SentenceSplitter() ``` 剛才的回傳結果就是下面這個串列 ` [SentenceSplitter(include_metadata=True, include_prev_next_rel=True, callback_manager=<llama_index.core.callbacks.base.CallbackManager object at 0x0000015DC58807C0>, id_func=<function default_id_func at 0x0000015DC233D0D0>, chunk_size=1024, chunk_overlap=200, separator=' ', paragraph_separator='\n\n\n', secondary_chunking_regex='[^,.;。?!]+[,.;。?!]?')] ` 上述寫好了文件切個與行程節點的規則, 稍後會一個個步驟講解。 接著開始為 documents 做標記 id ```python for doc in documents: docstore.set_document_hash(doc.get_doc_id(), doc.hash) ``` 而 doc.get_doc_id() 的功能就是取得 documents 的 id ```python= def get_doc_id(self) -> str: """TODO: Deprecated: Get document ID.""" return self.id_ ``` self.id_ 看起來就像是 `'109f26d7-6f6f-4e3f-b16d-04122bdb3d65'` 第二個參數 doc.hash: 主要是做哈希編碼 ```python= def hash(self) -> str: doc_identity = str(self.text) + str(self.metadata) return str(sha256(doc_identity.encode("utf-8", "surrogatepass")).hexdigest()) ``` self.text 就是資料裡面所以的文字 `'申請人\r\n本人、父、母、祖父、祖母、戶長、同居人或撫養人。\r\n如係...` self.metadata 就是資料本身的資訊 `{'file_path': 'C:\\Users\\Admin\\Desktop\\data\\出生地登記.txt', 'file_name': '出生地登記...` doc.hash 最後回傳值為: `'7f8e0bce3caef174c6e24cb4e76f33799bc0b6a587eaffd3bfd7301f5623525a'` 參數理解過後, 回到函數 ```python def set_document_hash(self, doc_id: str, doc_hash: str) -> None: """Set the hash for a given doc_id.""" metadata = {"doc_hash": doc_hash} self._kvstore.put(doc_id, metadata, collection=self._metadata_collection) ``` 目的是建立一個 doc_hash 的字典, 最後會將 metadata 儲存在 _kvstore.put 裡面, kvstore 就是 SimpleKVStore, 用於儲存 metadata 的類別。 因為我們有多個文件, 所以會有多個 doc ```python for doc in documents: docstore.set_document_hash(doc.get_doc_id(), doc.hash) ``` 跑完之後就可以儲存完所有 doc 的 metadata 接著我們進行下一步: run_transformations 目的是將切片文件轉換成節點。 ```python nodes = run_transformations( documents, # type: ignore transformations, show_progress=show_progress, **kwargs, ) ``` 我們先來看參數: documents 就是我們的原始文件, transformations 就是切片的必要資料, show_progress 就是是否輸出切片及轉節點的進度。 show_progress 預設是 False。