ChatGPT が間違った位置情報を ArcGIS API for Python で修正してみよう~ArcGIS と ChatGPT の連携~

【Esri Community Blog】

昨年の12月頃に登場し、世間を賑わせている ChatGPT ですが、今年に入っても3月頃に ChatGPT の API が登場し、GPT-4 が登場するなどして今もなお IT 業界はもちろん世界中に衝撃を与え続けています。 今回はそんな ChatGPT と ArcGIS を API で連携してみます。

ChatGPT について

ChatGPT は、OpenAI が開発した言語モデルの1つです。 GPT は、Generative Pre-trained Transformer の略で、トランスフォーマーと呼ばれる深層学習モデルを用いて自然言語処理のタスクを実行することができます。ChatGPT は、人工知能による自然言語対話のエージェントとして使用され、ユーザーが投げかけた質問や応答に対して適切な回答を生成することができます。ChatGPT は、巨大なデータセットを用いた事前学習により、多様な言語タスクにおいて高い精度を発揮します。また、OpenAI は ChatGPT を一般公開しており、開発者は API を利用して ChatGPT を自分のアプリケーションに組み込むことができます。

上記の文章は、 ChatGPT に「ChatGPT について教えてください」と入力した結果です。このように ChatGPT は自然な文章で、こちらの問いに対して、ある程度正確な回答をしてくれるサービスを提供しています。 本記事では、OpenAI社 から API として公開されている Chat completions を Python で使用していきます。こちらの API は、OpenAI のアカウントさえあれば使用可能です(執筆時点ではトライアル版として $5 分まで無償で利用可能)。

Python での利用方法は、OpenAI の API リファレンスに倣って利用します。なお、本記事で使用する学習モデルは gpt-3.5-turbo です。

観光地をお勧めしてもらう

ChatGPT でお勧めの観光地を教えてもらいます。例えば ChatGPT で、「東京都の観光地を教えてください。また、GeoJSON 形式で出力してください。」と聞くと図のような回答と GeoJSON 形式で値を返してもらえます。

2023-04-18_14h39_32.pngChatGPT で東京の観光地をおすすめ

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [139.8107, 35.7101]
      },
      "properties": {
        "name": "東京スカイツリー"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [139.7967, 35.7143]
      },
      "properties": {
        "name": "浅草寺"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [139.6991, 35.6764]
      },
      "properties": {
        "name": "明治神宮"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [139.8806, 35.6329]
      },
      "properties": {
        "name": "東京ディズニーリゾート"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [139.7706, 35.7147]
      },
      "properties": {
        "name": "上野公園"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [139.7006, 35.6719]
      },
      "properties": {
        "name": "代々木公園"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [139.7736, 35.6278]
      },
      "properties": {
        "name": "お台場"
      }
    }
  ]
}

一部、東京都内ではない施設も混ざっていますが、概ねあっていそうです。 実際にマップ上で確認してみると図のように観光地と提示された座標は間違っていなそうです。

2023-04-18_14h53_24.png

 ChatGPT で作成した東京都の GeoJSON を地図にプロット

次に Chat completions で試してみましょう。 Chat completions では、場面の説明とアシスタントとしての役割を与え、石川県の観光地について聞いてみました。Python コードと出力結果は下記の通りです。

# openai_key には OpenAI の API キーを設定
import os
import openai

openai.api_key = openai_key
   
completion = openai.ChatCompletion.create(
  model="gpt-3.5-turbo",
  messages=[
    {"role": "system", "content": "asisstant は、日本にある石川県を案内するAIアシスタントです。"},
    {"role": "assistant", "content": "AIアシスタントです。石川県の観光地についてなら何でも聞いてください。"},
    {"role": "user", "content": "石川県に旅行に行くのでお勧めの観光地を教えてください。また、お勧めしてくれた観光地の情報をすべて GeoJSON で出力してください"}
  ]
)

石川県には多くの観光地がありますが、以下の観光地がおすすめです。 

1. 金沢市の兼六園
2. 金沢市の21世紀美術館
3. 金沢市のひがし茶屋街
4. 輪島市の能登島
5. 能登町の越中島
6. 白山市の白山比咩神社

それぞれの観光地に関する情報を GeoJSON 形式で出力します。ただし、APIにおける文字数制限のため、以下では一部の観光地の情報のみを出力します。​

#```
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [136.6589841, 36.5610195]
      },
      "properties": {
        "name": "兼六園",
        "address": "〒920-0936 石川県金沢市兼六町1番1号",
        "description": "金沢城下町の高台にある日本庭園。"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [136.659319, 36.5616499]
      },
      "properties": {
        "name": "21世紀美術館",
        "address": "〒920-8509 石川県金沢市広坂1丁目2-1",
        "description": "建築家 SANAA 設計の美術館。"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [136.669555, 36.560626]
      },
      "properties": {
        "name": "ひがし茶屋街",
        "address": "〒920-0858 石川県金沢市東山1丁目12番1号",
        "description": "江戸時代から続く茶屋街。"
      }
    }
  ]
}
#```

有名な観光地がいくつか挙げられていますね。住所の情報も付随してくれているようです。ただ、東京都の越中島が出力されていますね。この点は修正をするために何度かやり取りをする必要がありそうですが、本題ではないのでおいておきましょう。また、API による文字数制限がかかったようです。GeoJSON では全ての位置情報が見えないですが、一旦この GeoJSON を ArcGIS API for Python で出力してみましょう。

GeoJSON 形式で出力 ArcGIS API for Python 上で出力

ArcGIS API for Python で GeoJSON として ArcGIS Online にアップロードしたのち、Feature Layer として公開したものを ArcGIS API for Python のマップに出力してみましょう。

from arcgis.gis import GIS,Item
gis=GIS("https://arcgis.com","ユーザー名","パスワード")

add_geojson=gis.content.add(item_properties={"title":"chatgpt で作りました",
                                          "type": "GeoJson"
                                          },
               data="./kanazawa.geojson" # 上記の GeoJSON を保存した .geojson を使用
               )

analyzed = gis.content.analyze(item=add_geojson)
publish_parameters = analyzed['publishParameters']
publish_parameters["name"]=add_geojson.title # アップロードしたファイルの名前を指定
publish_parameters['targetSR']={'wkid': 4326} # 今回は WGS84

publish_result=add_geojson.publish(publish_parameters)

2023-04-17_19h26_24.pngChatGPT で作成した GeoJSON を地図にプロット(兼六園)

2023-04-17_19h25_47.png

ChatGPT で作成した GeoJSON を地図にプロット(ひがし茶屋街)

どうやら出力された緯度経度が異なっているようです。21世紀美術館の位置にポイントがない他、兼六園は園外にポイントがあります。また、ひがし茶屋街は全く関係のないところに表示されています。

何度か修正を試してみましたが、石川県内の観光地をお勧めはしてくれても完全に正確な位置までは出すことができないようです。 この部分を ArcGIS API for Python の geocode で補ってみましょう。

ArcGIS API for Python でジオコーディング

ArcGIS で提供されているジオコーディングには用途別に機能が用意されています。 今回は、先ほど出力された GeoJSON に住所の情報が載っていましたのでジオコーディングによって、先ほどの GeoJSON の位置情報を正確な位置情報に変更してみましょう。

from arcgis.geocoding import geocode # geocode クラスをインポート

kanazawa=publish_result.layers[0].query() # 更新用の FeatureSet を取得
kanazawa_df=publish_result.layers[0].query(as_df=True) # 更新用の DataFrame を取得
for i,place in enumerate(kanazawa_df["address"]):
    address=place.split(" ")[1] # 郵便番号を削除
    geocode_result=geocode(address,for_storage=True) # geocode の結果を保存するので for_storage は True
    kanazawa.features[i].geometry["x"]=geocode_result[0]["location"]["x"] # 元のフィーチャの x 座標を書き換え
    kanazawa.features[i].geometry["y"]=geocode_result[0]["location"]["y"] # 元のフィーチャの y 座標を書き換え
    updates_result = publish_result.layers[0].edit_features(updates = [kanazawa.features[i]]) # 元のフィーチャをアップデート

上記のコードでジオコーディングした結果が下図の通りです。21世紀美術館はもちろん、兼六園も園内にポイントをあてることができました。

2023-04-18_15h46_22.pngChatGPT で作成した GeoJSON を修正し地図にプロット

また、ひがし茶屋街についても同様にひがし茶屋街の通りにポイントをあてられました。

2023-04-18_15h53_02.pngひがし茶屋街もポイントを修正

このように ChatGPT で間違っていた位置情報も ArcGIS で修正することができました。

最後に

今回は、ChatGPT (Chat completions) を利用して、おすすめの観光地を出力してもらいました。その観光地の位置情報を ArcGIS API for Python を使って修正をおこなってみました。このように ChatGPT にも不完全な点や不足している地図に関する機能を ArcGIS によって補足することができます。

ArcGIS では ArcGIS API for Python 以外にも API/SDK を提供しています。中には無償アカウントから利用できるものもございますのでぜひお試しください。

位置情報を扱う解析や地図アプリ開発には、様々なロケーションサービスを提供している ArcGIS の API / SDK を検討してみてください。

参考資料

ChatGPT(OpenAI ブログ)

ArcGIS Developers

ArcGIS Platform の紹介 ~API/SDK のラインナップと使い分け~

開発者アカウントの作成

ArcGIS API for Python

ジオコーディング