LlamaIndexとLangChainのAgentを組み合わせて文書を参照した多段推論を実現する
LlamaIndex概要
ChatGPTの知識を補完する仕組みとして、llama_indexがあります。 これを使うことで、文書やwebページをChatGPTに外部情報として渡してそれを参照して質問に回答してもらうことができるようになります。
使い方などは例えばこのnoteのシリーズが詳しいです。
実際に、例えば関内のwilipediaページを外部情報として与えた上で「横浜三塔と呼ばれる塔の名前を教えてください。」という質問をしてみる(LLMはgpt-3.5-turbo
を利用)と、
キングの塔(神奈川県庁本庁舎)・クイーンの塔(横浜税関)・ジャックの塔(横浜市開港記念会館)
という正しい答えが返ってきました。 Wikipediaには
キングの塔(神奈川県庁本庁舎)・クイーンの塔(横浜税関)・ジャックの塔(横浜市開港記念会館)は、地元では「横浜三塔」と呼ばれ、横浜港のシンボルとして長年市民に親しまれている。
という記述があるため、ここを参照にしていると思われます。
なお外部情報は以下のように与えており、正確な出力が得られるようにプロンプトテンプレートを更新しています。
BeautifulSoupWebReader = download_loader('BeautifulSoupWebReader') loader = BeautifulSoupWebReader() documents = loader.load_data(urls=['https://ja.wikipedia.org/wiki/関内']) index = GPTVectorStoreIndex.from_documents( documents, service_context=service_context, ) query_engine = index.as_query_engine( text_qa_template=QA_PROMPT, refine_template=REFINE_TEMPLATE, similarity_top_k=5, ) response = query_engine.query( '横浜三塔と呼ばれる塔の名前を教えてください。', )
テンプレートは以下です。
QA_PROMPT_TMPL = """ Let's work this out in a step by step way to be sure we have the right answer. 以下に、コンテキスト情報を提供します。 --------------------- {context_str} --------------------- このコンテキスト情報を考慮し、次の質問に回答してください: {query_str} """ REFINE_PROMPT_TMPL = """ Let's work this out in a step by step way to be sure we have the right answer. 質問: {query_str} 既存の回答: {existing_answer} 以下に、新しいコンテキスト情報を提供します。 ------------ {context_msg} ------------ 新しいコンテキスト情報を考慮し、必要に応じて既存の回答を改善してください。 """
ちなみに、通常のChatGPT(gpt-3.5 turbo)に同じ質問をしてみると以下のように間違った回答が返ってきました。
多段推論
では次に、「横浜三塔と呼ばれる塔の歴史を日本語で答えてください。」という質問をしてみようと思います。 これに答えるには、
というプロセスを踏む必要があります。
前セクションと同様に、LlamaIndexを利用して質問をしてみると以下のような答えが返ってきました。
キングの塔(神奈川県庁本庁舎)・クイーンの塔(横浜税関)・ジャックの塔(横浜市開港記念会館)は、地元では「横浜三塔」と呼ばれ、横浜港のシンボルとして長年市民に親しまれている。
どうやらプロセスの1.で止まってしまったようです。単純なLlamaIndexのquery
機能では、多段推論は難しそうというのが分かります。
Agentの利用
LangChainにはAgentと呼ばれる機能があり、これを利用することでLLMが適宜Google検索や計算機にアクセスした上で必要な情報を取得してタスクを解くことができるようになります。
以下のように、このAgent機能とLlamaIndexの文書参照質問回答機能を組み合わせることで多段推論が必要な質問に回答してもらうことを試してみました。 (c.f. LLamaIndexのチュートリアルをやってみる)
tools = [ Tool( name = "WikipediaSearch", func=lambda q: str(query_engine.query(q)), description="Wikipediaのページから検索します。" ), ] agent = initialize_agent(tools, llm, agent="zero-shot-react-description", verbose=True) agent.run('横浜三塔と呼ばれる塔の歴史を日本語で答えてください。')
これにより、上に記したプロセスを踏んで適切に回答してくれるのではと期待できます。 実行してみると、以下のような出力が得られました。
Final Answer: 横浜三塔は、キングの塔(神奈川県庁本庁舎)、クイーンの塔(横浜税関)、ジャックの塔(横浜市開港記念会館)の3つの塔で、キングの塔とクイーンの塔は1934年に完成し、それぞれ神奈川県庁本庁舎と横浜税関として建てられました。ジャックの塔は、元々は横浜町会所として建てられ、後に横浜市開港記念会館として再建されました。
キングの塔が完成したのは1928年なのでそこだけ間違えてしまっているのですが、他は正しい答えが出力されています。
回答に至るプロセスを確認してみると以下のようになっていました。
WARNING:llama_index.llm_predictor.base:Unknown max input size for gpt-3.5-turbo, using defaults. INFO:llama_index.indices.loading:Loading all indices. > Entering new AgentExecutor chain... I'm not sure what the "横浜三塔" are, so I should search for them on Wikipedia. Action: WikipediaSearch Action Input: "横浜三塔"INFO:llama_index.token_counter.token_counter:> [retrieve] Total LLM token usage: 0 tokens INFO:llama_index.token_counter.token_counter:> [retrieve] Total embedding token usage: 9 tokens Token indices sequence length is longer than the specified maximum sequence length for this model (2400 > 1024). Running this sequence through the model will result in indexing errors INFO:llama_index.token_counter.token_counter:> [get_response] Total LLM token usage: 2530 tokens INFO:llama_index.token_counter.token_counter:> [get_response] Total embedding token usage: 0 tokens INFO:llama_index.token_counter.token_counter:> [get_response] Total LLM token usage: 2530 tokens INFO:llama_index.token_counter.token_counter:> [get_response] Total embedding token usage: 0 tokens Observation: 横浜三塔は、キングの塔(神奈川県庁本庁舎)、クイーンの塔(横浜税関)、ジャックの塔(横浜市開港記念会館)の3つの塔で、横浜港のシンボルとして親しまれている。 Thought:So the 横浜三塔 are actually three towers: King's Tower (Kanagawa Prefectural Government Office), Queen's Tower (Yokohama Customs), and Jack's Tower (Yokohama Port Opening Memorial Hall). I should search for their history. Action: WikipediaSearch Action Input: "横浜三塔 歴史"INFO:llama_index.token_counter.token_counter:> [retrieve] Total LLM token usage: 0 tokens INFO:llama_index.token_counter.token_counter:> [retrieve] Total embedding token usage: 14 tokens INFO:llama_index.token_counter.token_counter:> [get_response] Total LLM token usage: 2604 tokens INFO:llama_index.token_counter.token_counter:> [get_response] Total embedding token usage: 0 tokens INFO:llama_index.token_counter.token_counter:> [get_response] Total LLM token usage: 2604 tokens INFO:llama_index.token_counter.token_counter:> [get_response] Total embedding token usage: 0 tokens Observation: 横浜三塔は、キングの塔(神奈川県庁本庁舎)、クイーンの塔(横浜税関)、ジャックの塔(横浜市開港記念会館)の3つの塔で、横浜港のシンボルとして親しまれています。ジャックの塔は、横浜町会所として建てられ、後に横浜市開港記念会館として再建されました。 Thought:So Jack's Tower was originally built as the Yokohama Town Hall and later rebuilt as the Yokohama Port Opening Memorial Hall. I should search for more information on the other two towers. Action: WikipediaSearch Action Input: "キングの塔 歴史" and "クイーンの塔 歴史"INFO:llama_index.token_counter.token_counter:> [retrieve] Total LLM token usage: 0 tokens INFO:llama_index.token_counter.token_counter:> [retrieve] Total embedding token usage: 25 tokens INFO:llama_index.token_counter.token_counter:> [get_response] Total LLM token usage: 2267 tokens INFO:llama_index.token_counter.token_counter:> [get_response] Total embedding token usage: 0 tokens INFO:llama_index.token_counter.token_counter:> [get_response] Total LLM token usage: 2267 tokens INFO:llama_index.token_counter.token_counter:> [get_response] Total embedding token usage: 0 tokens Observation: キングの塔とクイーンの塔は、それぞれ神奈川県庁本庁舎と横浜税関として建てられた建物であり、横浜三塔の一部として知られています。キングの塔は現在は神奈川県庁舎として使用されており、クイーンの塔は現在も横浜税関として使用されています。両塔とも、1934年に完成しました。 Thought:So King's Tower and Queen's Tower were originally built as the Kanagawa Prefectural Government Office and Yokohama Customs, respectively, and both were completed in 1934. I now know the final answer. Final Answer: 横浜三塔は、キングの塔(神奈川県庁本庁舎)、クイーンの塔(横浜税関)、ジャックの塔(横浜市開港記念会館)の3つの塔で、キングの塔とクイーンの塔は1934年に完成し、それぞれ神奈川県庁本庁舎と横浜税関として建てられました。ジャックの塔は、元々は横浜町会所として建てられ、後に横浜市開港記念会館として再建されました。
これをみると、
- まず横浜三塔の名前を調べる。
- 次にその歴史を調べて回答する。
というプロセスが正しく踏めていることが分かります。
まとめ
LlamaIndexとLangChainのAgentを組み合わせることで、文書を参照した多段推論を行う実験を簡易的にやってみました。
結果、LlamaIndexのquery
単体ではうまくいかなかった多段推論をAgent
と組み合わせることで実現することができました。
ただし、出力に間違った情報が含まれてしまっており完全な回答は得られていないため、今後改良すべきと考えられます。