MENU
  • HOME
  • Struccle
  • 取引実績
  • お問い合わせ
  • 資料DL
  • 会社概要
  • FAQ
  • Struccle記事
  • BigQuery記事
データ流通、検索エンジン開発のプロフェッショナル
DataStructor
  • HOME
  • Struccle
  • 取引実績
  • お問い合わせ
  • 資料DL
  • 会社概要
  • FAQ
  • Struccle記事
  • BigQuery記事
DataStructor
  • HOME
  • Struccle
  • 取引実績
  • お問い合わせ
  • 資料DL
  • 会社概要
  • FAQ
  • Struccle記事
  • BigQuery記事
  1. ホーム
  2. AI_Agent
  3. Agent開発
  4. AI Agent開発日記 2025/06/29

AI Agent開発日記 2025/06/29

2025 7/01
AI_Agent Agent開発
2025年6月29日2025年7月1日

やりたいこと

データを読み込むだけで、以下が自動で行われる仕組みを構築したい。

  • 読み込んだデータがElasticsearchに自動登録される
  • データと指示内容がGeminiに渡され、PlaybookやTool/Schemaが自動生成される
  • 生成された内容が自動でPlaybookやToolに反映され、管理用エージェントと紐づいて構成される

前回の調査日記

あわせて読みたい
AI Agent開発日記 2025/06/28 やりたいこと データを読み込むだけで、以下が自動で行われる仕組みを構築したい。 読み込んだデータがElasticsearchに自動登録される データと指示内容がGeminiに渡さ...
目次

bqとelasticsearchの同期の値をコンソールから入力できるように調整する

  • 現状
    • 下記コードで可能になった

コード

import requests
import json
import os
import argparse
import time
import unicodedata
import sys

try:
    import vars
except ImportError:
    vars = None
    print("⚠️ 警告: vars.py が見つかりません。APIキーが設定されない可能性があります。")

# --- グローバル設定 ---
PORT = os.getenv("PORT", "8080")
BASE_URL = f"http://localhost:{PORT}"
APP_PREFIX = "integration_service"

# --- デフォルトテスト設定値 (サンプル用に汎用化) ---
DEFAULT_BQ_DATASET = "your_test_dataset"
DEFAULT_BQ_TABLE = "your_source_table"
DEFAULT_ES_URL = "http://localhost:9200"
# BQからの同期先インデックス名(サンプル用)
DEFAULT_ES_INDEX_BQ = "sample_synced_data"


# ToolのOpenAPIスキーマ生成時、AIにコンテキストを与えるための設定
# [優先度1] AIが分析するElasticsearchのインデックス名。実データがあれば、これを元にスキーマが生成される。
DEFAULT_ES_INDEX_SCHEMA = "sample_product_index"
# [優先度2] 上記インデックスに接続できない/データがない場合の代替データ。
# このサンプルデータを元にスキーマが生成され、Elasticsearch環境なしでもテストが可能になる。
DEFAULT_DOC_EXAMPLES_SCHEMA = [
    {"item_id": "AB-123", "productName": "Super Duper Gadget", "price_usd": 199.99, "inStock": True,
     "details": {"color": "red", "weight_grams": 250}, "tags": ["electronics", "new", "popular"]},
    {"item_id": "XY-789", "productName": "Basic Utility Tool", "price_usd": 25.00, "inStock": False,
     "description": "A simple tool for everyday tasks.", "manufacturer_code": "MFR-002"}
]
DEFAULT_GEMINI_MODEL = "gemini-1.5-flash"

# Playbook Instructions生成時、AIにコンテキストを与えるための設定
DEFAULT_ES_INDEX_PLAYBOOK_INSTRUCTIONS = "sample_ticket_index"
DEFAULT_DOC_EXAMPLES_PLAYBOOK_INSTRUCTIONS = [
    {"ticket_id": "TICKET-001", "customer_name": "Alice Wonderland", "email": "alice@example.com",
     "subject": "Login Issue", "description": "I cannot log in to my account.", "status": "open", "priority": "high",
     "created_at": "2024-03-10T10:00:00Z", "agent_assigned": None, "tags": ["login", "account_access"]},
    {"ticket_id": "TICKET-002", "customer_name": "Bob The Builder", "subject": "Billing question",
     "status": "pending_customer_response", "priority": "medium", "created_at": "2024-03-09T15:30:00Z",
     "last_reply_by": "agent_support", "resolution_details": None, "related_issues": ["TICKET-005", "TICKET-008"]}
]
# スタンドアロンPlaybook作成時に使用する既存Tool名の仮定(サンプル用)
DEFAULT_CUSTOM_TOOL_NAME_PLAYBOOK_INSTRUCTIONS = "Sample_Search_Tool"

# --- サンプル用ID (実行前に実際の値に置き換えてください) ---
DEFAULT_DF_PROJECT_ID = "your-gcp-project-id"
DEFAULT_DF_LOCATION_ID = "global"
DEFAULT_DF_AGENT_ID = "your-dialogflow-agent-id"
DEFAULT_PARENT_PLAYBOOK_ID = "your-parent-playbook-id"

# toolの表示名・説明 (サンプル用の汎用的な値)
DEFAULT_GATC_TOOL_DISPLAY_NAME_BASE = "Sample_Tool"
DEFAULT_GATC_TOOL_DESCRIPTION = "AIが生成したスキーマに基づく汎用検索ツール(スクリプト経由)。"

# playbookの表示名・Goal (サンプル用の汎用的な値)
DEFAULT_GACP_PLAYBOOK_DISPLAY_NAME_BASE = "Sample_Playbook"
DEFAULT_GACP_PLAYBOOK_GOAL = "ユーザーの要求に基づいて情報を検索し、応答する。"
DEFAULT_DF_REFERENCED_TOOL_IDS = ["your-referenced-tool-id-1"]


# --- NEW: コンソール出力ヘルパー ---
def print_flow_header(title):
    print(f"\n===== {title} =====")


def print_flow_footer(success=True):
    status = "完了" if success else "中断"
    print(f"===== フロー{status} =====")


def print_step_header(message):
    print(f"\n--- {message} ---")


def print_process(message, indent=0):
    prefix = "  " * indent
    print(f"{prefix}⏳ {message}...")


def print_api_result(path, success, indent=0):
    prefix = "  " * indent
    status = "[OK]" if success else "[ERROR]"
    print(f"{prefix}--> API通信: {path} {status}")


def print_success(message, indent=0):
    prefix = "  " * indent
    print(f"{prefix}✅ {message}")


def print_warning(message, indent=0):
    prefix = "  " * indent
    print(f"{prefix}⚠️ {message}")


def print_info_block(title, content, indent=0):
    prefix = "  " * indent
    print(f"{prefix}--- {title} ---")
    for line in str(content).splitlines():
        print(f"{prefix}  {line}")
    print(f"{prefix}{'-' * (len(title) + 8)}")


def prompt_user(message, default_value="", indent=0):
    prefix = "  " * indent
    prompt_text = f"{prefix}▶ {message}"
    if default_value:
        prompt_text += f" (デフォルト: {default_value})"
    # ユーザー入力を正規化
    user_input = unicodedata.normalize('NFC', input(f"{prompt_text}: ").strip())
    return user_input or default_value


def prompt_for_action(message, skip_prompt, indent=0):
    prefix = "  " * indent
    full_message = f"{prefix}▶ {message} (yes/no)"
    if skip_prompt:
        print(f"{full_message} (自動実行 - yes)")
        return True
    user_input = input(f"{full_message}: ").strip().lower()
    return user_input in ["yes", "y"]


# --- ヘルパー関数 (APIリクエスト部分のみ改修) ---
def make_api_request(endpoint_path, payload, method="POST", timeout=240, indent=0):
    url = f"{BASE_URL}{endpoint_path}"
    response = None
    try:
        if method.upper() == "POST":
            response = requests.post(url, json=payload, timeout=timeout)
        else:
            print_warning(f"未対応のHTTPメソッドです: {method}", indent)
            return None
        response.raise_for_status()
        print_api_result(endpoint_path, success=True, indent=indent)
        return response.json()
    except requests.exceptions.HTTPError as http_err:
        print_api_result(endpoint_path, success=False, indent=indent)
        print_warning(f"HTTPエラー: {http_err}", indent + 1)
        if response is not None:
            try:
                error_body = json.dumps(response.json(), indent=2, ensure_ascii=False)
                print_info_block("エラーレスポンス", error_body, indent + 1)
            except json.JSONDecodeError:
                print_info_block("エラーレスポンス (非JSON)", response.text, indent + 1)
    except requests.exceptions.RequestException as req_err:
        print_api_result(endpoint_path, success=False, indent=indent)
        print_warning(f"リクエストエラー: {req_err}", indent + 1)
    except Exception as e:
        print_api_result(endpoint_path, success=False, indent=indent)
        print_warning(f"予期せぬエラー: {e}", indent + 1)
    return None


def check_api_key(key_name, key_type="API"):
    key_value = getattr(vars, key_name, None) if vars else None
    placeholder_value = "YOUR_KEY_HERE"
    key_present = key_value and key_value != placeholder_value and "YOUR_" not in str(key_value)
    if not key_present:
        print_warning(f"vars.pyの {key_name} が未設定です。この{key_type}関連のテストは失敗する可能性があります。")
    return key_present


def check_dialogflow_ids(project_id, agent_id, skip_prompt):
    if "your-gcp-project-id" in project_id or "your-dialogflow-agent-id" in agent_id:
        print_warning("Dialogflowのproject_idまたはagent_idがデフォルト値です。")
        if not prompt_for_action("この設定で続行しますか?", skip_prompt, indent=1):
            return False
    return True


def check_playbook_tool_ids(tool_ids, skip_prompt):
    if not tool_ids or any("your-" in tid for tid in tool_ids):
        print_warning("Playbook作成に使用するtool_idsがデフォルト値です。")
        if not prompt_for_action("この設定で続行しますか?", skip_prompt, indent=1):
            return False
    return True


# --- テスト関数 (UIのみ改修) ---
def test_sync_bq_to_es(skip_prompt=False):
    print_flow_header("データ同期 (BigQuery → Elasticsearch)")
    if not prompt_for_action("このテストを実行しますか?", skip_prompt):
        print("  スキップされました。");
        print_flow_footer(success=False);
        return

    # --- インタラクティブな入力部 ---
    if skip_prompt:
        # スキップ時はデフォルト値を使用
        dataset_id = DEFAULT_BQ_DATASET
        table_id = DEFAULT_BQ_TABLE
        es_url = DEFAULT_ES_URL
        es_index = DEFAULT_ES_INDEX_BQ
        print_info_block("使用する設定(自動)",
                         f"BQ Dataset: {dataset_id}\n"
                         f"BQ Table: {table_id}\n"
                         f"ES URL: {es_url}\n"
                         f"ES Index: {es_index}")
    else:
        # ユーザーに入力を促す
        print_step_header("同期設定の入力")
        dataset_id = prompt_user("BigQueryデータセットIDを入力してください", default_value=DEFAULT_BQ_DATASET)
        table_id = prompt_user("BigQueryテーブルIDを入力してください", default_value=DEFAULT_BQ_TABLE)
        es_url = prompt_user("ElasticsearchのURLを入力してください", default_value=DEFAULT_ES_URL)
        es_index = prompt_user("Elasticsearchのインデックス名を入力してください", default_value=DEFAULT_ES_INDEX_BQ)

    # --- ペイロード作成 ---
    payload = {
        "dataset_id": dataset_id,
        "table_id": table_id,
        "elasticsearch_url": es_url,
        "elasticsearch_index": es_index,
        "elasticsearch_encoded_api_key": getattr(vars, "ELASTIC_CLOUD_ENCODED_API_KEY", None) if vars else None
    }
    
    # APIキーに関する警告
    if not payload["elasticsearch_encoded_api_key"] and "localhost" not in es_url and "127.0.0.1" not in es_url:
        print_warning("Elasticsearch APIキーがvars.pyに未設定で、ES URLもローカルホストではありません。")
        if not prompt_for_action("この設定でテストを続行しますか?", skip_prompt, indent=1):
            print("  テストを中断しました。")
            print_flow_footer(success=False)
            return

    # --- APIリクエスト実行 ---
    print_step_header("同期実行")
    print_process("データを同期しています")
    response = make_api_request(f"/{APP_PREFIX}/data/sync_bq_to_es", payload, timeout=180)

    if response:
        print_success("データ同期が完了しました")
        print_info_block("APIからのメッセージ", response.get('status', '詳細不明'))
    else:
        print_warning("データ同期に失敗しました。詳細は上記のエラーを確認してください。")
    print_flow_footer(success=bool(response))


def test_generate_schema_and_create_tool_interactive(
        es_index_for_schema_gen, df_project_id, df_location_id, df_agent_id,
        df_tool_name_base, df_tool_description, skip_prompts,
        df_playbook_name_base, df_playbook_goal, parent_playbook_id):
    print_flow_header("Tool/Playbook連続作成フロー")
    if not prompt_for_action(f"このフローを実行しますか? (Agent: {df_agent_id})", skip_prompts):
        print("  スキップされました。");
        print_flow_footer(success=False);
        return

    if not check_api_key("GEMINI_API_KEY") or not check_dialogflow_ids(df_project_id, df_agent_id, skip_prompts):
        print_flow_footer(success=False);
        return

    # --- スキーマ生成 ---
    print_step_header("ステップ1: OpenAPIスキーマ生成")
    generated_openapi_schema_obj = None
    for i in range(3):
        print_process(f"スキーマを生成しています... (試行 {i + 1}/3)")
        payload = {"elasticsearch_index_name": es_index_for_schema_gen,
                   "elasticsearch_document_examples": DEFAULT_DOC_EXAMPLES_SCHEMA,
                   "gemini_model_name": DEFAULT_GEMINI_MODEL}
        response = make_api_request(f"/{APP_PREFIX}/generate/openapi_schema", payload, timeout=180, indent=1)

        if response:
            generated_openapi_schema_obj = response
            print_info_block("生成されたOpenAPIスキーマ", json.dumps(response, indent=2, ensure_ascii=False), indent=1)
            if skip_prompts:
                user_choice = "yes"
            else:
                user_choice = prompt_user("このスキーマでToolを作成しますか? (yes/no/retry)", indent=1).lower()

            if user_choice in ["yes", "y"]: break
            if user_choice in ["no", "n"]: print("  ユーザーにより中断されました。"); print_flow_footer(
                False); return None
        else:  # response is None
            if not prompt_for_action("スキーマ生成を再試行しますか?", skip_prompts, indent=1):
                print("  ユーザーにより中断されました。");
                print_flow_footer(False);
                return None

    if not generated_openapi_schema_obj:
        print_warning("有効なスキーマが得られませんでした。");
        print_flow_footer(False);
        return None

    # --- Tool作成 ---
    print_step_header("ステップ2: Dialogflow Tool作成")
    tool_name = prompt_user("Toolの表示名を入力してください", default_value=df_tool_name_base)
    tool_desc = prompt_user("Toolの説明を入力してください", default_value=df_tool_description)

    clean_es_index_name = es_index_for_schema_gen.replace('-', '_').replace('.', '_')
    final_tool_name = tool_name
    if es_index_for_schema_gen and not es_index_for_schema_gen in final_tool_name and not clean_es_index_name in final_tool_name:
        final_tool_name += f"_{clean_es_index_name}"
    print_info_block("最終的なTool表示名", final_tool_name)

    print_process("Toolを作成しています")
    payload = {"project_id": df_project_id, "location_id": df_location_id, "agent_id": df_agent_id,
               "tool_display_name": final_tool_name, "tool_description": tool_desc,
               "openapi_schema_string": json.dumps(generated_openapi_schema_obj)}
    response = make_api_request(f"/{APP_PREFIX}/dialogflow/create_tool", payload, timeout=120)

    if not (response and "tool_id" in response):
        print_warning("Toolの作成に失敗しました。");
        print_flow_footer(False);
        return None

    created_tool_id = response['tool_id']
    created_tool_display_name = response.get('display_name', final_tool_name)
    print_success(f"Tool『{created_tool_display_name}』(ID: {created_tool_id}) を作成しました")

    # --- Playbook作成 ---
    if prompt_for_action(f"作成したTool『{created_tool_display_name}』を使用してPlaybookを作成しますか?", skip_prompts):
        playbook_info = test_generate_instructions_and_create_playbook_interactive(
            is_standalone=False,  # このフラグでスタンドアロンでないことを示す
            es_index_for_instr_gen=es_index_for_schema_gen,
            doc_examples_for_instr_gen=DEFAULT_DOC_EXAMPLES_SCHEMA,
            gemini_model_for_instr_gen=DEFAULT_GEMINI_MODEL,
            tool_name_for_instr_gen=created_tool_display_name,
            df_project_id_interactive=df_project_id,
            df_location_id_interactive=df_location_id,
            df_agent_id_interactive=df_agent_id,
            df_playbook_display_name_base_interactive=df_playbook_name_base,
            df_playbook_goal_interactive=df_playbook_goal,
            df_tool_ids_interactive=[created_tool_id],
            skip_prompts_interactive=skip_prompts
        )
        # --- 親Playbookへ追加 ---
        if playbook_info and parent_playbook_id:
            if prompt_for_action(
                    f"作成したPlaybook『{playbook_info['display_name']}』を親Playbook(ID:{parent_playbook_id})に追加しますか?",
                    skip_prompts):
                add_child_playbooks_to_parent_interactive(
                    parent_playbook_id=parent_playbook_id,
                    created_child_playbooks=[playbook_info],
                    df_project_id=df_project_id,
                    df_location_id=df_location_id,
                    df_agent_id=df_agent_id,
                    skip_prompts=skip_prompts
                )
    print_flow_footer()
    return {"tool_id": created_tool_id, "display_name": created_tool_display_name}


def test_generate_instructions_and_create_playbook_interactive(
        is_standalone, es_index_for_instr_gen, doc_examples_for_instr_gen, gemini_model_for_instr_gen,
        tool_name_for_instr_gen, df_project_id_interactive, df_location_id_interactive, df_agent_id_interactive,
        df_playbook_display_name_base_interactive, df_playbook_goal_interactive, df_tool_ids_interactive,
        skip_prompts_interactive):
    header_text = "ステップ3: 関連Playbook作成" if not is_standalone else "ステップ1: Playbook作成"
    print_step_header(header_text)

    if is_standalone:  # スタンドアロンの場合のみ前提条件チェック
        if not check_api_key("GEMINI_API_KEY") or not check_dialogflow_ids(df_project_id_interactive,
                                                                           df_agent_id_interactive,
                                                                           skip_prompts_interactive):
            return None
        if not check_playbook_tool_ids(df_tool_ids_interactive, skip_prompts_interactive):
            return None

    # Instructions生成
    generated_instructions_markdown = None
    for i in range(3):
        print_process(f"Playbookの指示を生成しています... (試行 {i + 1}/3)", indent=1)
        payload = {"elasticsearch_index_name": es_index_for_instr_gen,
                   "elasticsearch_document_examples": doc_examples_for_instr_gen,
                   "gemini_model_name": gemini_model_for_instr_gen, "tool_name_in_playbook": tool_name_for_instr_gen}
        response = make_api_request(f"/{APP_PREFIX}/generate/playbook_instructions", payload, timeout=240, indent=2)
        if response and "playbook_instructions_markdown" in response:
            generated_instructions_markdown = response["playbook_instructions_markdown"]
            print_info_block("生成されたPlaybook Instructions", generated_instructions_markdown, indent=2)
            if skip_prompts_interactive:
                user_choice = "yes"
            else:
                user_choice = prompt_user("この指示でPlaybookを作成しますか? (yes/no/retry)", indent=2).lower()

            if user_choice in ["yes", "y"]: break
            if user_choice in ["no", "n"]: print("    ユーザーにより中断されました。"); return None
        else:
            if not prompt_for_action("指示の生成を再試行しますか?", skip_prompts_interactive, indent=2):
                print("    ユーザーにより中断されました。");
                return None

    if not generated_instructions_markdown:
        print_warning("有効な指示が得られませんでした。", indent=1);
        return None

    # Playbook作成
    playbook_name = prompt_user("Playbookの表示名を入力してください",
                                default_value=df_playbook_display_name_base_interactive, indent=1)
    playbook_goal = prompt_user("PlaybookのGoalを入力してください", default_value=df_playbook_goal_interactive,
                                indent=1)

    clean_es_index_name = es_index_for_instr_gen.replace('-', '_').replace('.', '_')
    final_playbook_name = playbook_name
    if es_index_for_instr_gen and not es_index_for_instr_gen in final_playbook_name and not clean_es_index_name in final_playbook_name:
        final_playbook_name += f"_{clean_es_index_name}"
    print_info_block("最終的なPlaybook表示名", final_playbook_name, indent=1)

    print_process("Playbookを作成しています", indent=1)
    payload = {"project_id": df_project_id_interactive, "location_id": df_location_id_interactive,
               "agent_id": df_agent_id_interactive, "playbook_display_name": final_playbook_name,
               "playbook_goal": playbook_goal, "playbook_instruction_text": generated_instructions_markdown,
               "tool_ids": df_tool_ids_interactive}
    response = make_api_request(f"/{APP_PREFIX}/dialogflow/create_playbook", payload, timeout=120, indent=1)

    if not (response and "playbook_id" in response):
        print_warning("Playbookの作成に失敗しました。", indent=1);
        return None

    created_playbook_id = response['playbook_id']
    created_playbook_name = response.get('display_name', final_playbook_name)
    print_success(f"Playbook『{created_playbook_name}』(ID: {created_playbook_id}) を作成しました", indent=1)
    return {"playbook_id": created_playbook_id, "display_name": created_playbook_name}


def add_child_playbooks_to_parent_interactive(
        parent_playbook_id, created_child_playbooks, df_project_id, df_location_id, df_agent_id, skip_prompts):
    header_text = "ステップ4: 親Playbookへの追加"
    print_step_header(header_text)

    print_process("親Playbookの既存の指示を取得しています")
    get_instr_payload = {"project_id": df_project_id, "location_id": df_location_id, "agent_id": df_agent_id,
                         "playbook_id": parent_playbook_id}
    parent_instr_response = make_api_request(f"/{APP_PREFIX}/dialogflow/get_playbook_instructions", get_instr_payload,
                                             timeout=120)

    if not (parent_instr_response and "instructions_text" in parent_instr_response):
        print_warning("親Playbookの指示取得に失敗しました。");
        return

    existing_parent_instructions = parent_instr_response["instructions_text"]

    child_playbook_info = created_child_playbooks[0]
    child_name = child_playbook_info["display_name"]
    child_desc_prompt = f"子Playbook『{child_name}』の説明を入力してください (親Playbookに追加されます)"

    if skip_prompts:
        child_description = f"これは '{child_name}' Playbook の自動生成された説明です。"
        print(f"  ▶ {child_desc_prompt}: (自動入力) {child_description}")
    else:
        child_description = prompt_user(child_desc_prompt, default_value=f"『{child_name}』を実行する", indent=1)

    instruction_to_add = f"\n- - ${{PLAYBOOK:{child_name}}} - {child_description}"
    new_parent_instructions = existing_parent_instructions + instruction_to_add

    print_info_block("更新後の親Playbookの指示プレビュー", new_parent_instructions, indent=1)

    if prompt_for_action("この内容で親Playbookを更新しますか?", skip_prompts, indent=1):
        print_process("親Playbookを更新しています", indent=2)
        update_instr_payload = {"project_id": df_project_id, "location_id": df_location_id, "agent_id": df_agent_id,
                                "playbook_id": parent_playbook_id, "new_instructions_text": new_parent_instructions}
        update_response = make_api_request(f"/{APP_PREFIX}/dialogflow/update_playbook_instructions",
                                           update_instr_payload, timeout=120, indent=2)
        if update_response:
            print_success("親Playbookの更新に成功しました。", indent=2)
            if "new_instructions_preview" in update_response:
                print_info_block("更新後の最終的な指示", update_response['new_instructions_preview'], indent=2)
        else:
            print_warning("親Playbookの更新に失敗しました。", indent=2)
    else:
        print("  更新はキャンセルされました。")


# --- メイン実行部 (元のロジックを維持) ---
if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Integration Service APIテストスクリプト")
    parser.add_argument(
        "--test",
        choices=["sync", "generate_and_create_tool", "generate_and_create_playbook", "all"],
        nargs="+",
        help="実行するテストを選択 (複数指定可)",
        default=["all"]
    )
    parser.add_argument("-y", "--yes", action="store_true",
                        help="全ての確認プロンプト(表示名入力含む)をスキップし、自動で 'yes' と回答、またはデフォルト値を使用します")
    parser.add_argument("--df_project_id", default=DEFAULT_DF_PROJECT_ID,
                        help=f"Dialogflow Project ID (デフォルト: {DEFAULT_DF_PROJECT_ID})")
    parser.add_argument("--df_location_id", default=DEFAULT_DF_LOCATION_ID,
                        help=f"Dialogflow Agent Location ID (デフォルト: {DEFAULT_DF_LOCATION_ID})")
    parser.add_argument("--df_agent_id", default=DEFAULT_DF_AGENT_ID,
                        help=f"Dialogflow Agent ID (デフォルト: {DEFAULT_DF_AGENT_ID})")
    parser.add_argument("--parent_playbook_id", default=DEFAULT_PARENT_PLAYBOOK_ID,
                        help=f"子Playbookを追加する先の親PlaybookのID (デフォルト: {DEFAULT_PARENT_PLAYBOOK_ID})")
    parser.add_argument("--gact_tool_name_base", default=DEFAULT_GATC_TOOL_DISPLAY_NAME_BASE,
                        help=f"Tool表示名入力時のデフォルトのベース名。(デフォルト: {DEFAULT_GATC_TOOL_DISPLAY_NAME_BASE})")
    parser.add_argument("--gact_es_index", default=DEFAULT_ES_INDEX_SCHEMA,
                        help=f"Tool作成テスト(スキーマ生成元)用ESインデックス名。(デフォルト: {DEFAULT_ES_INDEX_SCHEMA})")
    parser.add_argument("--gacp_playbook_name_base", default=DEFAULT_GACP_PLAYBOOK_DISPLAY_NAME_BASE,
                        help=f"Playbook表示名入力時のデフォルトのベース名。(デフォルト: {DEFAULT_GACP_PLAYBOOK_DISPLAY_NAME_BASE})")
    parser.add_argument("--gacp_es_index", default=DEFAULT_ES_INDEX_PLAYBOOK_INSTRUCTIONS,
                        help=f"スタンドアロンPlaybook作成テスト(Instructions生成元)用ESインデックス名。(デフォルト: {DEFAULT_ES_INDEX_PLAYBOOK_INSTRUCTIONS})")
    parser.add_argument("--gacp_playbook_goal", default=DEFAULT_GACP_PLAYBOOK_GOAL,
                        help=f"Playbook作成テスト用Playbookのゴール。(デフォルト: {DEFAULT_GACP_PLAYBOOK_GOAL})")
    parser.add_argument("--gacp_tool_ids", nargs="*", default=DEFAULT_DF_REFERENCED_TOOL_IDS,
                        help=f"スタンドアロンPlaybook作成テスト用参照ツールIDリスト。(デフォルト: {DEFAULT_DF_REFERENCED_TOOL_IDS})")
    args = parser.parse_args()

    print(f"テスト対象サービスURL: {BASE_URL}")
    print(f"実行対象テスト: {', '.join(args.test)}")
    if args.yes:
        print("注意: 全ての確認プロンプト(表示名入力含む)はスキップされます。")

    tests_to_run_flags = {"sync": False, "generate_and_create_tool": False, "generate_and_create_playbook": False}
    if "all" in args.test:
        for key in tests_to_run_flags: tests_to_run_flags[key] = True
    else:
        for test_name in args.test:
            if test_name in tests_to_run_flags:
                tests_to_run_flags[test_name] = True

    if tests_to_run_flags["sync"]:
        test_sync_bq_to_es(skip_prompt=args.yes)

    if tests_to_run_flags["generate_and_create_tool"]:
        test_generate_schema_and_create_tool_interactive(
            es_index_for_schema_gen=args.gact_es_index,
            df_project_id=args.df_project_id,
            df_location_id=args.df_location_id,
            df_agent_id=args.df_agent_id,
            df_tool_name_base=args.gact_tool_name_base,
            df_tool_description=DEFAULT_GATC_TOOL_DESCRIPTION,
            skip_prompts=args.yes,
            df_playbook_name_base=args.gacp_playbook_name_base,
            df_playbook_goal=args.gacp_playbook_goal,
            parent_playbook_id=args.parent_playbook_id
        )

    if tests_to_run_flags["generate_and_create_playbook"]:
        print_flow_header("スタンドアロンPlaybook作成フロー")
        if prompt_for_action(f"このフローを実行しますか? (Agent: {args.df_agent_id})", args.yes):
            created_playbook_info = test_generate_instructions_and_create_playbook_interactive(
                is_standalone=True,
                es_index_for_instr_gen=args.gacp_es_index,
                doc_examples_for_instr_gen=DEFAULT_DOC_EXAMPLES_PLAYBOOK_INSTRUCTIONS,
                gemini_model_for_instr_gen=DEFAULT_GEMINI_MODEL,
                tool_name_for_instr_gen=DEFAULT_CUSTOM_TOOL_NAME_PLAYBOOK_INSTRUCTIONS,
                df_project_id_interactive=args.df_project_id,
                df_location_id_interactive=args.df_location_id,
                df_agent_id_interactive=args.df_agent_id,
                df_playbook_display_name_base_interactive=args.gacp_playbook_name_base,
                df_playbook_goal_interactive=args.gacp_playbook_goal,
                df_tool_ids_interactive=args.gacp_tool_ids,
                skip_prompts_interactive=args.yes
            )
            if created_playbook_info and args.parent_playbook_id:
                if prompt_for_action(
                        f"作成したPlaybook『{created_playbook_info['display_name']}』を親Playbookに追加しますか?",
                        args.yes):
                    add_child_playbooks_to_parent_interactive(
                        parent_playbook_id=args.parent_playbook_id,
                        created_child_playbooks=[created_playbook_info],
                        df_project_id=args.df_project_id,
                        df_location_id=args.df_location_id,
                        df_agent_id=args.df_agent_id,
                        skip_prompts=args.yes
                    )
            print_flow_footer(success=bool(created_playbook_info))
        else:
            print("  スキップされました。")
            print_flow_footer(success=False)

    print("\nすべての選択されたテストの実行試行が完了しました。")

人気記事

  • BigQueryの無料枠を活用しよう!制限と注意点、活用方法を解説
  • BigQueryでエラー解決!よくあるエラーと対処法
  • BigQueryのレベル別学習リソースまとめ!初心者から上級者まで役立つ情報源
  • 【SUUMOスクレイピング】Struccleで物件データを全件収集
  • BigQuery入門!無料データでSQLの基本文字列関数をマスター
AI_Agent Agent開発
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次
カテゴリー
  • AI_Agent (153)
    • Agent開発 (153)
  • BigQuery (100)
    • BigQueryTips (11)
    • BigQueryでデータ分析 (49)
    • BigQueryのFAQ (1)
    • BigQuery入門 (8)
    • BigQuery学習教材 (22)
    • BigQuery導入ガイド (3)
    • BigQuery最新情報 (3)
    • BigQuery活用事例 (4)
  • Struccle (184)
    • Struccleでスクレイピング (10)
      • suumoの物件データを収集&分析 (1)
      • アニマルジョブの電話番号、メールアドレスを全件収集 (1)
      • データ集計 (6)
      • ホットペッパービューティーのヘアサロンデータを収集&分析 (1)
      • 食べログの飲食店データを収集&分析 (1)
    • Struccleデータ料金事例 (173)
      • 商品分析 (15)
      • 営業リスト (119)
      • 競合分析&市場調査 (58)
      • 自動車 (11)
      • 自社活用 (7)
    • Struccle活用企業様の紹介 (1)
  • 当ブログのコーディング実行環境設定 (4)
目次