nikkie-ftnextの日記

イベントレポートや読書メモを発信

LangChain素振りの記:CookbookよりRewrite-Retrieve-Read。retrieveの前にクエリを書き換えるのか〜

この記事はUzabase Advent Calendar 2023 5日目にしちゃいます!先行するんだ、GO!

はじめに

友情か? 使命か?1 nikkieです。

LLMに関心を持っており、1日1エントリという習慣を使ってたまに素振りしています。
今回は久しぶりにLangChainを素振りしました。
Rewrite-Retrieve-Readなる手法を写経します。

目次

Rewrite-Retrieve-Read

こちらの論文で提案された手法です。

この論文もとても気になるのですが、今回はLangChainのCookbookに沿って、使い方を追って掴むのを目標にしました。

Cookbook「Rewrite-Retrieve-Read」

スクリプトにして動かしました。
環境は以下です

  • Python 3.11.4
  • pip install langchain openai duckduckgo-search

ライブラリバージョン

aiofiles==23.2.1
aiohttp==3.9.0
aiosignal==1.3.1
annotated-types==0.6.0
anyio==3.7.1
attrs==23.1.0
Brotli==1.1.0
certifi==2023.11.17
charset-normalizer==3.3.2
click==8.1.7
dataclasses-json==0.6.2
distro==1.8.0
duckduckgo-search==3.9.6
frozenlist==1.4.0
h11==0.14.0
h2==4.1.0
hpack==4.0.0
httpcore==1.0.2
httpx==0.25.1
hyperframe==6.0.1
idna==3.4
jsonpatch==1.33
jsonpointer==2.4
langchain==0.0.339
langsmith==0.0.66
lxml==4.9.3
marshmallow==3.20.1
multidict==6.0.4
mypy-extensions==1.0.0
numpy==1.26.2
openai==1.3.4
packaging==23.2
pydantic==2.5.1
pydantic_core==2.14.3
PyYAML==6.0.1
requests==2.31.0
sniffio==1.3.0
socksio==1.0.0
SQLAlchemy==2.0.23
tenacity==8.2.3
tqdm==4.66.1
typing-inspect==0.9.0
typing_extensions==4.8.0
urllib3==2.1.0
yarl==1.9.3

Baseline

クエリを元に(contextを)Retrieveし、Readしてクエリに回答します。

組み立てたChainがこちら!

chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | model
    | StrOutputParser()
)
  1. クエリを元にDuckDuckGoで検索
  2. 検索結果をcontextに含めたプロンプトを作る
  3. プロンプトをgpt-3.5-turboへ送る

「what is langchain?」のような単純なクエリにはこれでうまくいきます。

LangChain is a framework built to help developers build applications powered by large language models (LLMs) more easily. It provides a generic interface to different foundation models, a framework to manage prompts, and simplifies the requirements of building an AI application without having to code all the details.

うまくいかない例はdistracted_query(気が散ったクエリ)

man that sam bankman fried trial was crazy! what is langchain?

Based on the given context, there is no information provided about "langchain."

このクエリをGPT-4に訳してもらったところ「あのサム・バンクマン・フライドの裁判は狂っていたね!」と言っているらしいです。
「what is langchain?」に答えるのに使える情報が検索結果に入ってこなかったのですね。

Rewrite-Retrieve-Read

気が散ったクエリ対策にrewriterを導入します。
ChatGPT(GPT-3.5)を使ってクエリをrewriteしています。

rewriter = (
    rewrite_prompt | ChatOpenAI(temperature=0) | StrOutputParser() | _parse
)
What is the definition and purpose of Langchain? **

あの気が散ったクエリ、めっちゃいい感じに書き換わっとる!

rewriterが書き直したクエリを元に、retrieveとreadを動かします。
全部を繋げたChainはこちら!

rewrite_retrieve_read_chain = (
    {
        "context": {"x": RunnablePassthrough()} | rewriter | retriever,
        "question": RunnablePassthrough(),
    }
    | prompt
    | model
    | StrOutputParser()
)

気が散ったクエリが書き直されたことで検索結果がLangChainに関係するものとなり、
https://duckduckgo.com/?q=What+is+the+definition+and+purpose+of+Langchain%3F
以下のような回答ができました。

LangChain is an open-source framework designed to simplify the creation of applications using large language models (LLMs). It provides a standard interface for chains, integrations with other tools, and end-to-end chains for common applications. LangChain enables LLM models to generate responses based on the most up-to-date information available online and simplifies the process of organizing large volumes of data for easy access by LLMs. With LangChain, you can construct dynamic, data-responsive applications.

雑感

終わりに

久しぶり(=バグフィックスが100上がったぶり)にLangChainを触りました。
Cookbookの「Rewrite-Retrieve-Read」の例、クエリをLLMでrewriteして、いい感じのcontextがretrieveできていました!
この実装はChainを構築する独特の書き方になっていて、LangChainの開発の進み具合に震撼しています。

LangChainのCookbookは論文で提案されたプロンプトが取り上げられている感じがします。
引き続き手を動かしつつ、一次情報の論文も確認していきたいなと思います。

P.S. Rewrite-Retrieve-Readに注目した経緯

先日聞いたこちらのセッション

このセッションをLangChainも取り上げていました。

その中でQuery Transformationsとして紹介されていたのがHyDERewrite-Retrieve-Read!

HyDEは別の記事で取り上げています

Query Transformationsの2つの手法を見て、回答するのに必要な情報をcontextに加えるためにクエリを変換するというのは納得だな〜と思います