Join the Webinar
Loading...
セッションについて
Retrieval Augmented Generation(RAG)とAI Agentsは、LLMアプリの中で最も人気のある2つの形態です。RAGは、LLMとベクトルデータベースを使用して、あなたのプライベートデータ上で「チャット」します。AI Agentsは、LLMと一連の関数を使用して、特定のタスクをどのように実行するかを決定します。このセッションでは、その両方を組み合わせます。LlamaIndexとMilvusを使用して、RAGを実行できるAI Agentを構築する方法をお見せします。
学べること:
- LlamaIndexとは?
- Milvusとは?
- AI Agentの仕組み
- AI Agentsを使用してRAGを実行する方法
本日は、SFwith Love AI Agents から、AIエージェントとその構築方法についての本日のセッションをご紹介できることを嬉しく思います。そしてゲストスピーカーの Yuin TangYuin は Zillow のシニアデベロッパーアドボケイトであり、Amazon U Eugene で auto ml に関する auto のソフトウェアエンジニアとして働いた経歴があります。コミュニティサイエンス、コンピューターサイエンス、統計学、神経科学を学び、IEEE、big Data を含むカンファレンスで研究論文を発表しています。彼はタピオカティーを飲むこと、家族と過ごすこと、水辺にいることを楽しんでいます。ようこそ、Eugene。ありがとう、Sachi。
皆さん、こんにちは。えー、本日はAIエージェントについてお話しします。えー、これに入る前に、タイトルを理解した人、タイトルのリファレンスが分かった人について、もう一度簡単に参加者の様子を見させてください。分かった方には追加ポイントがあります。えー、分かった方はチャットに書き込んでください。えー、それでは始めます。
私の名前は Yuin Tang です。私はここ Zillow のシニアデベロッパーアドボケイトで、右側にあるそのQRコードは私の LinkedIn につながります。それをスキャンしてフォローしていただければ、rag AIエージェント、ベクターデータベース、えー、LLM全般、そのようなものについて起きていることをさらに追うことができます。えー、誰かが「このポイントはどこで引き換えられますか?」と聞いていますね。引き換え先は、えー、あなたの心の中です。えー、これはただの、えー、追加ポイントなので、自分が社会の教養ある一員であることが分かるだけです。
えー、では、そうですね、私については少しそんなところです。そして Zillow はベクターデータベース企業です。私たちは、えー、vis の背後にいる会社で、これは、えー、スター数に基づくと GitHub 上で世界で最も人気のあるベクターデータベースです。ですので本日は、AIエージェントと we rag についてお話しし、特に LAMA Index と vis を使って、AIエージェントによりエージェント的な方法で RAG アプリケーションを構築する方法についてお話しします。最初に行うのは、プロジェクト概要を確認することです。
使用するテクノロジーについて確認します。このテクノロジーをどのように組み合わせるか、そしてこのプロジェクトのさまざまな部分について確認します。まず rag について少し取り上げます。rag とは何か、えー、そしてAIエージェントについて少し取り上げます。AIエージェントとは何か、どのように動作するのか。そして LAMA Index について簡単に触れます。これは、これらのAIエージェントを作成するために使用するオーケストレーターになります。また vis にも触れます。これは、AIエージェントが retrieval, augmented generation を行うために使用する rag のための Vector データベースです。
そして最後に、自分でこれを構築する方法と、それがどのようなものになるかを示すデモを順を追って説明します。では。ステップ1、プロジェクト概要を行います。本日は、えー、rag を行うAIエージェントを構築する方法についてお話しします。そしてこれら3つのテクノロジーを使用します。
つまり viss を使用します。Viss は私たちの Vector データベースになります。えー、viss は特にスケール、カスタマイズ性、継続的な利用の問題を対象としています。そして OpenAI を、えー、LLM として使用します。えー、OpenAI を聞いたことがない方は、チャットにコメントをください。
かなり珍しい少数派になるでしょう。えー、OpenAI と彼らが何者かについてはあまり触れません。えー、もしまだ聞いたことがないなら、Google が良い選択肢だと思います。えー、そして LAMA Index について話します。これは、えー、すべてを結び付けるために使用するオーケストレーター、フレームワークです。そしてこれは、物事がどのように動作するかの非常に大まかなアーキテクチャです。
では、RAG、つまり検索拡張生成を、AIエージェントを使って構築していきます。そのやり方は、ここで少し展開されていて、リストアップされていますよね?まずリクエストを受け取ります。ええと、クエリ時、つまり利用時に、これらのAIエージェントを使うとき、リクエストを受け取って、それをパッケージ全体に送ります。ええと、特にそれはLLMにルーティングされます。ここではOpenAIで表されています。そしてそのLLMがあなたのリクエストを受け取り、それを送信し、自分が持っているツールを確認して、それからそれらのツールを呼び出して、ええと、何かを実行します。
そしてこの場合、クエリツールがあり、それを呼び出してvisにクエリを投げます。利用前に行うこととしては、自分のデータを取り、それを埋め込み、visに入れて、クエリできるようにします。つまり最初に、ええと、自分のデータを取り、埋め込み、vissに入れ、それを使ってツールを作成します。そして利用時には、リクエストをアプリケーションに送ります。するとアプリケーションは、これらのツールのいくつかを呼び出して、Vector databaseに対してクエリを実行し、ragを行い、それから応答を返します。では、ragについて話しましょう。あ、質問があります。エージェントにOpenAI LLMプラスLAMA Indexを使う利点は、OpenAI agentsだけを使う場合と比べて何ですか?LAMA Indexは、単にエージェントを作るだけでなく、もっと多くのことを行うために使えるものです。
多くのものを一緒にルーティングする能力を与えてくれます。ですので、実際にこの点については、ええと、Llama Indexについてのセクションでごく簡単に話します。ええ、なので、ええと、この回答は後ほどもう一度します。では、ragとは何でしょうか?ええと、ragを聞いたことがない場合は、ええと、気軽にチャットに質問を投げてください。ragを聞いたことがある場合は、ええと、これは復習になります。
RAGはretrieval augmented generation、検索拡張生成です。基本的にそれが意味するのは、その言葉が示すとおりに聞こえるものです。何らかの検索を行うことで、応答の生成を拡張します。典型的なRAGアーキテクチャは、このような形になります。ええと、何かをする前、ragを行う前に、自分のデータを取り、それを埋め込み、visに入れます。
RAGの目的は、LLMで自分のデータにアクセスできるようにすることです。そしてこれは基本的に最初のステップで、自分のデータを取り、それをVUSに入れて、使えるようにするだけです。それから、ええと、何らかのフレームワークを使って、LLMとVector databaseを結び付けます。実際には、プロンプトとクエリを使って、手動で、などの形で自分でこれを行うこともできます。しかしLAMA Indexは、それらすべてをうまく結び付けるための非常に良い方法を提供してくれるフレームワークの1つです。
そこで行うこととしては、質問を取り、ええと、データがアクティブなデータベースに入ったら、質問を取り、その質問を尋ねます。LLMがあなたの質問を受け取り、「なるほど、この人は何を尋ねているのか?」という感じで解釈します。そしてそれを取り、ええと、検索されるべきものへと変換します。それからその検索文字列を取り、ええと、あなたのデータをvissに埋め込むために使ったのと同じ embeddings model にその検索文字列を入れます。そしてVector databaseであるVissを検索します。この場合、Vissは単なる例としてのVector databaseです。
その、ええと、そのベクトルのembeddingを求めてVector databaseを検索し、最も近いベクトルを見つけます。そしてそれらの、ええと、それらの文字列をLLMに返します。するとLLMは、「よし、これについてのコンテキストを確認した。これから、自分の質問に答えられるように、意味の通る形でこれを構造化して、それからユーザーに応答を返そう」と言います。これがragアーキテクチャの基本です。
データを取り出して、それをベクターデータベースに入れます。質問を取り出して、それをLLMに尋ねます。LLMはその質問を受け取り、ベクターデータベースを検索して関連する応答を探し、それから答えを返してくれます、いいですか?そして、それが基本的にragのすべてです。なので、私が今言ったことについて何か質問があれば、ええと、どうぞ遠慮なく、ええと、q and aに投稿してください。ええと、では次にAIエージェントとは何かを扱いましょう。つまりAIエージェントの中核として、AIエージェントは単にツールを使えるLLMです。それだけです。
ええと、ツールは単なる関数だと考えることができます。非常に、非常に基本的な例としては、電卓のようなものがあります。LLMに関するニュースに注目していたなら、おそらく、LLMは特に数学が苦手だということについて、かなり多くの、言ってみれば、ええと、騒ぎ、多くの論評があったのを見たことがあるでしょう。では、それを修正する方法の一例として、関数、または関数のセット、例えば加算関数、減算関数、乗算、つまり、指数、指数、何でもいいのですが、そういったものを作成できます。そしてこれらの関数を作成し、それから、「ねえ、この関数はこういうことをします」と書かれた文字列のようなものを作成します。
これはそれが受け取る入力で、これはそれがどのように動作するかで、そしてLLMにこれらの関数を呼び出す、これらの関数を実行するアクセス権を与えます。そしてLLMに、例えば、5足すAは何ですか、のような質問をしたとき、LLMが行う基本的な推論をする代わりに、何らかの関数を実行します。例えば、ああ、自分は加算へのこのアクセスを持っていることを知っているし、この人は私に物を足すよう求めているので、私ができることは、ええと、加算関数を呼び出して応答を得て、それからあなたに答えを返すことだ、というように。これがその背後にある基本的な考え方です。本質的に、このアーキテクチャは、それが何を、何をするのかを示しています。リクエストを受け取り、LLMに送信し、LLMはそれを何らかのツールセットに送信し、何らかのツールセットを呼び出します。
そこからの答えはLLMに戻ります。するとLLMは、よし、これで自分の、これで応答を形成するために必要なものが分かった、と言い、あなたに応答を返します。ええと、はい、ここにいくつか質問があります。ええと、実際に、このセクションをまとめてから、質問に答えます。つまり、ええと、そうですね、この背後にある基本的な考え方は、LLMにツールへのアクセスを、関数、実行可能な関数の形で与えることができるということで、それによってLLMができないことの一部をある程度補ったり、あるいは、まあ、LLMの機能を拡張したりできるということです。
そして、ええと、現在これらのエージェント的ワークフローを探求するために多くの作業が行われています。ええと、実生活での例としては、例えば、RAGを実行できることや、ウェブを検索できること、あるいは他の関数を作成することさえできることなどがあります。これらがAIエージェントの例です。ええと、では質問を受けます。LMでスプレッドシートを使ってこのプロセスと結果をテストするにはどうすればよいですか?まず、ええと、この質問で何を、何を意味しているのかを明確にしていただく必要があります。ええと、私は、私は、その、スプレッドシートを、例えばこのスプレッドシートで何をしたいのかが完全には分かりません。
なので、ええと、この質問を明確にしていただけますか?そして、ええと、ragについてその質問に答えてみます。はい、ではこれは前のスライド、または前のセクションに戻ります。LMSはどのようにベクトルを読むのですか?データベース内で待機している埋め込みモデルからマップを受け取るのですか?ええと、はい。ええと、ではRAGがどのように機能するかについて明確にしましょう。ではここで数枚スライドを戻りましょう。
これは私の、ええと、ここにあるビジュアルには入れていませんでした。おそらくそれは、ここでは私の落ち度です。埋め込みモデルと、それがどこに位置すべきかを示すこのビジュアルを入れるべきでした。つまりLLMが行うことは、ベクトルを読むことではありません。LLMはテキストを受け取り、そのテキストに対して何らかの推論をしようとします。例えば、あなたが尋ねた質問が、ええと、シアトルの大きさはどれくらいですか?だったとします。するとLLMが行うことは、よし、私はシアトルとサイズ、あるいはそのようなものを探している、という感じになり、シアトル、またはシアトルのサイズ、あるいはそのようなものをベクトル化します。
そしてそれは検索し、そのテキストを埋め込みモデルを使ってベクトル化し、そのテキストを埋め込みモデルに送り、埋め込みモデルがベクトル埋め込みを生成します。そしてそのベクトル埋め込みが、vis で検索される対象になります。そして vis は、よし、この埋め込みモデルとともにベクトル埋め込みモデルがある。ここに保存されている文として、「シアトルの人口は75万人です」と書かれたものがある、というように言います。そしてその文を LLM に渡し、LLM はそれを任意のコンテキストとともに受け取ることができます。
たとえば、ああ、より大きな、より大きな都市圏の人口は400万人、等々、等々、等々です。そしてそれがその回答をあなたに返します。ツールとは何か、例は? 先ほど AI エージェントについて話していたときに、いくつかツールの例を挙げました。たとえば、電卓です。ええと、ツールを使って rag を行うこともできますよね? クエリエンジンをツールとして使うこともできますし、その他のツールの例もあります。
たとえば Web を検索するもの、Web スクレイパーのようなもの、あるいは API を呼び出すもの、そういったものを使うことができます。つまりツールとは、手動でやらなければならないものを想像してください。たとえば、何らかの Python 関数を作るようなものです。もしかすると、「ねえ、私は、ええと、よくわからないけど、これらの数字を掛けたい、これらの数字を足したい、rag をやりたい、ええと、よくわからないけど、画像を作りたい」というようなものかもしれません。別の、別のモデルを呼び出して、自分のために画像を作ってもらいたいかもしれません。そういうものがツールの例です。
rag のための埋め込みを作るのに最適なモデルはありますか? ああ、これは rag に戻る話ですね。わかりました。あるいは埋め込みにはより良いモデルがあるのか、それとも OpenAI などを使えばよいのか? わかりました、はい、素晴らしい質問です。ええと、あなたが使うことになる、使いたいと思う埋め込みモデルは、基本的には、何をしたいかに依存します。単純に open ai を使うこともできます。
ただ、ええと、それはおそらく POC で、何かを素早く立ち上げるには非常に良いと思います。しかし、本当に本番環境に投入できるカスタマイズ可能なものを作りたいのであれば、私が提案するのは、hugging face に行って、彼らのモデル、オープンソースモデルをたくさん試してみて、自分のユースケースに最適なものを見つけることです。たとえば、テキストを扱うのであれば、おそらく sentence transformers のものが欲しくなるでしょう。画像を扱うのであれば、おそらく RESNET 50 のようなもの、あるいは何らかの vision transformer のようなものが欲しくなるでしょう。つまり状況によりますし、rag 用の埋め込みに対して特に良い、悪いモデルがあるとは言いません。なぜなら、それはあなたが何をしているかに大きく依存するからです。
ですから、あなたがやっていることの中には、ええと、何と言うんでしたっけ、ええと、業界特化型のものがあるかもしれません。たとえば finance 向け、legal 向け、healthcare 向けなどのモデルがあるかもしれません。そしてそうした特定のモデルが欲しくなるでしょう。そしてそれに対して埋め込みモデルをファインチューニングすることもできますし、あるいはおそらく、特定の埋め込みモデルが必要で、そのために LLM をファインチューニングしたいと思うでしょう。ええ、つまり、あなたのユースケース次第ということです。
価格付きの商品リストを持つスプレッドシートをRAGのツールとして使えますか?LLMが商品の価格についての質問に答える必要がある場合、その答えを持つことになりますか?ええ、はい、それはできます。ただし、正しくフォーマットする必要があります。ですので、ええと、たとえば、LLMに、そのスプレッドシートをどう検索するかについて指示を与える必要があります。あるいは、そのスプレッドシートを受け取ってJSONなどに変換できる、何らかのデータ変換ツールのようなものが必要になります。CSVで行うこともできますが、CSVはLLMにとって扱いが非常に難しいことで知られています。というのも、従来の、つまり、ファインチューニングされたLLMやファインチューニングされた埋め込みモデルを使っているのでない限り、CSVは英語、あるいは他のどの言語でも、従来の文の構造に従っていないからです。
RAG操作を実行したいPDFがあるとします。さらに別のテキストファイルがあって、そこには「PDF内でこれを見つけたら、それはレッドフラッグまたはグリーンフラッグである」と書かれているとします。RAGがこのテキストファイルに従い、PDF内でこれらのレッドフラッグやグリーンフラッグを見つけるようにするにはどうすればよいですか?この質問を完全には理解できているか自信がありません。ええと、私の解釈はこうです。もし私の解釈が間違っていれば、自由に質問を更新してください。おそらく、あなたはPDFのセットを持っていて、それらのPDFを検索したい。そして同時に、LLMに対して「このPDF内で何かを見つけたら」、たとえば「swag」のような単語を見つけたら、それはグリーンフラッグであり、つまりそのPDFファイルが必要である、という指示を与えたいのだと思います。
そして「not swag」や、たとえば「swag list」という単語を見つけたら、おそらくそれはレッドフラッグで、そのPDFファイルは無視したい、ということですね。ええと、基本的には、なぜテキストファイルが必要なのかは分かりませんが、おそらくそれはプロンプトを通して渡すだけになるでしょう。おお、さらにRAGの質問ですね。今日はRAGについての質問がたくさんありますね、皆さん。これはAIエージェントのウェビナーです。
ええと、まあ冗談です。RAGについての質問にも答えられます。ええ、RAGに特化した質問ですね。たとえば、各埋め込みがどのファイルから来たものかを示すメタデータ付きの埋め込み済みドキュメントが100個あり、ユニークなファイルが10個あるとします。つまり、1ドキュメントあたり10個の埋め込みです。ユニークなファイルごとに上位K件、たとえば3個の埋め込みをクエリする方法はありますか?そしてこの場合、合計30個のチャンクが返されるのでしょうか?それは良い質問ですね。
ええと、ユニークなファイルを取得し、そのユニークなファイルから上位3件を取得する方法はあります。ですのでVissでは、そして他のベクトルデータベースでこれができるかは分かりませんが、Vissではこれができると言えます。group buyと呼ばれる新しい関数を呼び出すことができます。もしLinkedInで私をフォローしているなら、数か月前に私がこれについて「これは本当に馬鹿げている」みたいに怒っていたのを見たことがあるかもしれません。でも、ユニークなファイルについて考えると、実際には理にかなっています。そして、この質問をしてくれたのは本当に興味深いと思います。というのも、チームがそれを構築したことを本当に検証してくれるからです。
ええと、visからユニークなファイルを取得できます。そして、その後にできることとして、それらのファイルに対応するチャンクを実際に取得し、そしてそのチャンクをソートできます。ですので、答えは「はい」です。そして、一般的なRAGアプリケーションよりも多くのカスタマイズが必要になります。おお、別の質問です。注文データテーブルに対してRAGを行うことはできますか?また、それをどのように最新の状態に保てばよいですか?この質問は分かりません。はい。
自分のエージェントに予測のケースを扱えるようにしたい場合、それはできますか?この質問には答えてもらう必要があります。これは、ああ、ライブストリームデータに対してRAGを行えますか?ええ、できます。なぜそれをしたいのかは分かりませんが。ええと、それはつまり、生成AI、LLMのようなものは本当のストリームではなく、リアルタイムではありません。LLMは遅く、リアルタイムではありません。ですので、リアルタイムでLLMにデータを流し込むことはできますが、役には立たないでしょう。なぜなら、LM自体が、あなたのパイプラインの、つまりあなたのボトルネックになるからです。
これは実際には質問ではなく、コメントです。ええと、もしシステムプロンプトにルールを入れすぎると、中間部分の問題や、LMがコンテキストを失うことにつながりませんか?システムプロンプトには制限があるのではないかと心配しています。つまり、そうですね、でもできることとしては、ベクターデータベース内のメタデータにタグ付けして、それからメタデータフィルタリングを行えばいいんです。つまりクエリを実行するときに、特定のメタデータでフィルタリングでき、その方法でルールを実装できます。おお、すごい。
ああ、別の質問があります。すごい。すでにRAGについてたくさん質問を受けていますね。では、会話型ERPシステムを作成していると仮定しましょう。注文データを会話型インターフェースを通じて利用できるようにしたいです。
どう進めればよいでしょうか?ええと、単に、データにタイムスタンプでタグ付けして、検索時にタイムスタンプでフィルタリングすればいいです。素晴らしい。では、これは飛ばしていきます。これは終わりです。はい。
LAMA Indexについて少し取り上げます。ええと、LAMA Indexとは何でしょうか?ええと、LAMA IndexはLMアプリケーションを構築するためのフレームワークです。Lang Chainを聞いたことがあれば、多少似ています。Lang Chainは、LLMの入力と出力をどのようにオーケストレーションし、連鎖させるかに焦点を当てています。LAMA Indexは、より良いデータ検索をどのように行い、それをLLMに入れるかに焦点を当てています。
ええと、LAMA Indexには、visを含む多くの人気ツール、ええと、他のベクターデータベース、他の埋め込みツール、ええと、他のLLM、これらさまざまなものとのインテグレーションもあります。では、Novus Mil vs.とは何でしょうか。分散型ベクターデータベースです。大規模で高スケールのユースケースに最適化されています。つまり基本的に、10億以上のベクターで構築しているなら、Novusはあなたにとって最適なベクターデータベースになります。
ええと、本番環境で10億以上のベクターを持つプロジェクトが50以上あります。実際にはそれは昨年の数字なので、今ではそれ以上かもしれません。ええと、おそらく今はそれ以上だと思います。ええと、VUSが非常に得意とする他の点としては、非常に高度にカスタマイズ可能な、ええと、インデックスと距離メトリクスのセットを持っていることです。インデックスや距離メトリクスについてさらに質問がある場合は、それに関する動画も記事もたくさんあります。本質的に、インデックスとはデータを整理する方法であり、データをどのように検索するかということです。
そして距離メトリクスとは、ええと、データ同士がどれだけ離れているかを比較する方法です。これを行う方法はたくさんあり、実際、ユースケースに適したインデックスと距離メトリクスを使用することは、アプリケーションにとって本当に本当に重要です。なぜなら、それぞれにトレードオフがあるからです。ええと、最後に、milには、エンタープライズ対応の機能がたくさんあります。ロールベースのアクセス制御、マルチテナンシーなど、誰も本当に聞きたがらないような非常に退屈なものすべてです。ただし、それについて聞きたい場合は別ですが。でも、その場合はおそらく別のウェビナーに来るべきでしょう。はい。
では、ベクターデータベース内のデータが実際にどのように見えるかも見てみましょう。それから、ええと、アーキテクチャを見て、その後デモに進みます。これがベクターデータの見た目です。これは1つのエントリなので、IDが必要で、埋め込みが必要です。IDはカスタマイズ可能で、埋め込みは単なる数字の列になります。これがベクターの見た目です。ええと、ベクターがどのようなものかについて多くの質問を受けます。
これです。数字の集まりです。それだけです。はい。そして今、ええと、この残りの部分が私たちがメタデータと呼ぶものです。メタデータとは本質的に、ベクターとIDに付けるデータで、クエリ時に使用したり、先ほど言及したようにそれでフィルタリングしたりできるようにするものです。
では、Milvus のアーキテクチャについても簡単に、ええと、見ていきましょう。Milvus は分散システムで、ええと、入出力はある意味で疎結合になっていますよね。そこで私たちは、Milvus を、ステートフルなコーディネーターサービスを使ってステートレスなノードを起動・停止する pub/sub システムとしてモデル化しています。そしておそらく、ベクトルデータベース全般とスケーリングの観点で皆さんに理解していただくうえで最も重要なのは、なぜ、ええと、pub/sub システムが必要なのか、ということです。なぜこのようなものが必要なのでしょうか?主な理由は、レプリカ間やインスタンス間で一貫性を保ちたいからです。一貫性と再整合性は別物で、どちらもスケールした状態で実現するのは非常に難しいものです。そして Viss は、必要に応じて選択できる 4 つの一貫性レベルを通じて、この多くを自動的に処理してくれます。
これはもう一度、リアルタイムデータストリーミングについて質問した方への回答でもあります。Viss にはリアルタイムでデータをストリーミングできます。そのために Kafka Pulsar を使用しており、いつ、どこでそれにアクセスできるかは一貫性レベルに依存します。実際、すべてを write 後に read できるようにすることも可能です。これは strong consistency と呼ばれますし、もっと緩いもの、私たちが eventual consistency と呼ぶものまであります。これは基本的に、システムが受け取った順序ですべてを処理します。
他に認識しておくべき点として、ここにあるこれらのノードの分離があります。クエリがどのように行われるかを処理する query node があります。データ取り込みを処理する data node があり、そして「データをどのように整理するか」を処理する index node があります。では、なぜこれらのノードは分かれているのでしょうか?なぜベクトルデータベースのこれらの異なる、ええと、機能それぞれに対して別々のノードを持っているのでしょうか?これを採用している主な理由は、これら 3 つすべてが同時にスケールする状況は決して起こらないからです。「やあ、私は 3 億件のドキュメントを取り込んでいて、同時に 3 億件のドキュメントに対してクエリもしています」というようなことは通常ありません。一般的には、それぞれ、ええと、各機能ごとに異なるスケールの仕方をするものがあります。
そして、ええと、これは特に重要です。なぜなら、これによってリソースを最適化でき、ええと、コストを抑えられ、さらに、ええと、ベクトルデータベースの機能に対してより多くの制御を持てるようになるからです。アーキテクチャ図には載っていませんが、理解しておくべき重要なこと、そしてデータが頻繁に変化する人にとって重要なこととして、VUS はデータをこれらのセグメントにインデックス化し、デフォルトサイズは 512 メガバイトです。ただし、規模が大きくなり、より多くのデータ、さらに多くのデータを扱うようになると、おそらくそのセグメントサイズを大きくしたくなるでしょう。その考え方は基本的に、小さなセグメントに対してインデックス化しクエリを行う場合、巨大なセグメントに対してインデックス化する場合よりも、はるかに、はるかに、ええと、高速な結果が得られるというものです。少し考えてみると、同じサイズの 200 個のセグメントを並列検索する big O は、たとえば「この巨大な、そう、膨大な量のデータを線形に走査したい」という場合の big O よりも、ええと、小さくなりますよね。そしてもう一つは、データを変更したり、データを更新したり、さらにデータを追加したりするにつれて、re-indexing と呼ばれることを行いたくなるという点です。
単に概念実証を作って、データを入れて、「このデータに対してインデックスを作成してほしい」と言いたいだけなら、このどれも重要ではありません。しかし本番環境、実際の利用では、現実としてデータは非常に頻繁に変わります。分単位、時間単位、日単位、週単位、月単位、何であれ、データは常に変化しており、常にデータを更新する必要があります。つまり現実として、このデータを更新していくと、それをうまくインデックス化することは非常に難しくなります。それを処理してくれるシステムがない限りです。そしてそれも Viss が行うことの一つです。それではこれから、ええと、デモに入っていきます。
では、本題に入る前に、ええと、ここまでのプレゼンを楽しんでいただけているなら、お願いがあります。あのQRコードをスキャンして、Visにスターを付けてください。ええ、そうしていただけると私の上司がとても喜びますし、ここで少し止まって質問にも答えます。自分のエージェントに予測のケースを処理させたい場合、それはできますか?ええと、データの順序に基づいて、ですか?待ってください、この質問はすでにされましたね。答えはイエスです。はい、できます。埋め込みを実行する際、異なる形式のデータをどのように構造化すればよいですか?仮に私のPDFにテキストデータ、表形式データが含まれているとします。
埋め込みはどのように実行できますか?あなたなら、何を、何を、何を提案しますか?ええと、PDFに関しては特に、Llama Parseというものを紹介します。ええ、Llama Indexの人たちには私から聞いたと言ってください。ええと、Llama Parseは彼らのPDF解析専用ツールのようなもので、本当に速くて、とてもよく機能します。ええと、私はPDFにはこれが好きです。ええと、後でそれを紹介するプロジェクトもいくつかあるかもしれませんが、これは、ええと、PDFを解析するのを助けてくれるもので、こうしたことを何も心配する必要がありません。基本的に、Visは私の問題を解決できますか?はい、VISがあなたのすべての問題を解決してくれます。
あなたは二度と何も考える必要がなくなり、VISがすべてをやってくれます。いえ、冗談です。でも、ええと、私は、この質問がわかりません。ええと、LAMA IndexとLane Chainをもう少し詳しく比較してもらえますか?Novusで作業するには、lanechainよりLAMA indexを選ぶべきですか?これらは根本的に異なるライブラリです。つまり、はい、同じカテゴリのライブラリではあります。どちらもLLMアプリケーションをオーケストレーションして作成するのを助けるものですが、根本的には焦点が違います。そして、適切な焦点に対して適切なライブラリを使うことをお勧めします。つまり、検索が多く関わること、LLMのためのデータが多いこと、LLMに出入りするデータが多いことをやりたいのであれば、LAMA Indexを使うべきです。LLMがどのように機能するか、そしてLLMの入力と出力をどう扱うかにもう少し関係するものを使うのであれば、lane chainを使いたくなるでしょう。つまり、これら2つのライブラリは、多くの同じ機能を実行できる別々のライブラリですが、実際にはまったく異なる形で組織されています。ええと、それぞれ組織化の基盤が異なります。ですから、何をしたいかに応じて、やりたいことに基づいてライブラリを選ぶべきです。Novusの主な利点は何ですか、ということですね?リレーショナルデータベースは、たとえば、Vectorデータベースが行うことを行いません。そして実はベクターデータ、ええと、ここで1枚スライドを戻ります。つまり、vector databaseというのは実は、ええと、vector databaseというのは良くない用語です。みんながそう呼びがちというだけで、実際にはcompute engineなのです。ですから望むなら、リレーショナルデータベースの上にcompute engineを構築することもできますが、パフォーマンスの問題にぶつかることになるのに、なぜ、なぜそんな面倒なことをするのでしょうか?なぜなら、そうすると、スケールする能力、複数インスタンスを立ち上げる能力がなくなるからです。プロキシもなく、関心事を分離する能力や、こうしたさまざまなこともできません。ええと、つまり、データが1000件あるなら、どのデータベースを使っても問題ではありません。本当に関係ありません。ええと、しかし本番環境に移行したいとき、そしてスケールするものがあるとき、そのときこそ、自分のユースケース向けに目的特化で作られたものが必要になります。そしてNovusは主に、物事を本当に本番環境に持っていき、触れることになるデータ量が非常に、非常に大きい人たちのそのユースケースに応えるために作られています。そのときNovusはあなたにとって有用になります。ええと、ですから、もし単に試しているだけなら、正直あまり関係ないと思います。よければNovusやFunで遊んでみてもいいでしょう。アジア人はツール間にrag操作を挟みながら複数のツールを実行できますか?はい。
それはそのように構造化するだけでいいです。vis は同じインデックス内で複数の embeddings をサポートできますか?ええと、いいえ、それはできません。なぜなら embeddings は同じ長さである場合にのみ比較できるからです。embeddings の長さが同じでない場合、数学的に比較することはできません。ええと、LLM とユーザーによって生成されたカスタムデータを持ちたいです。RAG はそれに適していますか?ええ、はい。
ええと、なぜ Pine Cone、Quadrant、あるいは wate の代わりに VUS を使うのですか?ええと、この質問には先ほど答えたと思います。VUS は、ええと、そして Viss は分散型である唯一のものです。うーん、本当に、これらのどれを使ってもいいです。先ほど言ったように、少量のデータで試しているなら、好きなものを使えばよく、問題ありません。自分自身のベクトルデータベース、ベクトル検索エンジンを作成して、それを使うこともできます。つまり、少量のデータを扱っている場合は本当に問題ではなく、本番環境に投入するものを構築しようとしていて、ええと、エンタープライズ対応にする必要がある場合にのみ、それが重要なことになります。
素晴らしい。では、これから見る内容をちょっと復習して、それからデモに入りましょう。覚えておいてください、AI エージェントで RAG を構築します。今 RAG についてたくさん質問がありましたね。RAG について多くの人の質問に答え、AI エージェントやそれがどう機能するかについても簡単に触れました。
ただし、この具体的な例では、何をするかというと、私たちのために RAG を行う AI エージェントを構築します、いいですか?そして OpenAI を使います。簡単だから、シンプルだから、そこにあるからです。そしていくつかの PDF を使います。ですので、PDF について質問していた皆さん、とても関連性の高い質問です。PDF を使います。Uber と Lyft の 10-K を使います。いいですか?では始めましょう。
さて、ここではこれを見ていきます。では、このリンクを下に貼りますので、皆さん入手できます。ええと、これは私の AI エージェントの cookbooks、ええと、repo の中の notebook の一つです。そして基本的にここでやることは、先ほど言ったように、RAG を行う AI エージェントを作成し、ええと、Uber と Lyft の 10-K の PDF に対して RAG を行うことです。ええと、ああ、デモに入る前に、AI エージェントについて軽くおさらいしてもらえますか?それは単なる実行可能な関数ですか?答えははいです。
基本的には、そのように動きます。それより少し複雑ですが、デモでそれがどう動くかがわかるでしょう。さて、始めましょう。ここで最初に行うことは、ええと、最初に行うことは、大量のデータをダウンロードすることです。そして実際にこれを行う前に、Docker compose up dash D も実行します。このための Docker、ええと、compose file は repo にあります。
チャットにリンクを貼りましたので、そこへ行って、それを取得し、ええと、Docker compose file を取得して、pull して、これを実行できます。私はすでに Docker、ええと、compose files を入れて、すでに実行しています。私の、ええと、container はすでに動いているので、この部分は実行しません。ええと、データもすべて repo に入っているので、実際にはこれらを実行する必要はありませんが、自分でダウンロードしたい場合、最初からやりたい場合は、これらをすべて行うことができます。ここで見る主な imports は Simple Directory reader で、これは Lama Index が、つまり、directory を読み込むための方法です。
うーん、そして Vector Store Index は彼らの、つまり、ええと、vector databases にアクセスする方法です。そして storage context は、さまざまな、うーん、ええと、データの保存方法を受け渡しするための方法です。LAMA Index における storage の context です。そして query engine tool も取得します。ですので、ええと、LAMA Index 内の executable functions についての誰かの質問に再び答えると、ちなみに Blank Chain 内でも同様です。
ええと、ツールにアクセスする方法、これらの関数にアクセスする方法は、彼らが作成した特定の種類の、ええと、クラスオブジェクトのようなものに基づいています。そしてツールのメタデータは基本的に、LLM に、あなたのツールに関する何らかのメタデータを与え、あなたが理解できるように、ええと、それがあなたのツールにどのようにアクセスし、どのように使うかを理解できるようにします。そして Vis Vector Store があります。これは llama index が vis とやり取りするための方法になります。なので、この次のセクションはおそらく一番長くかかることになります。そして基本的にここで行っているのは、すべてのデータを取得してベクトル化し、それを Vector database に入れることです。
では、これをステップごとに見ていきましょう、いいですね?ここでのステップは、Simple Directory Reader を呼び出し、それを使ってこれらのファイルを読み込むことです。この場合、2021 年の Lyft の 10 K ファイルと、2021 年の Uber の 10 K ファイルがあります。そして Simple Directory Reader を使って、これら両方のファイルをドキュメントのセットとして読み込みます。そこで、これらを Lyft Docs と Uber Docs と呼び、今度はインデックスを構築します。この場合、Lyft 用に 1 つ、Uber 用に 1 つ作成します。
そしてここでは、dimension として 1536 を渡しているのがわかります。dimension は単にベクトルの長さを指します。そしてこれは、あなたの embedding model によって変わります。この場合、OpenAI のデフォルトの embeddingmodel を使っているためです。OpenAI の次元数は 1536 です。なので dimension として 1536 を渡します。
次に、collection に名前を付けます。この場合、私は Lyft Collection を Lyfts、Uber Collection を Uber と名付けただけです。そして Overwrite equals true は単に、「このスキャンを実行したら、database base を上書きしてほしい」という意味です。そして今やることは、storage context を与えることです、いいですね?ここでは、Vector database へのこれらのアクセス、ええと、これらの接続を作成しました。そしてこれから storage context を使います。そうすることで、この接続を LAMA Index の内部で受け渡せます。そして単に、「この Vector store を渡したい、そして適用する Vector Store は Lyft または Uber です」と言います。
そして次に、Vector Store index を作成します。これは Llama Index がこれらの、うーん、これらの vector stores と、それらがインデックス化される方法とやり取りするための方法です。Vector stores は複数の、複数の種類のベクトルに対して複数の indexes を作成できます。つまり、複数の種類の vectors に対して複数の indexes を作成できます。VIS は最近、Multi-vector search と呼ばれるものを導入しました。これにより、同じエントリ内に複数の vectors を持つことができます。これらの vectors を互いに比較することはできません。たとえば Vector one と Vector two を比較することはできませんが、Vector two を、ええと、vectors のセット全体で比較することはできます。その場合、それは Vector one とは異なる vector index になります。
そして今度は、これらの Lyft docs、これらの Uber docs を渡し、これらに対して、うーん、ええと、ええと、index を作成します。なのでここで気づくと思いますが、私たちがやっていることは、Novis の Vector Vector store への接続を作成しているだけで、ここで実際にドキュメントの embeddings を作成し、それらを、ええと、vis に挿入しています。したがって、このステップこそが、この関数の実行にこれほど時間がかかっているステップです。そしてそれを特定の directories に persist するだけです。これは、ええと、任意ですが、本質的にこれによって可能になるのは、「あとで戻ってきて、これをもう一度扱いたい場合、これらの persistent directories からロードできる」と言えることです。
今やりたいのは、これらの indexes を取り出して query engines に変換することです。query engine は単に、Vector db とやり取りし、ええと、その Vector db を検索するための方法です。そしてここで適用する主なものは similarity top K です。これが意味するのは、結果が返ってくるということです。うーん、ええと、ここでは上位 3 件の結果が返ってきます、いいですね?つまり similarity top K equals three で、これが、これがこの意味のすべてです、はい?そしてここから tools の作成を始めます。
このようにして、これらを実行する能力を渡します、ええと、あー、あー、あー、これらのツールを実行する能力です。つまり私たちがやることは、これらを作成して、それらをクエリエンジンツールに変換し、このものにLyftエンジンを与えます。基本的には、ええと、このLyft用のクエリエンジンをLyftエンジンと呼び、UberのものをUberエンジンと呼びました。つまり、クエリエンジンツールがベクトルデータベースにクエリできる能力を持つために、クエリエンジンを渡す必要があります。そして、いくつかのメタデータも渡す必要があります。ここでのメタデータは、実際にはLLMがこのツールの使い方を理解するためのものです。
つまり、要するに、はい、これは単に関数を実行するだけなのですが、名前を付けます。そうすることで、ああ、これはこういう理由で呼び出すべきなんだ、ということが分かります。そして説明を与えます。この場合は、2021年のLyftの財務に関する情報を提供し、ツールへの入力として詳細なプレーンテキストの質問を使用する、と言っています。つまりこの説明で、LLMにそのツールが何をするのか、そしてそのツールをどのように使えるのかを伝えています。いいですか?これは重要です。なぜなら、基本的にLLMはテキストに基づいて推論しており、これによってAIエージェントとしてどのツールを使うべきかを理解できるからです。もうこれ実行しましたっけ?はい、もう実行しました。
さて、今度は実際のエージェントを作成します。実際のエージェントを作成するために、React agentというものをインポートし、OpenAIをインポートします。実はバッチデータベースですでにOpenAIを使っていますが、LLMとしてOpenAIをインポートし、React agentは単にreasoning action reactです。いいですか?そしてここでモデルをインポートします。つまり、使いたいLMはGPT-3 0.
5、ええと、3. 5 turbo oh 6 1 3だと言うだけです。これはGPT-3 0. 5のバージョンです。GPT-4にアクセスできるなら、GPT-4を使えます。そしてエージェントを作成します。これはReact agentになり、ツールのセットから作成します。
つまり、先ほどquery engine toolsと呼んだこのツールのリストを作成しました。なので、rag以外のことをしたい場合、クエリ以外のことをしたい場合は、他のツールを渡すことができます。そしてLLMを与え、verboseにすると言います。これをverboseな方法で行います。つまり、LLMを呼び出すと、その推論を入出力するということです。そこでLLMを呼び出して、2021年のLyftの収益成長率を返してくれることを期待します。
いいですか?素晴らしい。これはverbosityの機能です。2021年のLyftの収益成長に関する情報を見つけるためにLift 10 K toolを使用できます、と言っています。そして実行するアクションはLift 10 Kです。そしてそのアクションへの入力は、2021年のLyftの収益成長率は何でしたか?という質問です。そしてここで観察結果を返します。Lyftの収益成長率、Lyftの収益は前年と比較して2021年に36%増加しました。
そしてその観察結果を取り、それをLLMに戻して推論します。質問に答えるために必要な情報があります。こちらが答えです。Listの収益成長率、2021年は36%でした。いいですか?つまりそれが、それが、それがデモの基礎です。
本当にそれだけです。ええと、ここではかなり多くのコードを、やや急いで通り抜けたということは分かっています。なので、それについて質問があれば、その質問に答えられます。QAにもすでに2つ質問があるのが見えるので、順に答えていきます。最大、最小などの質問、つまり正しい結果を得るために未知の数のエントリを比較しなければならない質問に対して、visから関連するエントリを取得するコツはありますか。ええと、この場合、おそらく単に、ええと、つまり、visが行うことはベクトルデータベースです。
そしてベクトルデータベースは、ええと、意味的に類似したデータを見つける方法です。ですからこの場合、あなたが求めているものは実際には意味的類似性ではなく、比較によってできることです。これは Python スクリプトのようなものを使うほうがずっと簡単にできます。ただし、これを行う方法としてはメタデータフィルタリングを使います。そこで、たとえば、ええと、最長のエントリや最短のエントリが欲しい、あるいは、ええと、コメント投稿者の数が最も多いエントリが欲しい、などと言うことができます。その場合にすることは、単にメタデータフィルタを使って、ええと、その、あの、いわば、境界を設定し、それから何らかの再ランキングの仕組みを使って、これらを、ええと、何であれその順にランク付けすることです。つまり、いいえ、最大のコメントについて、最長のコメントについて、たとえば、よくわかりませんが、象について、という感じです。
その場合、つまり、何をするかというと、象を検索して、たくさんの結果が返ってきて、それから最も長い結果を見つける、ということになります。そんな感じです。OpenAI LLM を使っている場合でも、別の埋め込みを使えますか?はい、使えます。それから、もう一度マルチベクトルについて説明してもらえますか?はい、マルチベクトルとは、オブジェクトやエントリを表現する方法が複数ある場合、そのエントリを表す複数のベクトルを持てるということです。たとえば、3つの異なる埋め込みモデルがあり、それぞれ次元数が異なるとします。たとえば 384、768、1536 です。
できることとしては、これら3つの埋め込みをすべて保存しておき、比較したいときには、それらのいずれかに基づいて比較できます。ただし、毎回同じベクトル埋め込み同士で比較することを確実にする必要があります。つまり、368、ええと、384 を 768 や 1536 と比較することはできませんが、異なる 1536 次元のベクトル同士を比較することはできます。ええと、この録画はどこで見られますか?Saachi、これはあなた向けですね。登録していれば、ええと、メールで録画をお送りしますし、ウェビナー終了後まもなく YouTube にも掲載されます。ツールが内部でどのように動作するのかについてですが、LLM によるツールの使用とは、LM がツール名と検索テキストを含む回答を返し、その後ライブラリが私のマシン上でそれを処理して、その回答を LLM に送り返す、という意味ですか。
ええと、はい、待ってください、これを読み直します。ええと、つまり、LLM は基本的に入力を関数に送り込み、それから関数から出力を受け取ります。関数は、えっと、ここであなたが聞いている質問は、関数がどこで実行されるのか、ということだと思います。そして関数はローカルで、サーバー側またはクライアント側のどちらかで実行されます。いや、それはローカルとは言えないかもしれません。関数がある場所、関数がホストされている場所で実行されます。もしあなたのマシン上で実行しているなら、あなたのマシン上で実行されます。
はい。1つのベクトルデータベースにおけるマルチベクトルのシナリオで、各埋め込みモデルごとに別々のインデックスを持つことになりますか?各埋め込みモデルごとに別々のインデックスがある場合ですか?はい。はい、そうなります、はい。なぜなら、ええと、インデックスはデータにアクセスする方法であり、ええと、そして、同じサイズのベクトル埋め込みに対してのみインデックスを作成できるからです。同じ次元数のものを、ええと、数学的に比較できる必要があるからです。そしてはい、すべてを1つのベクトルデータベースにまとめて整理することはできます。少なくとも vis ではできます。繰り返しますが、他のベクトルデータベースで何ができるかについてはコメントできません。ええと、ローコードについて何かですね。
ええと、だから、よくわかりませんが、はい、ローコードと Zillow's cloud は使えます。Zillow's cloud にサインアップして、たくさんの、ええと、アップロード文書を渡すだけです。今はパイプラインがあります。Zillow's cloud には pipelines というものがあります。やることは、文書をアップロードするだけです。それが埋め込みを作成してくれて、追加のデータベースに入れてくれます。ですから、もしプログラミングの仕方がわからないなら、ええと、私はプログラミングを学ぶことを検討すると思います。
Devonの件を見たかどうかわかりませんが、ええと、Devonは、それをインデックス化した、といったことを言っていました。彼らは、ああ、13%くらいの問題を解決した、みたいな感じでした。そして最近になって、それが本当ではなかったことが人々にわかりました。なので、ええと、プログラミングが近い将来になくなることはありません。そしてカスタムなものを作れるようになりたいなら、プログラミングを学ばなければなりません。
ところで。ええと、ああ、そう、それ、それ、それが本当に、つまり、これが私の本当に、これが、これがこの件についての私の唯一の本当のコメントです。ノーコードやローコードは、単に他の誰かのコードです。なので、カスタマイズ可能なものが欲しいなら、自分で作らなければなりません。複数のクエリエンジンを使うことは、先ほど言及したViss Group five function group buyfunctionの良い代替になると思いますか、ええと、これらは根本的に異なるユースケースです。
ええと、つまり複数のクエリエンジンは、複数のデータベースにクエリしたい場合のもので、group buyは、同じ、ええと、セットの、ええと、ええと、ユニークな、すみません、1つのvector、ええと、collectionの中に保存されている同じdocumentsのセットからユニークなdocumentsが欲しい場合のものです。ええと、だから私の答えはノーだと思います。ええと、これらは異なるユースケースです。いいですね。これをちょうど良い時間でまとめられそうです。
どうやら、ええと、すべての質問に対応できたようで、まだ5分残っていますし、コード全体を一通り実行することもできました。なので、ええと、ここで締めてもいいと思います。他に質問があれば、たとえば、30秒くらい待って、ええと、今話すか、永遠に黙っているか、ということで。はい。このウェビナーを締める前に、Jenに最後に質問がある方はいますか?ここで数秒だけ待ちます。
また、繰り返しになりますが、この録画は、ええと、ウェビナー後まもなく利用可能になりますので、お待ちください。質問が1つあるようですね。LinkedInのQRコードをもう一度表示してほしい。ええと、はい、できます。ええと、私たちにはDiscordチャンネルもあります。
ええと、先ほど見逃した方のために、もう一度チャットに入れます。はい、これです。これをスキャンすると、LinkedInで私を見つけられます。後で追加の質問で連絡できますか?はい。LinkedInで私を見つけてください。
コメントでタグ付けする、投稿を作って投稿内で私をタグ付けする、そうすれば質問に答えられます。Efficient RagにVector DBSを使うことについて、あえて反対の立場を取るなら、何と言いますか?ええと、Vector databasesなしではRAGはできません。なので正直、この質問にどう答えればいいかわかりません。ええと、私は、つまり、私はそれは、私は、ええと、はい、私は、本当に、本当にわからないです、つまり、RAGの全体のポイント、RAGという概念全体は、あなたがdatabasesを持っていることに依存しています。はい、これで締めだと思います。
はい。あ、やっぱり違いました。もう1つ質問があります。はい。toolsについてですが、agentがemailを読んでそこから情報を統合し、それからwebを検索してactionを行うことはできますか?はい。
はい、できます。複数のtoolsが必要になります。そのそれぞれが、これらのtoolsの1つを行います。それぞれがこれらのことの1つを行います。たとえば、email読み取りtoolと、ええと、web検索toolとactionです。そして、これらすべてをつなげることができます。全部を1つのfunctionに入れることもできると思います。
ええと、でも、ええと、つまり、答えはイエスです。状況によります。多くの方法でできます。では。これで締めですと言う前に、もう一度、誰かが質問を入力し終えるのを待ちます、ええと、あ、そこに。
はい。こちらにもう1つ質問があります。ええと、すべてのユニークなfilesが別々のindexesにある場合、つまり1つのindexでgroup biを使うことはできないけれど、Wait, wait, wait, waitをまたいでいきたい、何?でも、ええと、複数のindexesをまたいでいきたいです。このmultiple query engineは、group filesを使う代わりに複数のdocumentsをチェックするために機能しますか?はい。
待って、待って。一意のファイルと別々のインデックスだから、groupは使わないということ?ええ、はい、はい、はい、はい、そうできますし、おそらくそれぞれの、ええと、クエリエンジンに異なるインデックスを渡すだけでよいでしょう。わかりました。ここで最後の質問はありますか?はい、これで大丈夫そうですね。あ、ええと、ええと、これは何ですか?あ、わかりました。
わかりました。あ、わかりました。これは質問へのお礼だけでした。では、ありがとう、Alex。わかりました。
本日はご参加いただき、皆さんありがとうございました。残りの一日も良い時間をお過ごしください。さようなら。
Meet the Speaker
Join the session for live Q&A with the speaker

Yujian Tang
Developer Advocate at Zilliz
Yujian Tang is a Developer Advocate at Zilliz. He has a background as a software engineer working on AutoML at Amazon. Yujian studied Computer Science, Statistics, and Neuroscience with research papers published to conferences including IEEE Big Data. He enjoys drinking bubble tea, spending time with family, and being near water.


