ESP32-S3 Bench Guide
ESP32‑S3 N16R8 벤치 가이드: 실시간 핀아웃, 강의, 시뮬레이터 및 벤치 로그
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
留学を検討している日本語ユーザー向けの、AIカウンセリング・チャットボットです。 単なるFAQボットではなく、対話を通じてユーザーの目的・潜在ニーズを引き出し、構造化された「カルテ」を裏で自動生成します。 詳細仕様は docs/SPEC.md を参照してください。 .env.example を .env.local にコピーし、Anthropic Console で発行したAPIキーを設定してください。 .env.local は .gitignore 対象です。本物のAPIキーは .env.local にのみ書き、.env.example には絶対に書かないでください。 • チャット単体の画面: http://localhost:3000/widget • トップページ(/)は現時点ではプレースホルダーです。 開発モード(NODE_ENV !== "production")では、チャット画面内に「開発用: カルテを表示」という折りたたみパネルが表示され、裏で更新されているカルテ(構造化データ)の中身をリアルタイムに確認できます。README 전문 보기 ↗
留学を検討している日本語ユーザー向けの、AIカウンセリング・チャットボットです。 単なるFAQボットではなく、対話を通じてユーザーの目的・潜在ニーズを引き出し、構造化された「カルテ」を裏で自動生成します。
詳細仕様は docs/SPEC.md を参照してください。
@anthropic-ai/sdk)npm install
.env.example を .env.local にコピーし、Anthropic Console で発行したAPIキーを設定してください。
cp .env.example .env.local
# .env.local
ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxxxxxxxxxx
# 使用モデル(任意。未指定なら既定で claude-opus-4-8 を使用)
ANTHROPIC_MODEL=
.env.local は .gitignore 対象です。本物のAPIキーは .env.local にのみ書き、.env.example には絶対に書かないでください。
npm run dev
/)は現時点ではプレースホルダーです。開発モード(NODE_ENV !== "production")では、チャット画面内に「開発用: カルテを表示」という折りたたみパネルが表示され、裏で更新されているカルテ(構造化データ)の中身をリアルタイムに確認できます。
/app
page.tsx … トップページ(プレースホルダー、規約リンクあり)
/widget/page.tsx … 埋め込み用チャット画面(本体)
/terms/page.tsx … 利用規約
/privacy/page.tsx … プライバシーポリシー
/api/chat/route.ts … Anthropicへのストリーミング応答
/api/karte/route.ts … カルテ(構造化データ)の差分抽出
/api/places/details/route.ts … Place Details (New) のサーバー側プロキシ(結果は保存しない)
/api/places/nearby/route.ts … Nearby Search (New) のサーバー側プロキシ(結果は保存しない)
/api/places/photo/route.ts … Place Photo (New) のサーバー側プロキシ(画像は保存しない)
/components
Chat.tsx … チャット本体(ストリーミング表示・送信中表示・エラー処理)
Message.tsx … 発言バブル
KarteSummary.tsx … 会話の区切りで表示するカルテ要約・確認UI
KarteDebugPanel.tsx … 開発用のカルテ生データ表示パネル
EmbedCloseButton.tsx … 埋め込み(iframe)時のみ表示される閉じるボタン
GoogleAttribution.tsx … Google Places/Maps 利用時の帰属表示(共通)
PlaceRatingBadge.tsx … 評価点+件数+Googleマップへのリンクのみの口コミ表示
SchoolMap.tsx … Maps JavaScript APIでの地図表示
AddressAutocomplete.tsx … Autocomplete (New) を使った住所入力補完
/lib
anthropic.ts … Anthropicクライアント初期化・モデル設定
prompt.ts … システムプロンプト・update_karteツール定義
karte.ts … カルテの型・差分マージ
chat.ts … チャットメッセージの型・共通バリデーション
knowledge.ts … 知識ベース本文の生成(data/cities.ts から文章を組み立てる。数値は直書きしない)
googlePlaces.ts … サーバー側 Places API 共有ヘルパー(サーバー専用キーのみ使用)
googleMapsBrowserLoader.ts … ブラウザ側 Maps JS API 共有ローダー(ブラウザ用キーのみ使用)
data/cities.ts … 都市別 生活費データ(構造化データの唯一の出所)
data/schools.ts … 学校データ(country/city/name/address + placeId等。Places本文は持たない)
/scripts
resolve-place-ids.ts … 【開発時ローカル実行専用】schools.ts の name+address から
placeId/lat/lngを解決し書き戻す。DB・Admin APIは無い。
/public
embed.js … HP設置用ローダースクリプト
/embed-test
index.html … 埋め込み動作確認用の簡易HTML(別ドメイン想定)
システムプロンプトに埋め込まれる都市別の生活費(家賃・食費・交通費など)は、lib/data/cities.ts が唯一の数値の出所です。lib/knowledge.ts はこのデータから説明文を生成するだけで、数値を直書きしません。
lib/data/cities.ts の該当レコード(AUSTRALIA_CITIES の1要素)を編集する。source / sourceUrl を実際に数値を取得した出所に更新する。fetchedAt(取得日)を更新する。confidence: "official"、そこに到達できず二次情報源に頼った場合は confidence: "secondary" とし、notes にその旨を書く。secondary のレコードは次回更新時に一次情報での再確認を優先すること。DBは使わず、このファイルへの直接編集のみで完結する(このリポジトリにDBは無い)。
Numbeo のデータは、スクレイピングはもちろん、手入力で転記した数値であっても使用しないこと。 Numbeo は利用規約上、データの商用利用をデータライセンス契約者に限定しており、この制限は「手入力かどうか」とは関係なく、値そのものに対してかかる。このボットは商用サービスであるため、Numbeo由来の数値を使うと利用規約違反になる。
数値を入力してよい出所は次のいずれかのみ:
これはコードでは強制できないため、データを追加・更新する人が上記ルールを守る運用上の約束事とする。
例外は開発・検証専用の snapshot だけ: 上記の禁止は「ユーザーに届くデータ」に対するもの。回答品質の確認のために、人間がブラウザで一度確認した数値を開発環境でのみ参照する経路だけは、下記「開発・検証専用の都市指数 snapshot」の条件下で認める。production で使うには (b) のライセンス確認が必要で、「一度手入力したから production でも使える」とは扱わない。
Chat が「シドニーって安全?」「メルボルンの生活費は高い?」のように都市について聞かれたときだけ参照する、人間が出典を確認して蓄積する都市情報のレイヤー。将来の I'm ready! Guide / City Guide でも同じデータを使う。
city_reference_data(1都市 × 1カテゴリ = 1行)+ city_reference_sources(1行に複数の出典)。カテゴリは safety / housing / food / transport / utilities / everyday。reviewed_at(こちらが最後に人間で確認した日)は必須。出典側の更新日が分からなければ null のままにする(不明な日付を作らない)。details.estimates へ分けて持ち、複数の出典を平均しない。lib/cityReference.ts の isSafetyComparable)。data/cities/australia/_template.json をコピーして data/cities/australia/<city>.json を作る(_ 始まりのファイルは取り込み対象外)。estimates・sources・reviewed_at を記入する。未確認のまま推測で埋めない(確認できていない都市は未登録のままでよい)。npx tsx scripts/import-city-reference-data.ts を実行する。検証に通った entry だけの SQL が supabase/seed/city_reference_data.generated.sql に出る(テンプレートの未記入文・出典なしの entry は自動で除外される)。読み取りは sanitized view(city_reference_public / city_reference_sources_public)だけを公開経路にしている。base table は anon / authenticated から一切読めず、内部メモ(review_note)は view に含めない。
Chat が「学生ビザで何時間働ける?」「セカンドってどう取るの?」のように聞かれたときだけ参照する、人間が公式情報を確認して蓄積するビザ情報のレイヤー。
visa_reference_data(1ビザ × 1カテゴリ = 1行)+ visa_reference_sources(1行に複数の出典)。migration は supabase/migrations/20261001_visa_reference_data.sql。eligibility / stay / study_rights / work_rights / same_employer / application / documents / costs / processing / second_third / specified_work / health_insurance / financial_capacity / genuine_student / arrival_preparationreviewed_at は 必須。ビザは変動性が高いため、6ヶ月を超えると Chat に「再確認推奨」が付く(自動削除はしない)。details に単位つきで持つ(limit には unit、amount には currency、duration には durationUnit)。単位の無い数値・通貨の無い金額は importer が弾く。summary の文章から数値を推測させないための仕組み。visa_reference_public / visa_reference_sources_public)だけ。base table は anon / authenticated から一切読めず、内部メモ(review_note / 出典の notes)は view に含めない。visa_key にサブクラスまで含め、同じ entry にまとめない。data/visas/australia/_template.json をコピーして data/visas/australia/<visa>.json を作る(_ 始まりは取り込み対象外)。summary・details・sources・reviewedAt を記入する。確認できていない項目は entry を作らない(または details.unverified に記録する)。npx tsx scripts/import-visa-reference-data.ts を実行する。検証を通った entry だけの SQL が supabase/seed/visa_reference_data.generated.sql に出る。一次情報は Department of Home Affairs です。以下を開いて、確認できた項目だけを登録してください。
Student visa (subclass 500) — eligibility / application(CoE 等)/ health_insurance(OSHC)/ genuine_student / work_rights(単位は fortnight のまま)/ study_rights / stay / costs(「from」表記を保持)/ financial_capacity(適用開始日も)/ documents / processing(確定日数として書かない)
Working Holiday visa (subclass 417) — eligibility(対象パスポートに日本が含まれるか・年齢)/ stay / work_rights / same_employer(制限と例外の具体条件)/ study_rights / application / documents / costs / second_third / specified_work(必要期間・対象業種・対象地域・必要な証拠)/ processing
現状、Student 500 は Study Australia で確認できた6カテゴリのみ登録済み(一次情報での照合は未了)。417 は1件も未登録で、Chat は数値を推測せず「確認できていない」と答えます。
Numbeo snapshot is development/evaluation only. Do not deploy or use in production without confirming an appropriate Numbeo licence.
この snapshot は開発・検証専用。適切な Numbeo のライセンスを確認しないまま production へ載せたり、production で使用したりしてはいけない。
Chat が都市の治安・生活費を聞かれたときの回答品質を確認するためだけに、人間がブラウザで一度確認した指数を開発環境で参照できる経路。正式なデータ源は上記の公的情報ベース(city_reference_data)で、この snapshot はそれを置き換えも上書きもしない。
| 層 | 実体 |
|---|---|
| 入力 | data/dev/numbeo/australia.json(人間が手入力。初期値はすべて null) |
| 読み取り | lib/devCitySnapshot.ts(サーバー専用。JSON を static import せず実行時に読む) |
| SQL 生成 | scripts/generate-dev-city-snapshot-sql.ts → supabase/seed/dev_city_snapshot.generated.sql |
| DB | dev_snapshot スキーマ(public ではないので PostgREST の API から到達できない)。migration には入れない |
production ガードは二重。NODE_ENV === "production" なら環境変数に関わらず無効で、そのうえで CITY_REFERENCE_DEV_SNAPSHOT=true の明示指定が必要(既定は OFF)。さらにアプリは dev 用 table を SELECT しないため、production のコード上に snapshot へ到達する経路が存在しない。
Numbeo のページを開いて、以下だけを目で確認して手入力する。ページ上に無い項目・読めない項目は null のままにする(0 で埋めない、推測しない)。
| 区分 | 記入欄 |
|---|---|
| Safety | safetyIndex / crimeIndex / safetyWalkingAloneDaylight / safetyWalkingAloneNight |
| Cost | costOfLivingIndex / rentIndex / groceriesIndex / restaurantPriceIndex |
| メタデータ | sourceUrls.safety(治安のページ)/ sourceUrls.costOfLiving(生活費のページ)/ capturedAt(確認した日 YYYY-MM-DD) |
対象は既存6都市(sydney / melbourne / brisbane / goldcoast / cairns / perth)のみ。ページ上の項目名が上記と対応しない場合は、その項目を空のままにして報告する。
数値を入れた区分には、その区分の出典 URL が必要(治安の数値があるなら sourceUrls.safety、生活費の数値があるなら sourceUrls.costOfLiving)。不足していると SQL 生成時に警告が出る。数値を入れていない区分の URL は求めない。
data/dev/numbeo/australia.json に手入力するsourceUrls に記録する(治安の数値は safety、生活費の数値は costOfLiving。Numbeo では治安と生活費が別ページのため用途別に持つ)capturedAt に記録するnpx tsx scripts/generate-dev-city-snapshot-sql.ts で SQL を生成するCITY_REFERENCE_DEV_SNAPSHOT=true npm run dev で Chat の回答を確認するChat 側の優先順位は、production が「公的情報 → 無ければ『確認済み情報なし』」、開発時にフラグ ON のときだけ「公的情報 → snapshot → 情報なし」。公的情報がある項目では snapshot は使われない。
Google Places のコンテンツ(学校名・評価・評価数・写真・周辺情報・営業時間など)は、DBにもファイルにも保存・キャッシュしない。 保存してよいのは placeId(と、地図表示に使う場合のみ座標)だけで、それ以外の本文は表示のたびに実行時にPlaces APIから取得する。このリポジトリにDBは無いため、placeId は lib/data/schools.ts の構造化データに持たせている。
lib/data/schools.ts: 学校ごとの country / city / name / address / placeId? / lat? / lng? / placeIdRefreshedAt?。ホームステイ型(教師の自宅に滞在するスタイル)等、固定キャンパスが無い学校は address を持たず、placeId 解決の対象外とする。scripts/resolve-place-ids.ts(開発時にローカル実行するスクリプトのみ。管理APIやDBは無い): schools.ts の name + address を Places API (New) Text Search で解決し、placeId / lat / lng / placeIdRefreshedAt を schools.ts に書き戻す。placeIdRefreshedAt が12か月を超えた、または未設定のレコードのみが対象。
GOOGLE_MAPS_SERVER_KEY=xxx npm run resolve-place-ids -- --dry-run
GOOGLE_MAPS_SERVER_KEY=xxx npm run resolve-place-ids
app/api/places/*): 提案フェーズ(学校を提示する瞬間)でのみ呼ぶ想定で、毎メッセージでは呼ばない。結果は一切保存しない。
GET /api/places/details?placeId=... … Place Details (New)。fieldMask は displayName, rating, userRatingCount, googleMapsUri, location, regularOpeningHours, photos のみ。reviews は含めない。POST /api/places/nearby … Nearby Search (New)。学校の lat/lng を中心に、category(shop / transit / activity)で周辺情報を出し分け。GET /api/places/photo?name=... … Place Photo (New)。画像は保存せず、Googleが発行する一時URLへリダイレクトするだけ(サーバーキーはクライアントに渡らない)。components/):
AddressAutocomplete.tsx … Autocomplete (New)(PlaceAutocompleteElement)。ブラウザ用キー(リファラ制限)+ セッショントークンで課金。SchoolMap.tsx … Maps JavaScript APIで地図を描画。Places結果を地図に重ねる場合は必ずこの地図上に表示すること。PlaceRatingBadge.tsx … 口コミは評価点+件数+Googleマップへのリンクのみ表示(例「★4.3(1,240件)」→タップでGoogleマップ)。レビュー本文は扱わない。GoogleAttribution.tsx … 地図あり/なしに応じた帰属表示の共通コンポーネント。placeId(と使う場合のみ座標)のみ。GOOGLE_MAPS_SERVER_KEY(サーバー専用): scripts/resolve-place-ids.ts と app/api/places/* からのみ使用。クライアントに渡さない。IP制限等を推奨。NEXT_PUBLIC_GOOGLE_MAPS_BROWSER_KEY(ブラウザ用): AddressAutocomplete / SchoolMap(Maps JavaScript API / Autocomplete)からのみ使用。必ずHTTPリファラ制限をかけること。このボットは、留学エージェントや語学学校のHPに scriptタグ1行 で設置できるウィジェットとして作られています。
設置したいHPの <body> 内に、以下の1行を追加するだけです。
<script src="https://<デプロイ先のドメイン>/embed.js" data-key="TENANT_KEY" async></script>
src には、このアプリをデプロイしたドメインの /embed.js を指定します。data-key には、設置元(エージェント・学校)を識別するための任意の文字列を指定します(将来のマルチテナント対応の土台。現時点では値を保持するのみです)。設置すると、ページ右下にチャット起動ボタンが表示されます。クリックすると /widget を読み込んだチャットパネルが開閉します。
npm run dev で開発サーバーを起動した状態で、embed-test/index.html をブラウザで直接開いてください(file:// で開いてOKです)。このファイルはNext.jsアプリの外にある、別ドメインのHPを想定した簡易HTMLです。
<!-- embed-test/index.html 内 -->
<script src="http://localhost:3000/embed.js" data-key="test-agent-001" async></script>
右下にチャット起動ボタンが表示されれば、埋め込みは成功しています。
/widget は他ドメインからのiframe埋め込みを前提に Content-Security-Policy: frame-ancestors *; を付与しています(next.config.ts)。本番運用時は、許可するホスト名を列挙するなど絞り込みを検討してください。postMessage で最小限の通信(開閉)を行っています。