Tous les produits
Search
Centre de documentation

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

Dernière mise à jour :Oct 11, 2026

Automatise les recherches complexes par la planification, plusieurs cycles de recherche web et la génération de rapports structurés. Ce modèle collecte et synthétise les informations sans intervention manuelle.

RemarqueCe document s'applique uniquement à la région Chine continentale (Pékin). Pour utiliser ce modèle, utilisez une clé API de la région Chine continentale (Pékin).

Prise en main

Obtenir une clé API et exporter la clé API en tant que variable d'environnement. Si vous utilisez un SDK pour vos appels, installez le SDK DashScope.

Le modèle suit un flux de travail en deux étapes : une phase de questions de suivi (le modèle précise le périmètre de votre recherche) et une phase de recherche approfondie (le modèle effectue des recherches, analyse les données et génère un rapport). La phase de questions de suivi permet au modèle de cerner précisément le sujet avant de lancer un long processus de recherche.

Actuellement, le modèle ne prend pas en charge le SDK DashScope pour Java ni les appels API compatibles OpenAI.

import os
import dashscope

# The following is the base_url for the Beijing region.
dashscope.base_http_api_url = 'https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api/v1'

# Configure the API key
# If not set, replace the following line with your Model Studio API key (format: 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 only supports streaming output
            stream=True
            # incremental_output=True Add this parameter for incremental output
        )

        return process_responses(responses, step_name)

    except Exception as e:
        print(f"An error occurred when calling the API: {e}")
        return ""

# Display 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 response
def process_responses(responses, step_name):
    current_phase = None
    phase_content = ""
    research_goal = ""
    web_sites = []
    references = []
    keepalive_shown = False  # Flag to check if the KeepAlive prompt has been shown

    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', {})

            # Phase change detection
            if phase != current_phase:
                if current_phase and phase_content:
                    # Display different completion descriptions based on phase and step names
                    if step_name == "Step 1: Model query confirmation" and current_phase == "answer":
                        print(f"\n Query confirmation phase completed")
                    else:
                        print(f"\n {current_phase} phase completed")
                current_phase = phase
                phase_content = ""
                keepalive_shown = False  # Reset KeepAlive prompt flag

                # Display different descriptions based on phase and step names
                if step_name == "Step 1: Model query confirmation" and phase == "answer":
                    print(f"\n Entering query confirmation phase")
                else:
                    print(f"\n Entering {phase} phase")

            # Process reference information in 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 in the WebResearch phase
            # Note: The qwen-deep-research-2025-12-15 model uses the streamingThinking status
            # instead of streamingQueries and streamingWebResult
            if phase == "WebResearch":
                if extra.get('deep_research', {}).get('research'):
                    research_info = extra['deep_research']['research']

                    # Process streamingThinking (snapshot model) or streamingQueries (mainline model) status
                    if status in ("streamingThinking", "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 streamingWebResult status (mainline model)
                    # The snapshot model merges this status using streamingThinking
                    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 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 == "streamingThinking":
                    print("   → Decomposing research tasks and summarizing web content (WebResearch phase)")
                elif status == "streamingQueries":
                    print("   → Generating research goals and search queries (WebResearch phase)")
                elif status == "streamingWebResult":
                    print("   → Performing searches, web page reading, and code execution (WebResearch phase)")
                elif status == "WebResultFinished":
                    print("   → Web search phase completed (WebResearch phase)")

            # When status is finished, display token consumption
            if status == "finished":
                if hasattr(response, 'usage') and response.usage:
                    usage = response.usage
                    print(f"\n    Token consumption 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":
                # Only display the prompt the first time entering the KeepAlive phase
                if not keepalive_shown:
                    print("Current step completed. Preparing for the next step.")
                    keepalive_shown = True
                continue

    if current_phase and phase_content:
        if step_name == "Step 1: Model query confirmation" and current_phase == "answer":
            print(f"\n Query confirmation phase completed")
        else:
            print(f"\n {current_phase} phase completed")

    return phase_content

def main():
    # Check API key
    if not API_KEY:
        print("Error: DASHSCOPE_API_KEY environment variable not set")
        print("Set the environment variable or modify the API_KEY variable directly in the code")
        return

    print("User initiates conversation: Research the application of artificial intelligence in education")

    # Step 1: Model query confirmation
    # The model analyzes the user's question and asks clarifying questions to define the research direction
    messages = [{'role': 'user', 'content': 'Research the application of artificial intelligence in education'}]
    step1_content = call_deep_research_model(messages, "Step 1: Model query confirmation")

    # Step 2: Deep research
    # Based on the query confirmation from Step 1, the model performs the full research process
    messages = [
        {'role': 'user', 'content': 'Research the application of artificial intelligence in education'},
        {'role': 'assistant', 'content': step1_content},  # Includes the model's query confirmation content
        {'role': 'user', 'content': 'I mainly focus on personalized learning and intelligent assessment'}
    ]

    call_deep_research_model(messages, "Step 2: Deep research")
    print("\n Research completed!")

if __name__ == "__main__":
    main()
echo "Step 1: Model query confirmation"
# The following is the base_url for the Beijing region.
curl --location 'https://{WorkspaceId}.cn-beijing.maas.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 application of artificial intelligence in education",
                "role": "user"
            }
        ]
    },
    "model": "qwen-deep-research"
}'

echo -e "\n\n"
echo "Step 2: Deep research"
# The following is the base_url for the Beijing region.
curl --location 'https://{WorkspaceId}.cn-beijing.maas.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 application of artificial intelligence in education",
                "role": "user"
            },
            {
                "content": "Tell me which specific application scenarios of artificial intelligence in education you want to focus on?",
                "role": "assistant"
            },
            {
                "content": "I mainly focus on personalized learning",
                "role": "user"
            }
        ]
    },
    "model": "qwen-deep-research"
}'

Spécifications

Modèle

Fenêtre de contexte (tokens)

Entrée max. (tokens)

Sortie max. (tokens)

qwen-deep-research

1 000 000

997 952

32 768

qwen-deep-research-2025-12-15

Remarqueqwen-deep-research : modèle principal, mis à jour en continu. qwen-deep-research-2025-12-15 : version snapshot offrant une profondeur et une qualité accrues, ainsi que l'appel d'outils MCP. Les deux modèles prennent en charge l'entrée d'images et font l'objet d'une facturation distincte.

Capacités principales

Suivez la progression via les champs phase (tâche en cours) et status (avancement de la tâche).

Questions de suivi et génération de rapport (phase : « answer »)

Cette étape analyse votre requête, pose des questions de clarification pour définir le périmètre, puis génère le rapport de recherche final.

Valeurs de statut possibles :

  • typing : génération du contenu textuel en cours
  • finished : génération du contenu textuel terminée
Planification de la recherche (phase : « ResearchPlanning »)

Le modèle élabore un plan de recherche à partir de votre requête.

Valeurs de statut possibles :

  • typing : élaboration du plan de recherche en cours
  • finished : plan de recherche terminé
Recherche web (phase : « WebResearch »)

Le modèle exécute plusieurs cycles de recherches web et d'analyse de contenu. Le statut WebResultFinished signale la fin de chaque cycle, tandis que finished marque la fin de la phase.

Valeurs de statut possibles :

  • streamingThinking : décomposition des tâches de recherche et synthèse du contenu web (spécifique à qwen-deep-research-2025-12-15, remplace streamingQueries et streamingWebResult)
  • streamingQueries : génération des requêtes de recherche (uniquement pour qwen-deep-research)
  • streamingWebResult : exécution des recherches web et analyse du contenu (uniquement pour qwen-deep-research)
  • WebResultFinished : cycle de recherche terminé
  • finished : phase de recherche web terminée
Maintien de connexion (phase : « KeepAlive »)

Cette phase maintient la connexion active entre les tâches de longue durée. Ignorez-la et poursuivez le traitement du flux.

Entrée d'images

Les deux modèles acceptent les images en entrée. Le modèle analyse l'image et intègre son contenu à sa recherche. Utilisez le format tableau pour le champ content en passant conjointement les objets image et text.

  • Formats pris en charge : JPEG, PNG, BMP, WEBP. Taille maximale de 10 Mo par image.
  • Jusqu'à 5 images par requête. Les URL publiques et l'encodage Base64 sont acceptés.
  • Le format de réponse est identique à celui des requêtes texte uniquement. Le modèle génère un rapport basé sur le contenu de l'image.
Exemple de requête
import os
import dashscope

# The following is the base_url for the Beijing region.
dashscope.base_http_api_url = 'https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api/v1'

API_KEY = os.getenv('DASHSCOPE_API_KEY')

messages = [
    {
        "role": "user",
        "content": [
            {"image": "https://example.aliyuncs.com/example.png"},
            {"text": "Analyze the data trends in this chart and conduct in-depth research on key findings"}
        ]
    }
]

responses = dashscope.Generation.call(
    api_key=API_KEY,
    model="qwen-deep-research",
    messages=messages,
    stream=True
)

for response in responses:
    if hasattr(response, 'output') and response.output:
        message = response.output.get('message', {})
        content = message.get('content', '')
        if content:
            print(content, end='', flush=True)
curl --location 'https://{WorkspaceId}.cn-beijing.maas.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": [
                    {"image": "https://example.aliyuncs.com/example.png"},
                    {"text": "Analyze the data trends in this chart and conduct in-depth research on key findings"}
                ],
                "role": "user"
            }
        ]
    },
    "model": "qwen-deep-research"
}'

Appel d'outils MCP

RemarqueL'appel d'outils MCP est uniquement pris en charge par qwen-deep-research-2025-12-15. Le modèle qwen-deep-research ne dispose pas de cette fonctionnalité.

L'appel d'outils via le protocole MCP (Model Context Protocol) permet à qwen-deep-research-2025-12-15 d'exploiter des sources de données privées ou spécifiques à un domaine durant la phase WebResearch (base de connaissances, documents internes, base de données propriétaire, etc.), en complément des recherches web standards. Transmettez la configuration du serveur MCP via le paramètre research_tools. Le format de réponse reste identique à celui des appels standards.

Pour plus de détails sur research_tools et les spécifications des outils MCP, consultez Qwen-Deep-Research .

Exemple de requête

import os
import dashscope

# The following is the base_url for the Beijing region.
dashscope.base_http_api_url = 'https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api/v1'

API_KEY = os.getenv('DASHSCOPE_API_KEY')

messages = [
    {
        "role": "user",
        "content": "Use the knowledge base to search for recently published product update announcements and compile them into a research report"
    }
]

responses = dashscope.Generation.call(
    api_key=API_KEY,
    model="qwen-deep-research-2025-12-15",
    messages=messages,
    stream=True,
    enable_feedback=False,
    research_tools=[{
        "type": "mcp",
        "server_label": "my-server",
        "server_url": "https://your-mcp-server.example.com/sse",
        "allowed_tools": ["search", "fetch"],
        "authentication": {
            "bearer": "your_jwt_token_here"
        }
    }]
)

for response in responses:
    if hasattr(response, 'output') and response.output:
        message = response.output.get('message', {})
        content = message.get('content', '')
        if content:
            print(content, end='', flush=True)
curl --location 'https://{WorkspaceId}.cn-beijing.maas.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": "Use the knowledge base to search for recently published product update announcements and compile them into a research report",
                "role": "user"
            }
        ]
    },
    "model": "qwen-deep-research-2025-12-15",
    "parameters": {
        "enable_feedback": false,
        "research_tools": [{
            "type": "mcp",
            "server_label": "my-server",
            "server_url": "https://your-mcp-server.example.com/sse",
            "allowed_tools": ["search", "fetch"],
            "authentication": {
                "bearer": "your_jwt_token_here"
            }
        }]
    }
}'

Facturation

Modèle

Coût d'entrée (pour 1K tokens)

Coût de sortie (pour 1K tokens)

Quota gratuit

qwen-deep-research

0,007742 $

0,023367 $

Aucun quota gratuit

qwen-deep-research-2025-12-15

À déterminer

À déterminer

Aucun quota gratuit

La facturation repose sur les tokens d'entrée (messages utilisateur et invites système) et les tokens de sortie (questions de suivi, plans de recherche, objectifs, requêtes de recherche et rapport final). Les deux modèles sont facturés séparément.

Mise en production

Utiliser la sortie en streaming

Le modèle prend uniquement en charge la sortie en streaming (stream=True). Une tâche de recherche unique peut s'exécuter pendant plusieurs minutes à travers des dizaines de cycles itératifs de recherche et de lecture, dépassant ainsi le délai d'expiration d'une requête synchrone. Le streaming permet de maintenir la connexion ouverte et de suivre la progression via les champs phase et status.

Gérer les erreurs

Vérifiez le code de statut de la réponse pour chaque fragment. En cas de code différent de 200, consultez les champs code et message afin de traiter l'erreur de manière appropriée.

Surveiller la consommation de tokens

Lorsque le status passe à finished, récupérez les statistiques d'utilisation des tokens depuis response.usage (tokens d'entrée, tokens de sortie et ID de requête).

Gérer le maintien de connexion

La phase KeepAlive assure le maintien de la connexion entre les tâches de longue durée. Ignorez cette phase et continuez à traiter le flux.

FAQ

  • Pourquoi le champ de sortie est-il vide pour certains fragments de réponse ?

    Les premiers fragments ne contiennent que des métadonnées. Le contenu arrive dans les fragments suivants, au fur et à mesure de sa génération par le modèle.

  • Comment savoir si une phase est terminée ?

    Une phase est considérée comme terminée lorsque le status passe à finished.

  • Le modèle prend-il en charge les appels API compatibles OpenAI ?

    Non, les appels API compatibles OpenAI ne sont pas pris en charge.

  • Comment les tokens d'entrée et de sortie sont-ils calculés ?

    Tokens d'entrée : messages utilisateur et invites système. Tokens de sortie : questions de suivi, plans de recherche, objectifs, requêtes de recherche et rapport final.

  • Quelle est la différence entre qwen-deep-research et qwen-deep-research-2025-12-15 ?

    qwen-deep-research : modèle principal, mis à jour en continu. qwen-deep-research-2025-12-15 : version snapshot offrant une profondeur et une qualité accrues, ainsi que la prise en charge MCP. Les deux modèles acceptent les entrées d'images et font l'objet d'une facturation distincte.

  • Comment transmettre des images pour la recherche ?

    Utilisez le format tableau pour le champ content : passez {"image": "URL"} et {"text": "description"} en tant qu'objets dans le tableau. Les deux modèles prennent en charge les entrées d'images.

  • Comment ignorer les questions de suivi et lancer directement la recherche ?

    Définissez enable_feedback sur false dans les parameters. Le modèle ignorera alors les questions de suivi et démarrera immédiatement la recherche.

Référence API

Pour les paramètres d'entrée et de sortie, consultez Qwen-Deep-Research.

Codes d'erreur

Si l'appel du modèle échoue et renvoie un message d'erreur, consultez la rubrique Codes d'erreur pour obtenir des instructions de résolution.

Limitation de débit

Consultez la rubrique Limitation de débit.