Postman Flows オンラインハッカソン2位「AIラーメン検索フロー」を振り返る

# はじめに
2024/5/8～5/22に開催された**Postman Flowsオンラインハッカソン**に参加し、見事2位入賞できました。
今回は本ハッカソンを通じて得たPostman Flowsの学びを振り返りたいと思います。


# ハッカソン概要
Postman Flowsハッカソンの概要は以下のとおりです。

> 2024/5/8〜5/22に渡って開催する Postman Flows オンラインハッカソンでは、Postman Flow を使って作った日常のお仕事やちょっとした作業を楽にしてくれる作品を募集します！下記の開催概要と応募要項をご覧いただき、ぜひハッカソンにご参加ください。

https://www.postman.com/postman/postman-flows/overview


# 作成したPostman Flows
私が作成したハッカソン作品は以下の通りです。

:::note info
* 概要: 目的地周辺のおすすめのラーメン屋さんを生成AIが検索してくれて、お店の評価やお店までの所用時間を表にして教えてくれます。
* Runボタンを押すと、これらの情報を元にGoogleの生成AIである**Gemini**に対しておすすめのラーメン屋さんを質問します。
* 質問への回答には、**店名、スープの種類、住所、評価をJSON形式で３つ出力する**ようにプロンプトエンジニアリングをしています。
* 次に**各おすすめのラーメン屋さんまでの出発地点からの距離と所要時間の確認**をGoogle Map APIのDistance Matrixを使って出力します。Distance Matrixでは公共交通機関を使うように設定してあります。
* 最後に検索結果を表形式でユーザーに表示するために、**ラーメン屋さんの店舗情報と距離と所要時間の結果をmarkdown形式の表にまとめて結合**します。
:::

Youtubeに実際の動画とFlowsを簡単に解説していますので、ぜひご覧ください！

https://www.youtube.com/watch?v=8Ik4d7ZAtFw&embeds_referring_euri=https%3A%2F%2Fwww.postman.com%2Fpostman%2Fpostman-flows%2Foverview&source_ve_path=Mjg2NjY


# 各機能の解説
以下、各機能を解説いたします。

## ①ラーメン検索の入力
まずラーメン屋さんを検索するための情報を入力する箇所です。
ここでは、**出発時刻、出発場所、目的地、許容範囲の距離**を入力します。
Flowsではテキストや数値、日付などのブロックがあるので、それを利用します。

![スクリーンショット 2024-12-15 11.28.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3706974/2405c77c-57ee-6200-1050-647a1f3b1063.png)


## ②入力情報を元にGoogle Geminiでラーメン屋さんを検索
ここがほぼ本作品のメインです。
入力情報の<b>現在地(currentPlace)と許容範囲の距離(range)</b>を変数として後続のブロックに渡し、Google Gemini APIをコールします。

![スクリーンショット 2024-12-15 11.34.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3706974/103ee761-dd31-4e45-213f-f60228be615c.png)

:::note info
もちろんGemini以外の生成AIを使ってもOKです！最初はAnthropic Claudeを使おうと思っていたのですが、APIでのコールの仕方が分からず断念しました💦
Google APIは後続フローでも利用しますが、公開情報が多いので非常に利用しやすかったです。
:::

指定したプロンプト文は以下の通りです。
検索結果のJSON形式での回答や、出力に必要な情報を情報を指示しています。

```json
{"contents":
    [
        {"parts":
            [
                {"text":"{{currentPalce}}から{{range}}km以内の美味しいラーメン屋を3つ教えてください。美味しいラーメン屋さんはGoogle Mapの星の数やレビュー数を参照してください。回答は#conditionタグに記載の条件に従ってください。#condition * JSON形式で回答してください * お店の情報は、'stores'プロパティの内にList型で列挙記してください * お店の情報はname（店名）、スープの種類（soup）、address（住所）、Google Mapの星の数（star）を記載してください。"}
            ]
        }
    ]
}
```

:::note warn
PostmanでAPIキーなどのシークレット情報を扱う場合は、公開の仕方に注意しましょう！Publicに公開してしまうとAPIキーが流出してしまうので、公開対象からは削除するようにしてください。
:::

## ③Google APIを使って、出発地点からの距離と所要時間を計算
生成AIを使って検索したおすすめ３つのラーメン屋さんの位置情報を元に、入力された現在地との距離と移動時間を計算します。
計算にはGoogle Map APIを使っており、移動手段は公共交通機関に制限しています。

![スクリーンショット 2024-12-15 11.44.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3706974/95d484d4-1a03-225d-e8f1-688bea550f0a.png)

使用したAPIは**Distance Matrix API**です。
```origins```に出発地点、```destinations```にGeminiで検索した各ラーメン屋さんの住所、```time```に現在時刻を入れています。
今回は```transit_mode```に```train|bus|subway```と、公共交通機関を指定しています。

```html
https://maps.googleapis.com/maps/api/distancematrix/json?key={{google-api-key}}&origins={{origins}}&destinations={{destinations}}&transit_mode=train|bus|subway|tram&language=ja&depature_time={{time}}
```

APIレスポンスから、```distance```と```duration```を抽出して、整形します。
Distance Matrix APIでは計算結果が、```rows```リスト内に```elements```リストとしてそれぞれ格納されますので、取得方法にはご注意ください。

以下は出力サンプルです。
```json
{
  "destination_addresses":
    ["San Francisco"],
  "origin_addresses":
    ["Vancouver"],
  "rows":
    [
      {
        "elements":
          [
            {
              "distance": { "text": "1 712 km", "value": 1711765 },
              "duration": { "text": "3 jours 16 heures", "value": 318119 },
              "status": "OK",
            },
          ],
      },
    ],
  "status": "OK",
}
```


なお、Distance Matrix APIの詳細なリクエスト/レスポンスは以下をご参照ください。

https://developers.google.com/maps/documentation/distance-matrix/overview?hl=ja


## ④検索したラーメン屋さんの情報をまとめる
最後に検索結果を表示用にまとめます。
各ラーメン屋さんのリスト形式の結果をJSONにそれぞれまとめた後、生成AIを使ってmarkdown形式にまとめてもらいます。

![スクリーンショット 2024-12-15 12.00.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3706974/ea1b4ee0-a532-e643-077f-68e5cf6b0cdd.png)

以下がプロンプト文です。
```recommend```にはそれぞれのラーメン屋さんのJSON結果が入ります。

```json
{"contents":
    [
        {"parts":
            [
                {"text":"あなたは優秀なAIアシスタントです。次の3つのお店の情報をmarkdownのテーブルにまとめてください。{{recommend1}}、{{recommend2}}、{{recommend3}}"}
            ]
        }
    ]
}
```


# 振り返り
Postman Flowsを使うのが初めてでしたが、UIが非常に使いやすかったのですぐに使いこなすことができました。
敷いてあげるなら、繰り返し処理、リストの分割処理などを実行できるブロックは、最初はすぐに使いこなすことができませんでした。

以下のブロック解説の記事を読んで、自分でサンプルを作って試してみることで、少しずつ動作を理解できました。

https://qiita.com/nagix/items/2ebedd0273e7eb13c2cf

まだまだFlowsの公開サンプルが少ないので、もっと増えていくと使いやすいかと思います。


# 最後に
今回はオンラインハッカソンという機会で初めて触れたPostman Flowsですが、実際に使ってみることで処理フロー可視化と使いやすいさを実感しました！
実際に本ハッカソンを契機に、チームメンバーでもFlowsを使ってみたいという人も出てきました。

皆さんもぜひPostman Flowsにチャレンジしてみてください！