All Products
Search
Document Center

Alibaba Cloud Model Studio:Deep research (Qwen-Deep-Research)

Last Updated:Jan 26, 2026

Qwen-Deep-Research automates complex research tasks by planning research steps, performing multiple rounds of web searches, and generating structured research reports. It can gather and synthesize information on complex topics without manual effort.

Note

This document applies only to the China (Beijing) region. Use an API key from the China (Beijing) region.

Getting started

Prerequisites

The model uses a two-step workflow:

  • Follow-up question: The model analyzes your initial query and asks clarifying questions to define the research scope.

  • Deep research: Based on your responses, the model performs web searches, analyzes content, and generates a structured research report.

Currently, the model does not support DashScope SDK for Java and OpenAI-compatible API.
import os
import dashscope

# Configure the API key
# If you have not configured the environment variable, replace the following line with your Model Studio API key: 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,
            # The qwen-deep-research model currently supports only streaming output
            stream=True
            # To use incremental output, add the incremental_output=True parameter
        )
        
        return process_responses(responses, step_name)
        
    except Exception as e:
        print(f"An error occurred when calling the API: {e}")
        return ""


# Display the phase content
def display_phase_content(phase, content, status):
    if content:
        print(f"\n[{phase}] {status}: {content}")
    else:
        print(f"\n[{phase}] {status}")

# Process the responses
def process_responses(responses, step_name):
    current_phase = None
    phase_content = ""
    research_goal = ""
    web_sites = []
    references = []
    keepalive_shown = False  # A flag to check if the KeepAlive prompt has been displayed

    for response in responses:
        # Check the response status code
        if hasattr(response, 'status_code') and response.status_code != 200:
            print(f"HTTP return code: {response.status_code}")
            if hasattr(response, 'code'):
                print(f"Error code: {response.code}")
            if hasattr(response, 'message'):
                print(f"Error message: {response.message}")
            print("For more information, see https://www.alibabacloud.com/help/en/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', {})

            # Detect phase changes
            if phase != current_phase:
                if current_phase and phase_content:
                    # Display different completion descriptions based on the phase name and step name
                    if step_name == "Step 1: Model follow-up question for confirmation" and current_phase == "answer":
                        print(f"\n Model follow-up question phase completed")
                    else:
                        print(f"\n {current_phase} phase completed")
                current_phase = phase
                phase_content = ""
                keepalive_shown = False  # Reset the KeepAlive prompt flag

                # Display different descriptions based on the phase name and step name
                if step_name == "Step 1: Model follow-up question for confirmation" and phase == "answer":
                    print(f"\n Entering model follow-up question phase")
                else:
                    print(f"\n Entering {phase} phase")
                    
            # Process reference information for the Answer phase
            if phase == "answer":
                if extra.get('deep_research', {}).get('references'):
                    new_references = extra['deep_research']['references']
                    if new_references and new_references != references:  # Avoid duplicate display
                        references = new_references
                        print(f"\n   References ({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"        Description: {ref['description'][:100]}...")
                            print()

            # Process special information for the WebResearch phase
            if phase == "WebResearch":
                if extra.get('deep_research', {}).get('research'):
                    research_info = extra['deep_research']['research']

                    # Process the streamingQueries status
                    if status == "streamingQueries":
                        if 'researchGoal' in research_info:
                            goal = research_info['researchGoal']
                            if goal:
                                research_goal += goal
                                print(f"\n   Research goal: {goal}", end='', flush=True)

                    # Process the streamingWebResult status
                    elif status == "streamingWebResult":
                        if 'webSites' in research_info:
                            sites = research_info['webSites']
                            if sites and sites != web_sites:  # Avoid duplicate display
                                web_sites = sites
                                print(f"\n   Found {len(sites)} relevant websites:")
                                for i, site in enumerate(sites, 1):
                                    print(f"     {i}. {site.get('title', 'No title')}")
                                    print(f"        Description: {site.get('description', 'No description')[:100]}...")
                                    print(f"        URL: {site.get('url', 'No link')}")
                                    if site.get('favicon'):
                                        print(f"        Icon: {site['favicon']}")
                                    print()

                    # Process the WebResultFinished status
                    elif status == "WebResultFinished":
                        print(f"\n   Web search completed. Found {len(web_sites)} reference sources.")
                        if research_goal:
                            print(f"   Research goal: {research_goal}")

            # Accumulate and display content
            if content:
                phase_content += content
                # Display content in real time
                print(content, end='', flush=True)

            # Display phase status changes
            if status and status != "typing":
                print(f"\n   Status: {status}")

                # Display status description
                if status == "streamingQueries":
                    print("   → Generating research goals and search queries (WebResearch phase)")
                elif status == "streamingWebResult":
                    print("   → Performing search, web page reading, and code execution (WebResearch phase)")
                elif status == "WebResultFinished":
                    print("   → Web search phase completed (WebResearch phase)")

            # When the status is 'finished', display token usage
            if status == "finished":
                if hasattr(response, 'usage') and response.usage:
                    usage = response.usage
                    print(f"\n    Token usage statistics:")
                    print(f"      Input tokens: {usage.get('input_tokens', 0)}")
                    print(f"      Output tokens: {usage.get('output_tokens', 0)}")
                    print(f"      Request ID: {response.get('request_id', 'Unknown')}")

            if phase == "KeepAlive":
                # Display the prompt only the first time the KeepAlive phase is entered
                if not keepalive_shown:
                    print("The current step is complete. Preparing for the next step.")
                    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 Model follow-up question phase completed")
        else:
            print(f"\n {current_phase} phase completed")

    return phase_content

def main():
    # Check the API key
    if not API_KEY:
        print("Error: The DASHSCOPE_API_KEY environment variable is not set.")
        print("Set the environment variable or directly modify the API_KEY variable in the code.")
        return
    
    print("User initiates conversation: Research the applications of artificial intelligence in education")
    
    # Step 1: Model follow-up question for confirmation
    # The model analyzes the user's question and asks follow-up questions to clarify the research direction.
    messages = [{'role': 'user', 'content': 'Research the applications of artificial intelligence in education'}]
    step1_content = call_deep_research_model(messages, "Step 1: Model follow-up question for confirmation")

    # Step 2: Deep research
    # Based on the content of the follow-up question in Step 1, the model executes the complete research process.
    messages = [
        {'role': 'user', 'content': 'Research the applications of artificial intelligence in education'},
        {'role': 'assistant', 'content': step1_content},  # Contains the model's follow-up question
        {'role': 'user', 'content': 'I am mainly interested in personalized learning and intelligent assessment.'}
    ]
    
    call_deep_research_model(messages, "Step 2: Deep research")
    print("\n Research complete!")

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"
}'

Core capabilities

The model uses the phase and status fields to indicate progress.

Phases

Phase

Phase description

Status

Status description

answer

Generates follow-up question or the final report

typing

Generating the texts

finished

Text generation is complete

ResearchPlanning

Creates a research outline

typing

Generating the research plan

finished

The research plan is complete

WebResearch

Web searches and content analysis

streamingQueries

Generating search queries

streamingWebResult

Performing web searches and analyzing page content

WebResultFinished

Web search and information extraction are complete

KeepAlive

Sent between long-running tasks to maintain the connection. Ignore this phase

Specifications

Model

Context window (Tokens)

Max input (Tokens)

Max output (Tokens)

qwen-deep-research

1,000,000

997,952

32,768

Billing

Model

Input price (per 1K tokens)

Output price (per 1K tokens)

Free quota

qwen-deep-research

$0.007742

$0.023367

No free quota

Rules: Billing is based on total input and output tokens. Input tokens include user messages and the model's built-in system prompts. Output tokens include all generated content: follow-up questions, research plans, research goals, search queries, and the final report.

Going live

Handle streaming output

The model supports only streaming output (stream=True). Parse the phase and status fields to track progress.

Handle errors

Check the response status code for non-200 statuses.

Monitor token usage

When the status is finished, retrieve token consumption statistics from response.usage, including input tokens, output tokens, and the request ID.

FAQ

  • Why is the output field empty for some response chunks?

    Early streaming chunks might contain only metadata. Subsequent chunks contain the actual content.

  • How can I determine if a phase is complete?

    A phase is complete when the status field changes to "finished".

  • Does the model support OpenAI-compatible API calls?

    No, the model does not currently support OpenAI-compatible API calls.

  • How are the input and output tokens calculated?

    Input tokens include the user messages and the model's built-in system prompts. Output tokens include all content generated by the model throughout the research process, such as the follow-up question, research plan, research goals, search queries, and the final report.

API reference

Qwen-Deep-Research API reference.

Error codes

If a call fails, see Error messages for troubleshooting.