「LangChain、Google Maps API、およびGradioを使用したスマートな旅行スケジュール提案システムの構築(パート3)」
「LangChain、Google Maps API、およびGradioを活用したスマートな旅行スケジュール提案システムの構築(パート3)」
次のロードトリップのインスピレーションになるアプリケーションの構築方法を学びましょう
この記事は、OpenAIとGoogle APIを使用して旅行の行程提案アプリケーションを構築し、gradioで生成されたシンプルなUIに表示する3部作の最終記事です。このパートでは、1部と2部で構築したエージェントとルート検索モジュールを組み合わせてUIを構築する方法について説明します。コードだけを見たい場合は、こちらから見つけることができます。
1. 2部の要点
この3部作の2部では、LLMコールの一連のウェイポイントのパースされたリストを受け取り、Google Maps APIとFoliumを使用してそれらの間のルートを生成し、インタラクティブなマップ上に表示するシステムを構築しました。このプロジェクトの目標は、「ベルリンからチューリッヒへの4日間の旅行で、地元のビールと食べ物をたくさん試す」といった旅行リクエストを簡単に入力できるアプリケーションを構築し、詳細な行程表とマップを提供することです。1部と2部のおかげで、すべてのコンポーネントが組み立てられました。さあ、それらを使いやすいUIに組み合わせるだけです。
2. マップをgradioに接続する
gradioは、機械学習モデルをショーケースすることができるインタラクティブなアプリを迅速に構築するための優れたライブラリです。Matplotlib、Bohkeh、およびPlotlyと連携するために設計されたgradio.Plot
コンポーネントがあります(詳細はこちら)。しかし、2部で生成したマップはfoliumで作成されています。これらの他のライブラリのいずれかを使用してそれらを再作成することも可能ですが、幸いなことに必要ありません。代わりに、foliumコードを再利用し、それをgradio
が理解できる形式に出力するleafmap
パッケージを使用できます。詳細はこちらをご覧ください。
これがどのように機能するかを示す簡単な例を見てみましょう。まず、望ましい形式のhtmlを出力する関数を作成します。
import leafmap.foliumap as leafmapimport foliumimport gradio as grdef generate_map(center_coordinates, zoom_level): coords = center_coordinates.split(",") lat, lon = float(coords[0]), float(coords[1]) map = leafmap.Map(location=(lat,lon), tiles="Stamen Terrain", zoom_start=zoom_level) return map.to_gradio()
ここでは、generate_map
関数はフォーマット「lat、lon」の座標の文字列とfoliumマップのズームレベルを受け取ります。マップを生成し、gradioが読み取れる形式に変換します。
次に、非常にシンプルなgradioインターフェースを構築しましょう。
demo = gr.Blocks()with demo: gr.Markdown("## 地図を生成する") with gr.Row(): with gr.Column(): #最初の列はボタン用 coordinates_input = gr.Textbox(value="",label="中心座標",lines=1) zoom_level_input = gr.Dropdown(choices=[1,2,3,4,5,6,7,8,9],label="ズームレベルを選択") map_button = gr.Button("地図を生成") with gr.Column(): #2番目の列は地図用 map_output = gr.HTML(label="旅行地図") map_button.click(generate_map, inputs=[coordinates_input,zoom_level_input], outputs=[map_output])# ノートブックで実行してUIを表示するには、以下を実行しますdemo.queue().launch(debug=True)
ここでは、Blocks
APIを使用して、アプリのUIを柔軟に設定できるようにしています。2つの列を持つ1行のコンポーネントを作成しています。最初の列には3つの要素が含まれています。ユーザーが望む中心座標を入力するテキストボックス、ズームレベルを選択するドロップダウン、クリックする必要のある「地図を生成」という名前のボタンです。
2番目の列には、マップのhtmlを表示するgradio.HTML()
コンポーネントであるmap_output
があります。
それでは、map_button
がクリックされたときに何が起こるかを定義する必要があります。これが起こると、coordinates_input
とzoom_input
から選択された値を受け取ってgenerate_map
関数を実行します。結果はmap_output
変数に送信されます。
これを実行すると、以下のUIが生成されます。
これは確かに洗練されたデザインではありませんが、gradioでマッピングツールを構築するための必須要素を含んでいます。
3. 旅行代理店のためのシンプルなUI
まずはコードを調べる前に、旅行マッパーのgradioアプリのいくつかの機能を見てみましょう。ただし、gradioには多種多様なコンポーネントがあり、洗練された見た目のUIを作成するための多くのオプションが用意されています。この旅行マッパーUIはまだPOC段階にあります。
基本的に、私たちのアプリには2つの列があります。最初の列には、ユーザがクエリを入力するためのテキストボックス、モデル間を切り替えるためのラジオボタンのセット、バリデーションチェックの出力を表示するテキストボックスがあります。
2番目の列には、leafmap.folium
を使用して生成されたマップと、LLM呼び出しの完全なテキストイティネラリ出力を表示するテキストボックスが含まれます。上のスクリーンショットでは、「マップを生成」ボタンは画面下部にあります。
gradioによってバックグラウンドで行われるすべての作業のおかげで、これらすべてのコードは非常に簡潔になっています。
import gradio as gr
from travel_mapper.TravelMapper import TravelMapperForUI, load_secrets, assert_secrets
from travel_mapper.user_interface.utils import generate_generic_leafmap
from travel_mapper.user_interface.constants import EXAMPLE_QUERY
def main():
# APキーをロードする
secrets = load_secrets()
assert_secrets(secrets)
# 旅行マッパーをセットアップする(part 2を参照)
travel_mapper = TravelMapperForUI(
openai_api_key=secrets["OPENAI_API_KEY"],
google_maps_key=secrets["GOOGLE_MAPS_API_KEY"],
google_palm_api_key=secrets["GOOGLE_PALM_API_KEY"],
)
# gradioでUIを構築する
app = gr.Blocks()
# アプリが最初にロードされたときに表示する汎用のマップを作成する
generic_map = generate_generic_leafmap()
with app:
gr.Markdown("## 旅行の提案を生成")
# 複数のタブを作成する
with gr.Tabs():
# 最初のタブを作成する
with gr.TabItem("マップを使用して生成"):
# タブ1内の行1を作成する
with gr.Row():
# 行1内の列1を作成する
with gr.Column():
text_input_map = gr.Textbox(
EXAMPLE_QUERY, label="旅行クエリ", lines=4
)
radio_map = gr.Radio(
value="gpt-3.5-turbo",
choices=["gpt-3.5-turbo", "gpt-4", "models/text-bison-001"],
label="モデル",
)
query_validation_text = gr.Textbox(
label="クエリのバリデーション情報", lines=2
)
# 行1内の列2を作成する
with gr.Column():
# マップが表示される場所
map_output = gr.HTML(generic_map, label="旅行マップ")
# 提案された旅行が表示される場所
itinerary_output = gr.Textbox(
value="ここにイティネラリが表示されます",
label="旅程の提案",
lines=3,
)
# 生成ボタン
map_button = gr.Button("生成")
# 2番目のタブを作成する
with gr.TabItem("マップなしで生成"):
# 2番目のタブ内の最初の行を作成する
with gr.Row():
# 最初の行内の最初の列を作成する
with gr.Column():
text_input_no_map = gr.Textbox(
value=EXAMPLE_QUERY, label="旅行クエリ", lines=3
)
radio_no_map = gr.Radio(
value="gpt-3.5-turbo",
choices=["gpt-3.5-turbo", "gpt-4", "models/text-bison-001"],
label="モデルの選択肢",
)
query_validation_no_map = gr.Textbox(
label="クエリのバリデーション情報", lines=2
)
# 最初の行内の2番目の列を作成する
with gr.Column():
text_output_no_map = gr.Textbox(
value="ここにイティネラリが表示されます",
label="旅程の提案",
lines=3,
)
# 生成ボタン
text_button = gr.Button("生成")
# ボタンがクリックされたときの処理の指示
# ここでは"generate_with_leafmap"メソッドの使用に注目してください
map_button.click(
travel_mapper.generate_with_leafmap,
inputs=[text_input_map, radio_map],
outputs=[map_output, itinerary_output, query_validation_text],
)
text_button.click(
travel_mapper.generate_without_leafmap,
inputs=[text_input_no_map, radio_no_map],
outputs=[text_output_no_map, query_validation_no_map],
)
# アプリを実行する
app.launch()
4. パッケージの作成
GitHubのリポジトリを見るとわかるように、旅行マッパーのコードはcookiecutterの標準テンプレートを使用して構造化されていますが、テンプレートのいくつかの重要な部分がまだ埋まっていません。理想的には、ユニットテストと統合テストを含め、リポジトリのセットアップを完了し、継続的インテグレーション/継続的デリバリー(CI/CD)のコンセプトを使用します。このPOCステージを超えてプロジェクトがさらに発展する場合、これらの側面は将来的に追加されます。
コードをローカルで実行するためのいくつかの方法があります。上記のmain
関数をdriver.py
というスクリプトに配置すれば、travel_mapper
プロジェクトのトップレベルからターミナルで実行できるはずです。パッケージが正常に実行された場合、ターミナルには次のようなメッセージが表示されます。
ローカルURLで実行中: http://127.0.0.1:7860
このURLをWebブラウザにコピーして貼り付けると、マシン上でローカルに実行されているGradioアプリが表示されます。もちろん、実際にウェブ上に展開する場合には(API呼び出しに関連する費用が発生するためお勧めしませんが)、さらに手順が必要ですが、それはこの記事の範囲を超えています。
ドライバは、run.sh
というBashスクリプトからも実行できます。このスクリプトは、コードベースのuser_interface
モジュールにあります。
# UIを実行# これはトラベルマッパーのプロジェクトのトップレベルディレクトリから実行しますexport PYTHONPATH=$PYTHONPATH:$(pwd)echo "トラベルマッパーUIを起動中"$(pwd)/travel_mapper/user_interface/driver.py
プロジェクトのトップレベルから実行すると、PYTHONPATH
が正しく設定されるため、プロジェクト固有のインポート文が常に認識されます。
以上がこのシリーズの内容であり、お読みいただきありがとうございます!フルコードベースはこちらで公開されています:https://github.com/rmartinshort/travel_mapper。改善の提案や機能の拡張に関するご意見は大歓迎です!
We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles