我有一個 GPTs,裡面塞了兩千多個 token 的「系統提示」。

它幫我回答所有關於我自己的問題——我的作品、我的技術棧、我在做的專案。每一次有人問我「你現在在做什麼」,它都能給出一個得體的回答。

這個 GPTs 運作得很好。只要我記得定期手動更新那些 token。

我不記得。

——所以我想做一個真正的 RAG 系統。讓文件自己爬、自己更新、自己進向量資料庫。我只要負責問問題就好。

選工具:為什麼是 Apify

要做 RAG,第一步永遠是:資料從哪裡來?

我可以自己寫爬蟲。Python 的 requests + BeautifulSoup,再補上 Playwright 處理 JS 渲染——這些我都會。但我不想維護。

我是獨立開發者。我的時間應該花在產品的核心邏輯上,不是在半夜被 site structure 改版吵醒。

Apify 的 Store 上有五萬多個 Actor,每一個都是打包好的 scraping 工具。最接近我需求的,是官方維護的 apify/website-content-crawler

它的賣點很直接:

- 輸入一個網址,它就能深層爬取整個網站

- 輸出是乾淨的 Markdown(不是 raw HTML)

- 內建 LangChain 整合

- 超過 14 萬人用過,月活 8K

對於一個不想寫爬蟲的人來說,這幾乎是最優解。

實戰:爬取技術文件

我第一個想餵給 LLM 的,是我的 side project VerifyAI 的網站。

在 Apify Console 建立一個 Actor task,輸入 URL,調整一些參數——maxCrawlPages 設 50,removeLinkFromText 設 true——然後按 Run。

跑了大概兩分鐘。結果是一個 JSON array,每個 entry 包含網站的某個 page,以 Markdown 格式呈現。

輸出長這樣:

`

{

"url": "https://verifyai.app/docs",

"markdown": "# VerifyAI Documentation\n\nVerifyAI is a reverse image search tool...",

"metadata": {

"title": "Docs | VerifyAI",

"description": "..."

}

}

`

直接可以吃。

串進向量資料庫

拿到 Markdown 之後,下一步是 chunking + embedding + 進 vector store。

我用的是最簡單的 stack:

- langchain 做 pipeline 串接

- RecursiveCharacterTextSplitter 做 chunking(chunk size 1000,overlap 200)

- OpenAI text-embedding-3-small 做 embedding

- Chroma 做本地 vector store(先跑通再考慮升級)

程式碼其實不多:

`python

from langchain_community.document_loaders import TextLoader

from langchain.text_splitter import RecursiveCharacterTextSplitter

from langchain_openai import OpenAIEmbeddings

from langchain_community.vectorstores import Chroma

讀取 Apify 輸出的 Markdown

loader = TextLoader("crawl_output.md")

docs = loader.load()

Chunking

splitter = RecursiveCharacterTextSplitter(

chunk_size=1000, chunk_overlap=200

)

chunks = splitter.split_documents(docs)

Embedding → Chroma

embeddings = OpenAIEmbeddings(model="text-embedding-3-small")

vectorstore = Chroma.from_documents(

chunks, embeddings, persist_directory="./chroma_db"

)

`

整段不到 30 行。從 crawler output 到可以查詢的 vector store,大概就是這個量級的工作。

查詢驗證

寫一個簡單的 query loop:

`python

retriever = vectorstore.as_retriever(search_kwargs={"k": 3})

query = "VerifyAI 支援哪些圖片來源?"

results = retriever.invoke(query)

for r in results:

print(f"[{r.metadata.get('source', '?')}] {r.page_content[:200]}")

`

第一次跑的時候,回來的 chunk 確實包含了「支援 Google Images、Bing Images、TinEye」這段文字。資料管線通了。

那一刻的感覺,老實說,比預期平淡。不是因為不興奮——是因為它本來就應該這麼簡單。

排程更新

單純一次性的 import 沒有意義。文件的價值在於它會自動更新。

Apify 的 Actor 可以設定 schedule。我在 Apify Console 開了每週排程,讓 website-content-crawler 每七天重新爬一次 VerifyAI 的網站。

然後寫了一個 CRON job,每週跑一次:

1. 觸發 Apify API 執行爬蟲

2. 下載最新的 Markdown output

3. 重新 chunking + embedding

4. 更新 Chroma 資料庫

整個流程不需要任何人介入。

這套管線目前跑了三週。我已經習慣每天問 GPTs 關於 VerifyAI 的問題,而它永遠回答最新的內容——因為資料每週更新一次。

下一步的計畫是擴展到更多來源:競品的 docs、相關的論壇討論、甚至 GitHub Issues。

但我可以慢慢來。因為爬蟲不是我寫的,維護也不是我的事——Apify 幫我扛了。

如果你想自己做一套類似的 RAG 管線,從 apify/website-content-crawler 開始,大概兩個小時內就能跑通。