無課金で物件の相場単価を知る!Difyでチャットボット作成

こんにちは。三度の飯より不動産が大好きな桑原です。Difyと 不動産情報ライブラリを利用し、特定地域の物件の相場単価を教えてくれるチャットボットを無料で作成してみました。今回はその作成方法をご紹介します。

チャットボットの完成イメージ

以下のような結果を出力するチャットボットの作成を目指します。

不動産情報ライブラリからデータを取得し、LLM(大規模言語モデル)を使って物件相場の単価を算出します。おまけで、今後の単価も予測してもらいましょう。


作成手順

1. 不動産情報ライブラリから物件データを取得

物件データの取得方法は2通りあります。いずれかの方法でお試しください。

対象方法
さくっと試したい方Webサイトから物件データをダウンロードする
踏み込んでみたい方APIを使って物件データを取得する

方法1:Webサイトから物件データをダウンロードする

  • 不動産情報ライブラリのサイトにアクセスする
  • 下図のように知りたい地域の情報を選択し、データをダウンロードする。ダウンロード後のデータはExcelで開くことができます。なお、その場で結果を一覧表示することもできます。ダウンロードする前の確認に使ってください。
  • (任意)ダウンロードしたExcelから、必要な情報のみフィルタリングする。例えば対象物件を中古マンションのみ、かつ築年数を2015年以降のみにフィルタリングする等。

※高精度のLLMを利用すれば、物件の種類や築年数をうまく分類して相場単価を教えてくれえると思いますが、必要な情報のみLLMにINPUTする方が精度は期待できます。

方法2:APIを使ってデータを取得する

  • APIの利用申請を行う。承認が得られたらAPIのKEYが発行されるので控えてください。
  • APIを使って物件データを取得する。以下のサンプルコードを参考にしてください。API_KEYには取得したご自身のAPI KEYを設定してください。
import requests
import pandas as pd
import argparse
import re
# APIアクセスとデータ制限の設定
API_KEY = "YOUR KEY"
BASE_URL = "https://www.reinfolib.mlit.go.jp/ex-api/external"
MIN_YEAR_AVAILABLE = 2005
# 都道府県名を対応するIDにマッピングする関数
def get_prefecture_id():
    return {
        '北海道': 1, '青森県': 2, '岩手県': 3, '宮城県': 4, '秋田県': 5, '山形県': 6, '福島県': 7,
        '茨城県': 8, '栃木県': 9, '群馬県': 10, '埼玉県': 11, '千葉県': 12, '東京都': 13,
        '神奈川県': 14, '新潟県': 15, '富山県': 16, '石川県': 17, '福井県': 18,
        '山梨県': 19, '長野県': 20, '岐阜県': 21, '静岡県': 22, '愛知県': 23,
        '三重県': 24, '滋賀県': 25, '京都府': 26, '大阪府': 27, '兵庫県': 28,
        '奈良県': 29, '和歌山県': 30, '鳥取県': 31, '島根県': 32, '岡山県': 33,
        '広島県': 34, '山口県': 35, '徳島県': 36, '香川県': 37, '愛媛県': 38,
        '高知県': 39, '福岡県': 40, '佐賀県': 41, '長崎県': 42, '熊本県': 43,
        '大分県': 44, '宮崎県': 45, '鹿児島県': 46, '沖縄県': 47
    }
# 不動産APIへのリクエストを実行する関数
def make_api_request(endpoint, params):
    try:
        # APIエンドポイントの完全なURLを構築
        response = requests.get(f"{BASE_URL}/{endpoint}",
                                headers={"Ocp-Apim-Subscription-Key": API_KEY},
                                params=params)
        response.raise_for_status()  # HTTPエラーの場合は例外を発生させる
        return response.json()
    except requests.RequestException as e:
        print(f"APIリクエストエラー: {e}")
        return None
# 都道府県(エリアコード)と市区町村名を使って市区町村コードを取得する関数
def get_city_code(area_code, city_name):
    data = make_api_request("XIT002", {"area": area_code})
    if data:
        for entry in data.get('data', []):
            if entry['name'] == city_name:
                return entry['id']
    return None  # 市区町村コードが見つからなければNoneを返す
# 入力された期間を年のリストに変換する関数
def get_year_range(period):
    start, end = (period.split('-') if '-' in period else (period, period))
    years = list(range(int(start), int(end) + 1))
    if min(years) < MIN_YEAR_AVAILABLE:
        raise ValueError(f"エラー: 指定された期間が利用可能な最小年 {MIN_YEAR_AVAILABLE} よりも前です。")
    return years
# 不動産データを取得して表示するメインの機能
def fetch_data(prefecture, city, period, district=None):
    # 指定された都道府県と市区町村のIDを取得
    area_code = get_prefecture_id().get(prefecture)
    city_code = get_city_code(area_code, city)
    if not city_code:  # 市区町村コードが見つからない場合のチェック
        print(f"{city} の市区町村コードが見つかりませんでした。")
        return
    combined_data = []  # 各年のデータフレームを保持するリスト
    for year in get_year_range(period):
        # 指定された期間内の各年のデータをリクエスト
        data = make_api_request("XIT001", {"year": year, "area": area_code, "city": city_code})
        if data and 'data' in data:
            df = pd.DataFrame(data["data"])  # JSONデータをデータフレームに変換
            if district:  # 地区でのフィルタリングが指定された場合
                df = df[df['DistrictName'] == district]
            combined_data.append(df[df['Type'] == '中古マンション等'])  # 中古マンション等でフィルタリング
    if combined_data:
        # 全てのデータフレームを連結し、表示用に処理
        df_final = pd.concat(combined_data, ignore_index=True)
        df_final['TradePrice'] = df_final['TradePrice'].apply(lambda x: f"{int(x):,}")  # 取引価格をフォーマット

        # 'BuildingYear' の処理を修正
        def format_building_year(year):
            if pd.isna(year):
                return None
            match = re.findall(r'(\d{4})', year)  # すべての4桁の年を抽出
            if match:
                return "年, ".join(match) + "年"  # 抽出された年を "YYYY年, YYYY年" の形式に結合
            return year

        df_final['BuildingYear'] = df_final['BuildingYear'].apply(format_building_year)

        pd.set_option('display.max_rows', None)  # pandasのオプションを設定し全行表示
        print(df_final)  # 最終的なデータフレームを出力
    else:
        print("指定されたクエリに利用可能なデータがありません。")
if __name__ == "__main__":
    # コマンドライン入力のための引数パーサー
    parser = argparse.ArgumentParser(description="不動産データ取得プログラム")
    parser.add_argument("--prefecture", required=True, help="都道府県名 (例: '東京都')")
    parser.add_argument("--city", required=True, help="市区町村名 (例: '港区')")
    parser.add_argument("--district", help="絞り込む地区名 (例: '赤坂')")
    parser.add_argument("--period", required=True, help="年または期間 (例: '2023' または '2016-2024')")
    args = parser.parse_args()
    # 引数で指定された条件に基づきデータを取得
    fetch_data(args.prefecture, args.city, args.period, args.district)
$ python3 real_estate.py --prefecture="福岡県" --city="小倉北区" --district="金田" --period="2023-2024"
   PriceCategory      Type Region MunicipalityCode Prefecture Municipality DistrictName  TradePrice PricePerUnit FloorPlan Area UnitPrice LandShape Frontage TotalFloorArea BuildingYear Structure Use Purpose Direction Classification Breadth CityPlanning CoverageRatio FloorAreaRatio      Period Renovation Remarks
0      不動産取引価格情報  中古マンション等                   40106        福岡県     北九州市小倉北区           金田   8,800,000                    4DK   65                                                    1980年       SRC  住宅      住宅                                          商業地域            80            400  2023年第2四半期       改装済み
1      不動産取引価格情報  中古マンション等                   40106        福岡県     北九州市小倉北区           金田   9,800,000                   4LDK   85                                                    1991年       SRC          住宅                                          商業地域            80            400  2023年第2四半期        未改装
2      不動産取引価格情報  中古マンション等                   40106        福岡県     北九州市小倉北区           金田   5,000,000                    2DK   75                                                    1991年       SRC          住宅                                          商業地域            80            400  2023年第2四半期        未改装
3      不動産取引価格情報  中古マンション等                   40106        福岡県     北九州市小倉北区           金田  10,000,000                   2LDK   75                                                    1991年       SRC  住宅      住宅                                          商業地域            80            400  2023年第3四半期        未改装
4      不動産取引価格情報  中古マンション等                   40106        福岡県     北九州市小倉北区           金田  29,000,000                   3LDK  100                                                    2006年        RC  住宅      住宅                                          商業地域            80            400  2023年第3四半期        未改装
5      不動産取引価格情報  中古マンション等                   40106        福岡県     北九州市小倉北区           金田  39,000,000                   3LDK   85                                                    2019年        RC  住宅      住宅                                          商業地域            80            400  2023年第4四半期        未改装

2. Difyの実行環境を構築

こちらのブログを参考にしてください。ConoHa VPSを使ってコミュニティ版のDifyを構築する手順です。この手順の場合、Dify自体は無料ですが、VPSの利用料は発生します。しかし、Difyのコミュニティ版は、メモリ4GB以上の環境であれば動作可能なため、PC上でも構築できます。そうすれば無料ですね。


3. LLM接続用のAPIキーを取得

今回は 「Groq」のAPIを使います。レート制限内のリクエスト数であれば、無料で利用可能です。詳細は公式サイトよりご確認ください。

  • Groqの公式サイトにアクセス
  • アカウント作成後、APIキー(SECRET KEY)を発行する

4. Dify上でLLM接続用のAPIキーを登録

  • 構築したDifyにブラウザでログインする
  • 右上のアカウントメニュー → 設定
  • モバイルプロバイダー → モデルに「groqcloud」を選択 → セットアップ
  • 先ほど発行したGroqのAPIキーを入力して保存

5. Difyでチャットボットを作成

  • Difyのスタジオにて「最初から作成」→「チャットボット」を選択
  • アプリに名前を付ける → 作成
  • 「手順」に以下のプロンプトを与える。
あなたは不動産業界のプロフェッショナルです。
以下に示す中古マンションの取引データに基づき、地域特性を考慮した詳細な分析を実施してください。
特に Prefecture, Municipality, DistrictName の情報を使用して、該当地域に関する人口推移や都市の発展状況を調査し、
未来予測に含めてください。
データ形式:
- TradePrice: 物件の売買成立価格(単位は円)
- Area: 物件の広さ(単位は平米)
- Period: 物件の売買が成立した年
- BuildingYear: 物件の建築年
- Prefecture, Municipality, DistrictName: 地域を特定する情報
分析手順:
1. 各物件の平米あたりの売買成立価格を年度ごとに計算し、地域(`Prefecture`, Municipality, DistrictName)ごとに集計する。
2. 地域ごとの年度別価格傾向を分析し、物件の築年数、状態、立地条件などの影響要因を検討する。
3. Prefecture, Municipality, DistrictName に基づいて、その地域の人口推移、都市計画、経済指標を強調し、これらが不動産市場に与える影響を評価する。
4. 未来のX年度の平米あたりの売買成立価格を予測する。この予測には、過去のデータだけでなく、地域経済の動向、人口動態などを考慮する。
5. 総合的な見解を示し、不動産市場の将来展望や区域に対応した投資戦略を提言する。
データ:
{{{input_data}}}}

このプロンプトにより、特定の地域に依存した分析と予測を実施し、信頼性の高い市場動向の把握を目指します。
  • 変数キー「input_data」を定義する
  • 変数「input_data」の歯車アイコンをクリックし、詳細設定画面を開く。フィールドタイプを「段落」、最大長(最大input文字数)を「20000」に設定する。最大長はLLMに依存します。エラーが出る際は調整してください。
  • 右上のLLM選択ボックスから使用するLLMを選択する。Groq APIで接続可能なモデルが複数表示されるので、お好みのモデルを選択してください。今回は「DeepSeek R1」を使うことにします。
  • 作成したアプリを保存する。右上の「公開する」→「更新」

6. チャットボットアプリを実行

  • 不動産情報ライブラリから取得した物件データをコピペする。ベタ貼りでもLLMがうまく処理してくれると思いますが、今回はLLMが理解しやすいようにjson形式で渡します。
  • チャット欄にて「start」と指示する。
  • 利用するLLMによって差異はありますが、冒頭で紹介したような分析結果が得られるはずです。

まとめと今後の展望

いかがでしょうか?
既に物件を所有している方は、得られた結果は妥当の範囲だったでしょうか?
精度は利用するLLMやINPUTするデータの量など、様々な要因で変わると思います。
結果はあくまで参考程度にし、むしろ作る工程を楽しんでいただければと思います。

なお、個人的には以下が現状の課題と考えており、今後改修しようと思っています。

  • 不動産情報スクリプトとDifyの実行が分離している。Difyから一度に処理できるようにしたい。
  • いま現在の将来予測はLLMが元々学習しているデータと、その学習期間に依存する。精度を上げるために、RAGで地域性の最新データを拡張検索させるようにしたい。

ブログの著者欄

桑原 謙吾

GMOインターネット株式会社

2016年にGMOインターネットグループ株式会社に中途入社。 システムの運用を経て、いまはインターン等の採用周りのテクニカルな企画と運営、また大学で単位制の授業をしたり。

採用情報

関連記事

KEYWORD

TAG

もっとタグを見る

採用情報

SNS FOLLOW

GMOインターネットグループのSNSをフォローして最新情報をチェック