■search.py
以下のコードを変更前→変更後に修正
ひとつ前の処理「embedding.py」のコード内で、余分な行の出力を避けるためembeddingカラムに出力する値を配列形式→文字列形式に変更したため、search.pyでは文字列の配列→数値の配列への変換処理を行ってからdistanceを計算するようにした
【変更前1】
df['distances'] = distances_from_embeddings(q_embeddings, df['embeddings'].apply(eval).apply(np.array).values, distance_metric='cosine')
【変更後1】
# 文字列の配列を数値の配列に変換 df['distances'] = distances_from_embeddings( q_embeddings, df['embeddings'].apply(lambda x: np.array([float(num) for num in x.split(',')])).values, distance_metric='cosine' )
学習データのcsvを読み込む際、文字をエンコードする個所が「ANSI」形式となっていたが、この形式だとエラーを起こすため「utf-8-sig」形式に変更した
【変更前2】
df = pd.read_csv('embeddings.csv', encoding="ANSI")
【変更後2】
df = pd.read_csv('embeddings.csv', encoding="utf-8-sig")
【変更後1と変更後2を修正した改修後のコード全体】
import pandas as pd import openai import numpy as np from openai.embeddings_utils import distances_from_embeddings def create_context(question, df, max_len=1800): """ 質問と学習データを比較して、コンテキストを作成する関数 """ # 質問をベクトル化 q_embeddings = openai.Embedding.create(input=question,engine='text-embedding-ada-002')['data'][0]['embedding'] # 質問と学習データと比較してコサイン類似度を計算し、 # 「distances」という列に類似度を格納 #df['distances'] = distances_from_embeddings(q_embeddings,df['embeddings'].apply(eval).apply(np.array).values, distance_metric='cosine') # 文字列の配列を数値の配列に変換 df['distances'] = distances_from_embeddings( q_embeddings, df['embeddings'].apply(lambda x: np.array([float(num) for num in x.split(',')])).values, distance_metric='cosine' ) # コンテキストを格納するためのリスト returns = [] # コンテキストの現在の長さ cur_len = 0 # 学習データを類似度順にソートし、トークン数の上限までコンテキストに # 追加する for _, row in df.sort_values('distances', ascending=True).iterrows(): # テキストの長さを現在の長さに加える cur_len += row['n_tokens'] + 4 # テキストが長すぎる場合はループを終了 if cur_len > max_len: break # コンテキストのリストにテキストを追加する returns.append(row["text"]) # コンテキストを結合して返す return "\n\n###\n\n".join(returns) def answer_question(question, conversation_history): """ コンテキストに基づいて質問に答える関数 """ # 学習データを読み込む #df = pd.read_csv('embeddings.csv', encoding="ANSI") df = pd.read_csv('embeddings.csv', encoding="utf-8-sig") context = create_context (question, df, max_len=200) # プロンプトを作成し、会話の履歴に追加 prompt = f"あなたはとあるホテルのスタッフです。コンテキストに基づいて、お客様からの質問に丁寧に答えてください。コンテキストが質問に対して回答できない場合は「わかりません」と答えてください。\n\nコンテキスト: {context}\n\n---\n\n質問: {question}\n回答:" conversation_history.append({"role": "user", "content": prompt}) try: # ChatGPTからの回答を生成 response = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=conversation_history, temperature=1, ) # ChatGPTからの回答を返す return response.choices[0]["message"]["content"].strip() except Exception as e: # エラーが発生した場合は空の文字列を返す print(e) return ""