chatGPTのAPIを使った東京観光情報BOTの開発と実装

この記事では、ChatGPT APIとホットペッパーAPIを利用して、東京の観光地や飲食店に関する情報を提供するボットの開発過程を解説します。このボットは、ユーザーが地名を入力すると、その地域の観光地の概要とおすすめの飲食店情報を取得できるように設計されています。

:::note
[github](https://github.com/mori-tt/Tourism_recommendation_bot)
よかったらgit cloneしてみてください！
:::
:::note
[OpenAI API](https://openai.com/index/openai-api/)
:::
:::note
[HOT PEPPER API](https://webservice.recruit.co.jp/doc/hotpepper/reference.html)
:::
:::note
[Gradio](https://www.gradio.app)
:::

## <font color="Blue">1. 各種インストール、環境設定</font>


#### 必要なライブラリのインストール
必要なライブラリをインストールします。
```:terminal
pip install gradio openai requests python-dotenv
```

#### 環境変数の設定
.env ファイルをプロジェクトのルートディレクトリに作成し、以下の内容を追加します。
```:.env
OPENAI_API_KEY=your_openai_api_key_here
HOT_PEPPER_API=your_hot_pepper_api_key_here
```

## <font color="Blue">2. main.py</font>

#### respond_to_query 関数
この関数は、ユーザーからのクエリに基づいて情報を取得し、結果を返す役割を持っています。

```python:main.py
def respond_to_query(query):
```
* query パラメータは、ユーザーからの入力（地名など）を受け取ります

```python:main.py
tourist_spot_description = fetch_tourist_spots(query)
response_text = f"観光地の概要（{query}）:\n{tourist_spot_description}\n\n"
```
* fetch_tourist_spots 関数を呼び出して、指定された地名の観光地の概要を取得します
* 取得した情報を response_text にフォーマットして格納します

```python:main.py
restaurants_by_genre = fetch_restaurants_by_keyword(query)
if not restaurants_by_genre:
    restaurant_text = "レストラン情報が取得できませんでした。"
else:
    restaurant_text = "おすすめの飲食店:"
    for genre, restaurants in restaurants_by_genre.items():
        restaurant_text += f"\n\n{genre}:\n" + "\n".join(
            f"{i+1}. {r['name']} - TEL: {r['tel']} - ジャンル: {r['genre']} - 予算: {r['budget']} - おすすめ料理: {r['recommended_dish']} - 口コミ数: {r['review_count']} - 詳細: {r['url']}"
            for i, r in enumerate(restaurants)
        )
```

* fetch_restaurants_by_keyword 関数を使用して、指定された地名に基づいた飲食店情報を取得します
* 取得した飲食店情報をジャンルごとに整理し、restaurant_text にフォーマットして追加します

```python:main.py
return response_text + restaurant_text
```
* 最終的に観光地の概要と飲食店情報を結合して返します

#### Gradio インターフェースの設定
```python:main.py
interface = gr.Interface(
    fn=respond_to_query,
    inputs="text",
    outputs="text",
    title="東京観光情報ボット",
    description="東京の行きたい観光地の地名を入力してください。観光地の概要と、飲食店情報（ラーメン、和食）のオススメについて出力します。"
)
interface.launch()
```
* Gradio ライブラリを使用して、Webベースのインターフェースを設定し、起動します
* respond_to_query 関数をインターフェースのコールバック関数として設定します


## <font color="Blue">3. api_handlers.py</font>

#### fetch_restaurants_by_keyword 関数
この関数は、指定されたキーワードに基づいて飲食店情報を取得します。
```python:api_handlers.py
def fetch_restaurants_by_keyword(keyword):
```
* keyword パラメータはユーザーからの入力（地名など）を受け取ります

```python:api_handlers.py
url = "http://webservice.recruit.co.jp/hotpepper/gourmet/v1/"
genre_results = {}
genres = {"ラーメン": "G013", "和食": "G004"}
```
* ホットペッパーAPIのエンドポイントURLを指定します
* genre_results はジャンルごとの結果を格納するためのディクショナリです
* genres は取得するジャンルとそのAPIコードをマッピングしたディクショナリです

```python:api_handlers.py
for genre_name, genre_code in genres.items():
    results = []
    params = {
        "key": os.getenv("HOT_PEPPER_API"),
        "keyword": keyword,
        "genre": genre_code,
        "order": 4,  # おすすめ順
        "count": 5,  # 5件ずつ取得
    }
```
* 各ジャンルについてAPIを呼び出し、パラメータを設定します
* os.getenv("HOT_PEPPER_API") でAPIキーを環境変数から取得します

```python:api_handlers.py
response = requests.get(url, params=params)
if response.status_code == 200:
    data = response.json()
    for shop in data['results']['shop']:
        results.append({
            'name': shop['name'],
            'tel': shop['tel'],
            'genre': shop['genre']['name'],
            'budget': shop['budget']['average'],
            'recommended_dish': shop.get('recommended_dish', '情報なし'),
            'url': shop['urls']['pc'],
            'review_count': shop.get('review_count', '情報なし')
        })
    genre_results[genre_name] = results
else:
    print(f"No {genre_name} shops found in API response.")
    genre_results[genre_name] = []
```
* APIからのレスポンスを解析し、必要な情報を抽出して results に追加します
* エラーが発生した場合は、そのジャンルの結果を空リストとして設定します

```python:api_handlers.py
return genre_results
```
* 最終的にジャンルごとの飲食店情報を含む辞書を返します

#### fetch_tourist_spots 関数
この関数は、指定された地名の観光地の概要を取得します

```python:api_handlers.py
def fetch_tourist_spots(area_name):
```
* area_name パラメータは、ユーザーからの入力（地名など）を受け取ります

```python:api_handlers.py
prompt = f"{area_name}の観光地について200文字で説明してください。"
response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    messages=[{"role": "system", "content": "You are a helpful assistant."},
              {"role": "user", "content": prompt}]
)
summary = response['choices'][0]['message']['content'].strip()
return summary[:200]
```
* ChatGPTを使用して、指定された地名の観光地についての説明を生成します
* 生成された説明から200文字を抽出して返します

これらの関数と設定により、東京観光情報ボットはユーザーに役立つ情報を提供し、観光や食事の計画をサポートします。

## <font color="Blue">4. 完成後の画面</font>
#### 入力前の画面
情報が欲しい地域の地名を入力します
![入力前の画面]( https://raw.githubusercontent.com/mori-tt/Tourism_recommendation_bot/main/images/input.jpg "入力前の画面")

#### 入力後の画面
入力した地名の観光地の概要とおすすめ飲食店（ラーメン、和食）が取得できます
![入力前の画面](https://raw.githubusercontent.com/mori-tt/Tourism_recommendation_bot/main/images/output.jpg "入力後の画面")