QEUR23_LMABYS14: Llama2の精度評価(LangChain-英語-その2)
~ プロンプト・エンジニアリングのチカラとは? ~
D先生 : “前回のトライアルでは、本来のLlama2のLLM(大規模言語モデル)実力をうまく発揮できなかったようです。”
QEU:FOUNDER : “前回の「単純にLangChain(LC)を使ってみた」という方法では、逆にパフォーマンスが悪くなったわけです。”
(Llama-v2-13b-GPTQ:今回->LCあり)
(Llama-v2-13b-GPTQ:前回->LCなし)
D先生 : “そして、FOUNDER・・・。今回の戦略は?”
Customize the prompt: プロンプトをカスタマイズする: RetrievalQA チェーンのプロンプトをカスタマイズして、LLM がより正確な回答を生成できるようにすることができます。
Use different chain types: さまざまなチェーン・タイプを使用する: 共有コンテキストでは、stuff、map_reduce、refine、map_rerank などのさまざまなチェーン・タイプについて説明します。 各チェーン・タイプには、抽出に対応するための異なるアプローチがあり、アプリケーションの特定の要件に基づいて使用できます。 たとえば、stuff チェーン・タイプは、取得したすべてのドキュメントをプロンプトに単に「詰め込み」ます。map_reduce チェーン・タイプは、質問を各ドキュメントにマップし、回答を 1 つの回答に絞り込みます。refine チェーン・タイプは、回答を反復的に絞り込みます。そして、map_rerank チェーンは、 type は質問を各ドキュメントにマッピングし、回答を再ランク付けして、それらを 1 つの回答にまとめます。
QEU:FOUNDER : “前回に読んでみたアドバイスのうち、この2種類(↑)が特に有効だと思います。ただし、チェーン・タイプのパラメタは「stuff」のままにしようと思います。”
D先生 : “なぜ他のパラメタ(map_reduce)にしないんですか?”
QEU:FOUNDER : “今回はベクトル・ストア(Vector Store)の中の情報量は少ないので、パラメタを変えてみても意義が少ないと思ったことと、他にやりたいことがあったのです。それでは、改造版のLLMとLangChainで質問に回答するプログラムを晒します”
# llama2-13B-chat-GPTQによる連続回答プログラム(LangChainつき)
import pandas as pd
import numpy as np
# LLM
from transformers import AutoTokenizer, pipeline, logging
from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig
# LangChain
from langchain import HuggingFacePipeline, PromptTemplate, LLMChain
from langchain.chains import RetrievalQA
from langchain.document_loaders import DirectoryLoader
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import Chroma
#Load all the .txt files from docs directory
loader = DirectoryLoader('/content/drive/MyDrive/LCdocs/',glob = "**/*.txt")
documents = loader.load()
len(documents)
# -----
print(documents[0].page_content[0:1500])
# -----
# 言語情報をChunk分割する
splitter = RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=64, separators=["\n\n", "\n", "。", ","],)
texts = splitter.split_documents(documents)
len(texts)
# -----
print(texts[30].page_content)
# -----
# モデル名
model_name_or_path = "TheBloke/h2ogpt-4096-llama2-13B-chat-GPTQ"
use_triton = False
tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, use_fast=True)
model = AutoGPTQForCausalLM.from_quantized(model_name_or_path,
use_safetensors=True,
trust_remote_code=False,
device="cuda:0",
use_triton=use_triton,
quantize_config=None)
"""
# To download from a specific branch, use the revision parameter, as in this example:
# Note that `revision` requires AutoGPTQ 0.3.1 or later!
model = AutoGPTQForCausalLM.from_quantized(model_name_or_path,
revision="gptq-4bit-32g-actorder_True",
use_safetensors=True,
trust_remote_code=False,
device="cuda:0",
quantize_config=None)
"""
# -----
# Inference can also be done using transformers' pipeline
# Prevent printing spurious transformers error when using pipeline with AutoGPTQ
logging.set_verbosity(logging.CRITICAL)
#print("*** Pipeline:")
pipe = pipeline(
"text-generation",
model=model,
tokenizer=tokenizer,
device=0, # GPUを使うことを指定 (cuda:0と同義)
max_new_tokens=512,
temperature=0.2,
top_p=0.95,
repetition_penalty=1.15
)
#################
##################################
model_name = "sentence-transformers/all-mpnet-base-v2"
model_kwargs = {"device": "cuda"}
embeddings = HuggingFaceEmbeddings(model_name=model_name, model_kwargs=model_kwargs)
db = Chroma.from_documents(texts, embeddings, persist_directory="db")
D先生 : “あれ? 「sentence-transformer」のモデルを変えちゃったんですか?”
#all-MiniLM-L6-v2(以前まで使っていたモデル)
#This is a sentence-transformers model: It maps sentences & paragraphs to a 384 dimensional dense
#vector space and can be used for tasks like clustering or semantic search.
#all-mpnet-base-v2(今回から使うモデル)
#This is a sentence-transformers model: It maps sentences & paragraphs to a 768 dimensional dense
#vector space and can be used for tasks like clustering or semantic search.
QEU:FOUNDER : “Huggingfaceのダウンロード実績をみても、今回から使い始めるモデルは人気があります。何しろ、モデルが大きい分だけ「判別力」が高いことが期待できます。”
D先生 : “そういうことですね。だから、「stuff」パラメタを敢えて変えなかったんですね。”
QEU:FOUNDER : “もしパラメタを変えるとすれば、次のステップです。あまり効果はないとは思いますが・・・。”
######################
##################
llm = HuggingFacePipeline(
pipeline = pipe,
model_kwargs = {"temperature": 0.2}
)
# Build prompt
template = """If you found unfamiliar noun in question provided, use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer. Write answer within 3 sentences or 20 words.
{context}
Question: {question}
Answer:"""
QA_CHAIN_PROMPT = PromptTemplate.from_template(template)# Run chain
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=db.as_retriever(search_kwargs={"k": 2}),
return_source_documents=True,
chain_type_kwargs={"prompt": QA_CHAIN_PROMPT},
verbose=False,
)
D先生 : “とうとう、「プロンプト・エンジニアリング(prompt engineering)」を始めましたね。”
(英語) If you found unfamiliar noun in question provided, use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer. Write answer within 3 sentences or 20 words.
(日本語) 設問に見慣れない名詞があった場合、以下の「文脈(context)」を利用して、「設問(question)」のあとで答えましょう。答えがわからない場合は、答えを作ろうとせず、わからないと答えましょう。答えは3文または20語以内に書きなさい。
D先生 : “プロンプトに答えを短くしようとする工夫が見られます。しかし、なにしろこの指示内容(↓)が面白いですね。”
「答えがわからない場合は、答えを作ろうとせず、わからないと答えましょう。」
QEU:FOUNDER : “これは「ハルシネーション」対策です。でも、この指示によって、どういう結果になるかはわかりません。”
######################
##################
# ----
# 質問の文字列リストを定義する
df = pd.read_excel("/content/drive/MyDrive/LCdocs/QEU-verify100-ja2(en).xlsx")
#print(df)
len(df)
# 英語のQA情報を読み込む
question_list = df["instructions(en)"].values
#print(question_list[0:20])
reference_list = df["response(en)"].values
#print(referece_list[0:20])
type_list = df["type"].values
print(type_list[0:20])
######################
##################
# -----
# 個別の質問応答のタスクを実行する関数を定義する
def repeat_qa(question):
# 質問に回答する
print(f"No.{i}: Question: {question}")
# Ask Questions
res = qa_chain( question )
answer = res["result"]
# -----
# Retrieve the page number from the source document
list_content = list(res['source_documents'][0])
#print(list_content)
# -----
# 整形する
arr_content = list_content[0]
#print(arr_content)
str_content = arr_content[1]
#print(str_content)
# -----
# 答えを表示する
print(f"Answer: {answer}")
print(f"Content: {str_content}")
return answer, str_content
# 繰り返し質問する
mx_output = []
for i in range(100): # len(df)
# 今回の質問を抽出する
question = question_list[i]
reference = reference_list[i]
val_type = type_list[i]
# 質問に回答する
answer, str_content = repeat_qa(question)
# 質問と回答のマトリックス(リスト)を生成する
mx_output.append([question, answer, reference, val_type, str_content])
# リストを出力する
#print("--------")
#print("generate answer list")
#print(answer_output)
print("--------")
print("generate output matrix")
print(np.array(mx_output[0:5]))
# -----
# Create DataFrame
mx_out = np.array(mx_output)
columns1 = ["Question", "Answer", "Reference", "Type", "Context"]
df_out = pd.DataFrame(data=mx_out, columns=columns1)
print(df_out)
# EXCEL ファイル (USverify100_Llama_en5(LC).xlsx) として出力
df_out.to_excel("/content/drive/MyDrive/USverify100_Llama_en5(LC).xlsx")
QEU:FOUNDER : “そして、以下が今回の回答の結果です。”
D先生 : “Contextの内容をみると、sentence-transformerを変えてもVector Storeがとくに大きく変わったようには思いません。それで、肝心のパフォーマンスは?”
D先生 : “おっと!!Classification(分類)質問なんかは、特にパフォーマンスが上がっています。まずは、Open_QAのNG事例を見てみましょうか・・・。”
D先生 : “以前と同様に、言い回しが長くなっただけで正解が多いですよね。それにしても、いままでに見たことがない「変な不正解」が少しだけ見られますね。次にClassificationに行きましょう。”
D先生 : “おっと!「ブランク(空白)回答」が見つかりました。ひょっとして、これこそが、プロンプトの例の指示への対応なのでしょうか・・・。”
QEU:FOUNDER : “多分、そうでしょう。・・・そして、先ほどD先生の言っていた「変な不正解」が見られます。「(その答えは)どこから来たんだろう?」と思う、変な回答がたまに出て来ています。”
D先生 : “まあ、それはLLMの醍醐味じゃないんですか・・・(笑)。これも意外と、プロンプトを変えれば何とかなるかもしれません。”
QEU:FOUNDER : “そこらへんはなんとも言えません。ただし、ぼんやりとわかってきたことがあります。”
QEU:FOUNDER : “「LangChain(その対抗シーズとしてLlamaIndex)を使いこなすこと」と、「LLMをFine tuningすること」はOR条件ではありません。つまり、片方をやれば他は不要というわけではありません。両方が相乗効果(1+1=3+α)を持つように「戦略的にチューニングを行って」、初めてLLMの本当のパワーが発揮されるんだろうと・・・。つまり、小生のようにやりたいことがはっきりしており、LLMに複雑な論理問題を解かせることに興味がなければ、GPT4や5もいらないわけです。”
D先生 : “GPTって、学習データを作成するのに便利ですね。”
QEU:FOUNDER : “小生には、それが最も魅力的に感じます(笑)。「プロンプト・エンジアリング=データベース・エンジニアリング」なんですよね。次は、日本語LCの構築に進みましょう。”
~ まとめ ~
QEU:FOUNDER : “とうとう、この人が出てきた!!”
C部長 : “当たり前ながら、すごい頭脳明晰な人で感心したわ・・・。”
QEU:FOUNDER : “最もすごいのは、彼の戦略と「心」なんでしょうけど・・・。”
C部長 : “どちらにしろ、(彼から)目が離せません。”
コメント
コメントを投稿