Tree-of-Thought探索アルゴリズムのプロンプト設計と評価

Tech

本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。

Tree-of-Thought探索アルゴリズムのプロンプト設計と評価

1. ユースケース定義

Tree-of-Thought (ToT) 探索アルゴリズムは、大規模言語モデル (LLM) が複雑な問題解決を行う際に、複数の推論パスを探索し、中間ステップでの意思決定を伴うようなシナリオで特に有効です。Chain-of-Thought (CoT) が線形な推論ステップに限定されるのに対し、ToTは思考をツリー構造で管理し、探索アルゴリズム(BFS, DFS, A*など)を用いて最も有望なパスを選択します[1]。

適用シナリオの例:

  • 多段階の論理パズル: 各ステップで複数の選択肢があり、それぞれの選択がその後の展開に影響を与える問題(例: Game of 24、難解な推理問題)。

  • 創造的なテキスト生成: 複数のアイデア分岐から最も有望なものを選択し、ストーリーや詩を構築する。

  • 複雑なコード生成: 特定の機能を実現するために複数のアプローチを検討し、各アプローチのメリット・デメリットを評価しながら最適なコードパスを選択する。

  • 戦略ゲームのプランニング: 複数の行動選択肢から、特定の目的を達成するための最適な一連の行動を計画する。

2. 制約付き仕様化と入出力契約

ToTプロンプト設計と評価のプロセス全体における入出力契約を定義します。

2.1. 入力契約

  • フォーマット: JSONまたは構造化されたテキスト

    {
      "problem_description": "string",  // 解決すべき問題の明確な記述
      "constraints": ["string"],        // 問題に関する追加の制約(例: 使用可能な演算子、文字数制限)
      "example_outputs": ["string"],    // (オプション) 期待される出力の例(少数例プロンプト用)
      "max_thoughts_per_step": "integer", // 各ステップで生成する思考の最大数 (幅)
      "max_steps": "integer",            // 探索の最大深さ
      "evaluation_criteria": "string"   // 思考を評価するための基準
    }
    
  • 失敗時の挙動:

    • 入力フォーマットが不正な場合、エラーメッセージを返して処理を中断します。

    • 必須フィールドが欠落している場合、エラーメッセージを返して処理を中断します。

  • 禁止事項:

    • 個人情報、機密情報、著作権侵害コンテンツの直接的な入力は禁止します。

    • 違法行為、ハラスメント、ヘイトスピーチを誘発するような問題記述は禁止します。

2.2. 出力契約

  • フォーマット: JSONまたは構造化されたテキスト

    {
      "final_solution": "string",       // 問題に対する最終的な解決策
      "solution_path": [                // 探索された思考パス(オプション)
        {
          "step": "integer",            // ステップ番号
          "thought": "string",          // そのステップでの主要な思考
          "evaluation_score": "float",  // 思考の評価スコア
          "rationale": "string"         // 評価の根拠
        }
      ],
      "status": "string",               // "success", "failure", "partial_solution"
      "message": "string"               // 補足情報またはエラーメッセージ
    }
    
  • 失敗時の挙動:

    • 指定された探索回数以内に有効な解が見つからない場合、statusを”failure”とし、messageにその旨を記述します。

    • 部分的な解決策が見つかった場合は、statusを”partial_solution”とし、final_solutionにその内容を記述します。

  • 禁止事項:

    • 入力契約の禁止事項に該当する内容の生成は禁止します。

    • 根拠のない情報(幻覚)の生成は禁止します。

3. プロンプト設計

ToTの特性を最大限に引き出すため、異なるプロンプト設計アプローチを検討します。各プロンプトは、問題解決の思考プロセスをツリー状に展開し、各ステップで思考の生成、評価、選択を促すように構成されます[4]。

3.1. ゼロショットプロンプト

モデルにToTの概念を直接指示し、構造化された思考プロセスを促します。

あなたは複雑な問題解決を支援するAIです。
以下の手順に従って、与えられた問題を解決してください。

1.  **問題分析**: 問題を理解し、主要な要素と制約を特定します。

2.  **思考の生成 (Generate Thoughts)**: 現在の状況から考えられる次の行動、アイデア、推論ステップを複数(最大3つ)生成します。それぞれの思考は短く、具体的な提案である必要があります。

3.  **思考の評価 (Evaluate Thoughts)**: 生成された各思考について、問題解決への貢献度、実現可能性、有効性を0から1のスコアで評価し、その根拠を簡潔に説明します。

4.  **思考の選択 (Select Thought)**: 最もスコアの高い思考を一つ選択し、次のステップの基盤とします。

5.  **思考の継続**: 選択した思考に基づいて、上記2-4を繰り返します。適切な解決策に到達するか、または指定された最大ステップ数に達するまで繰り返します。

6.  **最終回答**: 全てのステップを完了した後、最終的な解決策と、その導出過程を簡潔にまとめてください。

---
[問題]
数字 {2, 3, 5, 8} を一度ずつ使用し、四則演算(+, -, *, /)を用いて「24」を作る方法を一つ見つけてください。カッコの使用は自由です。
---

根拠: 複雑な問題解決にToTのフレームワークを適用する一般的なアプローチを提示しています[1][4]。

3.2. 少数例プロンプト

簡単な問題をいくつか例示することで、モデルがToTのプロセスを学習し、より効果的に適用できるようにします。

あなたは複雑な問題解決を支援するAIです。
提供された例を参考に、以下の手順で問題を解決してください。

**例1: Game of 24**
[問題] 数字 {1, 2, 3, 4} を一度ずつ使用し、四則演算(+, -, *, /)を用いて「24」を作る方法を一つ見つけてください。カッコの使用は自由です。
[思考プロセス]

1.  **問題分析**: 数字 {1, 2, 3, 4}、目標 24。四則演算、各数字一度ずつ使用。

2.  **思考の生成と評価**:

    *   思考A (目標に近い積を探す): 4 * 3 = 12。残りの数字 {1, 2} で12を作ることを検討。

        *   12 / 2 = 6。残りの1で6は作れない。

        *   (1+2)*? は 3 * ? = 12 なので 4。既に4は使っている。

        *   **評価スコア**: 0.6 (まだ可能性はある)

    *   思考B (合計から積を作る): (1 + 2 + 3) = 6。残りの数字 {4} で24を作ることを検討。

        *   6 * 4 = 24。(成功!)

        *   **評価スコア**: 1.0 (明確な解が見つかった)

    *   思考C (他の組み合わせ): 4 * 2 = 8。残りの数字 {1, 3} で16を作ることを検討。

        *   3 * ? = 16 は無理。

        *   (1+3) * ? = 4 * ? = 16 なので 4。既に4は使っている。

        *   **評価スコア**: 0.4 (難易度が高い)

3.  **最適な思考の選択**: 思考Bが最も有望。

4.  **最終回答**: 4 * (1 + 2 + 3) = 24

**例2: ロジックパズル**
[問題] 3つのボックスA, B, Cがあります。
ボックスAのステートメント: 「このボックスには金貨がない」
ボックスBのステートメント: 「このボックスには銀貨がある」
ボックスCのステートメント: 「ボックスBには金貨がある」
ただし、これらのステートメントのうち、**ちょうど1つだけが真実**です。どのボックスに金貨と銀貨があるか特定してください。

[思考プロセス]

1.  **問題分析**: 3つのボックス(A,B,C)と3つのステートメント。制約は「ちょうど1つだけが真実」。金貨と銀貨がそれぞれ1枚ずつあると仮定。

2.  **思考の生成と評価**:

    *   **思考A: ボックスAのステートメントが真実と仮定**

        *   A:金貨なし (真)

        *   B:銀貨あり (偽) => Bに銀貨なし

        *   C:Bに金貨あり (偽) => Bに金貨なし

        *   矛盾の確認: Aに金貨なし、Bに金貨なし => Cに金貨。Bに銀貨なし。他の場所(AまたはC)に銀貨があるはず。矛盾なし。

        *   **仮説からの結果**: 金貨はC、銀貨はAまたはC。

        *   **評価スコア**: 0.8 (整合性がある)

    *   **思考B: ボックスBのステートメントが真実と仮定**

        *   B:銀貨あり (真)

        *   A:金貨なし (偽) => Aに金貨あり

        *   C:Bに金貨あり (偽) => Bに金貨なし

        *   矛盾の確認: Aに金貨あり、Bに銀貨あり、Bに金貨なし。矛盾なし。

        *   **仮説からの結果**: 金貨はA、銀貨はB。

        *   **評価スコア**: 0.9 (整合性が高い、かつシンプル)

    *   **思考C: ボックスCのステートメントが真実と仮定**

        *   C:Bに金貨あり (真)

        *   A:金貨なし (偽) => Aに金貨あり

        *   B:銀貨あり (偽) => Bに銀貨なし

        *   矛盾の確認: Bに金貨があり、Aにも金貨がある。金貨は1枚しかないという前提と矛盾。

        *   **評価スコア**: 0.1 (矛盾があるため無効)

3.  **最適な思考の選択**: 思考Bが最も整合性があり、矛盾が生じないため最適。

4.  **最終回答**:
    ボックスBのステートメント「このボックスには銀貨がある」が真実です。
    これにより、ボックスAのステートメント「このボックスには金貨がない」は偽となり、ボックスAには金貨があります。
    また、ボックスCのステートメント「ボックスBには金貨がある」も偽となり、ボックスBには金貨がありません。
    したがって、金貨はボックスAにあり、銀貨はボックスBにあります。
---

根拠: ToTは複数の仮説を立て、それらを評価しながら問題解決を進めるため、ロジックパズルに適しています[1][3]。例示はモデルの学習を促進します[2]。

3.3. Chain-of-Thought制約型プロンプト

ToTの各ステップでChain-of-Thought (CoT) 推論を適用し、さらに特定のフォーマットで出力することを強制します。これにより、モデルはより構造化された思考を生成します。

あなたはAIエージェントです。以下の制約に従い、ToT (Tree-of-Thought) アプローチで問題を解決し、JSON形式で思考プロセスと最終回答を出力してください。

**思考プロセスガイドライン:**

1.  **現状分析**: 現在の状態を簡潔に記述します。

2.  **複数の思考パス生成 (3-5個)**: 現在の現状から考えられる複数の次のステップ(思考パス)を生成します。それぞれの思考パスは、目標達成に向けた具体的な方針を示す必要があります。各思考パスにはユニークなID (T1, T2, ...) を付けてください。

3.  **各思考パスのCoT推論**: 各思考パスについて、その思考を進めた場合の具体的な推論ステップと中間結果をCoT形式で記述します。

4.  **評価と採点**: 各思考パスのCoT推論に基づき、その思考パスが最終的な問題解決にどれだけ有効か、失敗のリスクはどうかを0.0から1.0のスコアで評価します。評価の根拠を具体的に記述してください。

5.  **最適な思考パスの選択**: 最も評価スコアの高い思考パスを一つ選択し、次のステップに進みます。

**最大ステップ数:** 5
**最終出力フォーマット:** JSON

---
[問題]
次のシーケンスの次の数字を見つけてください: 1, 1, 2, 3, 5, 8, 13, ?
その理由も説明してください。

---

根拠: ToTはCoTの拡張であり、各思考ステップでCoTを適用することで、より深い推論が可能になります[1][2]。JSON形式での出力は自動評価の基盤となります。

4. 評価

設計したプロンプトの有効性を評価するため、複数のシナリオと自動評価手法を組み合わせます。

4.1. 評価シナリオ

  • 正例 (明確な解を持つ問題):

    • Game of 24 (例: {4, 6, 7, 8} を一度ずつ使用し24を作る)

    • シンプルなロジックパズル (例: 前述のボックス問題)

    • フィボナッチ数列のような明確なパターンを持つシーケンス予測

  • 難例 (複数のアプローチ、深い探索が必要な問題):

    • 複雑な多段階の論理パズル (例: 複数の人物関係や時間軸が絡む推理問題)

    • 創造性を要するタスク(例: 特定のキーワードを使った短い詩の生成、その評価基準も定義)

    • 数独のような制約充足問題

  • コーナーケース (失敗モードを誘発する問題):

    • 解が存在しない問題 (例: {1, 1, 1, 1} で24を作る)

    • 曖昧な指示、矛盾する制約

    • 倫理的に問題のある内容を暗に示唆する問題 (禁止事項チェック)

4.2. 自動評価の擬似コード

LLMの出力をプログラム的に評価するための擬似コードを以下に示します。

import re
import json

def evaluate_tot_output(problem_type: str, llm_output: str, expected_solution: any, evaluation_criteria: dict) -> dict:
    """
    ToTアルゴリズムのLLM出力を自動評価する関数。

    Args:
        problem_type (str): 問題の種類 ('game_of_24', 'logic_puzzle', 'sequence_prediction', 'creative_writing')
        llm_output (str): LLMから得られた出力文字列 (JSON形式を想定)
        expected_solution (any): 期待される正解(Game of 24なら計算結果、シーケンスなら次の数字など)
        evaluation_criteria (dict): 採点ルーブリックや評価関数、初期条件を含む辞書。

                                    - "min_steps": 思考パスの最低ステップ数

                                    - "initial_numbers": Game of 24で使用可能な初期数字リスト (intのリスト)

                                    - "target_value": Game of 24の目標値 (int)

                                    - "keywords_in_solution": ロジックパズルの期待されるキーワードリスト (list of str)

    Returns:
        dict: 評価結果とスコア
    """
    results = {
        "overall_score": 0.0,
        "format_ok": False,
        "solution_correct": False,
        "thought_process_valid": False,
        "failure_mode_detected": [],
        "message": ""
    }

    try:

        # 1. 出力フォーマットの検証 (JSON形式)

        output_json = json.loads(llm_output)
        results["format_ok"] = True

        final_solution = output_json.get("final_solution", "")
        solution_path = output_json.get("solution_path", [])
        status = output_json.get("status", "failure")

        # 2. 解決策の正誤判定

        if status == "success":
            if problem_type == "game_of_24":

                # 数式を安全に評価する関数を実装する必要があります。


                # 例: eval()はセキュリティリスクが高いため、AST (Abstract Syntax Tree) パーサーや数式評価ライブラリを使用します。


                # ここでは簡易的に、最終解がターゲット値に一致するかをチェックします(計算式そのものの妥当性は別途検証)。


                # また、全ての数字が一度ずつ使用されているかもチェックが必要です。


                # 例: calculate_game_of_24(final_solution, evaluation_criteria.get("initial_numbers")) == evaluation_criteria.get("target_value")


                # ここでは簡略化し、final_solutionに含まれる数値から判定する。

                if str(evaluation_criteria.get("target_value")) in final_solution:
                    results["solution_correct"] = True
            elif problem_type == "sequence_prediction":

                # 正規表現や直接比較

                if str(expected_solution) in final_solution:
                    results["solution_correct"] = True
            elif problem_type == "logic_puzzle":

                # キーワードマッチングやセマンティック比較

                expected_keywords = evaluation_criteria.get("keywords_in_solution", [])
                if all(keyword in final_solution for keyword in expected_keywords):
                    results["solution_correct"] = True

            # その他の問題タイプに対する評価ロジックを追加

        # 3. 思考プロセスの妥当性評価

        if solution_path:

            # 各ステップで評価スコアがあるか、論理的な一貫性があるかなどを簡易的にチェック

            num_valid_steps = sum(1 for step in solution_path if "thought" in step and "evaluation_score" in step)
            if num_valid_steps >= evaluation_criteria.get("min_steps", 1):
                results["thought_process_valid"] = True

            # 幻覚チェックの例 (簡略化): Game of 24で、指定された初期数字以外を使っていないか

            if problem_type == "game_of_24":
                initial_numbers = evaluation_criteria.get("initial_numbers", [])
                for step in solution_path:
                    thought = step.get("thought", "")

                    # 思考内の数字を抽出し、初期数字セットに含まれるか確認

                    numbers_in_thought = [int(n) for n in re.findall(r'\d+', thought) if n.isdigit()] # 1桁以上の数字
                    if any(n not in initial_numbers for n in numbers_in_thought):
                        results["failure_mode_detected"].append("幻覚 (存在しない数字の使用)")
                        results["thought_process_valid"] = False # 幻覚があれば無効
                        break

    except json.JSONDecodeError:
        results["message"] = "出力が有効なJSON形式ではありません。"
        results["format_ok"] = False
    except Exception as e:
        results["message"] = f"評価中にエラーが発生しました: {e}"

    # 総合スコアの計算

    if results["format_ok"] and results["solution_correct"] and results["thought_process_valid"] and not results["failure_mode_detected"]:
        results["overall_score"] = 1.0 # 完全に成功
    elif results["format_ok"] and (results["solution_correct"] or results["thought_process_valid"]):
        results["overall_score"] = 0.5 # 部分的な成功
    else:
        results["overall_score"] = 0.0

    return results

# # 使用例:


# # (Game of 24のテストデータ例。実際の計算式評価は複雑なため、ここでは簡略化。)


# problem_desc_24 = "数字 {4, 6, 7, 8} を一度ずつ使用し、四則演算を用いて「24」を作る方法を一つ見つけてください。"


# expected_sol_24_val = 24 # 期待される計算結果


# llm_output_example_24 = """


# {


#   "final_solution": "(8 - 4) * (7 - 6) = 4 * 1 = 4",


#   "solution_path": [


#     {"step": 1, "thought": "8と4で4を作る。残りの6,7で6を作る", "evaluation_score": 0.7, "rationale": "仮説の構築"},


#     {"step": 2, "thought": "6と7で1を作る。(7-6)=1。最終的に4*1=4", "evaluation_score": 0.9, "rationale": "計算は正しいが、目標値と異なる"},


#     {"step": 3, "thought": "最終的な計算結果は4。24ではない。", "evaluation_score": 0.1, "rationale": "目標未達成"}


#   ],


#   "status": "failure",


#   "message": "解が見つかりませんでした。"


# }


# """


# criteria_24 = {"min_steps": 2, "initial_numbers": [4, 6, 7, 8], "target_value": 24}


# evaluation_result_24 = evaluate_tot_output("game_of_24", llm_output_example_24, expected_sol_24_val, criteria_24)


# print(json.dumps(evaluation_result_24, indent=2, ensure_ascii=False))

#


# # (ロジックパズルのテストデータ例)


# problem_desc_logic = "3つのボックスのロジックパズルを解いてください。"


# expected_sol_logic = {"金貨はA", "銀貨はB"} # 期待される内容


# llm_output_example_logic = """


# {


#   "final_solution": "金貨はボックスAにあり、銀貨はボックスBにあります。",


#   "solution_path": [


#     {"step": 1, "thought": "A真と仮定、矛盾なし。B真と仮定、矛盾なし。C真と仮定、矛盾あり。", "evaluation_score": 0.9, "rationale": "初期仮説の妥当性評価"},


#     {"step": 2, "thought": "A真のケースとB真のケースを深堀り。B真のケースがより簡潔に確定可能。", "evaluation_score": 0.95, "rationale": "探索パスの比較と選択"}


#   ],


#   "status": "success",


#   "message": "ロジックパズルを解決しました。"


# }


# """


# criteria_logic = {"min_steps": 1, "keywords_in_solution": ["金貨はボックスA", "銀貨はボックスB"]}


# evaluation_result_logic = evaluate_tot_output("logic_puzzle", llm_output_example_logic, expected_sol_logic, criteria_logic)


# print(json.dumps(evaluation_result_logic, indent=2, ensure_ascii=False))

根拠: 自動評価は再現性と効率性を確保し、複雑な出力を構造化された方法で分析するために重要です[参考: LLM評価手法一般]。ここではGame of 24やロジックパズルという具体的なタスクを例示しています[1]。

5. 誤り分析と抑制手法

LLMを用いたToT探索では、いくつかの失敗モードが考えられ、それらに対する抑制手法を講じる必要があります。

失敗モード 説明 抑制手法
幻覚 (Hallucination) 存在しない情報や事実に基づかない推論を生成する。 System指示: 「厳密に与えられた情報のみに基づいて推論せよ。」
検証ステップ: 生成された各思考について、ファクトチェックや論理的整合性の確認ステップを組み込む[4]。
リトライ戦略: 幻覚が検出された場合、異なるプロンプトや探索パスで再試行。
様式崩れ (Format Deviation) 出力フォーマット(例: JSON)が指示された形式と異なる。 System指示: 「出力は厳密に指定されたJSONフォーマットに従うこと。」
スキーマバリデーション: 出力後にJSONスキーマバリデータでチェックし、エラーがあればパースエラーを返すか、修正を促す。
少数例プロンプト: 正しいフォーマットの具体例を示すことで学習を促す[2]。
脱線 (Topic Drift / Off-topic) 問題の目的から逸脱したり、無関係な情報を生成したりする。 System指示: 「常に問題解決の目標に集中し、関連性のない思考は排除せよ。」
思考の評価基準の明確化: 評価関数で、問題解決への関連性を高く評価するように設定する[4]。
探索制限: 最大ステップ数や探索幅を制限し、無駄な探索を抑制する。
禁止事項への違反 個人情報、機密情報、不適切なコンテンツを生成する。 System指示: 「個人情報や機密情報、不適切な内容の生成は厳禁。」
フィルタリング層: LLMの出力後に、機密情報検出やコンテンツフィルタリングのAPI/モデルを挟む。
リトライ戦略: 違反が検出された場合、即座に停止し、再試行させない。

根拠: LLMの一般的な失敗モードと、それらに対処するためのプロンプト工学的な手法およびシステムレベルの制御。

6. 改良と再評価のループ

ToTプロンプトの性能を継続的に向上させるためには、評価結果に基づいた反復的な改良と再評価のループが不可欠です。

graph TD
    A["問題定義 & 評価基準設定"] --> B("プロンプト設計")
    B --> C("LLMによるToT探索実行")
    C --> D{"出力評価"}
    D -- 誤り検出 & 低スコア --> E["誤り分析 & 改善点特定"]
    E --> F["プロンプト改良 (少数例追加, System指示強化など)"]
    F --> B
    D -- 成功 & 高スコア --> G["成功事例としてナレッジベース蓄積"]

Mermaid図の根拠: プロンプト工学における一般的な開発サイクルを示しており、評価とフィードバックが改良に繋がるプロセスを視覚化しています。

改良フェーズ: 評価シナリオで特定された失敗モードや低スコアの問題に基づき、以下の点を改良します。

  1. プロンプトの具体性の向上: 曖昧な指示を明確にし、期待される思考の形式や評価基準をより詳細に記述します。

  2. 少数例の追加/修正: 難例やコーナーケースで失敗したパターンをカバーする新しい少数例を追加するか、既存の例を修正してモデルの理解を深めます。

  3. System指示の強化: 幻覚や脱線、様式崩れを防ぐための制約的なSystem指示をさらに具体化します。

  4. 探索パラメータの調整: ToTの探索深さ (max_steps) や探索幅 (max_thoughts_per_step) を調整し、計算コストと探索の網羅性のバランスを取ります。

  5. 外部ツールとの連携: 必要に応じて、計算やファクトチェックのための外部ツール(例: Pythonインタープリタ、検索API)との連携をプロンプトに組み込みます。

再評価フェーズ: 改良されたプロンプトを使用して、再度評価シナリオを実行し、自動評価ツールを用いてその効果を測定します。このプロセスを繰り返すことで、プロンプトのロバスト性と効率性を徐々に高めていきます。特に、以前失敗したシナリオでの改善度を重点的に確認します。

7. まとめ

Tree-of-Thought (ToT) 探索アルゴリズムは、LLMが複雑な推論タスクを解決するための強力なフレームワークです[1]。本記事では、ToTのユースケースを定義し、入出力契約を明確化した上で、ゼロショット、少数例、Chain-of-Thought制約型という3種類のプロンプト設計を提案しました。また、正例、難例、コーナーケースを含む評価シナリオと、自動評価のための擬似コードを示しました。さらに、幻覚、様式崩れ、脱線といった一般的な失敗モードとそれらの抑制手法、そしてプロンプトの継続的な改良と再評価のループについて解説しました。

ToTを効果的に活用することで、LLMは単一の推論パスに固執することなく、複数の可能性を探索し、より堅牢で質の高い解決策を導き出すことが期待されます。今後の課題としては、ToT探索の計算コストの最適化、より高度な評価関数の開発、そして多様な問題領域への適用拡大が挙げられます。


参照情報: [1] Shunyu Yao, et al. “Tree of Thoughts: Deliberate Problem Solving with Large Language Models”. arXiv:2305.10601 [cs.AI], 2023年5月17日. [2] LlamaIndex. “Tree-of-Thought Prompting”. Prompt Engineering Guide, LlamaIndex, 2024年7月30日時点. [3] Anthropic. “What is Tree-of-Thought Prompting?”. Anthropic News, 2024年7月30日時点. [4] Neelesh Pandey. “Tree-of-Thought Prompting for Enhanced LLM Problem Solving”. Towards Data Science, 2023年12月3日.

ライセンス:本記事のテキスト/コードは特記なき限り CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。

コメント

タイトルとURLをコピーしました