QEUR23_LLMDSS5: 高品質データセット(ja)を、より「高品質」に(3分の1)
~ やっと「3分の1(5k)」が終わった ~
・・・ 前回のつづきです ・・・
QEU:FOUNDER : “前回はDollyデータセットの持つ欠陥について話ました。今回は、そのデータをどのように「力業」で改善したのかを紹介しましょう。”
C部長 : “これはDeepLによる機械翻訳の修正ですよね?”
D先生 : “いやいや、修正に当たっては、かなりの工夫をしています。私もずいぶん苦労しました。単純作業だが、なにしろ量がねぇ。例えば・・・。”
C部長 : “なんだ・・・。単に翻訳プロンプトの情報をいれただけですよね?”
D先生 : “本来は、このような翻訳情報を入れなくてもLLMは翻訳のための学習をしてくれるんですよ。それを敢えて翻訳の学習プロンプトを追加したということは・・・。”
QEU:FOUNDER : “今回は多言語の単語間の一致性を極度に上げてみたいと思っています。英語は「BOOK」、日本語は「本」、中国語は「書」・・・。これらは、本来、トークン変換(言語情報をベクトル情報に変換)するとバラバラなベクトルになるものを、この作業を通じて(ベクトルを)ムリヤリに関連付けさせるんです。そういえば、このJSON表示プログラムの紹介をしていなかった。プログラムをドン!!”
以下の仕様に基づいて、Pythonプログラムを作成してください。/n/n
```仕様/n
- JSONファイル「'databricks-dolly-15k-ja.json」を読み込む/n
- JSONファイルには以下の項目がある/n
"index","instruction","input","output","category":/n
- JSONファイルで読み込んだ情報をTkinterで1レコード毎に表示する/n
- Tkinterのカンバスの大きさは(ヨコ)800x(タテ)400とする/n
- カンバスに表示する項目は、上から順番に以下のようにすること。各項目はFrameの中に入れること/n
"index","instruction","input","output","category":/n
- カンバスに以下の5つのボタンを配置する/n
「戻る(-100)」、「戻る(-1)」、「次へ(+1)」、「次へ(+100)」、「終了」/n
- 「終了」ボタンを押すとカンバスが閉じ、プログラムが終了する/n
- 「次へ(+1)」ボタンを押すと次のレコードを表示する/n
- 「戻る(-1)」ボタンを押すと前のレコードを表示する/n
- 「次へ(+100)」ボタンを押すと100レコード後の情報を表示する/n
- 「戻る(-100)」ボタンを押すと100レコード前の情報を表示する/n
- 「戻る(-1)」、「戻る(-100)」ボタンを押して情報が無い場合には、レコード番号は0として表示する/n
```
C部長 : “なんですか?この、わけのわからない呪文は・・・。”
D先生 : “FOUNDER・・・。「(プログラムを)ドン!」の間違いです。これは、GPT4に投げるためのプロンプトです。これを使って、GPTさんにプログラムを作ってもらったんですよね。”
QEU:FOUNDER : “正確には、(GPTに)70%ぐらい作ってもらった。それでも、特に時間がかかる「システムの大まかな構造」を作ってくれるのですごく役にたったけどね。それでは本当のプログラムをドン!!”
# -*- coding: utf-8 -*-
import json
import tkinter as tk
from tkinter import font
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.master.title("JSONファイルの表示")
self.master.geometry("1100x650")
self.pack()
self.create_widgets()
def create_widgets(self):
self.index_label = tk.Label(self, font = font1)
self.index_label.pack(side="top")
# ----
self.instruction_message = tk.Message(self, bg="#aafaff", width = 1050, font = font1)
self.instruction_message.pack(side="top")
# ----
self.input_message = tk.Message(self, bg="#aafaff", width = 1050, font = font1)
self.input_message.pack(side="top")
# ----
self.output_message = tk.Message(self, bg="#aafaff", width = 1050, font = font1)
self.output_message.pack(side="top")
# ----
self.category_label = tk.Label(self, font = font1)
self.category_label.pack(side="top")
# -----
self.prev_100_button = tk.Button(self, text="戻る(-100)", command=self.prev_100)
self.prev_100_button.pack(side="left")
self.prev_button = tk.Button(self, text="戻る(-1)", command=self.prev)
self.prev_button.pack(side="left")
self.next_button = tk.Button(self, text="次へ(+1)", command=self.next)
self.next_button.pack(side="left")
self.next_100_button = tk.Button(self, text="次へ(+100)", command=self.next_100)
self.next_100_button.pack(side="left")
self.quit_button = tk.Button(self, text="終了", command=self.master.quit)
self.quit_button.pack(side="right")
def prev_100(self):
if (self.current_index - 100) < 0:
index0 = 0
index = 0
instruction = "No instruction"
input_data = "No input"
output_data = "No output"
category = "No category"
return
else:
index0 = int(self.current_index) - 100
index = str(data[index0]["index"])
instruction = str(data[index0]["instruction"])
input_data = str(data[index0]["input"])
output_data = str(data[index0]["output"])
category = str(data[index0]["category"])
self.current_index = self.current_index - 100
self.index_label.config(text=f"Index: {index}")
self.instruction_message.config(text=f"Instruction: {instruction}")
self.input_message.config(text=f"Input: {input_data}")
self.output_message.config(text=f"Output: {output_data}")
self.category_label.config(text=f"Category: {category}")
def prev(self):
if (self.current_index - 1) < 0:
index0 = 0
index = 0
instruction = "No instruction"
input_data = "No input"
output_data = "No output"
category = "No category"
return
else:
index0 = int(self.current_index) - 1
index = str(data[index0]["index"])
instruction = str(data[index0]["instruction"])
input_data = str(data[index0]["input"])
output_data = str(data[index0]["output"])
category = str(data[index0]["category"])
self.current_index = self.current_index - 1
self.index_label.config(text=f"Index: {index}")
self.instruction_message.config(text=f"Instruction: {instruction}")
self.input_message.config(text=f"Input: {input_data}")
self.output_message.config(text=f"Output: {output_data}")
self.category_label.config(text=f"Category: {category}")
def next(self):
if (self.current_index + 1) >= len(data):
index0 = len(data) - 1
index = len(data) - 1
instruction = "No instruction"
input_data = "No input"
output_data = "No output"
category = "No category"
return
else:
index0 = int(self.current_index) + 1
index = str(data[index0]["index"])
instruction = str(data[index0]["instruction"])
input_data = str(data[index0]["input"])
output_data = str(data[index0]["output"])
category = str(data[index0]["category"])
self.current_index = self.current_index + 1
self.index_label.config(text=f"Index: {index}")
self.instruction_message.config(text=f"Instruction: {instruction}")
self.input_message.config(text=f"Input: {input_data}")
self.output_message.config(text=f"Output: {output_data}")
self.category_label.config(text=f"Category: {category}")
def next_100(self):
if (self.current_index + 100) >= len(data):
index0 = len(data) - 1
index = len(data) - 1
instruction = "No instruction"
input_data = "No input"
output_data = "No output"
category = "No category"
return
else:
index0 = int(self.current_index) + 100
index = str(data[index0]["index"])
instruction = str(data[index0]["instruction"])
input_data = str(data[index0]["input"])
output_data = str(data[index0]["output"])
category = str(data[index0]["category"])
self.current_index = self.current_index + 100
self.index_label.config(text=f"Index: {index}")
self.instruction_message.config(text=f"Instruction: {instruction}")
self.input_message.config(text=f"Input: {input_data}")
self.output_message.config(text=f"Output: {output_data}")
self.category_label.config(text=f"Category: {category}")
if __name__ == '__main__' :
with open("databricks-dolly-15k-review-1_of_3-ja.json", "r", encoding="utf-8") as f:
data = json.load(f)
# -----
root = tk.Tk()
#文字サイズ、フォントを指定。
font1 = font.Font(family='Helvetica', size=11, weight='bold')
app = Application(master=root)
app.current_index = 0
app.mainloop()
QEU:FOUNDER : “プログラムの紹介が終わったので、Dollyデータセットの修正の話にもどりましょう。Cさん、このプロンプトを見て違和感を感じない?”
C部長 : “えっ!?別に違和感はないですが・・・。”
D先生 : “これは、「Q&A」になっていないです。Qでは「アレクサンダー・マクガイア」であり、Aでは「Alexander McGuire」です。”
C部長 : “同じじゃん・・・。”
QEU:FOUNDER : “人生経験を積んだCさんじゃなく、まっさらなLLM(大規模言語モデル)の立場になって考えてみてください。「アレクサンダー・マクガイア」と「Alexander McGuire」は同義である保証はどこにある?”
D先生 : “(同義である)保証はどこにもないです。固有名詞の場合は特にね・・・。だから、以下のようにプロンプトを修正しているんです。ここまでくると、「修正」というより「改造」ですが・・・。”
QEU:FOUNDER : “だから「カッコ」を徹底的に活用しました。これには、とてつもない手間がかかった・・・。”
C部長 : “じゃあ、質問ですが・・・。「カッコの中のモノ(単語)」が同意語であることを、LLMはどのように認識するんですか?”
D先生 : “徹底的に「練習」してますよ・・・(笑)。”
QEU:FOUNDER : “「まあ、このように今回のデータセットは徹底的に「手を入れている」んです。従って、作業が遅いわけで、まだ3分の1(5k)です。ちなみに、これでも完全な改造ではないことを認めます。”
>寄付のお願い(click here)<
QEU:FOUNDER : “それでも、なんとか寄付をください。このプロジェクトをつづけるために・・・。”
~ まとめ ~
QEU:FOUNDER : “修正の完成量が、まだ「5k」と、まだ少ないものの、一応はここで「仮リリース」をしておきましょう。”
C部長 : “このデータ・セットのスタイルは以前も見たことがあります。拡張子を見ると「jsonl」というんですか?”
QEU:FOUNDER : “正式には「JSON Line」という書式らしいですよ。大量のJSON情報を束ねるための型式らしいです。このファイルを作るためのPythonプログラムは以下のようになります。簡単ですよ。見た目は・・・。”
# 収縮版JSONファイル(jsonl)を作成する
import json
import pandas as pd
import numpy as np
#with open('databricks-dolly-15k-ja.json', 'r', encoding='utf-8') as f:
# data = json.load(f)
with open('databricks-dolly-15k-review-1_of_3-ja.json', 'r', encoding='utf-8') as f:
data = json.load(f)
# ----
arr_index = []
arr_instruction = []
arr_input = []
arr_output = []
arr_category = []
# ----
for i in range(5000): ### len(data)
arr_index.append(data[i]['index'])
#print(i, data[i]['index'])
arr_instruction.append(data[i]['instruction'])
arr_input.append(data[i]['input'])
arr_output.append(data[i]['output'])
arr_category.append(data[i]['category'])
# ----
# データフレームを作成する
mx_df = np.array([arr_instruction]).T
df = pd.DataFrame(mx_df, columns=["instruction"])
#print(df)
# ----
# 項目の追加
df['input'] = arr_input
df['output'] = arr_output
print(df)
# JSONLファイルに変換して出力
with open('databricks-dolly-5k-review-ja.jsonl', 'w', encoding="utf-8") as f:
for row in df.to_dict(orient='records'):
f.write(json.dumps(row, ensure_ascii=False) + '\n')
D先生 : “すごく簡単なプログラムですね。それにしても、なぜ5kだけ抽出したんですか?いっそのこと15kにすればいいのに・・・。”
QEU:FOUNDER : “小生の貧弱なPCのスペックでは、15k全部の変換が出来なかったんだよね。もちろん、元のデータを切り刻んで処理すればできるんだろうけど、現時点ではムダだね。”
D先生 : “このデータをどこにポストしましたか?”
QEU:FOUNDER : “ここら辺のgithubにおいてあると思います。”
コメント
コメントを投稿