すべてのプロダクト
Search
ドキュメントセンター

Alibaba Cloud Model Studio:詳細調査 (Qwen-Deep-Research)

最終更新日:Dec 04, 2025

複雑なトピックに関する従来の手動検索は時間がかかり、ウェブ検索を組み込んだモデルは、深く体系的な分析に苦労することがよくあります。Qwen-Deep-Research は、調査ステップの計画、複数回の詳細な検索の実行、情報の統合、構造化された調査レポートの生成を自動化します。

重要

このドキュメントは、中国 (北京) リージョンにのみ適用されます。モデルを使用するには、中国 (北京) リージョンの API キー を使用する必要があります。

クイックスタート

API キーを取得し、API キーを環境変数として設定する必要があります。SDK を使用して呼び出しを行う場合は、DashScope SDK をインストールする必要もあります。

このモデルは、調査範囲を明確にするためのフォローアップ質問と、検索を実行してレポートを生成する詳細調査という 2 段階のワークフローを採用しています。

現在、このモデルは DashScope SDK のみをサポートしています。Java DashScope SDK および OpenAI 互換 API はサポートされていません。
import os
import dashscope

# API キーを設定
# 環境変数を設定していない場合は、次の行を Model Studio の API キーに置き換えてください:API_KEY = "sk-xxx"
API_KEY = os.getenv('DASHSCOPE_API_KEY')

def call_deep_research_model(messages, step_name):
    print(f"\n=== {step_name} ===")
    
    try:
        responses = dashscope.Generation.call(
            api_key=API_KEY,
            model="qwen-deep-research",
            messages=messages,
            # qwen-deep-research モデルは現在、ストリーミング出力のみをサポートしています
            stream=True
            # 増分出力を使用するには、incremental_output=True パラメーターを追加します
        )
        
        return process_responses(responses, step_name)
        
    except Exception as e:
        print(f"API 呼び出し時にエラーが発生しました:{e}")
        return ""


# フェーズの内容を表示
def display_phase_content(phase, content, status):
    if content:
        print(f"\n[{phase}] {status}: {content}")
    else:
        print(f"\n[{phase}] {status}")

# 応答を処理
def process_responses(responses, step_name):
    current_phase = None
    phase_content = ""
    research_goal = ""
    web_sites = []
    references = []
    keepalive_shown = False  # KeepAlive プロンプトが表示されたかどうかを確認するためのフラグ

    for response in responses:
        # 応答のステータスコードを確認
        if hasattr(response, 'status_code') and response.status_code != 200:
            print(f"HTTP リターンコード:{response.status_code}")
            if hasattr(response, 'code'):
                print(f"エラーコード:{response.code}")
            if hasattr(response, 'message'):
                print(f"エラーメッセージ:{response.message}")
            print("詳細については、https://www.alibabacloud.com/help/model-studio/error-code をご参照ください")
            continue

        if hasattr(response, 'output') and response.output:
            message = response.output.get('message', {})
            phase = message.get('phase')
            content = message.get('content', '')
            status = message.get('status')
            extra = message.get('extra', {})

            # フェーズの変更を検出
            if phase != current_phase:
                if current_phase and phase_content:
                    # フェーズ名とステップ名に基づいて異なる完了説明を表示
                    if step_name == "Step 1: Model follow-up question for confirmation" and current_phase == "answer":
                        print(f"\n モデルのフォローアップ質問フェーズが完了しました")
                    else:
                        print(f"\n {current_phase} フェーズが完了しました")
                current_phase = phase
                phase_content = ""
                keepalive_shown = False  # KeepAlive プロンプトフラグをリセット

                # フェーズ名とステップ名に基づいて異なる説明を表示
                if step_name == "Step 1: Model follow-up question for confirmation" and phase == "answer":
                    print(f"\n モデルのフォローアップ質問フェーズに入ります")
                else:
                    print(f"\n {phase} フェーズに入ります")
                    
            # Answer フェーズのリファレンス情報を処理
            if phase == "answer":
                if extra.get('deep_research', {}).get('references'):
                    new_references = extra['deep_research']['references']
                    if new_references and new_references != references:  # 重複表示を避ける
                        references = new_references
                        print(f"\n   リファレンス ({len(references)}):")
                        for i, ref in enumerate(references, 1):
                            print(f"     {i}. {ref.get('title', 'No title')}")
                            if ref.get('url'):
                                print(f"        URL: {ref['url']}")
                            if ref.get('description'):
                                print(f"        説明:{ref['description'][:100]}...")
                            print()

            # WebResearch フェーズの特別情報を処理
            if phase == "WebResearch":
                if extra.get('deep_research', {}).get('research'):
                    research_info = extra['deep_research']['research']

                    # streamingQueries ステータスを処理
                    if status == "streamingQueries":
                        if 'researchGoal' in research_info:
                            goal = research_info['researchGoal']
                            if goal:
                                research_goal += goal
                                print(f"\n   調査目標:{goal}", end='', flush=True)

                    # streamingWebResult ステータスを処理
                    elif status == "streamingWebResult":
                        if 'webSites' in research_info:
                            sites = research_info['webSites']
                            if sites and sites != web_sites:  # 重複表示を避ける
                                web_sites = sites
                                print(f"\n   {len(sites)} 件の関連ウェブサイトが見つかりました:")
                                for i, site in enumerate(sites, 1):
                                    print(f"     {i}. {site.get('title', 'No title')}")
                                    print(f"        説明:{site.get('description', 'No description')[:100]}...")
                                    print(f"        URL: {site.get('url', 'No link')}")
                                    if site.get('favicon'):
                                        print(f"        アイコン:{site['favicon']}")
                                    print()

                    # WebResultFinished ステータスを処理
                    elif status == "WebResultFinished":
                        print(f"\n   ウェブ検索が完了しました。{len(web_sites)} 件のリファレンスソースが見つかりました。")
                        if research_goal:
                            print(f"   調査目標:{research_goal}")

            # コンテンツを蓄積して表示
            if content:
                phase_content += content
                # コンテンツをリアルタイムで表示
                print(content, end='', flush=True)

            # フェーズのステータス変更を表示
            if status and status != "typing":
                print(f"\n   ステータス:{status}")

                # ステータスの説明を表示
                if status == "streamingQueries":
                    print("   → 調査目標と検索クエリを生成中 (WebResearch フェーズ)")
                elif status == "streamingWebResult":
                    print("   → 検索、ウェブページの読み取り、コードの実行を実行中 (WebResearch フェーズ)")
                elif status == "WebResultFinished":
                    print("   → ウェブ検索フェーズが完了 (WebResearch フェーズ)")

            # ステータスが 'finished' の場合、トークン使用量を表示
            if status == "finished":
                if hasattr(response, 'usage') and response.usage:
                    usage = response.usage
                    print(f"\n    トークン使用量の統計:")
                    print(f"      入力トークン:{usage.get('input_tokens', 0)}")
                    print(f"      出力トークン:{usage.get('output_tokens', 0)}")
                    print(f"      リクエスト ID:{response.get('request_id', 'Unknown')}")

            if phase == "KeepAlive":
                # KeepAlive フェーズに初めて入ったときのみプロンプトを表示
                if not keepalive_shown:
                    print("現在のステップは完了しました。次のステップの準備をしています。")
                    keepalive_shown = True
                continue

    if current_phase and phase_content:
        if step_name == "Step 1: Model follow-up question for confirmation" and current_phase == "answer":
            print(f"\n モデルのフォローアップ質問フェーズが完了しました")
        else:
            print(f"\n {current_phase} フェーズが完了しました")

    return phase_content

def main():
    # API キーを確認
    if not API_KEY:
        print("エラー:DASHSCOPE_API_KEY 環境変数が設定されていません。")
        print("環境変数を設定するか、コード内の API_KEY 変数を直接変更してください。")
        return
    
    print("ユーザーが会話を開始:教育における人工知能の応用を調査")
    
    # ステップ 1:確認のためのモデルのフォローアップ質問
    # モデルはユーザーの質問を分析し、調査の方向性を明確にするためにフォローアップの質問をします。
    messages = [{'role': 'user', 'content': '教育における人工知能の応用を調査'}]
    step1_content = call_deep_research_model(messages, "Step 1: Model follow-up question for confirmation")

    # ステップ 2:詳細調査
    # ステップ 1 のフォローアップ質問の内容に基づいて、モデルは完全な調査プロセスを実行します。
    messages = [
        {'role': 'user', 'content': '教育における人工知能の応用を調査'},
        {'role': 'assistant', 'content': step1_content},  # モデルのフォローアップ質問を含む
        {'role': 'user', 'content': '主にパーソナライズされた学習とインテリジェント評価に関心があります。'}
    ]
    
    call_deep_research_model(messages, "Step 2: Deep research")
    print("\n 調査完了!")

if __name__ == "__main__":
    main()
echo "Step 1: Model follow-up question for confirmation"
curl --location 'https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation' \
--header 'X-DashScope-SSE: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
    "input": {
        "messages": [
            {
                "content": "Research the applications of artificial intelligence in education", 
                "role": "user"
            }
        ]
    },
    "model": "qwen-deep-research"
}'

echo -e "\n\n" 
echo "Step 2: Deep research"
curl --location 'https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation' \
--header 'X-DashScope-SSE: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
    "input": {
        "messages": [
            {
                "content": "Research the applications of artificial intelligence in education", 
                "role": "user"
            },
            {
                "content": "Which specific application scenarios of artificial intelligence in education would you like to focus on?", 
                "role": "assistant"
            },
            {
                "content": "I am mainly interested in personalized learning.", 
                "role": "user"
            }
        ]
    },
    "model": "qwen-deep-research"
}'

モデルの可用性

モデル

コンテキストウィンドウ (トークン)

最大入力 (トークン)

最大出力 (トークン)

qwen-deep-research

1,000,000

997,952

32,768

コア機能

このモデルは、phasestatus フィールドを使用してワークフローのステータスを示します。phase フィールドは現在のコアタスクを示し、status フィールドはそのタスクの進捗状況を示します。

フォローアップ質問とレポート生成 (phase: "answer")

モデルはユーザーの最初の質問を分析し、調査範囲を確認するためにフォローアップの質問をします。このフェーズは、最終レポートが生成される際に再利用されます。

ステータスの変更:

  • typing:テキストコンテンツを生成中。

  • finished:テキスト生成が完了。

調査計画 (phase: "ResearchPlanning")

このフェーズでは、ユーザーの要件に基づいて調査の概要を作成します。

ステータスの変更:

  • typing:調査計画を生成中。

  • finished:調査計画が完了。

ウェブ検索 (phase: "WebResearch")

このフェーズでは、モデルは検索を実行し、情報を処理します。

ステータスの変更:

  • streamingQueries:検索クエリを生成中。

  • streamingWebResult:ウェブ検索を実行し、ページコンテンツを分析中。

  • WebResultFinished:ウェブ検索と情報抽出が完了。

永続的接続 (phase: "KeepAlive")

このメッセージは、長時間実行されるタスク間で接続を維持するために送信されます。このフェーズにはビジネス関連のコンテンツは含まれておらず、無視できます。

課金情報

モデル

入力価格 (1,000 トークンあたり)

出力価格 (1,000 トークンあたり)

無料クォータ

qwen-deep-research

$0.007742

$0.023367

無料クォータなし

課金方法:課金は、入力トークンと出力トークンの総数に基づきます。入力トークンには、ユーザーメッセージのコンテンツとモデルに組み込まれたシステムプロンプトが含まれます。出力トークンには、フォローアップの質問、調査計画、調査目標、検索クエリ、最終的な調査レポートなど、生成されたすべてのコンテンツが含まれます。

本番環境への適用

ストリーミング出力の処理

このモデルはストリーミング出力 (stream=True) のみをサポートしています。応答を処理する際には、phasestatus フィールドを解析して、現在のフェーズとその完了ステータスを判断する必要があります。

エラーの処理

応答のステータスコードを確認し、200 以外のステータスに対するエラーを処理します。ストリーミング応答の初期段階では、一部の応答チャンクにはメタデータのみが含まれている場合があります。後続のチャンクには実際のコンテンツが含まれます。

トークン消費量の監視

statusfinished の場合、response.usage からトークン消費量の統計を取得できます。これらの統計には、入力トークン数、出力トークン数、およびリクエスト ID が含まれます。

接続の管理

モデルは、長時間実行されるタスク間で接続を維持するために KeepAlive フェーズの応答を送信することがあります。このフェーズの内容は無視して、後続の応答の処理を続けることができます。

よくある質問

  • 一部の応答チャンクで output フィールドが空なのはなぜですか?

    ストリーミング応答の初期段階では、一部の応答チャンクにはメタデータのみが含まれている場合があります。後続のチャンクには実際のコンテンツが含まれます。

  • フェーズが完了したかどうかを判断するにはどうすればよいですか?

    status フィールドが "finished" に変わると、フェーズは完了です。

  • モデルは OpenAI 互換 API 呼び出しをサポートしていますか?

    いいえ、現在このモデルは OpenAI 互換 API 呼び出しをサポートしていません。

  • 入力トークンと出力トークンの数はどのように計算されますか?

    入力トークンには、ユーザーから送信されたメッセージのコンテンツと、モデルに組み込まれたシステムプロンプトが含まれます。出力トークンには、フォローアップの質問、調査計画、調査目標、検索クエリ、最終的な調査レポートなど、調査プロセス全体でモデルによって生成されたすべてのコンテンツが含まれます。

API リファレンス

Qwen-Deep-Research の入出力パラメーターについては、「Qwen-Deep-Research API リファレンス」をご参照ください。

エラーコード

呼び出しが失敗した場合は、「エラーメッセージ」を参照してトラブルシューティングを行ってください。

レート制限

レート制限については、「レート制限」をご参照ください。