1632913320
類似性検索は、元の入力に密接に関連するアイテムの検索を処理する機械学習フィールドのサブセットです。製品、音楽、映画のおすすめなどに非常に役立ちます。あなたは見たオフィスをので、ここでは、Netflixの上であなたが好きかもしれないいくつかの他のショーをしています。あなたはSpotifyでベイサイドを頻繁に聴いているので、これらの他のポップパンクバンドをチェックしてください。
類似性検索を使用して、カスタマーサポートを自動化することもできます。顧客が質問をしたときに、以前に尋ねた同様の質問と回答を簡単に見つけることができたらどうでしょうか。
この記事では 、マネージド類似性検索サービスであるPineconeを使用してそれを行うPythonFlaskアプリを構築します。
デモアプリに入る前に、解決しようとしている問題を調べてみましょう。あなたが数千または数百万の顧客を抱える大企業の幹部であると想像してみてください。カスタマーサポートチームは、毎日同じ質問を繰り返し受けます。時間とお金を節約するために、優れた公開ドキュメントとFAQページを用意することで、サポートプロセスを合理化できます。しかし、どうすれば顧客が必要な情報を確実に見つけられるようにできるでしょうか。結局のところ、ドキュメントの作成は戦いの半分にすぎません。
多くの企業が採用しているアプローチの1つは、カスタマーサービスのチャットボットを使用することです。顧客が最初に会話を開始するとき、彼らはロボットとチャットしています。顧客が質問を入力すると、ボットは問題の解決を支援しようとします。ボットが正確で関連性のある質問と回答で応答できる場合、顧客は自分で問題を解決できる可能性があります。それでも問題が解決しない場合、顧客は実際に助けてくれる人間と話すように要求できます。人工知能と機械学習は、私たちのすべての問題を解決できるわけではありません—少なくともまだです。
それでは、デモアプリを見てみましょう。以下に、アプリの動作の簡単なアニメーションを示します。ユーザーが質問を入力してフォームを送信すると、ユーザーの元の質問に回答することを期待して、関連する質問が表示されます。
デモアプリ—カスタマーサービスチャットボット
かなりきちんとしていますよね?では、これはどのように機能するのでしょうか?
アプリを構築する際に、Quoraからの質問と回答のデータセットを最初に見つけました。このデータセットには数十万の質問が含まれていますが、最初の50,000を使用しています。次に、それらの質問を受け取り、埋め込みモデルを実行して、いわゆるベクトル埋め込みを作成しました。ベクトル埋め込みは、本質的に、種々の入力間の類似性を決定するために、機械学習アルゴリズムのためのメタデータを提供する数のリストです。平均単語埋め込みモデルを使用しました。次に、これらのベクトル埋め込みを、Pineconeが管理するインデックスに挿入しました。
これで、ユーザーが質問を送信すると、PineconeのSDKを使用してベクター埋め込みのインデックスをクエリするAPIエンドポイントにリクエストが送信されます。エンドポイントは5つの同様の質問を返し、それらの結果はアプリのUIでユーザーに表示されます。
言い換えると、マネージド類似性検索ソリューションとしてのPineconeは、推奨を返すためのエンジンを提供します。埋め込みモデルを介してデータを実行することによって生成されるベクトル埋め込みを持ってくるだけです。
自分で試してみたい場合は、GitHubでこのアプリのコードを見つけることができます。README
自分のマシン上でローカルにアプリケーションを実行する方法について説明します。
プロジェクトの背後にある動機を理解し、アプリがどのように機能するかについての概要を理解したところで、実際のコードを掘り下げて、内部で何が起こっているかを見てみましょう。簡単にするために、すべてのバックエンドコードはapp.py
ファイルに含まれています。このファイルは、以下で完全に再現されています。
from dotenv import load_dotenv
from flask import Flask
from flask import render_template
from flask import request
from flask import url_for
import json
import os
import pandas as pd
import pinecone
import requests
from sentence_transformers import SentenceTransformer
app = Flask(__name__)
pinecone_index_name = "question-answering-chatbot"
DATA_DIR = "tmp"
DATA_FILE = f"{DATA_DIR}/quora_duplicate_questions.tsv"
DATA_URL = "https://qim.fs.quoracdn.net/quora_duplicate_questions.tsv"
def initialize_pinecone():
load_dotenv()
PINECONE_API_KEY = os.environ["PINECONE_API_KEY"]
pinecone.init(api_key=PINECONE_API_KEY)
def delete_existing_pinecone_index():
if pinecone_index_name in pinecone.list_indexes():
pinecone.delete_index(pinecone_index_name)
def create_pinecone_index():
pinecone.create_index(name=pinecone_index_name, metric="cosine", shards=1)
pinecone_index = pinecone.Index(name=pinecone_index_name)
return pinecone_index
def download_data():
os.makedirs(DATA_DIR, exist_ok=True)
if not os.path.exists(DATA_FILE):
r = requests.get(DATA_URL)
with open(DATA_FILE, "wb") as f:
f.write(r.content)
def read_tsv_file():
df = pd.read_csv(
f"{DATA_FILE}", sep="\t", usecols=["qid1", "question1"], index_col=False
)
df = df.sample(frac=1).reset_index(drop=True)
df.drop_duplicates(inplace=True)
return df
def create_and_apply_model():
model = SentenceTransformer("average_word_embeddings_glove.6B.300d")
df["question_vector"] = df.question1.apply(lambda x: model.encode(str(x)))
pinecone_index.upsert(items=zip(df.qid1, df.question_vector))
return model
def query_pinecone(search_term):
query_question = str(search_term)
query_vectors = [model.encode(query_question)]
query_results = pinecone_index.query(queries=query_vectors, top_k=5)
res = query_results[0]
results_list = []
for idx, _id in enumerate(res.ids):
results_list.append({
"id": _id,
"question": df[df.qid1 == int(_id)].question1.values[0],
"score": res.scores[idx],
})
return json.dumps(results_list)
initialize_pinecone()
delete_existing_pinecone_index()
pinecone_index = create_pinecone_index()
download_data()
df = read_tsv_file()
model = create_and_apply_model()
@app.route("/")
def index():
return render_template("index.html")
@app.route("/api/search", methods=["POST", "GET"])
def search():
if request.method == "POST":
return query_pinecone(request.form.question)
if request.method == "GET":
return query_pinecone(request.args.get("question", ""))
return "Only GET and POST methods are allowed for this endpoint"
ここで起こっていることを、メソッドごと、行ごとに分解してみましょう。
1〜11行目で、アプリの依存関係をインポートします。私たちのアプリは以下に依存しています:
dotenv.env
ファイルから環境変数を読み取るためflask
Webアプリケーションのセットアップ用json
JSONを操作するためos
環境変数を取得するためにもpandas
データセットを操作するためpinecone
PineconeSDKを使用するためrequests
データセットをダウンロードするためのAPIリクエストを作成するためsentence_transformers
埋め込みモデル用13行目に、アプリの名前をFlaskに伝えるためのボイラープレートコードをいくつか提供します。
15〜18行目で、アプリで使用されるいくつかの定数を定義します。これらには、Pineconeインデックスの名前、質問データを保存するディレクトリ、データセットのファイル名、およびデータセットのダウンロード元のURLが含まれます。
20〜23行目で、initialize_pinecone
メソッドは.env
ファイルからAPIキーを取得し、それを使用してPineconeを初期化します。
25〜27行目で、このdelete_existing_pinecone_index
メソッドは、使用しているものと同じ名前のインデックス(「question-answering-chatbot」)をPineconeインスタンスで検索します。既存のインデックスが見つかった場合は、削除します。
29〜33行目で、このcreate_pinecone_index
メソッドは、選択した名前(「question-answering-chatbot」)、「コサイン」近接メトリック、および1つのシャードのみを使用して新しいインデックスを作成します。
35〜41行目で、このdownload_data
メソッドは必要に応じてQuoraの質問と回答のペアのデータセットをダウンロードします。ファイルがディレクトリにすでに存在する場合は、そのファイルtmp
を使用します。
43〜50行目で、このread_tsv_file
メソッドはpandas
ライブラリを使用してTSVファイルを読み取り、各行をデータフレームに挿入します。また、データセットで見つかった重複する質問もすべて削除します。
52〜57行目では、このcreate_and_apply_model
メソッドはsentence_transformers
ライブラリを使用して平均単語埋め込みモデルを操作します。次に、モデルを使用して質問をエンコードすることにより、各質問のベクトル埋め込みを作成します。次に、ベクトル埋め込みが松ぼっくりインデックスに挿入されます。
これまでに説明した各メソッドは、バックエンドアプリの起動時に77〜82行目で呼び出されます。この作業により、ユーザー入力に基づいて実際に松ぼっくりインデックスをクエリする最終ステップの準備が整います。
84〜94行目で、アプリに2つのルートを定義します。1つはホームページ用、もう1つはAPIエンドポイント用です。ホームページはindex.html
JSおよびCSSアセットとともにテンプレートファイルを提供し、APIエンドポイントはPineconeインデックスをクエリするための検索機能を提供します。
最後に、59〜75行目で、このquery_pinecone
メソッドはユーザーの入力を受け取り、それをベクトル埋め込みに変換してから、Pineconeインデックスにクエリを実行して同様の質問を見つけます。このメソッドは、/api/search
エンドポイントがヒットしたときに呼び出されます。これは、ユーザーが新しい検索クエリを送信するたびに発生します。
視覚的な学習者のために、アプリの仕組みの概要を示す図を次に示します。
アプリのアーキテクチャとユーザーエクスペリエンス
では、これをすべてまとめると、ユーザーエクスペリエンスはどのようになりますか?
ユーザーは私たちのサイトにアクセスし、「Pythonの学習方法」という質問を入力し、過去に尋ねられた同様の質問を見つけてから、リンクをクリックしてQuoraの質問と回答を確認できます。
カスタマーサービスのシナリオに従って、ユーザーは、サポートに問い合わせることなく、当社の製品の使用方法について質問したり、同様の質問を見つけたり、リンクをクリックしたり、質問に答える役立つサポートページに移動したりできます。代表。
これで、実際の問題を解決するための簡単なPythonアプリを作成しました。このアプリをさらに改善するために、質問が行われるたびに新しい質問と回答をインデックスに含めることができます。また、顧客のフィードバックを使用してモデルを微調整し、返された結果が適切かどうかを知ることもできます。結局のところ、フィードバックは、モデルが有用な結果を提供する上でより良くなるのに役立つものです。
ストーリーの教訓は明確である必要があります。類似性検索は、顧客により良い結果を提供するのに役立ちます。また、マネージドサービスとして、Pineconeを使用すると、ベクターベースのレコメンデーションシステムを簡単に本番環境に移行できます。
Link: https://dzone.com/articles/build-a-customer-service-chatbot-using-python-flas
1632913320
類似性検索は、元の入力に密接に関連するアイテムの検索を処理する機械学習フィールドのサブセットです。製品、音楽、映画のおすすめなどに非常に役立ちます。あなたは見たオフィスをので、ここでは、Netflixの上であなたが好きかもしれないいくつかの他のショーをしています。あなたはSpotifyでベイサイドを頻繁に聴いているので、これらの他のポップパンクバンドをチェックしてください。
類似性検索を使用して、カスタマーサポートを自動化することもできます。顧客が質問をしたときに、以前に尋ねた同様の質問と回答を簡単に見つけることができたらどうでしょうか。
この記事では 、マネージド類似性検索サービスであるPineconeを使用してそれを行うPythonFlaskアプリを構築します。
デモアプリに入る前に、解決しようとしている問題を調べてみましょう。あなたが数千または数百万の顧客を抱える大企業の幹部であると想像してみてください。カスタマーサポートチームは、毎日同じ質問を繰り返し受けます。時間とお金を節約するために、優れた公開ドキュメントとFAQページを用意することで、サポートプロセスを合理化できます。しかし、どうすれば顧客が必要な情報を確実に見つけられるようにできるでしょうか。結局のところ、ドキュメントの作成は戦いの半分にすぎません。
多くの企業が採用しているアプローチの1つは、カスタマーサービスのチャットボットを使用することです。顧客が最初に会話を開始するとき、彼らはロボットとチャットしています。顧客が質問を入力すると、ボットは問題の解決を支援しようとします。ボットが正確で関連性のある質問と回答で応答できる場合、顧客は自分で問題を解決できる可能性があります。それでも問題が解決しない場合、顧客は実際に助けてくれる人間と話すように要求できます。人工知能と機械学習は、私たちのすべての問題を解決できるわけではありません—少なくともまだです。
それでは、デモアプリを見てみましょう。以下に、アプリの動作の簡単なアニメーションを示します。ユーザーが質問を入力してフォームを送信すると、ユーザーの元の質問に回答することを期待して、関連する質問が表示されます。
デモアプリ—カスタマーサービスチャットボット
かなりきちんとしていますよね?では、これはどのように機能するのでしょうか?
アプリを構築する際に、Quoraからの質問と回答のデータセットを最初に見つけました。このデータセットには数十万の質問が含まれていますが、最初の50,000を使用しています。次に、それらの質問を受け取り、埋め込みモデルを実行して、いわゆるベクトル埋め込みを作成しました。ベクトル埋め込みは、本質的に、種々の入力間の類似性を決定するために、機械学習アルゴリズムのためのメタデータを提供する数のリストです。平均単語埋め込みモデルを使用しました。次に、これらのベクトル埋め込みを、Pineconeが管理するインデックスに挿入しました。
これで、ユーザーが質問を送信すると、PineconeのSDKを使用してベクター埋め込みのインデックスをクエリするAPIエンドポイントにリクエストが送信されます。エンドポイントは5つの同様の質問を返し、それらの結果はアプリのUIでユーザーに表示されます。
言い換えると、マネージド類似性検索ソリューションとしてのPineconeは、推奨を返すためのエンジンを提供します。埋め込みモデルを介してデータを実行することによって生成されるベクトル埋め込みを持ってくるだけです。
自分で試してみたい場合は、GitHubでこのアプリのコードを見つけることができます。README
自分のマシン上でローカルにアプリケーションを実行する方法について説明します。
プロジェクトの背後にある動機を理解し、アプリがどのように機能するかについての概要を理解したところで、実際のコードを掘り下げて、内部で何が起こっているかを見てみましょう。簡単にするために、すべてのバックエンドコードはapp.py
ファイルに含まれています。このファイルは、以下で完全に再現されています。
from dotenv import load_dotenv
from flask import Flask
from flask import render_template
from flask import request
from flask import url_for
import json
import os
import pandas as pd
import pinecone
import requests
from sentence_transformers import SentenceTransformer
app = Flask(__name__)
pinecone_index_name = "question-answering-chatbot"
DATA_DIR = "tmp"
DATA_FILE = f"{DATA_DIR}/quora_duplicate_questions.tsv"
DATA_URL = "https://qim.fs.quoracdn.net/quora_duplicate_questions.tsv"
def initialize_pinecone():
load_dotenv()
PINECONE_API_KEY = os.environ["PINECONE_API_KEY"]
pinecone.init(api_key=PINECONE_API_KEY)
def delete_existing_pinecone_index():
if pinecone_index_name in pinecone.list_indexes():
pinecone.delete_index(pinecone_index_name)
def create_pinecone_index():
pinecone.create_index(name=pinecone_index_name, metric="cosine", shards=1)
pinecone_index = pinecone.Index(name=pinecone_index_name)
return pinecone_index
def download_data():
os.makedirs(DATA_DIR, exist_ok=True)
if not os.path.exists(DATA_FILE):
r = requests.get(DATA_URL)
with open(DATA_FILE, "wb") as f:
f.write(r.content)
def read_tsv_file():
df = pd.read_csv(
f"{DATA_FILE}", sep="\t", usecols=["qid1", "question1"], index_col=False
)
df = df.sample(frac=1).reset_index(drop=True)
df.drop_duplicates(inplace=True)
return df
def create_and_apply_model():
model = SentenceTransformer("average_word_embeddings_glove.6B.300d")
df["question_vector"] = df.question1.apply(lambda x: model.encode(str(x)))
pinecone_index.upsert(items=zip(df.qid1, df.question_vector))
return model
def query_pinecone(search_term):
query_question = str(search_term)
query_vectors = [model.encode(query_question)]
query_results = pinecone_index.query(queries=query_vectors, top_k=5)
res = query_results[0]
results_list = []
for idx, _id in enumerate(res.ids):
results_list.append({
"id": _id,
"question": df[df.qid1 == int(_id)].question1.values[0],
"score": res.scores[idx],
})
return json.dumps(results_list)
initialize_pinecone()
delete_existing_pinecone_index()
pinecone_index = create_pinecone_index()
download_data()
df = read_tsv_file()
model = create_and_apply_model()
@app.route("/")
def index():
return render_template("index.html")
@app.route("/api/search", methods=["POST", "GET"])
def search():
if request.method == "POST":
return query_pinecone(request.form.question)
if request.method == "GET":
return query_pinecone(request.args.get("question", ""))
return "Only GET and POST methods are allowed for this endpoint"
ここで起こっていることを、メソッドごと、行ごとに分解してみましょう。
1〜11行目で、アプリの依存関係をインポートします。私たちのアプリは以下に依存しています:
dotenv.env
ファイルから環境変数を読み取るためflask
Webアプリケーションのセットアップ用json
JSONを操作するためos
環境変数を取得するためにもpandas
データセットを操作するためpinecone
PineconeSDKを使用するためrequests
データセットをダウンロードするためのAPIリクエストを作成するためsentence_transformers
埋め込みモデル用13行目に、アプリの名前をFlaskに伝えるためのボイラープレートコードをいくつか提供します。
15〜18行目で、アプリで使用されるいくつかの定数を定義します。これらには、Pineconeインデックスの名前、質問データを保存するディレクトリ、データセットのファイル名、およびデータセットのダウンロード元のURLが含まれます。
20〜23行目で、initialize_pinecone
メソッドは.env
ファイルからAPIキーを取得し、それを使用してPineconeを初期化します。
25〜27行目で、このdelete_existing_pinecone_index
メソッドは、使用しているものと同じ名前のインデックス(「question-answering-chatbot」)をPineconeインスタンスで検索します。既存のインデックスが見つかった場合は、削除します。
29〜33行目で、このcreate_pinecone_index
メソッドは、選択した名前(「question-answering-chatbot」)、「コサイン」近接メトリック、および1つのシャードのみを使用して新しいインデックスを作成します。
35〜41行目で、このdownload_data
メソッドは必要に応じてQuoraの質問と回答のペアのデータセットをダウンロードします。ファイルがディレクトリにすでに存在する場合は、そのファイルtmp
を使用します。
43〜50行目で、このread_tsv_file
メソッドはpandas
ライブラリを使用してTSVファイルを読み取り、各行をデータフレームに挿入します。また、データセットで見つかった重複する質問もすべて削除します。
52〜57行目では、このcreate_and_apply_model
メソッドはsentence_transformers
ライブラリを使用して平均単語埋め込みモデルを操作します。次に、モデルを使用して質問をエンコードすることにより、各質問のベクトル埋め込みを作成します。次に、ベクトル埋め込みが松ぼっくりインデックスに挿入されます。
これまでに説明した各メソッドは、バックエンドアプリの起動時に77〜82行目で呼び出されます。この作業により、ユーザー入力に基づいて実際に松ぼっくりインデックスをクエリする最終ステップの準備が整います。
84〜94行目で、アプリに2つのルートを定義します。1つはホームページ用、もう1つはAPIエンドポイント用です。ホームページはindex.html
JSおよびCSSアセットとともにテンプレートファイルを提供し、APIエンドポイントはPineconeインデックスをクエリするための検索機能を提供します。
最後に、59〜75行目で、このquery_pinecone
メソッドはユーザーの入力を受け取り、それをベクトル埋め込みに変換してから、Pineconeインデックスにクエリを実行して同様の質問を見つけます。このメソッドは、/api/search
エンドポイントがヒットしたときに呼び出されます。これは、ユーザーが新しい検索クエリを送信するたびに発生します。
視覚的な学習者のために、アプリの仕組みの概要を示す図を次に示します。
アプリのアーキテクチャとユーザーエクスペリエンス
では、これをすべてまとめると、ユーザーエクスペリエンスはどのようになりますか?
ユーザーは私たちのサイトにアクセスし、「Pythonの学習方法」という質問を入力し、過去に尋ねられた同様の質問を見つけてから、リンクをクリックしてQuoraの質問と回答を確認できます。
カスタマーサービスのシナリオに従って、ユーザーは、サポートに問い合わせることなく、当社の製品の使用方法について質問したり、同様の質問を見つけたり、リンクをクリックしたり、質問に答える役立つサポートページに移動したりできます。代表。
これで、実際の問題を解決するための簡単なPythonアプリを作成しました。このアプリをさらに改善するために、質問が行われるたびに新しい質問と回答をインデックスに含めることができます。また、顧客のフィードバックを使用してモデルを微調整し、返された結果が適切かどうかを知ることもできます。結局のところ、フィードバックは、モデルが有用な結果を提供する上でより良くなるのに役立つものです。
ストーリーの教訓は明確である必要があります。類似性検索は、顧客により良い結果を提供するのに役立ちます。また、マネージドサービスとして、Pineconeを使用すると、ベクターベースのレコメンデーションシステムを簡単に本番環境に移行できます。
Link: https://dzone.com/articles/build-a-customer-service-chatbot-using-python-flas