スマートシティの総合案内をOpenAIにさせてみた

### 今回はスマートシティの総合案内をAIにして貰うプログラムを考えてみました。
### ここでは流山市がスマートシティになったと仮定して総合案内をさせてみます。
:::note info
前提条件：
　Python： 3.12.1
　WEBフレームワーク：Flask
　OpenAIモデル：gpt-4o 
:::
Flaskは事前にインストールしておきます。
 ```
 $ pip install flask
 ```
 総合案内プログラムは
 ```python
 from flask import Flask, request
import openai
import json
import os

# Web開発するためのフレームワークFlaskを使用
# Flaskアプリインスタンス生成
app = Flask(__name__)

# 環境変数からAPI_KEYを取得する
plus_key = os.environ["OPENAI_PLUS_KEY"]
client = openai.Client(api_key=plus_key)

@app.route("/chat", methods=["POST"])
def chat():
    try:
        # JSONデータをSHIFT_JISで強制デコード
        data = request.data.decode("shift_jis", errors="ignore")  
        json_data = json.loads(data)  # JSON デコード

        if not json_data or "message" not in json_data:
            return app.response_class(
                response=json.dumps({"error": "Invalid JSON: 'message' field is required"}, ensure_ascii=False),
                status=400,
                mimetype="application/json"
            )
        
        user_input = json_data["message"]
        print(user_input)
        
        messages=[
                {"role": "system", "content": 
                 "あなたは流山市役所のAI総合案内係です。"
                 "流山市役所職員として各申請手続きの方法などを案内してやってください。"
                 "また、可能な限り一般的な質問にも答えるようにしてください。"
                 "来訪者の質問が不明確な場合は、どのような情報が必要か聞いてやってください。"},
                {"role": "user", "content": user_input}
            ]
        
        responses = client.chat.completions.create(
            model="gpt-4o",
            messages=messages,
            max_tokens=300,
            temperature=0.7
        )
        
        reply = responses.choices[0].message.content.strip()

        # 🔥 JSON レスポンスの Unicode エスケープを防ぐ
        return app.response_class(
            response=json.dumps({"response": reply}, ensure_ascii=False), 
            status=200, 
            mimetype="application/json"
        )
# 以下の例外チェックはOSもJSONコードもShift_JISに固定ならば特に必要ないです。
    except json.JSONDecodeError:
        return app.response_class(
            response=json.dumps({"error": "Invalid JSON format"}, ensure_ascii=False),
            status=400,
            mimetype="application/json"
        )
    except UnicodeDecodeError:
        return app.response_class(
            response=json.dumps({"error": "Encoding error: Ensure Shift_JIS encoding"}, ensure_ascii=False),
            status=400,
            mimetype="application/json"
        )
    except Exception as e:
        return app.response_class(
            response=json.dumps({"error": str(e)}, ensure_ascii=False),
            status=500,
            mimetype="application/json"
        )

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)
```
このコードを実行して総合案内を起動させ質問を受付けます。
```
$ python <このプログラム名>.py
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5000
 * Running on http://192.168.0.3:5000
```
では次にCURLコマンドを叩いて質問してみます。
```
curl -X POST http://127.0.0.1:5000/chat -H "Content-Type: application/json; charset=shift_jis" --data-binary "{\"message\": \"年金支給の手続きは何課で相談すれば良いですか？\"}"
```
AI総合案内の回答（Response)は以下の様なものでした。
gpt-4oですとかなり親切な回答が出来るようです。
```
{"response": "年金支給の手続きについては、市役所の「国民年金課」で相談することができます。具体的な手続きや必要書類についても、国民年金課の窓口で詳しく案内してもらえます。また、事前に電話で 問い合わせてみるのも良いでしょう。何か他にお手伝いできることがあれば教えてください。"}
```
尚、プログラム中のmessagesのプロンプトによってはもっと親切な回答が可能かもしれません。