jollen.org

Jollen 的 Blog
Jollen's email: jollen # jollen.org
more:  Jollen's Training

Qwen3.5 上下文管理實作:以對話聊天為例

.作者:Jollen
.日期:July 30, 2026 at 8:00 AM


延續前一篇文章對 Qwen3.5 GDN 的研究,本文將進一步分析上下文管理的實作方式。主要目標是在 Apple 裝置上提升對話品質,並支援目標明確的 Vibe Coding 工作流程。

Qwen3.5 上下文管理實作:以對話聊天為例

何謂多輪對話?對話型 AI 文字生成,需要歷史資訊,才能「理解」使用者接續輸入的內容;意思是,前面的對話內容,必須加到這次對話的提示詞。

前文提及,Qwen3.5 採用 Gated DeltaNet 與 Gated Attention 組成的混合架構。以 0.8B 模型為例,24 層模型包含 18 層 Gated DeltaNet 與 6 層 Gated Attention。

GDN 能將依序輸入的資訊,更新至固定大小的 recurrent state;Gated Attention 則使用 KV cache,保留可供注意力機制直接查找的歷史資訊。

這項功能看似只是保存聊天紀錄,實際上包含 Prompt 組合、模型狀態、KV cache 與歷史裁切等多個環節。要如何整合「多輪對話」與 Qwen GDN 技術呢?

對話紀錄需要重新送進模型

每次使用者送出新聊天訊息時,應用程式要負責組合 System Prompt、歷史對話與目前問題,再將組合後的 Prompt 送入模型;這個工作不是 LLM 模型的責任,而是上層的應用程式負責。

這就是技術上,為什麼應用程式的 Context 管理技術,直接影響對話品質的原因。

聊天室畫面看到的是一串對話。應用程式內部保存更多提示詞資訊。

Qwen3.5 提示詞結構包含:

  • sytem prompt
  • user prompt
  • assistent prompt

它的固定結構為:

<|im_start|>system
原則與指令
<|im_end|>
<|im_start|>user
使用者原文
<|im_end|>
<|im_start|>assistant
...

以下以 Swift 程式碼展示一段簡化的對話 Prompt Renderer。Prompt Renderer 負責將對話提示詞,轉換成模型輸入的格式(ChatML)。

struct ChatExchange {
    let user: String
    let assistant: String
}

func renderChatPrompt(
    system: String,
    history: [ChatExchange],
    currentUser: String,
    maxExchanges: Int = 6
) -> String {
    let recentHistory = history.suffix(maxExchanges)

    var prompt = """
    <|im_start|>system
    \(system)
    <|im_end|>
    """

    for exchange in recentHistory {
        prompt += """

        <|im_start|>user
        \(exchange.user)
        <|im_end|>
        <|im_start|>assistant
        \(exchange.assistant)
        <|im_end|>
        """
    }

    prompt += """

    <|im_start|>user
    \(currentUser)
    <|im_end|>
    <|im_start|>assistant
    """

    return prompt
}

這段程式定義一組「完整的」對話(Exchange)包含 userassistant

  • user 目前輸入的對話
  • assistant 存放歷史對話

接著,再定義「每次只取最近六輪完整對話」;這裡的「完整」代表 userassistant 必須成對保留。

若未使用 assistant 管理歷史對話,LLM 生成交字時,會有很明顯的「狀況外」等健忘現象。

開發者只要做好基本研究工作,再搭配一小段 Code Snippet,就可以收工了。後續真正寫程式的工作,就由 AI 接手。

接下來,打開 Claude Code,執行以下 Vibe Coding Task Contract:

實作 GDN 對話上下文管理。

請將上述 Swift Prompt Renderer 移植至目前專案。

實作限制如下:
1. 保留 `ChatExchange` 的 `user` 與 `assistant` 成對結構。
2. 每次只保留最近六個完整 exchange。
3. 不得修改歷史裁切演算法。
4. 不得新增摘要、RAG 或 checkpoint 邏輯。
5. 完成後加入 Prompt 輸出測試。

Vibe Coding 時,限制「不得修改歷史裁切演算」,並保持 exchange 作為歷史裁切單位(Atomic),避免拆散同一輪的使用者輸入與模型回答。

實務上,裁切條件不應只依照對話輪數。系統仍需計算 token 數量,並預留模型輸出的 token budget。當 Prompt 接近 context window 上限時,才從最舊的完整 exchange 開始移除。

小結

上述實作很適合「短對話」,應用程式直接保留最近數輪訊息即可。但是,當對話持續增加時,系統可加入一份精簡的 memory capsule。

在需要精確「回想之前對話」內容時,還可透過 RAG、資料庫或檔案工具重新取得「記憶」。

本專欄

RAG、語意搜尋與 LLM

第 20 篇,共 20 篇 · 連載中

本文由 Jollen 純手工撰寫,網站由 AI Agent 維護。轉載請註明出處與作者,並全文引用。轉載時請在文章開頭或結尾明顯處註明「本文出處:https://www.jollen.org,已取得原作者同意並授權使用。」
訂閱電子報:不定期 Jollen's Blog 精選文章隨 Moko365 電子報寄送;請透過 Moko365 電子報訂閱(可隨時取消)。

Copyright(c) 2001–2026 www.jollen.org. All rights reserved.
Last update: July 30, 2026 at 4:14 PM