2025年12月22日

データサイエンスエージェントにポッドキャスト作成機能を持たせてみた!


Content

こんにちは!みっちーです!



これまでのADKに関する記事で、「データサイエンスエージェント」は、SQLによるデータ抽出、Pythonによる高度な分析・可視化、そして「考察サブエージェント」によるデータ分析結果の考察の生成までを自動で行えるようになりました!



ですが、昨今の多忙な社会において、レポートを確認する時間がなかなか取れないという方もいると思います。多忙な中でも、移動中や作業中に、ラジオのように分析結果を聴き流せたら…と思われる方もいるのではないでしょうか



そこで今回は、データサイエンスエージェントに「分析結果をポッドキャスト(音声)にして届ける機能」を追加します!Gemini 2.5 Flashのマルチモーダル機能(音声生成)を活用し、分析結果をMCが語りかけるラジオ形式の音声ファイルとして出力する機能を実装していきます。

今回のゴール:分析結果を「聴く」体験へ

これまでのエージェントは、テキストとグラフ画像を出力して終わりでした。今回実装する機能では、以下のようなフローを実現します。

データ分析 & 考察: 従来通り、データの集計、可視化、インサイトの生成を行います。

台本作成: 分析結果(テキスト)を元に、MCがリスナーに語りかける形式の「ポッドキャスト台本」を自動作成します。

音声生成: 作成された台本を読み上げさせ、音声ファイル(.wav)としてArtifactに保存します。

これにより、ユーザーは「このデータの分析結果をポッドキャストにして」と頼むだけで、分析内容を耳で確認できるようになります。

前提条件

本記事の実装を進める前に、以下の環境が整っていることを確認してください。

実装手順

それでは、実装していきましょう!今回は新しいサブエージェント「Podcast Agent」を作成し、それをRoot Agentに統合します。

1. 依存ライブラリの追加

音声生成機能を利用するために、Google GenAI SDKを追加します。python/agents/data-science/pyproject.tomlを開き、依存関係を追加してください。

[tool.poetry.dependencies]
# ... (既存の依存関係) ...
mcp = "^1.15.0"
google-genai = "^1.0.0" # この行を追加

追加したら、ターミナルで poetry lock を実行して poetry.lock ファイルを更新し、その後 poetry install を実行してライブラリをインストールしてください。

2. ポッドキャスト用ツールの作成

ポッドキャスト作成に必要な「台本作成」と「音声生成」の2つの機能を、それぞれツールとして実装します。

python/agents/data-science/data_science/sub_agents/podcast/ ディレクトリを作成し、その中に tools.py を作成します。

# python/agents/data-science/data_science/sub_agents/podcast/tools.py

import io
import logging
import wave
from google import genai
from google.adk.tools import ToolContext
from google.genai import types

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

MODEL_GEMINI_2_5_FLASH = "gemini-2.5-flash"
MODEL_GEMINI_2_5_FLASH_PREVIEW_TTS = "gemini-2.5-flash-preview-tts"

client = genai.Client()

def write_podcast_script(analysis_result: str) -> str:
"""
データ分析の結果を元に、ポッドキャストの台本を作成します。
Args:
analysis_result: 分析結果や考察を含むテキスト。
Returns:
生成されたポッドキャストの台本。
"""
prompt = f"""あなたはプロフェッショナルな放送作家です。
以下のデータ分析結果を元に、MCがリスナーに語りかける形式の、リスナーが楽しめるポッドキャスト台本を作成してください。

【分析結果】
{analysis_result}

# 指示
- 専門用語は噛み砕き、聴覚だけで理解できるように工夫してください。
- 明るく楽しい雰囲気で、親しみやすい口調で語りかける形式にしてください。
- 出力は MCの語りのみを含めてください。
"""
response = client.models.generate_content(
model=MODEL_GEMINI_2_5_FLASH,
contents=prompt
)
return response.text

async def podcast_speaker(script: str, tool_context: ToolContext) -> dict[str, str]:
"""
スクリプトに基づいてポッドキャストの音声を生成し、Artifactに保存します。
Args:
script: 音声化するスクリプト。
tool_context: 現在のツール呼び出しのコンテキスト。
Returns:
処理結果と保存されたファイル名。
"""
# Gemini APIを使ってテキストを音声に変換
response = client.models.generate_content(
model=MODEL_GEMINI_2_5_FLASH_PREVIEW_TTS,
contents=f"""明るくハキハキとしたトーンで内容を読み上げてください。
{script}""",
config=types.GenerateContentConfig(
response_modalities=["AUDIO"],
speech_config=types.SpeechConfig(
voice_config=types.VoiceConfig(
prebuilt_voice_config=types.PrebuiltVoiceConfig(
voice_name='Aoede',
)
)
)
)
)

audio_content = None
if response and response.candidates:
candidate = response.candidates[0]
if candidate.content and candidate.content.parts:
part = candidate.content.parts[0]
if part.inline_data:
audio_content = part.inline_data.data

if audio_content is None:
return {"status": "failure", "detail": "failed to generate podcast audio"}

# WAVファイルとしてメモリ上に保存
wav_on_memory = io.BytesIO()
with wave.open(wav_on_memory, 'wb') as wf:
wf.setnchannels(1)
wf.setsampwidth(2)
wf.setframerate(24000)
wf.writeframes(audio_content)

# Artifactとして保存
await tool_context.save_artifact(
filename="podcast.wav",
artifact=types.Part.from_bytes(data=wav_on_memory.getvalue(), mime_type="audio/wav"),
)
return {
"status": "success",
"detail": "Audio generated successfully and stored in artifacts.",
"filename": "podcast.wav",
}

3. プロンプトの定義

次に、ポッドキャストエージェントへの指示を定義します。このエージェントは、先ほど作成した2つのツールを順序よく使ってタスクを完遂する必要があります。

同じディレクトリに prompts.py を作成します。

# python/agents/data-science/data_science/sub_agents/podcast/prompts.py

def return_instructions_podcast() -> str:
return """あなたは熟練したポッドキャストプロデューサー兼オーディオエンジニアです。あなたの仕事は、与えられた分析結果から高品質なポッドキャスト音声を生成することです。

# 指示
以下のステップを順番に実行し、ポッドキャストを作成してください。

1. **台本作成**: 受け取った分析結果(テキスト)を引数にして、`write_podcast_script` ツールを呼び出し、ポッドキャストの台本を作成してください。
2. **音声生成**: 作成された台本(テキスト)を引数にして、`podcast_speaker` ツールを呼び出し、音声ファイルを生成してください。
3. **完了報告**: 音声生成ツールの実行結果(ファイル名など)を確認し、ユーザーに「ポッドキャストを作成しました」と報告してください。

# 注意
- 台本作成ツールと音声生成ツールは、**必ず**順番に実行してください。
"""

4. ポッドキャストエージェントの作成

ツールとプロンプトを組み合わせて、エージェントを定義します。このエージェントは、先ほど作成した2つのツールを使って、自律的にポッドキャスト作成フローを実行します。

同じディレクトリに agent.py を作成します。

# python/agents/data-science/data_science/sub_agents/podcast/agent.py

import os
from google.adk.agents import Agent
from google.adk.tools import load_artifacts
from .tools import podcast_speaker, write_podcast_script
from .prompts import return_instructions_podcast

MODEL_GEMINI_2_5_FLASH = "gemini-2.5-flash"

podcast_agent = Agent(
name="podcast_agent",
model=MODEL_GEMINI_2_5_FLASH,
instruction=return_instructions_podcast(),
tools=[write_podcast_script, podcast_speaker, load_artifacts]
)

そして、python/agents/data-science/data_science/sub_agents/__init__.py を更新して、新しいエージェントを公開します。

# python/agents/data-science/data_science/sub_agents/__init__.py

from .bqml.agent import root_agent as bqml_agent
from .analytics.agent import root_agent as ds_agent
from .bigquery.agent import database_agent as db_agent
from .insight.agent import insight_agent
from .podcast.agent import podcast_agent # 追加

__all__ = ["bqml_agent", "ds_agent", "db_agent", "insight_agent", "podcast_agent"] # 追加

5. 既存ツールの改修

ポッドキャストエージェントは、考察エージェントが生成した「インサイト」を台本の素材として利用します。そのため、既存の call_insight_agent ツールを修正して、生成された考察を後続のエージェントが参照できるように tool_context.state に保存する処理を追加します。

python/agents/data-science/data_science/tools.pycall_insight_agent 関数を以下のように修正してください。

async def call_insight_agent(
question: str,
tool_context: ToolContext,
) -> str:
# ... (前半は変更なし) ...

agent_tool = AgentTool(agent=insight_agent)
insight_agent_output = await agent_tool.run_async(
args={"request": insight_prompt}, tool_context=tool_context
)

# 【追加】考察結果をstateに保存する
tool_context.state["insight_agent_output"] = insight_agent_output

# ... (後半は変更なし) ...
return final_response

6. Root Agentへの統合

最後に、司令塔である Root Agent がこの新機能を使えるようにします。

tools.py の修正

python/agents/data-science/data_science/tools.py の末尾に、Root Agent用の呼び出しツールを追加します。

# python/agents/data-science/data_science/tools.py の末尾に追加

# ... (import文に podcast_agent を追加) ...
from .sub_agents import ds_agent, db_agent, insight_agent, podcast_agent

# ... (既存のツール) ...

async def call_podcast_agent(
question: str,
tool_context: ToolContext,
) -> str:
"""
Tool to call the podcast agent.
This tool gathers previous analysis results and insights from the state
and asks the podcast_agent to create an audio podcast based on them.

**IMPORTANT:** This tool will automatically save the generated audio file (podcast.wav)
to the Artifacts. The returned text is the script of the podcast.
"""
# 過去の分析結果と考察を収集
db_output = tool_context.state.get("db_agent_output", "")
ds_output = tool_context.state.get("ds_agent_output", "")
insight_output = tool_context.state.get("insight_agent_output", "")

# 入力を整形
podcast_input = f"""
以下の分析結果と考察を元に、ポッドキャストを作成してください。

ユーザーの要望: {question}

【データ分析結果】
{db_output}
{ds_output}

【考察・インサイト】
{insight_output}
"""

agent_tool = AgentTool(agent=podcast_agent)
output = await agent_tool.run_async(
args={"request": podcast_input},
tool_context=tool_context
)
return output

agent.py の修正

Root Agentが新しいツールを使えるように、toolsリストに追加します。podcast_agent はツール経由で呼び出すため、sub_agents には追加しません。

# python/agents/data-science/data_science/agent.py

# ... (import文の修正) ...
from .sub_agents import bqml_agent # podcast_agent は削除(ツール経由で呼ぶため)
from .sub_agents.bigquery.tools import (
get_database_settings as get_bq_database_settings,
)
from .prompts import return_instructions_root
from .tools import call_db_agent, call_ds_agent, call_insight_agent, call_mcp_tool, call_podcast_agent # call_podcast_agent を追加

# ... (setup_before_agent_call はそのまま) ...

root_agent = Agent(
model=os.getenv("ROOT_AGENT_MODEL"),
name="db_ds_multiagent",
instruction=return_instructions_root(),
global_instruction=(
f"""
You are a Data Science and Data Analytics Multi Agent System.
Todays date: {date_today}
"""
),
sub_agents=[bqml_agent], # podcast_agent は追加しない
tools=[
call_db_agent,
call_ds_agent,
call_insight_agent,
load_artifacts,
call_mcp_tool(),
call_podcast_agent, # この行を追加
],
before_agent_callback=setup_before_agent_call,
generate_content_config=types.GenerateContentConfig(temperature=0.01),
)

prompts.py の修正

Root Agentの指示書(プロンプト)に、ポッドキャスト作成の手順を追加します。

# python/agents/data-science/data_science/prompts.py

def return_instructions_root() -> str:

instruction_prompt_root_v2 = """
# ... (前略) ...

# 7. **Respond:** ... (既存のステップ7)

# 8. **Podcast Generation (`call_podcast_agent` - if applicable):** If the user asks to create a podcast from the analysis, use this tool. This will generate an audio file and save it to Artifacts.

# **Tool Usage Summary:**

# * **Greeting/Out of Scope:** answer directly.
# * **SQL Query:** `call_db_agent`. ...
# * **SQL & Python Analysis:** `call_db_agent`, then `call_ds_agent`. ...
# * **BQ ML `call_bqml_agent`:** ...
# * **Podcast:** `call_podcast_agent`. Use this when the user explicitly requests a podcast.

# ... (後略) ...
"""
return instruction_prompt_root_v2

動作確認

すべての実装が完了したら、ADKを起動して試してみましょう。

trainテーブルの国ごとの売上を分析し、その結果について考察してください。その後、その内容をポッドキャストにしてください。

このプロンプトを実行すると、エージェントは以下の図のように処理を行います。



処理完了後、Artifactタブに podcast.wav が生成されていれば大成功です!再生してみると、Gemini 2.5の自然な日本語音声で、データ分析結果がラジオ番組のように解説されるはずです。

まとめ

今回は、データサイエンスエージェントに「音声出力」という新しい表現力を与えました。単なるテキストの読み上げではなく、親しみやすいMCによる語りかけ形式にすることで、難解なデータ分析結果も楽しく、直感的に理解できるようになります。

このようにADKとGeminiのマルチモーダル機能を組み合わせれば、エージェントの可能性は無限に広がります。ぜひ皆さんも、自分だけのユニークなエージェントを作ってみてください!

2025年12月22日 データサイエンスエージェントにポッドキャスト作成機能を持たせてみた!

Category Google Cloud

ご意見・ご相談・料金のお見積もりなど、
お気軽にお問い合わせください。

お問い合わせはこちら