簡易RAG問答引擎的構建與體驗

RAG(檢索增強生成)是結合檢索與生成式 AI 的技術框架。核心邏輯是先從外部知識庫精準檢索相關信息,再將其作為上下文輸入大模型生成回答。技術上依賴檢索引擎(如向量數據庫、BM25)、大語言模型(如 GPT、LLaMA)及數據預處理技術。通過檢索增強,解決大模型知識滯后、幻覺問題,提升回答準確性。應用廣泛,涵蓋智能客服、醫療問答、法律檢索、教育輔導等場景,能基于特定領域知識提供精準、可控的生成內容。

wow-RAG 是 Datawhale 推出的 RAG 技術實踐項目,網址:datawhalechina/wow-rag: A simple and trans-platform rag framework and tutorial ? ?https://github.com/datawhalechina/wow-rag

選擇文檔

我們從網絡上或其他途徑選定一個文檔,txt格式的。在jupyter notebook主目錄下新建一個docs文件夾,把.txt文件放進去。

# 從指定文件讀取,輸入為List
from llama_index.core import SimpleDirectoryReader,Document
documents = SimpleDirectoryReader(input_files=['./docs/大模型推理.txt']).load_data()

創建 SimpleDirectoryReader 實例,通過 input_files 參數指定要讀取的單個文件:./docs/大模型推理.txt;調用 load_data() 方法讀取文件內容并轉換為文檔對象列表

可能出現的報錯

這一步可能遇到的報錯為:

ValueError: numpy.dtype size changed, may indicate binary incompatibility. Expected 96 from C header, got 88 from PyObject

錯誤根源是?NumPy 和 Pandas 版本不兼容?導致的二進制接口沖突

Pandas 依賴 NumPy 的底層二進制接口,但當前安裝的 NumPy 和 Pandas 版本不匹配(可能是 NumPy 版本過舊,或 Pandas 版本過新導致不兼容)。
該錯誤并非 llama_index 直接引起,而是數據處理庫的依賴沖突導致 llama_index 的文件讀取功能無法正常加載(因為 SimpleDirectoryReader 依賴 Pandas 處理表格類文件)。

可以運行以下代碼來檢查版本:

import numpy as np
import pandas as pd
import scipyprint(f"NumPy 版本: {np.__version__}")       # 需顯示 1.26.x
print(f"Pandas 版本: {pd.__version__}")     # 建議 2.0.x ~ 2.2.x
print(f"SciPy 版本: {scipy.__version__}")   # 建議 1.11.x

SciPy 對 NumPy 版本有嚴格限制,必須將 NumPy 降級到?1.26.x?系列(既滿足 SciPy 要求,又能兼容 Pandas):

# 強制卸載當前 NumPy 并安裝兼容版本
pip uninstall -y numpy
pip install numpy==1.26.4  # 此版本與 SciPy、Pandas 兼容性最佳

pip安裝后應該restart kernel來應用改變

顯示為這樣就沒問題了

構建向量索引

# 構建向量索引
from llama_index.core import VectorStoreIndex
#index = VectorStoreIndex.from_documents(documents,embed_model=embedding)
# 想要看到進度條的話,加一個參數 show_progress=True
index = VectorStoreIndex.from_documents(documents,embed_model=embedding,show_progress=True)

向量索引:將文本內容轉換為高維向量(嵌入向量),并建立索引結構,以便快速檢索語義相似的文本片段。

from_documents() :
輸入:documents:上一步加載的文檔對象列表(來自 SimpleDirectoryReader)。embed_model=embedding:指定用于文本向量化的嵌入模型(需提前定義,如 embedding = OpenAIEmbedding())。
功能:將文檔內容分割為更小的文本塊(如段落、句子)。使用 embed_model 將每個文本塊轉換為向量表示。將向量存儲到索引結構中,支持快速相似度檢索。
輸出:返回一個 VectorStoreIndex 對象(存儲在 index 變量中)。

Parsing nodes(解析節點): 這是構建索引的第一步,LlamaIndex 會對輸入的 documents 文檔列表進行預處理,將原始文檔分割為更小的文本單元(稱為 “節點”,Node)。節點是向量索引的基本處理單位(通常對應段落、句子或固定長度的文本片段)

Generating embeddings(生成嵌入向量):這是構建索引的核心步驟,LlamaIndex 會調用指定的 embed_model(嵌入模型),將上一步解析出的所有節點(文本片段)轉換為高維向量(嵌入向量)。這些向量是后續語義檢索的基礎。

問答

query_engine = index.as_query_engine(llm=llm)
# 回答提問
response = query_engine.query("大模型推理是什么?")
response

index.as_query_engine() 將之前構建的向量索引(index)轉換為可執行查詢的引擎。

llm=llm 參數:顯式指定用于生成回答的大語言模型(LLM)。若不指定 llm,LlamaIndex 會使用默認模型(通常是 OpenAI 的 GPT 系列)。

Response(response='大模型推理指的是一種在回答問題前,將問題拆解為更小的推理步驟或思考過程的方法。這種模型不僅學習如何給出答案,還學習如何通過一系列邏輯步驟進行推理。簡而言之,大模型推理是一種結合了推理過程和答案輸出的方法,旨在提高模型回答問題的透明度和可解釋性。', source_nodes=[NodeWithScore(node=TextNode(id_='c4b39c48-0d68-4ad4-a6b8-066d2996982d', embedding=None, metadata={'file_path': 'docs\\大模型推理.txt', 'file_name': '大模型推理.txt', 'file_type': 'text/plain', 'file_size': 22722, 'creation_date': '2025-07-21', 'last_modified_date': '2025-07-21'}, excluded_embed_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], excluded_llm_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], relationships={<NodeRelationship.SOURCE: '1'>: RelatedNodeInfo(node_id='b0e1d00f-4808-4606-b5ea-f38cf6522f83', node_type='4', metadata={'file_path': 'docs\\大模型推理.txt', 'file_name': '大模型推理.txt', 'file_type': 'text/plain', 'file_size': 22722, 'creation_date': '2025-07-21', 'last_modified_date': '2025-07-21'}, hash='fc891f08c5725428a6ea72c71b389cb0a718156509c4b2a4c42db880268b6595'), <NodeRelationship.NEXT: '3'>: RelatedNodeInfo(node_id='c41f7751-4d0b-4644-afa4-1336c6754a74', node_type='1', metadata={}, hash='b12dc0fd22c420bcfefb4bf02ea246dc75127380caad1c4c69d8547ff3c6a6f5')}, metadata_template='{key}: {value}', metadata_separator='\n', text='總的來說,大模型可以分為常規大模型和推理型大模型,我們大多數人口中的大模型一般都是指常規大模型,本文重點介紹推理型大模型,并盡可能將大模型的推理過程解釋清楚,最后再來說說deepseek為什么能成功,用了哪些技術。\r\n\r\n什么是推理型大模型\r\n與常規 LLM 相比,推理型 LLM 在回答問題前,往往會先將問題拆解為更小的步驟(通常稱為推理步驟或思考過程),也可以說是思維鏈COT。\r\n\r\n\r\n普通大模型直接給出答案,沒有給出求解過程。推理型大模型會將推理過程和答案一起輸出。那么,“思考過程”、“推理步驟”或“思維鏈”(CoT, Chain-of-Thought)究竟意味著什么?\r\n\r\n\r\n我在之前的復旦大學文章中也提到過過思維鏈,可以說某種程度上,思維鏈直接決定了大模型的推理規劃能力:\r\n\r\n\r\n愛吃牛油果的璐璐:細說復旦大學,斯坦福大學智能代理AI-Agent(二更)\r\n280 贊同 · 16 評論文章\r\n\r\n愛吃牛油果的璐璐:大模型中的思維鏈、思維樹、思維圖\r\n19 贊同 · 2 評論文章\r\n雖然我們可以探討大模型是否真的能像人類那樣思考,但這些步驟將整個過程拆解為更小,且結構化的推理。推理型大模型不僅學習“回答什么”,更學習“如何回答”。\r\n\r\n\r\n為了理解推理型大模型的構建過程,我們首先需要探討一個范式轉變。\r\n\r\nTrain-time compute 到 Test-time compute\r\n大模型從關注訓練階段的擴展(訓練時計算)轉向關注推理階段(測試時計算),下面對兩者分別進行介紹。\r\n\r\n訓練時計算:Train-time compute\r\n在 2024 年上半年之前,為了提升大模型在預訓練階段的性能,開發者通常會增加以下幾個方面的規模:\r\n\r\n? 模型參數(parameters)\r\n\r\n? 數據集(tokens )\r\n\r\n? 計算量(FLOPs )\r\n\r\n這三者合稱為訓練時計算(train-time compute),它體現了預訓練數據作為“ AI 之燃料”的理念。基本上,預訓練投入越大,最終得到的模型就會越出色。\r\n\r\n\r\n訓練時計算不僅包括訓練期間所需的計算量,還涵蓋了微調時所需的計算量。\r\n\r\n\r\n長期以來,這些因素一直是提升 LLMs 性能的關鍵。研究人員通過各種 Scaling Law 探討模型規模(包括計算量、數據集大小和模型參數數量)與模型性能之間的關系。這些定律屬于所謂的“冪律”:某一變量(例如計算量)的增加會導致另一變量(例如性能)按比例發生變化。\r\n\r\n\r\n通常,這些關系會在對數-對數坐標系下展示(呈現直線),以突出計算量的大幅增加。', mimetype='text/plain', start_char_idx=0, end_char_idx=1103, metadata_seperator='\n', text_template='{metadata_str}\n\n{content}'), score=0.6528139357784619), NodeWithScore(node=TextNode(id_='82ac4f70-ec78-499f-9d5e-04cbec54208c', embedding=None, metadata={'file_path': 'docs\\大模型推理.txt', 'file_name': '大模型推理.txt', 'file_type': 'text/plain', 'file_size': 22722, 'creation_date': '2025-07-21', 'last_modified_date': '2025-07-21'}, excluded_embed_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], excluded_llm_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], relationships={<NodeRelationship.SOURCE: '1'>: RelatedNodeInfo(node_id='b0e1d00f-4808-4606-b5ea-f38cf6522f83', node_type='4', metadata={'file_path': 'docs\\大模型推理.txt', 'file_name': '大模型推理.txt', 'file_type': 'text/plain', 'file_size': 22722, 'creation_date': '2025-07-21', 'last_modified_date': '2025-07-21'}, hash='fc891f08c5725428a6ea72c71b389cb0a718156509c4b2a4c42db880268b6595'), <NodeRelationship.PREVIOUS: '2'>: RelatedNodeInfo(node_id='87986d57-a6cc-4617-8958-00d597301f3e', node_type='1', metadata={'file_path': 'docs\\大模型推理.txt', 'file_name': '大模型推理.txt', 'file_type': 'text/plain', 'file_size': 22722, 'creation_date': '2025-07-21', 'last_modified_date': '2025-07-21'}, hash='63a1927e6be275695f51cfcc2e469dfbe8aec9a18bdd496632b388b953b6ef75')}, metadata_template='{key}: {value}', metadata_separator='\n', text='使用之前提到的 80 萬高質量數據樣本(其中 60 萬條推理示例 + 20 萬條非推理示例)進行訓練。\r\n\r\n\r\n2. 學生模型通過不斷對比自己的輸出分布和教師模型的輸出分布,來學習 DeepSeek-R1 的推理方式。\r\n\r\n這樣“蒸餾”出來的小模型性能依舊出色,因為它不僅學到了 80 萬條數據中的知識,還學到了 DeepSeek-R1 如何作答的思路。\r\n\r\nDeepSeek不太成功的嘗試\r\n還記得我們之前提到的 過程獎勵模型(PRMs) 和 蒙特卡洛樹搜索(MCTS) 嗎?DeepSeek 團隊也曾試圖用這些方法來培養模型的推理能力,但并未取得理想成果。\r\n\r\n在 MCTS 中,由于搜索空間極其龐大,研究人員不得不大幅限制節點擴展。此外,訓練一個能夠細化評估推理過程的獎勵模型本身就是一項困難的任務。\r\n\r\n在結合 PRMs 的 Best-of-N 技術中,他們遇到的主要問題是計算開銷過高,需要頻繁地對獎勵模型進行再訓練,以防止出現所謂的 “reward-hacking”(對獎勵函數的漏洞進行投機利用)。\r\n\r\n這并不代表這些技術就完全不適用,但至少說明了它們在實際應用中面臨著一些挑戰。\r\n\r\n結語\r\n以上就是關于推理型大模型的概念與 DeepSeek-R1 的有關介紹。希望這篇內容能幫助你更好地理解 “測試時計算擴展” 的潛力所在。也再次感謝為大模型探索道路上做出貢獻和努力的研究者們,像你們致敬!', mimetype='text/plain', start_char_idx=9003, end_char_idx=9614, metadata_seperator='\n', text_template='{metadata_str}\n\n{content}'), score=0.5625440768569911)], metadata={'c4b39c48-0d68-4ad4-a6b8-066d2996982d': {'file_path': 'docs\\大模型推理.txt', 'file_name': '大模型推理.txt', 'file_type': 'text/plain', 'file_size': 22722, 'creation_date': '2025-07-21', 'last_modified_date': '2025-07-21'}, '82ac4f70-ec78-499f-9d5e-04cbec54208c': {'file_path': 'docs\\大模型推理.txt', 'file_name': '大模型推理.txt', 'file_type': 'text/plain', 'file_size': 22722, 'creation_date': '2025-07-21', 'last_modified_date': '2025-07-21'}})

Response 對象由三個關鍵部分組成:
response:生成的自然語言回答內容。
source_nodes:LLM 生成回答時參考的文檔節點(文本片段)。
metadata:源文檔的元數據信息(如文件路徑、大小等)。

source_nodes 表示引用的文檔節點,這是一個包含 NodeWithScore 對象的列表,每個對象代表一個被檢索到的相關文本片段,包含 文本內容 和 匹配分數。

NodeWithScore(node=TextNode(id_='c4b39c48-0d68-4ad4-a6b8-066d2996982d',  # 節點唯一標識text='總的來說,大模型可以分為常規大模型和推理型大模型...推理型大模型不僅學習“回答什么”,更學習“如何回答”。',  # 核心文本內容metadata={'file_path': 'docs\\大模型推理.txt', ...},  # 源文件信息relationships={...},  # 節點間關系(如前序/后序節點)),score=0.6528139357784619  # 語義相似度分數(0-1,越高越相關)
)

0.65 的相似度分數表明該片段與問題 “大模型推理是什么?” 高度相關,是生成回答的主要依據。

NodeWithScore(node=TextNode(id_='82ac4f70-ec78-499f-9d5e-04cbec54208c',text='使用之前提到的 80 萬高質量數據樣本...但至少說明了它們在實際應用中面臨著一些挑戰。',metadata={...},),score=0.5625440768569911  # 相似度略低
)
metadata={'c4b39c48-0d68-4ad4-a6b8-066d2996982d': {'file_path': 'docs\\大模型推理.txt', ...},'82ac4f70-ec78-499f-9d5e-04cbec54208c': {'file_path': 'docs\\大模型推理.txt', ...}
}

記錄所有引用節點的源文件信息,包括文件路徑、名稱、大小、修改日期等,確保回答可追溯到原始文檔,增強可信度。

這個?Response?對象完整呈現了從 “問題輸入” 到 “答案輸出” 的閉環:基于向量索引的精準檢索 → 上下文構建 → LLM 生成可靠回答,同時通過?source_nodes?和?metadata?保證了回答的可追溯性和可信度,是 LlamaIndex 知識增強問答能力的典型體現。

參考文章

https://github.com/datawhalechina/wow-raghttps://github.com/datawhalechina/wow-rag

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/90212.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/90212.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/90212.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++11特性學習 Day1

nullptr對于c中null (void*)0&#xff0c;所以在為函數傳參傳入0時&#xff0c;無法清楚地分辨是int類型的0還是指的是空指針null在C11中清晰的將空指針變為了nullptr&#xff0c;0專指int型的數字0override關鍵字在子類中對父類的函數的覆寫之后加上override關鍵字&#xff0…

微算法科技(NASDAQ: MLGO)探索優化量子糾錯算法,提升量子算法準確性

隨著量子計算技術的飛速發展&#xff0c;量子計算機在解決復雜計算問題上的潛力日益顯現。然而&#xff0c;量子計算面臨的一個重大挑戰是量子比特的脆弱性&#xff0c;即量子比特容易受到環境噪聲和干擾的影響&#xff0c;導致量子態的塌縮和計算結果的錯誤。微算法科技&#…

MongoDB數據庫詳解-針對大型分布式項目采用的原因以及基礎原理和發展-卓伊凡|貝貝|莉莉

MongoDB數據庫詳解-針對大型分布式項目采用的原因以及基礎原理和發展-卓伊凡|貝貝|莉莉由于老產品即時通訊私有化軟件就是采用MongoDB &#xff0c;但是版本實在太低&#xff0c;要做大更新&#xff0c;其次針對10年前完美運營的項目來到10年后的現在就不一定行&#xff0c;優雅…

Kotlin 中的單例模式(Singleton)與對象聲明

在 Kotlin 中&#xff0c;類描述的是一種通用結構&#xff0c;可以多次實例化&#xff0c;也可以用多種方式實例化。但有時我們只需要單個實例&#xff0c;不多不少。單例模式能幫你更好地組織代碼&#xff0c;把相關的方法聚合在一起。 單例模式是什么&#xff1f; 單例模式是…

Shell 編程基礎入門從認識到實戰

對于剛接觸 Linux 或 Unix 系統的開發者來說&#xff0c;Shell 腳本往往是自動化操作的第一道門檻。它不像 Python 那樣語法簡潔&#xff0c;也不像 Java 那樣有完善的面向對象體系&#xff0c;但卻能以極少的代碼實現強大的系統管理功能。本文將從 Shell 的基本概念講起&#…

混合遺傳粒子群算法在光伏系統MPPT中的應用研究

混合遺傳粒子群算法在光伏系統MPPT中的應用研究 前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家&#xff0c;覺得好請收藏。點擊跳轉到網站。 摘要 本文針對光伏系統最大功率點跟蹤(MPPT)問題&#xff0…

機器視覺的布料絲印應用

在紡織印染行業&#xff0c;布料絲印工藝的精度直接決定產品外觀質量與市場競爭力。傳統絲印設備依賴機械定位與人工校準&#xff0c;面對高密度圖案、柔性面料或復雜紋理時&#xff0c;易出現套色偏移、油墨滲透不均等問題&#xff0c;導致良品率波動與生產成本攀升。 隨著機…

前端常用類庫

常用類庫 類庫作用 類庫可以幫助我們快速實現項目業務的開發與功能的實現, 幫助我們解放勞動力提高生產效率, 前端中的類庫與框架都是由原生javascript編寫, 提供給其他開發者應用于某一業務環境或者需求。一般有開發者/團隊開源維護. 優秀的類庫需要具備高度封裝可用, 穩定, …

通俗易懂循環神經網絡(RNN)指南

本文用直觀類比、圖表和代碼&#xff0c;帶你輕松理解RNN及其變體&#xff08;LSTM、GRU、雙向RNN&#xff09;的原理和應用。什么是循環神經網絡 循環神經網絡&#xff08;Recurrent Neural Network, RNN&#xff09;是一類專門用于處理序列數據的神經網絡。與前饋神經網絡不同…

【SVM】支持向量機實例合集

基于Java的SVM(支持向量機)實例合集 以下是一個基于Java的SVM(支持向量機)實例合集,包含核心代碼示例和應用場景說明。這些例子基于流行的機器學習庫(如LIBSVM、Weka、JSAT)實現。 數據準備與加載 使用LIBSVM格式加載數據集: // 加載LIBSVM格式數據 svm_problem pr…

Python100個庫分享第38個—lxml(爬蟲篇)

目錄專欄導讀&#x1f4da; 庫簡介&#x1f3af; 主要特點&#x1f6e0;? 安裝方法Windows安裝Linux/macOS安裝驗證安裝&#x1f680; 快速入門基本使用流程HTML vs XML解析&#x1f50d; 核心功能詳解1. XPath選擇器2. CSS選擇器支持3. 元素操作&#x1f577;? 實戰爬蟲案例…

imx6ull-系統移植篇17——linux頂層 Makefile(上)

目錄 前言 頂層 Makefile 源碼簡析 版本號 MAKEFLAGS 變量 命令輸出 靜默輸出 設置編譯結果輸出目錄 代碼檢查 模塊編譯 設置目標架構和交叉編譯器 調用 scripts/Kbuild.include 文件 交叉編譯工具變量設置 頭文件路徑變量 導出變量 make xxx_defconfig 過程 …

OpenCV 官翻6 - Computational Photography

文章目錄圖像去噪目標理論OpenCV中的圖像去噪1、cv.fastNlMeansDenoisingColored()2、cv.fastNlMeansDenoisingMulti()附加資源圖像修復目標基礎概念代碼補充資源練習高動態范圍成像&#xff08;HDR&#xff09;目標理論基礎曝光序列HDR1、將曝光圖像加載到列表中2、將曝光序列…

APT32F1732RBT8愛普特微電子 32位MCU國產芯片 智能家居/工業控制 首選

APT32F1732RBT8 愛普特微電子&#xff0c;32位MCU國產芯片一、產品簡介APT32F1732RBT8 是愛普特微電子&#xff08;APT&#xff09;推出的高性能32位ARM Cortex-M0內核MCU&#xff0c;主頻高達48MHz&#xff0c;內置64KB Flash8KB RAM&#xff0c;專為智能家居、工業控制、消費…

Smart Tomcat

本篇博客的內容是教你借助idea中的插件,把tomcat集成到idea中安裝 Smart Tomcat 插件搜索下載 ,如果一直處于加載界面,就嘗試一下科學上網配置 Smart Tomcat 插件 點擊右上角的 "Add Configuration"選擇左側的 "Smart Tomcat" 在 Name 這一欄填寫一個名字(…

Linux_shell編寫

title: Linux_4 shell編寫 shell pwd (/root/A/2025_7/19/myshell) 首先需要設計命令行提示 &#xff08;MakeCommandLine()&#xff09; 首先獲取相關信息 getenv(“name”) // 獲取用戶名 const char* GetUserName() {const char* name getenv("USER");if (name …

【數據結構】棧的深入解析--用C語言實現

文章目錄1.棧的概念2.棧的底層結構3.棧的功能4.棧的實現4.1.棧結構的定義4.2.棧的初始化4.3.棧的銷毀4.4.入棧4.5.出棧4.6.取棧頂元素4.7.獲取棧中有效元素個數5.完整代碼Stack.hStack.cmain.c運行結果1.棧的概念 是一種特殊的線性表&#xff0c;只允許數據在固定的一段進行插…

Git倉庫核心概念與工作流程詳解:從入門到精通

Git倉庫的基本概念版本庫&#xff08;Repository&#xff09;是Git的核心概念&#xff0c;你可以簡單理解為一個被Git管理的目錄。這個目錄里的所有文件都能被Git跟蹤&#xff0c;記錄每次修改和刪除&#xff0c;讓你可以隨時追溯歷史或在未來某個時刻"還原"文件。Gi…

Web開發 05

1 React庫&#xff08;人話詳解版&#xff09;別慌&#xff0c;React 剛接觸時是會有點懵&#xff0c;咱們用 “人話 類比” 一步步拆&#xff1a;核心概念先抓牢組件&#xff08;Component&#xff09;把它想成 “樂高積木”&#xff0c;比如做個社交 App&#xff0c;頂部導航…

RustDesk 自建中繼服務器教程(Mac mini)

&#x1f4d6; 教程目標 在家里的 Mac mini 上部署 RustDesk 中繼服務器 (hbbs hbbr)&#xff0c;讓你從辦公室、筆電或手機 低延遲、安全 地遠程控制家里的 Windows 和 Mac mini。 ? 不依賴第三方服務器 ? 支持 P2P 和中繼雙模式 ? 全流量可控、跨平臺 &#x1f3d7;? 架…