QEUR23_CHRLTM6 - Semantic Searchによる類似度の計測
~ LLMは社会のパワーだ!! ~
QEU:FOUNDER(設定年齢65歳) : “それでは、今回は最後のステップである類似度の計測をやります。前回のEXCELファイルをインプットとして使用します。”
D先生(設定年齢65歳) : “ここら辺のことは、前回の記事をみればわかるので省略します。それでは、プログラムをドン!!”
# -----
import re, math, time
# ----
import pandas as pd
import numpy as np
import json
from langchain_core.prompts import ChatPromptTemplate
from jinja2 import Environment, FileSystemLoader
# ----
# 選択してね(今回はCohere)
import cohere
from langchain_groq import ChatGroq
from langchain_cohere import ChatCohere
# 中略(EXCELデータの読み込み)
###############################
# STR -> LIST分割
###############################
# ---
def list_string(str_answer):
# 文字列を段落に分割する(for answer A)
paragraphs = re.split(r'\n\s*\n', str_answer.strip())
# ---
array_answer = []
for paragraph in paragraphs:
array_answer.append(paragraph.strip())
#print(paragraph.strip())
# ---
#print("----")
#print(array_answer)
return array_answer
# ---
# str_goal_A
list_goal_A = list_string(str_goal_A)
print(list_goal_A)
QEU:FOUNDER(設定年齢65歳) : “ちなみに、ここに上げたGOAL文の機能は今回の類似度計測につかいません。”
D先生(設定年齢65歳) : “なぜ?”
QEU:FOUNDER : “この意味は後で説明します。つづきに行きましょう。”
# -----
# EXCELシートから、文字列を抽出する
# -----
# Question(Initial)
arr_QInitial = df_qq.loc[:,'QInitial'].values
#print(arr_QInitial)
# -----
# Answer(Initial)
arr_AInitial = df_qq.loc[:,'AInitial'].values
#print("--- Answer(Initial) ---")
#print(arr_AInitial[0])
# -----
# Fact Based Answer
arr_FBA = df_qq.loc[:,'FBA'].values
#print("--- Fact Based Answer ---")
#print(arr_FBA[0])
# -----
# Fact Based Question
mx_FBQs = df_qq.loc[:,'FBQ1':'FBQ5'].values
print("--- mx_FBQs ---")
print(mx_FBQs[0,:])
##################################
# イニシアル質問とQQの類似度を比較する
##################################
# -----
#import cohere
#co = cohere.Client("COHERE_API_KEY") # Your Cohere API key
co = cohere.Client() # Your Cohere API key
# -----
# Creating Embedding(arrayは一次元ベクトル)
def create_embedding(str_answer):
# -----
#array_answer_A
num_answer = len(str_answer)
#print(num_answer)
response_answer = co.embed(
texts=[str_answer],
model='embed-english-v3.0',
input_type='search_document'
)
embeddings_answer = response_answer.embeddings
#print(embeddings_answer[0])
return num_answer, embeddings_answer
# -----
import numpy as np
import seaborn as sns
from sklearn.metrics.pairwise import cosine_similarity
import matplotlib as mpl
import matplotlib.pyplot as plt
# -----
# Fact Based Question
mx_similarity = np.zeros([num_df,5])
#print(mx_similarity)
# ---
for i in range(num_df): # num_df
# -----
arr_FBQs = mx_FBQs[i, :]
# -----
# QInitial
num_QInitial, embeddings_A = create_embedding(arr_QInitial[i])
# -----
# Cosine Similarity(A-B)
for j in range(5): # num_FBQs
# -----
arr_FBQs = mx_FBQs[i, :]
num_FBQs, embeddings_B = create_embedding(arr_FBQs[j])
val_similarity = cosine_similarity(embeddings_A, embeddings_B)[0][0]
mx_similarity[i,j] = val_similarity
if i%2 == 0 and j%2 == 0:
print(f"Cosine similarity between sentences A and B @{i}/{j}:", val_similarity)
# -----
# グラフ化する(ヒートマップ)
plt.figure(figsize=(12,8))
sns.heatmap(mx_similarity)
plt.show()
# -----
# 中間値となるインディックスを出力する
def find_median_index(numbers):
# リストをソートしたコピーを作成
sorted_numbers = sorted(numbers)
# 中間値を計算
median = np.median(sorted_numbers)
# 元のリストで中間値のインデックスを見つける
median_index = numbers.index(median)
return median, median_index
# ---
arr_index = []
arr_result = []
for i in range(num_df):
# 中間値のインデックスを見つける
list_numbers = mx_similarity[i,:].tolist()
result, index = find_median_index(list_numbers)
arr_index.append(index)
arr_result.append(result)
print(f"中間値のインデックス: {index}")
print(f"中間値: {result}")
# ----
print(arr_index)
print(arr_result)
# -----
# mx_similarity
arr_columns = ['SIM1','SIM2','SIM3','SIM4','SIM5',]
df_SIM = pd.DataFrame(mx_similarity, columns=arr_columns)
#df_SIM
# -----
# medium position
df_SIM.loc[:,'MINDEX'] = arr_index
df_SIM.loc[:,'MVALUE'] = arr_result
df_SIM
# -----
df_out = df_qq.copy()
df_concat = pd.concat([df_out, df_SIM],axis=1)
df_concat
# EXCELファイルに変換して保存する
df_concat.to_excel('qq_JED_step1A(4).xlsx', sheet_name='new_sheet_name')
QEU:FOUNDER : “そういうことです。以上の4つのタスクで1STEP目のGOAL_A文のQuestion to Question(QQ)処理プロセスが完了します。”
D先生: “前回のU-R戦争のディベート用システムよりも、今回は、はるかに洗練されている印象を受けました。次は、GOAL_Bでも同じQQ処理をするんでしょう?”
QEU:FOUNDER : “もちろん、(GOAL_B文に対しても)やりますよ。その後でEVALUATORに登場してもらって、ディベートの評価にいきましょう。”
D先生: “本当に面白いわ。このプロジェクト・・・。”
~ まとめ ~
C部長 : “ああ・・・。あかんかった!”
QEU:FOUNDER : “ここまで(↑)やらんでもいいとは思うが・・・。大変な成果があったと思うが・・・。”
D先生: “成果!?どういう意味?”
QEU:FOUNDER : “その前に、ちょっと話をそらすよ・・・。小生は、もともと今回のプロジェクトにおいて、トマ・ピケティ信者と共に、もう一人の先生(↓)の信者をおきたかったんですよ。”
D先生: “このJ国人の先生なの?いやあ・・・。なかなかに、このオッサンは採用がむずかしい・・・。”
QEU:FOUNDER : “この人、昔、大好きだったのよ。小生がネトウヨのとき・・・(笑)。それにしても、小生にとって不思議なのは、保守の反対語ってリベラルなの?教えて、D先生・・・。”
D先生: “へ?違うんですか?”
QEU:FOUNDER : “この人(↑)の好き嫌いの一覧を見てみてみ・・・。”
D先生: “あれ!?じゃあ、「保守の反対」ってなんなんですか?”
QEU:FOUNDER : “・・・というか、リベラルの反対語はパターナリズムでしょ?ちなみに、これは小生個人の感覚ですが・・・。”
QEU:FOUNDER : “ちなみに、もう一つの見方があります。”
D先生: “もうひとつあるの!?”
C部長 : “なぜ「いわゆる保守派」の党が急進・加速主義にはいるんですか!?”
QEU:FOUNDER : “あの(政党の)人たち、日頃やっていることから、こうしか見えないんだわ(笑)。あと、D先生の質問に答えます。ドン!!”
D先生: “由来は孔子様か・・・。考えてみれば、当たり前だ・・・。名前がしっかり定義されていないから、政(まつりごと)もうまくうごかないんでしょうね。”
QEU:FOUNDER : “ちなみに、この時代の「衛」という国は、かなり評判が悪かったらしいです。お寺の「おみくじ(↓)」にもなっています。”
D先生: “驚いた・・。結構、説得力があります。じゃあ、なんとか「名を正しくすること」はできないんですかねえ・・・?”
QEU:FOUNDER : “(名を正す方法は)あるよ。最新のテクノロジーを使えば・・・。各政党が自分のLLMモデルを開発し、それを、みんな(有権者)に使ってもらえばいいんです。システムのユーザー(有権者)は、我々のBONSAI2プロジェクトを通じて、各政党がどのような考え方を持っているのかを理解してもらいます。簡単なGUIでいけるんじゃないかな?CohereのPlaygroundの例(↓)を参考に出します。皆が使えば、有権者のもつ関心事にたいして、その党の「標準的なスタンス」を出してくれます。”
D先生: “それは便利だ・・・。もし、我々のBONSAI2システムを使ったら?”
QEU:FOUNDER : “2つの政党のLLMをインポートして、EVALUATER(ディベートの観衆)に指定します。そうすると、あらゆる事項の政党ごとの差異が明確になります。もっというと、A政党とB政党は、結局のところとれほど差がないという結果も出てくるんです。”
D先生: “先ほどの、2次元プロットを見ればうなづけますよね。いまならば、LLMモデルのPre-trainingには1億も使わないですよ。大き目の政党ならば、ぜんぜんやれます。”
QEU:FOUNDER : “この先生(↓)は、今回の選挙結果の読み方について、うまくまとめてくれています。「I党とR党は、長くはもたない」というのは、小生も同意見です。それでも、全体的にちょっと悲観的すぎるかな?もし、これから「名を正せば」、J国はうまくいく可能性はあると思うよ。なにしろ、これは世界初のイノベーションでしょう・・・。”
D先生: “いままでなかった、全く新しい流れ(↑)もできている。”
QEU:FOUNDER : “結論とすれば、歴史的に大きな意味を持つ選挙になったとおもいます。今後、大成功するんじゃないかな?「LLM+BONSAI2+ひとり街宣の合わせ技」を使えばの話だがね・・・(笑)。”