← 地図へ / 使い方 / 地図に場所を足そう / プライバシーポリシー
スターアニスの技術
制定 2026年10月14日
スターアニスは、地図の下のホイールを回して近くのお店を1軒ずつ送る、店探しのサイトです。 この頁では、その裏でどの技術を、何のために、どう使っているかを、できるだけ具体的に書きます。 あわせて、どこまで保証できて、どこからは保証できないかも書きます。
全体の流れ
お店の情報は、ホットペッパーグルメ Web サービスから毎晩すべて取り直します。そこに、地図のデータ(OpenStreetMap)や AI が作った紹介文・拡大した写真・場面の判定を重ね、見に来た方には地図とお店のページとして出します。 見に来た方の操作で AI が動くことはありません。AI が働くのは夜の作り置きの時だけです。
並び順 ── H3 のうずまき
近くのお店を「近い順に100軒」並べると、東京駅のような店の多い所では 270m 先までしか届かず、ホイールを回しても景色が変わりません。 そこで、地球を六角形で敷き詰める H3(Uber が公開している仕組み)を使います。 地図の中心の六角形をリング0、それに接する6枚をリング1、その外の12枚をリング2…と数え、100軒の枠をリングごとに配ります。 リングの中は中心から見た方位の順、同じ六角形の中は近い順です。
★この並べ方はブラウザ(JavaScript)とサーバ(Python)の両方に同じ算法で書いてあり、同じ入力で同じ並びになることをテストで確かめています。 片方だけ直して並びがずれる、ということを防ぐためです。
地図と場所 ── OpenStreetMap ほか
- 地図の絵: OpenStreetMap のタイルを、MapLibre GL JS で描きます
- 道路・交差点・目印: OpenStreetMap の日本のデータ(毎週取り直し)から、osmium で名前のある交差点・道路・施設を抜き出します。 お店のページの「最寄りの交差点」や、検索の候補の「目印」(ホテル・病院・公園…)になります
- まわりの場所: 同じデータから 公園・美術館・図書館・劇場・映画館・式場・美容院・宝飾店・習い事の教室 を抜き、 お店ごとにいちばん近い所までの距離を測ります。公園のような広い所は、真ん中ではなく敷地の端から測ります(中にあれば 0m)。 「こんな時に」の理由の「日比谷公園まで110m」はここから来ます。まだ載っていない場所は 地図に場所を足そう で呼びかけています
- 歩いた道のり: GraphHopper で、お店から駅までの徒歩の道のりを計算し、直線では近くても線路の向こう側、という駅を外します
- 海抜: 国土地理院の標高タイルから。天気は気象のデータの予報を、今週の営業時間の表に添えます
- 地図の中心の番地: 住居表示の辞書(jageocoder)で、地図の中心の住所を引きます
お店の情報 ── 毎晩の取り込み
- ホットペッパーグルメ Web サービスの API で、毎晩すべての掲載店(約14万軒)を取り直します。小エリアごとに100件ずつ引き、間を空けて問い合わせます
- 取り直した結果、項目が変わったお店は変更履歴に残し、お店のページの「最近変わったところ」に出します。元の値を書き換えることはしません
- 取り込みに2日続けて出てこなかったお店は「掲載終了の候補」とし、店舗ページと店名サーチ API で裏を取ってから終了の印を付けます。 取り込みから落ちただけで実は営業中、というお店(20軒に1軒ほどありました)に、終了の札を掛けないためです
- 掲載終了のお店では、写真・キャッチコピー・紹介文・クーポンを出しません。出してよい項目は「掲載中・掲載終了・削除」の3つの状態ごとに、1か所の表で決めています
AI の使い分け
AI は「用途ごとに向いているものを選び、任せる範囲を決めて」使っています。
| 紹介文 | gemma(運営者の機器の中で動く言語モデル)。ホットペッパーの項目から料理と雰囲気の文を書きます。 金額・時刻・人数・駅のような変わりやすい事実は書かせず、表と「この店のポイント」が毎日のデータから出します。 元の項目が変わった紹介文は、書き直すまで出しません |
|---|---|
| 写真 | Real-ESRGAN。掲載の写真(238px)を GPU で4倍に拡大します(1枚約2秒)。内容・構図・文字は変えません。 掲載が終わった時や写真が差し替わった時は、拡大した写しも消します |
| 掲載文の読み取り | Jev(TypeSafe)。キャッチやお店からのひとことのような自由記述から、「一人でも入りやすい」「ベビーカーで入れる」 「お通しなし」など10種類の事実を読みます。文は作らせず、選択肢で答えさせ、元の文を引用で添えます。確からしさの低い答えは使いません。 送るのはお店の掲載文だけで、見に来た方の入力は送りません |
| 使わないところ | 検索の欄に打った言葉、おすすめ度、そろい具合、場面の判定の決まりには AI を使いません(辞書・ルール・計算)。 試した別の AI(場面の分類)は、正しく分けられた割合が低かったので採用しませんでした |
おすすめ度
おすすめ度(★)は口コミの点数ではありません。立地 25%・価格 25%・営業努力 30%・2軒目 20% の4つの軸で、 近くの同じジャンルのお店の中での順位から決める目安です。比べる相手は半径2.5km ほど(20軒に足りなければ広げ、5軒に満たなければ★を出しません)。 上位3% が★5.0、いちばん下は★2.5 です。毎日、朝に計算し直します。出し方は 使い方 にすべて書いています。
「こんな時に」
お店のページの「こんな時に」は、お店の事実を先に読み、その組み合わせに場面の見出しを付ける作りです。
- 事実を札にする: 曜日ごとの営業の区切りと料理のラストオーダー(「残業後にも」=22時以降も料理を頼める)、平均予算、子ども連れの欄、 駅からの距離、席・個室・コース、Jev が読んだ事実、まわりの場所(公園のそば…)など
- 札の組み合わせで場面を決める: 例えば「幼稚園帰り、親子でほっと一息」は「カフェ」+「子ども連れOK」+「午後に開いている」。 札は7つの型(夕飯・昼ごはん・予定の前後に・子どもと・大人数・ひと休み・お酒とお祝い)に分かれていて、型をまたいで組み合わせられます
- 理由を事実で書く: カードの「このお店なら」には、条件になった事実をそのまま書きます(「L.O. 22:30まで・上野駅から約300m」)
場面は、基本の30と、暮らしの場面89(友人・デート・子ども・習い事・一人の時間・家族…)があります。地図の検索欄で場面の言葉を打つと、そのカードが出るお店に絞れます。
そろい具合と Lean による証明
カードの名前の横の「そろい具合 85%」は、この場面の条件とあるとよい事実が、そのお店の掲載情報でどれだけそろっているかです。 当たる確率ではありません。決まりは次のとおりです。
この決まりは、形式検証の道具 Lean 4 で書き、 どんな入力でも次の性質が破られないことを証明しています(証明に途中の省略や、勝手な前提はありません)。
- 無い条件の組があれば、あるとよい事実に関係なく、カードは出さない
- 条件の組が1つも無い決まりでは、カードを出さない(空っぽの条件で「そろっている」にしない)
- カードを出すかどうかは、あるとよい事実に左右されない
- 出すカードの点数は、必ず 70〜100%
- 条件付きのカードは、85% を超えない
- 「そろっている」なら、どの条件の組にもそろった事実がある
- あるとよい事実が増えても、点数は下がらない
theorem missing_group_hides (groups : List (List TagState)) (plus : List Bool)
(h : groups.any (fun g => groupRank g == 0) = true) :
status groups = .none ∧ fit groups plus = 0
サイトで実際に点数を計算しているのは Python です。そこで、Python の本番の計算と、Lean で証明した定義に同じ入力を3,000通り余り入れ、 すべて同じ答えになることを、公開のたびに確かめています(片方だけを変えると、この確かめで公開が止まります)。
保証の範囲: Lean が保証するのは「決まりの論理」です。掲載文の読み取りが正しいか、お店が本当にその場面に合うか、見に来た方が満足するかは、 証明では保証できません。それは の評価や、人の確認で見ていきます。
言葉で探す
地図の検索欄に「上野で残業後に一人で夕飯」のように打つと、場所・場面・人数・予算に分けて探します。分けるのは辞書と正規表現で、 AI は使いません。打った言葉を外の AI に渡さないためです。場所は駅・エリア・目印の索引で引き、「えびす」「ebisu」のような読みでも引けます (駅の読みは Wikidata、料理・地名の読みは Sudachi の辞書)。辞書を直すたびに、200問を超える例題で読み取りが崩れていないかを確かめています。
AI から使う道具(MCP)
Claude・ChatGPT・Gemini などの AI サービスから、このサイトの検索を道具として使えます(MCP: Model Context Protocol)。 場所・ジャンル・設備・いま営業中で探す、1軒の詳しい情報(おすすめ度・こんな時に・2軒目)、代わりのお店、店名で引く、 載っていないお店の目安、場面の評価、の7つの道具があります。写真・電話番号・紹介文の全文は返さず、どの答えにもクレジットと注意書きを付けます。 つなぎ方は 使い方 にあります。
品質の守り方
- 公開の前に必ず全部のテスト: 57層の自動テスト(Python・Deno+linkedom・本物の Chrome)を通らなければ、公開は止まります。 通った後は、公開中の URL を実際に叩く確かめ(煙テスト)を走らせます
- わざと壊して確かめる: 直した所を元に戻すとテストが落ちるかを、道具(break_check)で毎回確かめます。テストが本当に見張れているかの確認です
- 手元だけで通るテストを防ぐ: GitHub の CI と同じ条件(データベースや外のデータが無い・時刻が UTC)でも、公開の前に同じテストを走らせます
- 決まりの証明: そろい具合の決まりは Lean で証明し、本番の計算と照らし合わせます(上)
- 見張り: 毎晩・毎日の仕事が止まっていないか、地図のデータが古くなっていないかを見張り、止まればメールで知らせます
プライバシーと安全
- 会員登録はありません。名前・メールアドレス・電話番号はお預かりしていません。記録するもの・使い道・保存期間は プライバシーポリシー に書いています
- 見に来た方の入力を AI に渡しません。外の AI に送るのは、お店の掲載文だけです
- サイトはお店のデータを読むだけで、書き換えるのは夜の作り置きだけです。データベースの控えを毎日取っています
- 入口は1つ: サイトへの通り道は Cloudflare を経由する1本だけで、中の機械を直接外に出していません。運営者用の画面は認証の後ろにあります
- 攻撃への備え: 1つの接続元からの要求の数に上限を設け、怪しいアクセスは IP アドレスごとに見つけて止められるようにしています。 止める数値や仕組みの細部は、攻撃の手がかりになるので公開しません
この頁の内容は、仕組みが変わったら書き直します。お問い合わせは [email protected] まで。運営: 合同会社スターアニス