1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

シェアモビリティの標準的なデータフォーマット GBFSAdvent Calendar 2023

Day 5

GBFSをChatGPTで操作可能にしてみる

Last updated at Posted at 2023-12-04

GBFSアドベントカレンダー2023の5日目です。

みなさん、ChatGPT使ってますか?
いやー、昨年の発表以来、大盛り上がりですね。Qiitaの人気記事にも毎週なにかしらのChatGPT関連の記事がランクインしているように思います。

折しもChatGPTを自分でカスタマイズして特化させる機能がOpenAIから発表されましたね。GPTs。
今回はGBFSとこれを絡めていきたいと思います。

前提

まず今回の記事の前提です。

  • ChatGPT4(2023/11/17時点のモデル)
  • ChatGPT Plus(or Enterprise)

本記事では、OpenStreet株式会社(ハローサイクリング) / 公共交通オープンデータ協議会のバイクシェア関連情報(GBFS形式)をCC-BY4.0に従って利用しています。
https://ckan.odpt.org/dataset/c_bikeshare_gbfs-openstreet

GBFSとはなんぞや

この記事を読むような方はそもそもGBFSをご存知かと思うのですが…
ChatGPTから流れてくる方もいらっしゃると思うので、説明記事をご紹介します!!(他力本願)

@kumatiraさんが素晴らしい記事を書いてくださっているので、私のGBFS関連の記事の始まりは全てこの記事の紹介です。

GPTsとは

ChatGPTについては万巻の書があるので説明を省きますが、GPTsについては少し補足です。

ChatGPTの開発元であるOpenAIが2023/11/6に公開した、ChatGPTの新機能です。
機能的には RAG(Retrieval Augmented Generation) です。
単なる対話AIでしかないChatGPTに、ウェブ検索などのさまざまな機能を(その呼び出しの判断ごと)追加するもので、Langchainを使って実現できるものと同様のことができます。

ただそれをChatGPTと対話しながら作れたり、ノーコードでウィザード式に作れるのが特徴です。

詳しくは公式ページを。

今回は、GBFSのデータが取れるAPIをGPTsに組み込み、ChatGPTでGBFSを操作できるようにします。

GPTsの作り方(基本設定)

まず、GPTsの作り方の簡単な説明をしつつ、今回のGPTsの設定をしていきます。

なお、前提にあるとおり、GPTsはPlusかEnterpriseユーザー限定です。無償ユーザーの方は、フーンと思いながら読んでください。

またChatGPTはしばしばUIが変わります。この記事は2023/11月時点のUIで説明をしています。
今後、UIが変更されたら読み替えてください。

ChatGPTのトップ画面から説明していきます。

  1. ChatGPT画面右上の「Explore」を選択
  2. Create a GPT」を選択

そうすると次のような画面になります。

スクリーンショット 2023-11-17 23.08.15.png

画面左側がGPTsの設定画面、右側がプレビュー画面です。
初期では「Create」になっていて、ChatGPTと対話しながらGPTsを作れる画面になっています。

Configure」を選ぶと、次の画面になります。

スクリーンショット 2023-11-17 23.02.40.png

私はこちらの方が好きなので、こちらをメインに説明していきます。

項目 説明 今回の設定例
⚪︎に+のところ アイコンの設定です。アイコン画像を用意しなくてもDALL-Eで生成できます。 DALL-Eを使って作ってもらいました。ださい。
Name このGPTsの名前です。 「OpenStreetGBFS」
Description このGPTsの説明です。 「OpenStreetが公開するGBFSのstation_informationを操作します」
Instruction このGPTsになにをさせたいか、役割や、口調、予備知識などを与えます。 「あなたはOpenStreetのエンジニアです。GBFSのstation_information APIを使い、指示された情報を示したり、コードを実装、実行してください」
Conversation starters ユーザープロンプトの例示の設定です。このGPTsをどう使っていいかの例を示すなど、まずユーザーに試してほしいことなどを記述します。 今回は設定しません
Knowledge データソースになるファイルを指定できます。指定できるファイルは決まっているようですが、PDF、CSVなどが指定できます。文章ファイルの場合、ベクトル化されてChatGPTが参照できるようです。 今回は使いません。
Capabilities このGPTsで使う拡張機能です。 Web Browsing: OFF
DALL-E Image Generation: OFF
Code Interpreter: ON
Actions このGPTsで使用するAPIを指定できます。 後述するGBFSのAPIエンドポイントを指定します。

さて、Actionsに指定するGBFSのAPIエンドポイントの設定については次章に譲ります。
まずそれ以外の項目を埋めます。埋めたのがこちら。

スクリーンショット 2023-11-17 23.25.34.png

Actions

では、ActionsにGBFSのAPIを設定していきましょう。

Actionsの「Create new action」を選択します。
すると次のAPIの設定画面になります。

スクリーンショット 2023-11-17 23.30.31.png

Schemaのプレースホルダーに書いてあるとおり、OpenAPI形式で指定ができます。
また「Import from URL」や「Examples」には、既存のAPI定義を取り込んだり、テンプレを指定できます。

今回は、OpenStreetがODPTで公開しているGBFSの定義を作っていきます。
フルスクラッチで定義を書いてもいいのですが、今回、これもChatGPTに作ってもらいましょう。

ここは面倒なので、作った過程を共有します。

できたYAML形式の定義がこちらなのですが、3点誤りがあるため直します。
貼り付けた定義は修正後のものです。

  • servers:urlで、最後のスラッシュが不要。urlにスラッシュがついていると、呼び出し時、hellocycling//station_information.jsonとなり、404になります
  • operationIdの追加。不要かと思いましたがこれ必須でした
  • GBFSの共通レスポンスでlast_updatedとversionを指示し忘れてたのを修正
openapi: 3.0.0
info:
  title: GBFS Of OpenStreet Bikeshare Service
  description: This is a GBFS API Server of OpenStreet.
  version: 1.0.0
servers:
  - url: https://api-public.odpt.org/api/v4/gbfs/hellocycling
    description: Product API end point

paths:
  /station_information.json:
    get:
      summary: List all station information. id, position, vehicle capacity and soon.
      operationId: List stations
      responses:
        '200':
          description: A list of station information including location, name, and vehicle capacity.
          content:
            application/json:
              schema:
                type: object
                properties:
                  ttl:
                    type: integer
                  last_updated:
                    type: integer
                  version:
                    type: string
                  data:
                    type: object
                    properties:
                      stations:
                        type: array
                        items:
                          $ref: '#/components/schemas/Station'

components:
  schemas:
    Station:
      type: object
      properties:
        lat:
          type: number
          format: float
          description: Latitude of the station.
        lon:
          type: number
          format: float
          description: Longitude of the station.
        name:
          type: string
          description: Name of the station.
        address:
          type: string
          description: Address of the station.
        station_id:
          type: string
          description: Unique identifier of the station.
        rental_uris:
          type: object
          properties:
            ios:
              type: string
              description: Station URL for iOS devices.
            web:
              type: string
              description: Station URL for PC web browsers.
            android:
              type: string
              description: Station URL for Android devices.
        parking_hoop:
          type: boolean
          description: Are parking hoops present at this station?
        parking_type:
          type: string
          description: Type of parking. Values are "parking_lot", "street_parking", "underground_parking", "sidewalk_parking", and "other".
        contact_phone:
          type: string
          description: Contact phone number for the station.
        is_charging_station:
          type: boolean
          description: Does the station support charging of electric vehicles?
        vehicle_type_capacity:
          type: object
          properties:
            num_bikes_now:
              type: integer
              description: Current number of bikes at the station.
            num_bikes_limit:
              type: integer
              description: Maximum number of bikes the station can hold.
            num_bikes_parkable:
              type: integer
              description: Current number of bikes the station can park.
            num_bikes_rentable:
              type: integer
              description: Current number of bikes the station can rent.

さて、この定義をSchemaに貼り付けます。
ODPTのこのAPIは認証がないので、Authenticationは「None」のままでいいです。Privacy Policyも特に指定がないので空にします。

貼り付けると、このように利用可能なアクションが表示され、テスト可能になります。

スクリーンショット 2023-11-17 23.51.44.png

「Test」をすると実際にAPIが実行され、プレビュー画面でデバッグできます。

スクリーンショット 2023-11-17 23.53.25.png

はい、ダメでした…
要するに「レスポンスとは受け取れたけどデカすぎて使えないよ」ということです…

APIを絞る

仕方ないのでAPIを絞ります。
ここはこの記事の本題ではないので、やったことだけ説明します。

  1. python flaskでsystem_information.jsonを「東京都小平市」に絞るAPIを実装
  2. 同APIをローカルホストで実行
  3. VisualStudioCodeのポートフォワーディングでローカルホストのAPIを外部実行可能なURLを発行
  4. APIを認証が不要な「公開」に設定
  5. GPTsのActionsのSchemaに指定したOpenAPIのserversを発行されたURLに変更

これで無事、APIが動作しました。

大したソースではありませんが、1.のソースは一応示しておきます。
(このソースも半ばGithub Copilotに書かせています)

import requests
import json
import flask

app = flask.Flask(__name__)

@app.route('/station_information.json')
def station_information():
    url = "https://api-public.odpt.org/api/v4/gbfs/hellocycling/station_information.json"
    res = requests.get(url)
    station_information = json.loads(res.text)

    _d = {}
    _d["last_updated"] = station_information["last_updated"]
    _d["ttl"] = station_information["ttl"]
    _d["version"] = station_information["version"]
    _d["data"] = {}
    _d["data"]["stations"] = []

    for station in station_information["data"]["stations"]:
        if "東京都小平市" in station["address"]:
            _d["data"]["stations"].append(station)

    return flask.jsonify(_d)

if __name__ == '__main__':
    app.run()

動かしてみる

動かしてみた結果がこちらです。

スクリーンショット 2023-11-23 0.31.01.png

スクリーンショット 2023-11-23 0.31.23.png

スクリーンショット 2023-11-23 0.31.45.png

コードを示してくれと言ったけど、結果を示しているところはありますが…、全般的にはだいぶいいですね!

GBFSはJSON仕様としては、比較的シンプルなものの、非エンジニア職にはやはり扱いにくいものですし、エンジニア職でも解析しようとしたらコードを書かねばなりません。
GPTsにしておくことで、その操作がパッとできるのはちょっとしたやりたいこと、知りたいことをパッと形にしてくれます。

APIやドキュメントと組み合わせることで、会社やオープンデータとしてある資産を生かす道が広がるのではないでしょうか。

と言ったところで、今回の記事を終わりたいと思います。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?