Skip to main content
文本產生

多輪對話

通義千問 API 是無狀態的,不會儲存對話歷史。要實現多輪對話,需在每次請求中顯式傳入歷史對話訊息,並可結合截斷、摘要、召回等策略,高效管理上下文,減少 Token 消耗。

本文介紹如何通過 OpenAI 相容的 Chat Completion 介面或 DashScope 介面實現多輪對話。 Responses API 可更便捷地實現多輪對話,參見:OpenAI相容-Responses

工作原理

實現多輪對話的核心是維護一個 messages 數組。每一輪對話都需要將使用者的最新提問和模型的回複追加到此數組中,並將其作為下一次請求的輸入。 以下樣本為多輪對話時 messages 的狀態變化:
  1. 第一輪對話 messages 數組添加使用者問題。
// 使用文本模型
[
    {"role": "user", "content": "推薦一部關於太空探索的科幻電影。"}
]

// 使用多模態模型,以 Qwen-VL 為例
// {"role": "user",
//       "content": [{"type": "image_url","image_url": {"url": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20251031/ownrof/f26d201b1e3f4e62ab4a1fc82dd5c9bb.png"}},
//                   {"type": "text", "text": "請問圖片展現了有哪些商品?"}]
// }
  1. 第二輪對話 messages數組添加大模型回複內容與使用者的最新提問。
// 使用文本模型
[
    {"role": "user", "content": "推薦一部關於太空探索的科幻電影。"},
    {"role": "assistant", "content": "我推薦《xxx》,這是一部經典的科幻作品。"},
    {"role": "user", "content": "這部電影的導演是誰?"}
]

// 使用多模態模型,以 Qwen-VL 為例
//[
//    {"role": "user", "content": [
//                    {"type": "image_url","image_url": {"url": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20251031/ownrof/f26d201b1e3f4e62ab4a1fc82dd5c9bb.png"}},
//                   {"type": "text", "text": "請問圖片展現了有哪些商品?"}]},
//    {"role": "assistant", "content": "圖片展示了三件商品:一件淺藍色背帶褲、一件藍白條紋短袖襯衫和一雙白色運動鞋。"},
//    {"role": "user", "content": "它們屬於什麼風格?"}
//]

快速開始

  • OpenAI相容
  • DashScope
Python
import os
from openai import OpenAI

def get_response(messages):
    client = OpenAI(
        # 各地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/zh/model-studio/get-api-key
        # 若沒有配置環境變數,請用阿里雲百鍊API Key將下行替換為:api_key="sk-xxx",
        api_key=os.getenv("DASHSCOPE_API_KEY"),
        # 以下為新加坡地區URL,調用時請將WorkspaceId替換為真實的業務空間ID,各地區的URL不同。
        base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
    )
    # 模型列表:https://www.alibabacloud.com/help/zh/model-studio/getting-started/models
    completion = client.chat.completions.create(model="qwen-plus", messages=messages)
    return completion

# 初始化一個 messages 數組
messages = [
    {
        "role": "system",
        "content": """你是一名阿里雲百鍊手機商店的店員,你負責給使用者推薦手機。手機有兩個參數:螢幕尺寸(包括6.1英寸、6.5英寸、6.7英寸)、解析度(包括2K、4K)。
        你一次只能向使用者提問一個參數。如果使用者提供的資訊不全,你需要反問他,讓他提供沒有提供的參數。如果參數收集完成,你要說:我已瞭解您的購買意向,請稍等。""",
    }
]
assistant_output = "歡迎光臨阿里雲百鍊手機商店,您需要購買什麼尺寸的手機呢?"
print(f"模型輸出:{assistant_output}\n")
while "我已瞭解您的購買意向" not in assistant_output:
    user_input = input("請輸入:")
    # 將使用者問題資訊添加到messages列表中
    messages.append({"role": "user", "content": user_input})
    assistant_output = get_response(messages).choices[0].message.content
    # 將大模型的回複資訊添加到messages列表中
    messages.append({"role": "assistant", "content": assistant_output})
    print(f"模型輸出:{assistant_output}")
    print("\n")

多模態模型的多輪對話

多模態模型支援在對話中加入圖片、音頻等內容,其多輪對話的實現方式與文本模型主要有以下不同:
  • 使用者訊息(user message)的構造方式:多模態模型的使用者訊息不僅包含文本,還包含圖片、音頻等多模態資訊。
  • DashScope SDK介面:使用 DashScope Python SDK 時,需調用 MultiModalConversation 介面;使用DashScope Java SDK 時,需調用 MultiModalConversation 類。
多模態模型請參見:映像與視頻理解KimiQwen-Omni的實現方法請參見非即時(Qwen-Omni)。Qwen-VL-OCR、Qwen3-Omni-Captioner是為特定單輪任務設計的模型,不支援多輪對話。
  • OpenAI相容
  • DashScope
Python
from openai import OpenAI
import os

client = OpenAI(
    # 各地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/zh/model-studio/get-api-key
    # 若沒有配置環境變數,請用百鍊API Key將下行替換為:api_key="sk-xxx"
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # 以下為新加坡地區URL,調用時請將WorkspaceId替換為真實的業務空間ID,各地區的URL不同。
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1"
)
messages = [
        {"role": "user",
         "content": [
            {
                "type": "image_url",
                "image_url": {
                    "url": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20251031/ownrof/f26d201b1e3f4e62ab4a1fc82dd5c9bb.png"
                },
            },
            {"type": "text", "text": "請問圖片展現了有哪些商品?"},
        ],
    }
]
completion = client.chat.completions.create(
    model="qwen3-vl-plus",  #  可按需更換為其它多模態模型,並修改相應的 messages
    messages=messages,
    )
print(f"第一輪輸出: {completion.choices[0].message.content}")

assistant_message = completion.choices[0].message
messages.append(assistant_message.model_dump())
messages.append({
        "role": "user",
        "content": [
        {
            "type": "text",
            "text": "它們屬於什麼風格?"
        }
        ]
    })
completion = client.chat.completions.create(
    model="qwen3-vl-plus",
    messages=messages,
    )

print(f"第二輪輸出: {completion.choices[0].message.content}")

思考模型的多輪對話

思考模型返回reasoning_content(思考過程)與content(回複內容)兩個欄位。更新 messages 數組時,僅保留content欄位,忽略reasoning_content欄位。
[
    {"role": "user", "content": "推薦一部關於太空探索的科幻電影。"},
    {"role": "assistant", "content": "我推薦《xxx》,這是一部經典的科幻作品。"}, # 添加上下文時請勿添加reasoning_content欄位
    {"role": "user", "content": "這部電影的導演是誰?"}
]
思考模型詳情參見:深度思考映像與視頻理解視覺推理
Qwen3-Omni-Flash(思考模式)實現多輪對話請參見全模態
  • OpenAI相容
  • DashScope
  • Python
  • Node.js
  • HTTP

範例程式碼

from openai import OpenAI
import os

# 初始化OpenAI用戶端
client = OpenAI(
    # 各地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/zh/model-studio/get-api-key
    # 如果沒有配置環境變數,請用阿里雲百鍊API Key替換:api_key="sk-xxx"
    api_key = os.getenv("DASHSCOPE_API_KEY"),
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1"
)

messages = []
conversation_idx = 1
while True:
    reasoning_content = ""  # 定義完整思考過程
    answer_content = ""     # 定義完整回複
    is_answering = False   # 判斷是否結束思考過程並開始回複
    print("="*20+f"第{conversation_idx}輪對話"+"="*20)
    conversation_idx += 1
    user_input = input("請輸入你的訊息(輸入 exit 結束對話):")
    # 輸入 exit 結束多輪對話,避免迴圈無法退出
    if user_input.strip().lower() == "exit":
        print("對話已結束。")
        break
    user_msg = {"role": "user", "content": user_input}
    messages.append(user_msg)
    # 建立聊天完成請求
    completion = client.chat.completions.create(
        # 您可以按需更換為其它深度思考模型
        model="qwen-plus",
        messages=messages,
        extra_body={"enable_thinking": True},
        stream=True,
        # stream_options={
        #     "include_usage": True
        # }
    )
    print("\n" + "=" * 20 + "思考過程" + "=" * 20 + "\n")
    for chunk in completion:
        # 如果chunk.choices為空白,則列印usage
        if not chunk.choices:
            print("\nUsage:")
            print(chunk.usage)
        else:
            delta = chunk.choices[0].delta
            # 列印思考過程
            if hasattr(delta, 'reasoning_content') and delta.reasoning_content != None:
                print(delta.reasoning_content, end='', flush=True)
                reasoning_content += delta.reasoning_content
            else:
                # 開始回複
                if delta.content != "" and is_answering is False:
                    print("\n" + "=" * 20 + "完整回複" + "=" * 20 + "\n")
                    is_answering = True
                # 列印回複過程
                print(delta.content, end='', flush=True)
                answer_content += delta.content
    # 將模型回複的content添加到上下文中
    messages.append({"role": "assistant", "content": answer_content})
    print("\n")

應用於生產環境

多輪對話會帶來巨大的 Token 消耗,且容易超出大模型上下文最大長度導致報錯。以下策略可協助您有效管理上下文與控製成本。

1. 上下文管理

messages 數組會隨對話輪次增加而變長,最終可能超出模型的 Token 限制。建議參考以下內容,在對話過程中管理上下文長度。

1.1. 上下文截斷

當對話歷史過長時,保留最近的 N 輪對話歷史。該方式實現簡單,但會丟失較早的對話資訊。

1.2. 滾動摘要

為了在不丟失核心資訊的前提下動態壓縮對話歷史,控制上下文長度,可隨著對話的進行對上下文進行摘要: a. 對話歷史達到一定長度(如上下文長度最大值的 70%)時,將對話歷史中較早的部分(如前一半)提取出來,發起獨立 API 呼叫使大模型對這部分內容產生“記憶摘要”; b. 構建下一次請求時,用“記憶摘要”替換冗長的對話歷史,並拼接最近的幾輪對話。

1.3. 向量化召回

滾動摘要會丟失部分資訊,為了使模型可以從海量對話歷史中“回憶”起相關資訊,可將對話管理從“線性傳遞”轉變為“按需檢索”: a. 每輪對話結束後,將該輪對話存入向量資料庫; b. 使用者提問時,通過相似性檢索相關對話記錄; c. 將檢索到的對話記錄與最近的使用者輸入拼接後輸入大模型。

2. 成本控制

輸入 Token 數會隨著對話輪數增加,顯著增加使用成本,以下成本管理原則供您參考。

2.1. 減少輸入 Token

通過上文介紹的上下文管理原則減少輸入 Token,降低成本。

2.2. 使用支援上下文緩衝的模型

發起多輪對話請求時,messages 部分會重複計算並計費。阿里雲百鍊對qwen-maxqwen-plus等模型提供了上下文緩衝功能,可以降低使用成本並提升響應速度,建議優先使用支援上下文緩衝的模型。
上下文緩衝功能自動開啟,無需修改代碼。

錯誤碼

如果模型調用失敗並返回報錯資訊,請參見錯誤碼進行解決。
Token Plan
模型體驗
用量統計與效能監控
資產中心
服務支援
多輪對話 - Alibaba Cloud Model Studio