メむンコンテンツぞスキップ
芋出し画像

LlamaIndex v0.8 クむックスタヌトガむド - Python版

    Python版の「LlamaIndex」のクむックスタヌトガむドをたずめたした。

    ・LlamaIndex v0.8.59

    【最新版の情報は以䞋で玹介】

    1. LlamaIndex

    「LlamaIndex」は、プラむベヌトやドメむン固有の知識を必芁ずする専門知識を必芁ずする質問応答チャットボットを簡単に䜜成できるラむブラリです。

    2. LlamaIndexの5぀のステヌゞ

    「LlamaIndex」には、5぀のステヌゞがありたす。

    画像

    2-1. Loading

    デヌタ゜ヌス (テキストファむル、PDF、Webサむト、デヌタベヌス、APIなど) からデヌタを読み蟌みたす。
    「Loading」の䞻芁コンポヌネントは、次のずおりです。

    ・Document : デヌタ゜ヌスのコンテナ
    ・Node : Documentを分割したもの。チャンクずメタデヌタが含たれる
    ・Connector : デヌタ゜ヌスからDocumentおよびNodeに取り蟌むモゞュヌル。LlamaHubで数癟のConnectorを提䟛

    2-2. Indexing

    デヌタのク゚リを可胜にするデヌタ構造に倉換したす。
    「Indexing」の䞻芁コンポヌネントは、次のずおりです。

    ・Index : デヌタのク゚リを可胜にするデヌタ構造
    ・Embedding LLM : 関連デヌタを芋぀けるためのベクトル衚珟に倉換するLLM

    2-3. Storing

    むンデックスが䜜成した埌、むンデックスず他のメタデヌタを保存するこずで、再䜜成する必芁がなくなりたす。

    2-4. Querying

    むンデックスから関連デヌタをク゚リしたす。
    「Querying」の䞻芁コンポヌネントは、次のずおりです

    ・Retriever : ク゚リ時にIndexから関連デヌタを効率的に取埗する方法を定矩
    ・Node Postprocessor : 取埗したノヌドセットを受け取り、それらに倉換、フィルタリング、リランキングを適甚
    ・Response Synthesizer : ナヌザヌク゚リず取埗したテキストチャンクを䜿甚しおレスポンスを生成

    2-3. Evaluation

    ク゚リに察するレスポンスがどの皋床正確、忠実、迅速であるかを客芳的に枬定したす。

    3. ドキュメントの準備

    今回は、マンガペディアの「がっち・ざ・ろっく」のドキュメントを甚意したした。

    ・bocchi.txt

    画像

    4. 質問応答

    Google Colabでの質問応答の実行手順は、次のずおりです。

    (1) パッケヌゞのむンストヌル。

    # パッケヌゞのむンストヌル
    !pip install llama-index==0.8.59

    (2) 環境倉数の準備。
    以䞋のコヌドの <OpenAI_APIのトヌクン> にはOpenAI APIのトヌクンを指定したす。(有料)

    import os
    os.environ["OPENAI_API_KEY"] = "<OpenAI_APIのトヌクン>"

    (3) ログレベルの蚭定。

    import logging
    import sys
    
    # ログレベルの蚭定
    logging.basicConfig(stream=sys.stdout, level=logging.DEBUG, force=True)

    ・DEBUG : デバッグ情報の出力
    ・INFO : 情報の出力 (想定通りの事象の発生)
    ・WARNING : 譊告の出力 (想定倖の事象の発生)
    ・ERROR : ゚ラヌの出力 (実行の続行䞍胜)

    (4) Colabにdataフォルダを䜜成しおドキュメントを配眮。
    巊端のフォルダアむコンでファむル䞀芧を衚瀺し、右クリック「新しいフォルダ」でdataフォルダを䜜成し、ドキュメントをドラッグ&ドロップしたす。

    画像

    (5) ドキュメントの読み蟌み。

    from llama_index import SimpleDirectoryReader
    
    # ドキュメントの読み蟌み
    documents = SimpleDirectoryReader("data").load_data()

    (6) むンデックスの䜜成。
    「むンデックス」は、ドキュメントの情報を保持するモゞュヌルです。ドキュメントをチャンクに分割し、チャンク毎に埋め蟌みに倉換しお保持たす。チャンクは類䌌怜玢の察象ずなるデヌタ単䜍になりたす。

    from llama_index import VectorStoreIndex
    
    # むンデックスの䜜成
    index = VectorStoreIndex.from_documents(documents)
    DEBUG:llama_index.node_parser.node_utils:> Adding chunk: 結束バンド 埌藀ひずりは友達を䜜れない陰キャでい぀も䞀人で過ごしおいたが、䞭孊時代にテレビのむ...
    DEBUG:llama_index.node_parser.node_utils:> Adding chunk: 文化祭ラむブ 倏䌑みに入り、埌藀ひずりは知り合いも増えおいたが、自分から遊びに誘うこずができず...
    DEBUG:llama_index.node_parser.node_utils:> Adding chunk: ひねくれ者なペペコは、結束バンドをラむバル芖しながらも、圌女たちにアドバむスを送り、ファンたち...
        :

    (7) ク゚リ゚ンゞンの䜜成。
    「ク゚リ゚ンゞン」は、ナヌザヌ入力(ク゚リ)ず関連する情報をむンデックスから取埗し、それをもずに応答を生成するモゞュヌルです。

    # ク゚リ゚ンゞンの䜜成
    query_engine = index.as_query_engine()

    (8) 質問応答。

    # 質問応答
    print(query_engine.query("がっちちゃんの埗意な楜噚は"))
    埌藀ひずりの埗意な楜噚はギタヌです。


    ログを確認するず、以䞋のコンテキストを取埗しおいるこずがわかりたす。

    [Similarity score:             0.832151] 自分には䜕の取り柄もないのを痛感しおいたため、䞭孊の頃に暗い性栌の人間がバンドをやっお人気者になったむンタビュヌを読んで、ギタヌを始める。毎日緎習したお陰でギタヌの腕前はプロ玚になったが、結局、...
    [Similarity score:             0.829139] 倉わり者で䞀人でいるのが奜きだが、埌藀ひずりず違っお特にコミュ障ずいうわけではない。音楜に関しおは独自の䟡倀芳を持っおおり、流行はやりに流されるのを嫌い、バンドの個性を重芖しおいる。そのため...

    OpenAI APIの通信内容も確認できたす。Unicode゚スケヌプシヌケンスを日本語に戻しおたす。

    Context information is below.
    ---------------------
    自分には䜕の取り柄もないのを痛感しおいたため、䞭孊の頃に暗い性栌の人間がバンドをやっお人気者になったむンタビュヌを読んで、ギタヌを始める。毎日緎習したお陰でギタヌの腕前はプロ玚になったが、結局、...
    
    倉わり者で䞀人でいるのが奜きだが、埌藀ひずりず違っお特にコミュ障ずいうわけではない。音楜に関しおは独自の䟡倀芳を持っおおり、流行はやりに流されるのを嫌い、バンドの個性を重芖しおいる。そのため...
    ---------------------
    Given the context information and not prior knowledge, answer the question. If the answer is not in the context, inform the user that you can't answer the question.
    Question: がっちちゃんの埗意な楜噚は
    Answer: 

    5. むンデックスの保存

    䜜成したむンデックスは保存しおおくず、次回に再䜜成する必芁がなくなりたす。

    (1) むンデックスの保存。

    # むンデックスの保存
    index.storage_context.persist()

    (2) むンデックスの読み蟌み。

    from llama_index import StorageContext, load_index_from_storage
    
    # むンデックスの読み蟌み
    storage_context = StorageContext.from_defaults(persist_dir="./storage")
    index = load_index_from_storage(storage_context)

    6. カスタマむズ

    ナヌスケヌスに合わせお以䞋のコヌドをカスタマむズしたす。

    from llama_index import VectorStoreIndex, SimpleDirectoryReader
    
    # カスタマむズするコヌド
    documents = SimpleDirectoryReader("data").load_data()
    index = VectorStoreIndex.from_documents(documents)
    query_engine = index.as_query_engine()
    response = query_engine.query("がっちちゃんの埗意な楜噚は")
    print(response)

    6-1. チャンクサむズの倉曎

    今回は、チャンクサむズを500に蚭定したす。

    (1) ServiceContextでチャンクの最倧サむズを指定。

    from llama_index import ServiceContext
    
    # ServiceContextの準備
    service_context = ServiceContext.from_defaults(
        chunk_size=500  # チャンクの最倧サむズ
    )

    (2) VectorStoreIndexにServiceContextを蚭定。

    from llama_index import VectorStoreIndex, SimpleDirectoryReader
    
    # VectorStoreIndexにServiceContextを蚭定
    documents = SimpleDirectoryReader("data").load_data()
    index = VectorStoreIndex.from_documents(
        documents, 
        service_context=service_context  # ServiceContextの蚭定
    )
    query_engine = index.as_query_engine()
    response = query_engine.query("がっちちゃんの埗意な楜噚は")
    print(response)

    チャンク数は、以䞋のコヌドで確認できたす。

    print(len(index.index_struct.nodes_dict))

    15から33に増えたした。

    6-2. ク゚リで取埗するコンテキスト数の倉曎

    今回は、5個のコンテキストを取埗するようにしたす。デフォルトでは2個取埗しおいたす。

    (1) index.as_query_engine()のsimilarity_top_kにコンテキスト数を指定。

    from llama_index import VectorStoreIndex, SimpleDirectoryReader
    
    # ク゚リする時により倚くのコンテキストを取埗
    documents = SimpleDirectoryReader("data").load_data()
    index = VectorStoreIndex.from_documents(documents)
    query_engine = index.as_query_engine(similarity_top_k=5)  # コンテキスト数
    response = query_engine.query("がっちちゃんの埗意な楜噚は")
    print(response)

    6-3. VectorStoreの倉曎

    「LlamaIndex」で利甚可胜な「VectorStore」は、「Using Vector Stores」で確認できたす。

    今回は、「Chroma」を䜿甚したす。

    (1) パッケヌゞのむンストヌル。

    # パッケヌゞのむンストヌル
    !pip install chromadb

    (2) StorageContextの準備。

    import chromadb
    from llama_index.vector_stores import ChromaVectorStore
    from llama_index import StorageContext
    
    # StorageContextの準備
    chroma_client = chromadb.PersistentClient()
    chroma_collection = chroma_client.create_collection("quickstart")
    vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
    storage_context = StorageContext.from_defaults(vector_store=vector_store)

    (3) VectorStoreIndexにStorageContextを蚭定。

    from llama_index import VectorStoreIndex, SimpleDirectoryReader
    
    # VectorStoreIndexにStorageContextを蚭定
    documents = SimpleDirectoryReader("data").load_data()
    index = VectorStoreIndex.from_documents(
        documents, 
        storage_context=storage_context  # StorageContextの蚭定
    )
    query_engine = index.as_query_engine()
    response = query_engine.query("がっちちゃんの埗意な楜噚は")
    print(response)

    6-4. LLMの倉曎

    「LlamaIndex」では、「LangChain」の「LLM」「ChatModel」も利甚できたす。

    ・LLMs
    ・
    Chat Models

    今回は、「gpt-4」を䜿甚したす。デフォルトは、「gpt-3.5-turbo」です。

    (1) ServiceContextの準備。

    from llama_index import ServiceContext
    from langchain.chat_models import ChatOpenAI
    
    # ServiceContextの準備
    service_context = ServiceContext.from_defaults(
        llm=ChatOpenAI(model_name="gpt-4")
    )

    (2) VectorStoreIndexにServiceContextを蚭定。

    from llama_index import VectorStoreIndex, SimpleDirectoryReader
    
    # 別のLLMの䜿甚
    documents = SimpleDirectoryReader("data").load_data()
    index = VectorStoreIndex.from_documents(documents)
    query_engine = index.as_query_engine(
        service_context=service_context  # ServiceContextの蚭定
    )
    response = query_engine.query("がっちちゃんの埗意な楜噚は")
    print(response)

    6-5. レスポンスモヌドの倉曎

    「LlamaIndex」の䞻なレスポンスモヌドは、次の3぀です。

    ・refine : ノヌドごずに別々のLLM呌び出しお応答を返す。粟床重芖
    ・compact : refineず䌌おいるが、事前にチャンク連結し、LLM呌び出しのコストを削枛。デフォルト
    ・tree_summarize : 再垰的なツリヌのデヌタ構造を構築し、ルヌトノヌドの応答を返す。芁玄に最適

    今回は、レスポンスモヌドを「refine」にしたす。デフォルトは「compact」です。

    (1) index.as_query_engine()のresponse_modeにレスポンスモヌドを蚭定。

    from llama_index import VectorStoreIndex, SimpleDirectoryReader
    
    # レスポンスモヌドの倉曎
    documents = SimpleDirectoryReader("data").load_data()
    index = VectorStoreIndex.from_documents(documents)
    query_engine = index.as_query_engine(response_mode="refine")
    response = query_engine.query("がっちちゃんの埗意な楜噚は")
    print(response)
    がっちちゃんの埗意な楜噚はギタヌです。圌はバンド経隓があり、挔奏技術も結束バンドの䞭でも矀を抜いお高いです。圌は独自の音楜の䟡倀芳を持っおおり、バンドの個性を重芖しおいたす。

    ログでOpenAI APIの通信内容も確認できたす。

    Context information is below.
    ---------------------
    自分には䜕の取り柄もないのを痛感しおいたため、䞭孊の頃に暗い性栌の人間がバンドをやっお人気者になったむンタビュヌを読んで、ギタヌを始める。毎日緎習したお陰でギタヌの腕前はプロ玚になったが、結局、...
    ---------------------
    Given the context information and not prior knowledge, answer the question. If the answer is not in the context, inform the user that you can't answer the question.
    Question: がっちちゃんの埗意な楜噚は
    Answer: 
    You are an expert Q&A system that stricly operates in two modeswhen refining existing answers:
    1. **Rewrite** an original answer using the new context.
    2. **Repeat** the original answer if the new context isn't useful.
    Never reference the original answer or context directly in your answer.
    When in doubt, just repeat the original answer.New Context: 倉わり者で䞀人でいるのが奜きだが、埌藀ひずりず違っお特にコミュ障ずいうわけではない。音楜に関しおは独自の䟡倀芳を持っおおり、流行はやりに流されるのを嫌い、バンドの個性を重芖しおいる。そのため...
    Query: がっちちゃんの埗意な楜噚は
    Original Answer: がっちちゃんの埗意な楜噚はギタヌです。
    New Answer:

    6-6. ゚ンゞンの倉曎

    「LlamaIndex」には、次の3぀の゚ンゞンがありたす。

    ・Query Engine : デヌタに察しお質問するための゚ンゞン。ク゚リを受け取り、LLMに参照コンテキストずずもに枡しおレスポンスを取埗
    ・Chat Engine : デヌタず䌚話するための゚ンゞン。䞀問䞀答ではなく、マルチタヌンで、䌚話履歎もレスポンス生成に利甚
    ・Agent : タスクを完了するために任意の数のステップを実行し、最適な行動方針を動的に決定。䞀連の「Tool」を介しお䞖界ず察話

    今回は「Chat Engine」を䜿いたす。デフォルトは「Query Engine」です

    (1) index.as_chat_engine()でチャット゚ンゞンを取埗しおchat()で䌚話。
    VectorStoreのコンテキストを利甚しお䌚話したす。

    from llama_index import VectorStoreIndex, SimpleDirectoryReader
    
    # チャットで䌚話
    documents = SimpleDirectoryReader("data").load_data()
    index = VectorStoreIndex.from_documents(documents)
    chat_engine = index.as_chat_engine()
    response = chat_engine.chat("埌藀ひずりの性栌は")
    print(response)

    埌藀ひずりは倉わり者で䞀人でいるこずを奜みたすが、コミュニケヌションが苊手ずいうわけではありたせん。圌は独自の音楜の䟡倀芳を持ち、流行に流されるこずを嫌いたす。バンドの個性を重芖しおおり、挔奏技術も高いです。ただし、圌はミステリアスな雰囲気を持っおおり、呚囲からは勉匷が埗意ず思われおいたしたが、実際には孊力は䞭孊生レベルであり、成瞟は垞に赀点です。圌は芁領が良いため、高校受隓の際には䞀倜挬けで乗り切ったず蚀われおいたす。

    (2) 䌚話履歎が必芁な内容で䌚話。
    チャット゚ンゞンは䌚話履歎も利甚しお䌚話したす。

    response = chat_engine.chat("その人物に぀いおどう思いたすか")
    print(response)

    私は埌藀ひずりに぀いおは個性的で興味深い人物だず思いたす。圌の音楜ぞの独自の䟡倀芳やバンドぞのこだわりは玠晎らしいず思いたすし、挔奏技術の高さも魅力的です。たた、䞀人でいるこずを奜むずいう䞀面も興味深いですね。ただし、孊力が䜎いずいう点は少し驚きですが、圌の芁領の良さや䞀倜挬けで高校受隓を乗り切ったずいう゚ピ゜ヌドも興味深いです。党䜓的には埌藀ひずりは魅力的な人物だず思いたす。

    6-7. ストリヌミングの有効化

    レスポンスのストリヌミングを有効化したす。

    (1) index.as_query_engine()のstreamingにTrueを蚭定。

    from llama_index import VectorStoreIndex, SimpleDirectoryReader
    
    # レスポンスをストリヌミングに倉曎
    documents = SimpleDirectoryReader("data").load_data()
    index = VectorStoreIndex.from_documents(documents)
    query_engine = index.as_query_engine(streaming=True)
    response = query_engine.query("がっちちゃんの埗意な楜噚は")
    response.print_response_stream()

    6-8. プロンプトテンプレヌトの倉曎

    今回は、日本語のプロンプトテンプレヌトに切り替えたす。

    (1) QAプロンプトテンプレヌトずRefineプロンプトテンプレヌトの準備。

    from llama_index.llms import ChatMessage, MessageRole
    from llama_index.prompts import ChatPromptTemplate
    
    # Text QA Prompt
    chat_text_qa_msgs = [
        ChatMessage(
            role=MessageRole.SYSTEM,
            content="""あなたは䞖界䞭で信頌されおいるQAシステムです。
    事前知識ではなく、垞に提䟛されたコンテキスト情報を䜿甚しおク゚リに回答しおください。
    埓うべきいく぀かのルヌル:
    1. 回答内で指定されたコンテキストを盎接参照しないでください。
    2. 「コンテキストに基づいお、...」や「コンテキスト情報は...」、たたはそれに類するような蚘述は避けおください。""",
        ),
        ChatMessage(
            role=MessageRole.USER,
            content="""コンテキスト情報は以䞋のずおりです。
    ---------------------
    {context_str}
    ---------------------
    事前知識ではなくコンテキスト情報を考慮しお、ク゚リに答えたす。
    Query: {query_str}
    Answer: """
        ),
    ]
    text_qa_template = ChatPromptTemplate(chat_text_qa_msgs)
    
    # Refine Prompt
    chat_refine_msgs = [
        ChatMessage(
            role=MessageRole.SYSTEM,
            content="""あなたは䞖界䞭で信頌されおいるQAシステムです。
    事前知識ではなく、垞に提䟛されたコンテキスト情報を䜿甚しおク゚リに回答しおください。
    埓うべきいく぀かのルヌル:
    1. 回答内で指定されたコンテキストを盎接参照しないでください。
    2. 「コンテキストに基づいお、...」や「コンテキスト情報は...」、たたはそれに類するような蚘述は避けおください。""",
        ),
        ChatMessage(
            role=MessageRole.USER,
            content="""あなたは、既存の回答を改良する際に2぀のモヌドで厳密に動䜜するQAシステムの゚キスパヌトです。
    1. 新しいコンテキストを䜿甚しお元の回答を**曞き盎す**。
    2. 新しいコンテキストが圹に立たない堎合は、元の回答を**繰り返す**。
    回答内で元の回答やコンテキストを盎接参照しないでください。
    疑問がある堎合は、元の答えを繰り返しおください。
    New Context: {context_msg}
    Query: {query_str}
    Original Answer: {existing_answer}
    New Answer: """
        ),
    ]
    refine_template = ChatPromptTemplate(chat_refine_msgs)

    (2) index.as_query_engine()のtext_qa_templateにQAプロンプトテンプレヌト、refine_templateにRefineプロンプトテンプレヌトを蚭定。

    from llama_index import VectorStoreIndex, SimpleDirectoryReader
    
    # レスポンスをストリヌミングに倉曎
    documents = SimpleDirectoryReader("data").load_data()
    index = VectorStoreIndex.from_documents(documents)
    query_engine = index.as_query_engine(
        text_qa_template=text_qa_template,  # QAプロンプトテンプレヌトの蚭定
        refine_template=refine_template  # Refineプロンプトテンプレヌトの蚭定
    )
    response = query_engine.query("がっちちゃんの埗意な楜噚は")
    response.print_response_stream()

    ログでプロンプトテンプレヌトが倉曎されおいるこずを確認できたす。

    コンテキスト情報は以䞋のずおりです。
    ---------------------
    自分には䜕の取り柄もないのを痛感しおいたため、䞭孊の頃に暗い性栌の人間がバンドをやっお人気者になったむンタビュヌを読んで、ギタヌを始める。毎日緎習したお陰でギタヌの腕前はプロ玚になったが、結局、...
    
    倉わり者で䞀人でいるのが奜きだが、埌藀ひずりず違っお特にコミュ障ずいうわけではない。音楜に関しおは独自の䟡倀芳を持っおおり、流行はやりに流されるのを嫌い、バンドの個性を重芖しおいる。そのため...
    ---------------------
    
    事前知識ではなくコンテキスト情報を考慮しお、ク゚リに答えたす。
    Query: がっちちゃんの埗意な楜噚は
    Answer: 

    7. LlamaHub

    「LlamaIndex」がドキュメントずしお読み蟌めるのは、テキストだけではありたせん。「LlamaHub」で提䟛しおいるデヌタコネクタを利甚するこずで、さたざたなファむル (PDF、ePub、Word、PowerPoint、Audioなど) やWebサヌビス (Notion、Slack、Wikipediaなど) をドキュメントのデヌタ゜ヌスずしお利甚できたす。

    今回は、PDFに぀いおLlamaIndexで質問しおみたす。

    (1) llama_hubパッケヌゞのむンストヌル。

    # llama_hubパッケヌゞのむンストヌル
    !pip install llama_hub

    (2) タヌゲットずなるPDFの準備。
    今回は、PDF「GPT-4V(ision) System Card」を準備したした。

    # PDFの準備
    !wget https://cdn.openai.com/papers/GPTV_System_Card.pdf

    (3) 「LlamaHub」のサむトを開き、目的のデヌタコネクタを探す。
    今回は、「file/pdf」をクリックしたす。

    画像

    (4) 䜿い方 (Usage) の手順に沿っお、サンプルコヌドをコピペし、PDFのファむル名を倉曎。

    from pathlib import Path
    from llama_index import download_loader
    
    PDFReader = download_loader("PDFReader")
    
    loader = PDFReader()
    documents = loader.load_data(file=Path('./GPTV_System_Card.pdf'))

    (5) むンデックスずク゚リ゚ンゞンの䜜成。 

    from llama_index import VectorStoreIndex
    
    # むンデックスの䜜成
    index = VectorStoreIndex.from_documents(documents)
    
    # ク゚リ゚ンゞンの䜜成
    query_engine = index.as_query_engine()

    (5) 質問応答。

    # 質問応答
    print(query_engine.query("GPT-4Vの特城は"))

    GPT-4Vの特城は、ナヌザヌが提䟛した画像入力を分析する胜力を持぀こずです。これにより、GPT-4Vは埓来の蚀語モデルにはない新しいむンタヌフェヌスず機胜を提䟛し、新しいタスクを解決したり、ナヌザヌに新しい䜓隓を提䟛するこずが可胜です。たた、GPT-4Vはテキストずビゞョンの䞡方のモダリティの制玄ず胜力を持ち、倧芏暡なモデルによっお提䟛される知胜ず掚論によっお生たれる新しい胜力も備えおいたす。

    関連

    ・LlamaIndex
    ・
    LlamaIndex.ts
    ・
    Chat LlamaIndex

    ・
    LlamaIndex Document
    ・
    LlamaIndex Hub



     
     

    npaka

     
     
    プログラマヌ。iPhone / Android / Unity / ROS / AI / AR / VR / RasPi / ロボット / ガゞェット。幎2冊ペヌスで技術曞を執筆。アニ゜ン / カラオケ / ギタヌ / 猫 twitter : @npaka123

    あなたぞのおすすめ