最近 Cursor 發布 2.0 版本,其中一個比較亮點的功能就是它可以同時指揮 8 個 Agent 執行任務,最後選擇你覺得最好的那個答案。
而在底層模型層面,來自中國本土團隊的 RWKV 項目也帶來了更具突破性的成果:RWKV7-G0a3 13.3B ——當前全球最強的開源純 RNN 大語言模型。
這一版本以 RWKV6-world-v2.1 14B 為基礎,繼續訓練了 2 萬億 tokens(並融合了 35B 來自 DeepSeek v3.1 的高品質語料),在保持完全 RNN 架構、無注意力機制(No Attention)、無微調、無刷榜的前提下,取得了與主流 Transformer 模型相媲美甚至更優的表現。

在多項權威基準測試中(包括 MMLU、MMLU-Pro、GSM8K、MATH500、CEval 等),RWKV7-G0a3 在語言理解、邏輯推理與數學推演等任務上均實現顯著提升。其中,MMLU-Pro 測評顯示模型在多學科綜合知識上的掌握更加扎實;GSM8K 與 MATH500 結果表明,其在中高難度數學與邏輯問題上的推理能力已達到同規模模型的領先水平。與此同時,RWKV7-G0a3 繼續保持了 RWKV 系列一貫的高推理效率與低顯存占用優勢,展現出純 RNN 架構在大模型時代下的強大潛力。
Uncheatable Eval 使用最新的論文、新聞、代碼與小說等實時數據進行評測,通過“壓縮率”(即 Compression is Intelligence)指標,衡量模型在真實語料下的語言建模能力與泛化水平。

MMLU 系列用於測評語言模型在多學科知識與認知推理方面的能力,其中 MMLU Pro 為進階版本,包含更複雜的問題設計與更嚴苛的評測標準。

欲獲取更多詳細信息,請訪問該模型的 官方公眾號文章 閱讀。
這意味著:
在以 Transformer (deep learning architecture) 架構主導的大模型時代,RWKV 所代表的“純 RNN”路線再度崛起:以更低的計算與顯存成本、更自然的時序記憶機制,走出一條與主流 LLM 截然不同的進化路徑。
在 RWKV 命名規則中,G0a3 標識了訓練數據在版本與品質上的升級(例如:品質層級為 G# > G#a2 > G#,數據規模層級為 G1 > G0),即便參數量相同,G0a3 系列在泛化能力上也具備潛在優勢。綜合來看,RWKV7-G0a3 13.3B 的發布,不僅刷新了 RNN 模型性能的新高度,也象徵著 RWKV 系列在“擺脫 Transformer 架構壟斷”路徑上邁出了一步。
下載 RWKV7-G0a3 13.3B 模型(.pth 格式):
下載 .gguf 格式: modelscope.cn/models/shou…
下載 Ollama 格式: ollama.com/mollysama
可以使用 RWKV Runner、Ai00 或 rwkv pip 等推理工具在本地部署 RWKV 模型。
RWKV 模型同時兼容主流推理框架,如 llama.cpp 與 Ollama。
目前最快的 RWKV 推理工具是 Albatross。
由於 RWKV7-G0a3 13.3B 屬於新模型,建議優先使用 RWKV Runner 以確保結果穩定與準確。
更多關於部署與推理的使用教程,可參考 RWKV 官網 - 模型部署和推理教程。
首先,我們要知道模型並發的效果,那我們要知道連接了發起了一個請求之後,它是怎麼回覆的:

我們現在對的網絡請求已經進行了截取,這是其中的一些數據,我們將一下核心的數據寫到 json 文件裡面讓它能夠更好的展示:

首先我們知道這是一個流式返回,但是一次流式返回了包含的內容非常多,這裡就是我們並發的關鍵了,這裡的 index 代表並發的下標,而 delta.content 是具體的內容,這樣我們知道了 SSE 實現並發的原理了,實際上就是調用 SSE,後端在一次 SSE 的返回中返回同一個問題的不同的結果並通過下標來區分。
我們已經把 SSE 返回機制摸清楚了。下面就輕鬆地走一遍“邊生成邊展示”的整個流程:從流式到達、到何時更新、再到怎麼把半成品 HTML 安全地渲染出來,最後配上 UI 的滾動與分批加載。讀完你就能一眼看懂這套實時渲染是怎麼跑起來的。
先說結論:這件事其實就五步,順次串起來就好了——流式接收、增量累積與觸發、HTML 提取與補全、UI 局部更新、以及 iframe 的分批渲染。下面逐段拆開講。
// 使用 ReadableStream 讀取流式數據
const reader = response.body.getReader();
const decoder = new TextDecoder("utf-8");
let partial = ""; // 處理不完整的行
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value, { stream: true });
partial += chunk;
// 逐行解析 SSE 格式:data: {...}
const lines = partial.split("\n");
partial = lines.pop() || ""; // 保留不完整的行
for (const line of lines) {
if (!line.startsWith("data: ")) continue;
const json: StreamChunk = JSON.parse(data);
// 處理每個 chunk...
}
}
這裡的代碼的核心要點如下:
split('\n') 拆開,半截 JSON 用 partial 暫存。TextDecoder(..., { stream: true }) 負責拼接多字節字符,避免中文或 emoji 被截斷。data: 開頭的有效行,忽略心跳、空行、註釋。[DONE] 僅結束對應流 index,其餘繼續處理。// 為每個 index 累積內容
contentBuffers[index] += delta;
// 判斷是否應該觸發渲染
const lastLength = lastRenderedLength.get(index) || 0;
const shouldRender = this.shouldTriggerRender(
contentBuffers[index],
lastLength
);
if (shouldRender && onProgress) {
const htmlCode = this.extractHTMLCode(contentBuffers[index]);
onProgress(index, contentBuffers[index], htmlCode);
lastRenderedLength.set(index, contentBuffers[index].length);
}
這裡的代碼的核心要點如下:
lastRenderedLength 比較控制頻率,避免“來一點就刷”。private static shouldTriggerRender(
newContent: string,
oldLength: number,
): boolean {
// 1. 首次渲染:內容超過 20 字符
if (oldLength === 0 && newLength > 20) {
return true;
}
// 2. 關鍵閉合標籤出現(語義區塊完成)
const keyClosingTags = [
'</header>', '</section>', '</main>',
'</article>', '</footer>', '</nav>',
'</aside>', '</div>', '</body>', '</html>'
];
const addedContent = newContent.substring(oldLength);
for (const tag of keyClosingTags) {
if (addedContent.includes(tag)) {
return true; // 區塊完成,立即渲染
}
}
// 3. 內容增長超過 200 字符(防止長時間不更新)
if (newLength - oldLength > 200) {
return true;
}
return false;
}
這裡的代碼的核心要點如下:
</section>、</div>),保證塊級內容完整展示。private static extractHTMLCode(content: string): string {
// 方式1: 完整的 ```html 代碼塊
const codeBlockMatch = content.match(/```html\s*([\s\S]*?)```/);
if (codeBlockMatch) return codeBlockMatch[1].trim();
// 方式2: 未完成的代碼塊(流式渲染)
const incompleteMatch = content.match(/```html\s*([\s\S]*?)$/);
if (incompleteMatch) {
return this.autoCompleteHTML(incompleteMatch[1].trim());
}
// 方式3: 直接以 <!DOCTYPE 或 <html 開頭
if (trimmed.startsWith('<!DOCTYPE') || trimmed.startsWith('<html')) {
return this.autoCompleteHTML(trimmed);
}
return '';
}
private static autoCompleteHTML(html: string): string {
// 移除最後不完整的標籤(如 "<div cla")
if (lastOpenBracket > lastCloseBracket) {
result = html.substring(0, lastOpenBracket);
}
// 自動閉合 script、body、html 標籤
// 確保瀏覽器可以渲染未完成的 HTML
return result;
}
這裡的代碼的核心要點如下:
<div cla>)自動裁剪,再補上 </script>、</body>、</html> 等關鍵閉合。await AIService.generateMultipleResponses(
userPrompt,
totalCount,
(index, content, htmlCode) => {
// 實時更新對應 index 的結果
setResults((prev) =>
prev.map((result, i) =>
i === index
? {
...result,
content, // 原始 Markdown 內容
htmlCode, // 提取的 HTML 代碼
isLoading: false,
}
: result
)
);
}
);
這裡的代碼的核心要點如下:
prev.map 保證不可變數據結構,減少重渲染。content 用於 Markdown 文本,htmlCode 用於預覽展示。sessionStorage,刷新或返回依舊保留上下文。// 找出已準備好但還未渲染的索引
const readyIndexes = results
.filter(({ result }) => !result.isLoading && result.htmlCode)
.map(({ index }) => index)
.sort((a, b) => a - b);
// 第一次渲染:一次性全部加載(用戶體驗優先)
if (!hasRenderedOnce.current) {
setIframeRenderQueue(new Set(readyIndexes));
hasRenderedOnce.current = true;
return;
}
// 後續渲染:分批加載(每批 8 個,間隔 300ms)
// 避免一次性創建太多 iframe 導致卡頓
const processBatch = () => {
const toAdd = stillNotInQueue.slice(0, batchSize); // 8 個
toAdd.forEach((index) => newQueue.add(index));
if (stillNotInQueue.length > batchSize) {
setTimeout(processBatch, 300); // 繼續下一批
}
};
這裡的代碼的核心要點如下:
通過語義閉合與字數閾值控制更新頻率讓畫面穩定流暢,HTML 半成品自動補齊避免黑屏,iframe 分批掛載減輕主線程壓力並配合 requestAnimationFrame 提升滾動順滑度,狀態由 sessionStorage 兜底並以日誌輔助調參;整體邏輯是流式接收邊累積、攢到關鍵點就渲染一幀、UI 精準更新該動的那格,調順節奏即可實現實時渲染的又快又穩。
前面我們說了這麼多代碼相關的,接下來我們可以把我們的項目運行起來看一下最終運行的效果:

為了讓 UI 的效果顯示得更好,建議使用 33%縮放的螢幕效果。

在輸入框輸入我們要問的問題,點擊發送,你會看到這樣的效果:

這會你能實時看到 24 個頁面實時渲染的效果:

這樣我們就借助 RWKV7-G0a3 13.3B 模型實現了跟 Cursor2.0 版本一模一樣的效果了。
RWKV7-G0a3 13.3B 是由中國團隊推出的最新一代純 RNN 大語言模型,在無 Attention 架構下實現了與主流 Transformer 模型相媲美的性能,並在多項基準測試中表現優異。它以更低顯存占用和高推理效率展示了 RNN 架構的強大潛力。而前端並發實現中,通過 SSE 流式返回不同 index 的內容,實現了同時生成多個模型響應的並行效果。結合智能觸發渲染與分批 iframe 更新,最終達成了類似 Cursor 2.0 的多 Agent 實時對比體驗。