開かれた学術研究: 本プロジェクトは、LLMの観光情報生成能力を体系的に評価する、再現可能な実験システムです。すべてのコード、実験手順、ドキュメント、サンプルデータをCC BY 4.0ライセンスで公開しています。実験データは再現スクリプトにより生成可能です。
本研究は、大規模言語モデル(Large Language Model, LLM)の地域観光紹介における性能を体系的に比較評価するための実験システムです。異なるLLM、ペルソナ、旅行タイプの組み合わせによる64パターンの実験を通じて、各モデルの特性を定量的・定性的に分析します。
- 性能比較: 異なるLLMの観光情報生成能力の定量的評価
- ペルソナ影響: ペルソナ設定が出力内容に与える影響の分析
- ターゲット適応: ターゲット層(旅行タイプ)による応答特性の評価
- 再現性: 再現可能な実験環境の構築と共有
- ✅ 完全自動化: 64パターンの実験を自動実行
- ✅ 堅牢な設計: エラーハンドリング、リトライ、中断・再開機能
- ✅ データ分析支援: JSON/CSV出力、テキスト統計、類似度分析、感情分析
- ✅ 学術標準準拠: ISO 8601形式、CC BY 4.0ライセンス、完全なドキュメント
- ✅ 検証済み: 単体テスト、統合テスト、実環境での動作確認済み
# 1. リポジトリのクローン
git clone https://github.com/nshrhm/llm-tourism.git
cd llm-tourism
# 2. 仮想環境作成と依存関係インストール
python -m venv venv
source venv/bin/activate # Linux/Mac
pip install -r requirements.txt
# 3. 環境変数設定
cp .env.example .env
# .envファイルを編集してOPENROUTER_API_KEYを設定
# 4. 検証テスト(2パターンのみ)
python3 scripts/auto_test.py
# 5. 本実験実行(64パターン)
bash scripts/run_experiment.sh本システムは以下の環境で動作確認済みです。
- OS: Linux (WSL2), macOS, Windows
- Python: 3.10, 3.11, 3.12 ✓
- メモリ: 4GB以上推奨
- ストレージ: 500MB以上
| 項目 | 結果 | 詳細 |
|---|---|---|
| 単体テスト | ✅ 11/11合格 | APIクライアント、ヘルパー関数 |
| 統合テスト | ✅ 成功 | 4パターンの実験実行 |
| API接続 | ✅ 成功 | OpenRouter認証・レスポンス確認 |
| データ生成 | ✅ 成功 | JSON 4件、CSV 1件生成 |
| 成功率 | ✅ 100% | 4/4パターン成功 |
| 平均応答時間 | 6.5秒 | モデル: GPT-5.1 |
| 平均トークン数 | 592トークン | 範囲: 523-660 |
| 平均文字数 | 635文字 | 範囲: 563-709 |
openai/gpt-5.1-chat- OpenAI GPT-5.1anthropic/claude-sonnet-4.5- Anthropic Claude Sonnet 4.5google/gemini-2.5-flash- Google Gemini 2.5 Flashx-ai/grok-4-fast- xAI Grok-4 Fast
- 旅行代理店スタッフ: プロフェッショナルな旅行提案
- 旅行系YouTuber: エンターテイメント性の高い紹介
- 地方自治体職員: 地域活性化の視点
- SNSインフルエンサー: トレンドを意識した紹介
- 家族旅行: 子供連れの家族向け
- カップル旅行: ロマンチックな雰囲気重視
- 外国人観光客: 日本初訪問者向け
- シニア旅行: 60歳以上のシニア層向け
あなたは{ペルソナ}です。以下の指示に従って、必ず日本語で回答してください。
下関の観光名所を紹介してください。紹介相手は、{旅行タイプ}を計画しています。
1000文字程度で日本語で要約してください。
注: プロンプトには日本語出力を明示的に指定しています(英語出力問題の修正)
山口県下関市を研究対象地域として選定
選定理由:
- 歴史的観光地と自然景観の両方を有する
- 多様な観光資源(関門海峡、温泉、歴史遺産、ふぐグルメ)
- 国内外の観光客層の多様性
- 中規模都市として汎用性の高い知見が得られる
- Python: 3.10以上
- API: OpenRouter経由でLLMにアクセス
- メモリ: 4GB以上推奨
- ストレージ: 実験データ用に500MB以上
requests: API通信pandas: データ処理と分析pyyaml: 設定ファイル管理python-dotenv: 環境変数管理tqdm: プログレスバー表示pytest: 単体テスト
sentence-transformers: テキスト類似度分析transformers: 感情分析(日本語BERT)scikit-learn: 統計分析・クラスタリング
git clone https://github.com/nshrhm/llm-tourism.git
cd llm-tourismpython -m venv venv
source venv/bin/activate # Linux/Mac
# または
venv\Scripts\activate # Windowspip install -r requirements.txtcp .env.example .env
# .envファイルを編集してOpenRouter APIキーを設定OpenRouter APIキーの取得方法:
- OpenRouterにアクセス
- アカウント作成・ログイン
- API Keysページでキーを生成
.envファイルのOPENROUTER_API_KEYに設定
# .envファイルの例
OPENROUTER_API_KEY=sk-or-v1-xxxxxxxxxxxxxxxxxxconfig/experiment_config.yaml で実験パラメータを確認・調整できます。
bash scripts/run_experiment.shこのスクリプトは以下を自動実行します。
- 環境チェック
- 実験実行(64パターン)
- データ変換(JSON→CSV)
- 統計サマリー生成
- 完了レポート表示
# 実験の実行
python -m src.experiment_runner
# データの変換(JSON→CSV)
python -m src.data_converter# 2パターンのみで動作確認
python3 scripts/auto_test.py# プロンプト生成のテスト
from src.prompt_generator import PromptGenerator
generator = PromptGenerator()
prompts = generator.generate_all_prompts()
print(f"生成されたプロンプト数: {len(prompts)}")
# APIクライアントのテスト
from src.api_client import OpenRouterClient
client = OpenRouterClient()
response = client.generate(
model="openai/gpt-5.1-chat",
prompt="下関の観光名所を紹介してください",
max_tokens=100
)
print(response['response'])実験を実行する前に、サンプルデータで構造を確認できます。
- 📁
data/examples/- 4モデルのサンプル(JSON形式) - 📄
data/examples/sample_results.csv- サンプルデータ(CSV形式) - 📖
data/examples/README.md- サンプルデータの詳細説明
保存先: data/raw/(実験実行後に生成)
{
"session_id": "session_20250121_143022",
"experiment_id": "exp_000",
"timestamp": "2025-11-21T14:30:22.123456+09:00",
"model": {
"name": "openai/gpt-5.1-chat",
"display_name": "OpenAI GPT-5.1"
},
"persona": {
"id": "travel_agent",
"name": "旅行代理店スタッフ"
},
"travel_type": {
"id": "family",
"name": "家族旅行"
},
"prompt": "あなたは旅行代理店スタッフです...",
"response": "下関は山口県の西端に位置し...",
"performance": {
"tokens_used": 660,
"latency_ms": 6792
},
"metadata": { ... },
"api_parameters": { ... }
}保存先: data/processed/experiment_results.csv
カラム構成:
| カラム名 | データ型 | 説明 |
|---|---|---|
session_id |
string | セッション識別子 |
experiment_id |
string | 実験識別子 |
timestamp |
datetime | 実行日時(ISO 8601) |
model |
string | モデル名 |
model_display_name |
string | モデル表示名 |
persona_id |
string | ペルソナID |
persona_name |
string | ペルソナ名 |
travel_type_id |
string | 旅行タイプID |
travel_type_name |
string | 旅行タイプ名 |
prompt |
text | 入力プロンプト |
response |
text | 生成テキスト |
tokens_used |
integer | 使用トークン数 |
latency_ms |
integer | 応答時間(ミリ秒) |
response_char_count |
integer | 文字数 |
response_word_count |
integer | 単語数(推定) |
response_line_count |
integer | 行数 |
prompt_char_count |
integer | プロンプト文字数 |
実験を実行せずにデータ構造や分析例を確認できるサンプルデータを提供しています。
import json
import pandas as pd
# JSONサンプル(4モデルから1つずつ)
with open('data/examples/exp_000_gpt5_sample.json', 'r', encoding='utf-8') as f:
sample = json.load(f)
print(f"モデル: {sample['model']['display_name']}")
print(f"文字数: {len(sample['response'])}")
# CSVサンプル
df = pd.read_csv('data/examples/sample_results.csv')
print(df[['model_display_name', 'response_char_count', 'tokens_used']])詳細は data/examples/README.md をご覧ください。
================================================================================
LLM地域観光紹介性能比較実験 - 自動検証テスト
================================================================================
【ステップ1】プロンプト生成器の初期化
✓ 64個のプロンプトを生成
✓ テスト用に4パターンを選択
【ステップ2】APIクライアントの初期化
✓ APIクライアント初期化成功
【ステップ3】実験実行(自動モード)
実験実行中: 100%|██████████| 4/4 [00:32<00:00, 8.06s/実験, 成功=4, 失敗=0]
【実験結果】
- 成功: 4件
- 失敗: 0件
- 実行時間: 32.3秒
【ステップ4】データ変換
✓ データ変換完了
- レコード数: 4
- 出力ファイル: data/processed/experiment_results.csv
✓ すべてのコンポーネントが正常に動作しています!
条件: 旅行代理店スタッフ × 外国人観光客(日本初訪問)
山口県の最西端に位置する下関は、日本の歴史と海の魅力が凝縮された港町で、
初めて日本を訪れる外国人旅行者にも訪れやすい場所です。市の象徴ともいえる
関門海峡は、本州と九州を隔てる重要な水路で、潮の流れが速く迫力があります。
海峡沿いには散策路が整備され、行き交う船や対岸の門司港レトロ地区を眺めな
がら散歩が楽しめます。徒歩で海峡を渡れる関門トンネル人道もユニークな体験
として人気です...
(文字数: 601、トークン: 545、応答時間: 5.6秒)
llm-tourism/
├── README.md # 本ファイル
├── LICENSE # CC BY 4.0ライセンス
├── CITATION.cff # 引用情報(BibTeX等)
├── CONTRIBUTING.md # 貢献ガイドライン
├── CHANGELOG.md # 変更履歴
├── .gitignore # Git除外設定
├── .env.example # 環境変数テンプレート
├── requirements.txt # Python依存関係
├── pytest.ini # テスト設定
├── config/
│ └── experiment_config.yaml # 実験設定
├── src/
│ ├── __init__.py
│ ├── api_client.py # OpenRouter APIクライアント
│ ├── prompt_generator.py # プロンプト生成器
│ ├── experiment_runner.py # 実験実行エンジン
│ └── data_converter.py # データ変換ツール
├── data/
│ ├── examples/ # サンプルデータ(4モデル)
│ ├── raw/ # JSON生データ(実験実行後に生成)
│ ├── processed/ # CSV処理済みデータ(実験実行後に生成)
│ └── archive/ # アーカイブデータ
├── docs/
│ ├── methodology.md # 実験方法論(学術論文スタイル)
│ ├── results.md # 結果報告テンプレート
│ ├── manual.md # データ分析マニュアル
│ └── diagrams/
│ ├── system_flow.mermaid # システムフロー図
│ └── architecture.drawio # アーキテクチャ図
├── scripts/
│ ├── run_experiment.sh # 自動実行スクリプト
│ ├── auto_test.py # 検証テストスクリプト
│ └── debug_api.py # API接続デバッグ
└── tests/
└── test_api_client.py # 単体テスト
import pandas as pd
# データ読み込み
df = pd.read_csv('data/processed/experiment_results.csv')
# モデル別の基礎統計
model_stats = df.groupby('model').agg({
'response_char_count': ['mean', 'std', 'min', 'max'],
'tokens_used': ['mean', 'std'],
'latency_ms': ['mean', 'std']
}).round(2)
print(model_stats)from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
# モデルのロード
model = SentenceTransformer('paraphrase-multilingual-mpnet-base-v2')
# 埋め込みベクトル生成
embeddings = model.encode(df['response'].tolist())
# コサイン類似度計算
similarity_matrix = cosine_similarity(embeddings)from transformers import AutoTokenizer, AutoModelForSequenceClassification
# 日本語BERTモデルのロード
model_name = "daigo/bert-base-japanese-sentiment"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(model_name)
# 感情スコア計算
# 詳細はdocs/manual.mdを参照詳細な分析手法はdocs/manual.mdを参照してください。
- ✅ APIキーは絶対にコミットしない(
.gitignoreで保護) - ✅ 実験データの取り扱いは研究倫理規定に準拠
- ✅ 生成されたテキストの著作権はLLM提供者の利用規約に従う
- ✅ 個人情報を含むプロンプトの使用禁止
- ✅ すべてのデータとコードをCC BY 4.0で公開(オープンサイエンス)
本研究では以下の情報を記録し、完全な再現性を確保しています。
- 実験パラメータ: YAML設定ファイルで明示的に管理
- 実行日時: ISO 8601形式、タイムゾーン付き
- モデルバージョン: APIレスポンスから取得
- システム環境: Python version、ライブラリバージョン(
requirements.txt) - 乱数シード: 該当する場合は固定値を使用
Error: OpenRouter API key not found
解決方法:
.envファイルが存在するか確認OPENROUTER_API_KEYが正しく設定されているか確認- APIキーが
sk-or-v1-で始まっているか確認
Error: 401 Client Error: Unauthorized
解決方法:
- APIキーが有効か確認(OpenRouter Keys)
- アカウントにクレジットがあるか確認
- 新しいAPIキーを生成して
.envを更新
解決方法:
config/experiment_config.yamlでrequest_delayを増やしてください。
api:
request_delay: 5 # 2秒 → 5秒に変更解決方法:
data/raw/とdata/processed/ディレクトリの書き込み権限を確認- ディスク容量を確認(500MB以上推奨)
解決方法:
# pipをアップグレード
pip install --upgrade pip
# 個別にインストール
pip install requests pandas pyyaml python-dotenv tqdm
# PyTorchのインストール(感情分析を使用する場合)
pip install torch --index-url https://download.pytorch.org/whl/cpu# API接続テスト
python3 scripts/debug_api.py
# 単体テスト実行
pytest tests/ -v本研究への貢献を歓迎します!詳細はCONTRIBUTING.mdを参照してください。
- Issuesでバグ報告・機能提案
- Pull Requestで改善提案
- 実験結果の共有
- ドキュメントの改善
- 新しい分析手法の追加
本研究を引用する場合は、以下の形式を推奨します。
@software{llm_tourism_2025,
author = {白濵 成希},
title = {LLM地域観光紹介性能比較実験システム},
year = {2025},
url = {https://github.com/nshrhm/llm-tourism},
license = {CC-BY-4.0}
}詳細はCITATION.cffを参照してください。
本プロジェクトは Creative Commons Attribution 4.0 International (CC BY 4.0) ライセンスの下で公開されています。
- ✅ 実験システム(コード): CC BY 4.0
- ✅ 実験データ: CC BY 4.0
- ✅ ドキュメント: CC BY 4.0
詳細はLICENSEファイルを参照してください。
研究に関する問い合わせ:
- GitHub Issues: リポジトリのIssues
- Email: [nshirahama@ieee.org]
- OpenRouter API Documentation: https://openrouter.ai/docs
- 観光情報学研究:
docs/methodology.mdに記載 - テキストマイニング手法:
docs/manual.mdに記載
詳細はCHANGELOG.mdを参照してください。
- 2025-11-21: プロジェクト初版リリース
- Phase 1-5完了: 基盤構築、コアシステム、データ処理、ドキュメント、品質保証
- 検証テスト実施(4パターン、成功率100%)
- 単体テスト11件合格
オープンサイエンス: すべてのコード、データ、ドキュメントをCC BY 4.0ライセンスで公開し、学術コミュニティへの貢献を目指しています。