【LangChain】外部の文書を解釈したQAbotを作り、その受け答えが適切かを確かめる
LangChainで文書データを読み込んだQ&Abotの評価を行う
LangChainを使うことで、外部の文書を解釈させてその内容に則したQAbotを作るといったことが簡単に実現できます。今回は、そうして出来たQ&Abotが適切に文書を解釈しているのかを確かめる方法を紹介します。
今回の方法を応用すれば、
①外部の文書を解釈させたAIを作る
②その知識を利用したChatbotを作る
③そのChatbotが適切に動作するか検証する
といったことなどが可能です。
最終的なアウトプット
最終的には以下のようなアウトプットを目指します。
文書の内容に則した質問に対して、「実際の答え」というのが人間が作成した回答、「出力された答え」というのがAIによる回答です。
両者の内容が一致しているかどうかに応じて、CORRECTかINCORRECTかを教えてくれます。
注)今回はGPT3のtext-davici-003を使っています。
Example 0:
質問: Steins Gateの主人公は誰?
実際の答え: 岡部倫太郎です。
出力された答え: 岡部倫太郎
正しいかどうか: CORRECT
Example 1:
質問: 橋田と紅莉栖は何を開発した?
実際の答え: 電話レンジ(仮)とタイムリープマシンです。
出力された答え: 電話レンジ(仮)を開発した。
正しいかどうか: INCORRECT
Example 2:
質問: 未来ガジェット研究室の初期メンバーは何人?
実際の答え: 3人
出力された答え: 3人です。
正しいかどうか: CORRECT
文書の読み込みと例の生成
まずは、必要なライブラリのインポートです。
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores.faiss import FAISS
from langchain.text_splitter import CharacterTextSplitter
from langchain import OpenAI, VectorDBQA
次に、文書をAIに渡します。
今回はWikipediaのSteins Gateのページからあらすじを引っ張ったテキストファイルを渡しました。(https://ja.wikipedia.org/wiki/STEINS;GATE)
with open('テキストファイルのパス') as f:
SG = f.read()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
texts = text_splitter.split_text(SG)
embeddings = OpenAIEmbeddings()
docsearch = FAISS.from_texts(texts, embeddings)
qa = VectorDBQA.from_llm(llm=OpenAI(), vectorstore=docsearch)
実際にAIの検証として行いたいQ&Aを用意します。
自分で作ることもできますが、自動で生成してくれもします。
自分で作る場合:
examples = [
{
"query": "Steins Gateの主人公は誰?",
"answer": "岡部倫太郎です。"
},
{
"query": "橋田と紅莉栖は何を開発した?",
"answer": "電話レンジ(仮)とタイムリープマシンです。"
},
{
"query": "未来ガジェット研究室の初期メンバーは何人?",
"answer": "3人"
}
]
自動で生成させる場合:
from langchain.evaluation.qa import QAGenerateChain
example_gen_chain = QAGenerateChain.from_llm(OpenAI())
new_examples = example_gen_chain.apply_and_parse([{"doc": t} for t in texts[:5]])
このような例を自動で生成してくれます:
[{'query': 'What was the name of the invention created by the Future Gadget Lab?',
'answer': 'The invention created by the Future Gadget Lab was called the "Telephone Microwave (temporary)".'}]
例の自動生成は、example_gen_chainを利用していますが、裏で英語のプロンプトが使われているようなので日本語の出力をさせることが難しそうです。
example_gen_chainのプロンプトから手動で実装すれば日本語でも出来そうです。
Q&Abotの評価
QAEvalChainというチェーンを使うことで質疑応答に対する評価が出来ます。
今回は文書データを食わせたQ&Abotの評価を行っていますが、実際はどんなQ&Abotに対しても適用できそうな感じです。
以下では先ほどの例とAIのQA結果をQAEvalChainに投げています。
from langchain.evaluation.qa import QAEvalChain
predictions = qa.apply(examples)
llm = OpenAI(temperature=0)
eval_chain = QAEvalChain.from_llm(llm)
graded_outputs = eval_chain.evaluate(examples, predictions)
結果を出力させます。
for i, eg in enumerate(examples):
print(f"Example {i}:")
print("質問: " + predictions[i]['query'])
print("実際の答え: " + predictions[i]['answer'])
print("出力された答え: " + predictions[i]['result'])
print("正しいかどうか: " + graded_outputs[i]['text'])
print()
結果
Example 0:
質問: Steins Gateの主人公は誰?
実際の答え: 岡部倫太郎です。
出力された答え: 岡部倫太郎
正しいかどうか: CORRECT
Example 1:
質問: 橋田と紅莉栖は何を開発した?
実際の答え: 電話レンジ(仮)とタイムリープマシンです。
出力された答え: 電話レンジ(仮)を開発した。
正しいかどうか: INCORRECT
Example 2:
質問: 未来ガジェット研究室の初期メンバーは何人?
実際の答え: 3人
出力された答え: 3人です。
正しいかどうか: CORRECT
ちゃんと文書から質問に対する答えを引っ張ってきてくれていることが分かります。
2つ目の質問はもう実質CORRECT!笑
もっと沢山の質問を列挙させることによって、Q&Abotの信頼性を高められそうです。
業務用Chatbotなどは信頼性が結構重要だと思うので、このような方法で検証することは結構重要かも。
ちなみに、どのようにしてCORRECTかINCORRECTかを判別させているのかはQAEvalChainのプロンプトを可視化させれば一目瞭然です。
以下のようにして評価させていました。以下はプロンプトです。
You are a teacher grading a quiz.
You are given a question, the student's answer, and the true answer, and are asked to score it as either CORRECT or INCORRECT.
Example Format:
QUESTION: question here
STUDENT ANSWER: student's answer here
TRUE ANSWER: true answer here
GRADE: CORRECT or INCORRECT here
Please remember to grade them based on being factually accurate. Begin!
QUESTION: 未来ガジェット研究室の初期メンバーは何人?
STUDENT ANSWER: 3人です。
TRUE ANSWER: 3人
GRADE:
予想通りという感じでしたが、普通に二つが同じ答えかどうかをLLMに聞いていただけです。
ただ、それでもちゃんと精度が担保できているので秀逸ですね。
おわりに
このような形で、文書を読み込ませたQAbotの評価を行うことが出来ます。
QAEvalChainがミソでしたね。
最後にQAEvalChainの中身を可視化させて思いましたが、LangChainの各チェーンのプロンプトをまとめる記事とか欲しいなーと思ったので頑張って作ろうかなと思います。
Discussion