AI Agent + Search: Chọn TinyFish tối ưu chi phí hay Firecrawl cào mọi ngóc ngách

AI Agent + Search: Chọn TinyFish tối ưu chi phí hay Firecrawl cào mọi ngóc ngách

Table of Contents

Tuần trước mình ngồi tối ưu con bot gom thông tin thực đơn của các quán ăn quanh khu Hóc Môn. Để con agent tự mò mẫm qua đống phòng thủ Cloudflare, xử lý mấy trang Single Page App (SPA) ngập ngụa JavaScript, rồi parse đống HTML rác về markdown sạch cho LLM nuốt, mình đã tốn kha khá credit bên Firecrawl. Xót tiền, mình thử đổi gió qua TinyFish-một cái tên mới nổi cam kết cung cấp Search và Fetch hoàn toàn free (0 credit).

Đây là hành trình mình thử nghiệm, thất bại và đặt hai con này lên bàn cân kỹ thuật để xem đâu là lớp mạng (web layer) phù hợp cho AI agent của bạn.

Bản chất: Tại sao AI Agent cần Web Layer riêng?

Nếu bạn nghĩ chỉ cần dùng http.Get() hay curl trong Go/Python để cào web cho AI agent thì bạn sắp ăn “trái đắng” rồi. Web hiện đại rất phức tạp:

  1. Dynamic JS Rendering: Quá nhiều trang web hiển thị nội dung bằng React/Svelte/Vue. Gửi request thường chỉ nhận về cái vỏ HTML trống rỗng.
  2. Anti-Bot Defenses: Các hệ thống bảo vệ như Cloudflare, Akamai sẽ chặn đứng request từ IP của các cloud provider (AWS, DigitalOcean).
  3. Context Window & Cost: HTML thô chứa quá nhiều thẻ script, CSS, class rác. Nếu nạp thẳng đống này vào LLM, bạn sẽ vừa tốn tiền token vừa làm giảm độ chính xác của mô hình do nhiễu thông tin.

Một Web Layer sinh ra để làm trung gian xử lý đống “rác” đó:

graph TD
    Agent[Agent] -->|Gửi Request| Web[Web Layer
TinyFish / Firecrawl] Web -->|Vượt Bot & Render JS| Internet[Mạng Internet] Internet -->|Trả về| Raw[Trang Web Thô] Raw -->|Lọc & Trích xuất| Clean[Markdown / JSON sạch] Clean -->|Nạp Context| Agent

Cả TinyFish và Firecrawl đều giải quyết bài toán này, nhưng hướng tiếp cận của tụi nó lại rất khác nhau.


Đặt hai công cụ lên bàn cân

Để dễ hình dung, mình đã tóm tắt các thông số cốt lõi của cả hai bên vào bảng dưới đây:

Tiêu chíTinyFishFirecrawl
Chi phí Search/FetchMiễn phí hoàn toàn (0 credit)Tính credit (1-5 credits/trang)
API Tìm kiếm (Search)Trả về title, snippet, URL. Hỗ trợ lọc theo location, language, recency_minutes, và purpose.Trả về kết quả kèm full nội dung trang của các kết quả đó (Tốn 2 credits/10 kết quả).
Cào web hàng loạt (Fetch/Scrape)Tải tối đa 10 URL song song một lúc. Trả về Markdown, HTML, JSON.Chuyển đổi 1 URL thành Markdown, HTML, JSON, hoặc Screenshot.
Crawl diện rộngKhông hỗ trợ crawl đệ quy tự động. Phải tự code logic duyệt link.Rất mạnh với /crawl (bất đồng bộ) và /map (quét toàn bộ sơ đồ URL của website).
Tương tác trình duyệtRất mạnh: Agent API chạy goal bằng ngôn ngữ tự nhiên, còn Browser API cung cấp direct Chrome CDP/Playwright connection.Hỗ trợ /interact (2 credits/phút trình duyệt) bằng code tương tác cơ bản, và Agent (Preview).
Tối ưu hóa mạng (Cache)Hỗ trợ caching thông qua ttl và conditional request với etag, last_modified.Tập trung vào hệ thống proxy nâng cao để chống chặn, không chú trọng cache phía client quản lý.

Điểm khác biệt lớn nhất: Caching & Cấu trúc chi phí

Hãy nói về tiền trước. Với Firecrawl, mô hình của họ là “pay-as-you-go” trên mọi API call. Bạn dùng /scrape mất 1 credit, /crawl mất 1 credit/trang, /map mất 1 credit, thậm chí /search mất 2 credits cho mỗi 10 kết quả. Gói Free chỉ cho 1.000 credits/tháng, rất nhanh hết nếu bạn chạy crawl dữ liệu liên tục.

Ngược lại, TinyFish cho phép bạn Search và Fetch miễn phí không giới hạn. Họ chỉ tính credit khi bạn dùng Agent API (để thực hiện các workflow phức tạp như tự điền form, click, login bằng ngôn ngữ tự nhiên) hoặc Browser API (khởi tạo trình duyệt Chrome cloud để tự điều khiển bằng Playwright/CDP).

Hơn nữa, TinyFish hỗ trợ cơ chế caching rất thông minh. Giả sử bạn cần giám sát một trang tin tức 5 phút một lần để xem có bài viết mới không. Với TinyFish, bạn có thể truyền thêm validator etag hoặc last_modified thu được từ lần fetch trước:

from tinyfish import TinyFish

client = TinyFish()
result = client.fetch.get_contents(
    urls=["https://example.com/news"],
    if_none_match='W/"etag-value-here"',
    include_etag_and_last_modified=True
)

if result.results[0].not_modified:
    print("Nội dung không đổi, bỏ qua xử lý để tiết kiệm token!")

Nếu trang web chưa có cập nhật, server sẽ trả về trạng thái not_modified ngay lập tức mà không cần tải hay render lại toàn bộ trang. Việc này giúp giảm tải mạng và tăng tốc độ xử lý cho agent một cách đáng kể.


Trải nghiệm code thực tế

Để bạn có góc nhìn trực quan, đây là cách mình implement tính năng tìm kiếm và đọc nội dung bằng cả hai thư viện trong Python.

1. Sử dụng TinyFish (Search + Fetch miễn phí)

Quy trình của TinyFish là tách biệt rõ ràng: bạn Search để tìm URL, sau đó dùng Fetch để lấy nội dung chi tiết của các URL đó.

from tinyfish import TinyFish

client = TinyFish()

# Bước 1: Tìm kiếm các bài viết liên quan
search_res = client.search.query(
    query="hướng dẫn cấu hình GRPC Go",
    purpose="Tìm link tài liệu chất lượng về gRPC bằng Golang",
    location="VN",
    language="vi"
)

urls_to_fetch = [r.url for r in search_res.results[:3]]
print(f"Tìm thấy {len(urls_to_fetch)} link hữu ích. Tiến hành fetch...")

# Bước 2: Fetch song song nội dung của các URL này (vẫn miễn phí!)
fetch_res = client.fetch.get_contents(
    urls=urls_to_fetch,
    format="markdown"
)

for page in fetch_res.results:
    print(f"\n--- Tiêu đề: {page.title} ---")
    print(page.text[:300])  # In thử 300 ký tự đầu tiên

2. Sử dụng Firecrawl (Scrape + Crawl toàn site)

Với Firecrawl, nếu bạn muốn cào toàn bộ một website tài liệu hoặc blog, họ cung cấp API /crawl chạy bất đồng bộ rất tiện lợi.

from firecrawl import FirecrawlApp

app = FirecrawlApp(api_key="your_firecrawl_api_key")

# Crawl đệ quy toàn bộ trang web bất đồng bộ
crawl_status = app.crawl_url(
    "https://docs.nestjs.com",
    params={
        "limit": 50,
        "scrapeOptions": {"formats": ["markdown"]}
    },
    wait_until_done=False
)

# Bạn sẽ nhận được crawl_id để poll trạng thái sau đó
print(f"Đang bắt đầu crawl. ID nhiệm vụ: {crawl_status['id']}")

Quyết định cuối cùng: Nên chọn bên nào?

Nói gọn lại: không có công cụ nào hoàn hảo cho mọi trường hợp. Lựa chọn của bạn phụ thuộc vào bài toán cụ thể đang giải quyết.

Bạn nên chọn TinyFish nếu:

  • Tối ưu hóa chi phí là ưu tiên hàng đầu: Bạn cần chạy hàng ngàn tác vụ tìm kiếm và trích xuất trang web mỗi ngày. Việc tách biệt Search/Fetch miễn phí giúp bạn tiết kiệm được một khoản tiền lớn.
  • Cần kiểm soát cache chặt chẽ: Bạn đang xây dựng các hệ thống monitoring, aggregator cần thăm dò (poll) website liên tục và tận dụng etag/last_modified.
  • Cần tương tác sâu thông qua trình duyệt: Bạn muốn con agent tự đăng nhập, bấm nút, vượt captcha phức tạp thông qua giao diện CDP/Playwright hoặc qua Goal ngôn ngữ tự nhiên.

Bạn nên chọn Firecrawl nếu:

  • Cần cào toàn bộ website (Crawl): Bạn muốn nạp toàn bộ docs của một thư viện vào RAG database mà không muốn tự viết logic duyệt liên kết đệ quy phức tạp.
  • Cần sơ đồ URL nhanh (Map): Bạn muốn quét nhanh xem một domain đang có bao nhiêu sub-pages hoạt động mà không cần tải nội dung trang.
  • Cần trích xuất dữ liệu có cấu trúc ăn liền (Extract): Bạn muốn định nghĩa một schema JSON (ví dụ thông tin sản phẩm: tên, giá, hãng) và để API tự dùng LLM parse ra kết quả chính xác mà không cần tự viết prompt.

Hiện tại, mình đang chọn giải pháp lai: Dùng TinyFish làm công cụ grounding chính cho các tác vụ search/fetch thông tin của agent hàng ngày để giữ hóa đơn ở mức $0, và chỉ gọi sang Firecrawl khi cần quét sitemap hoặc cào toàn bộ một trang tài liệu mới.

Còn bạn thì sao? Lớp mạng cho AI agent của bạn đang chạy bằng gì? Hãy chia sẻ trải nghiệm thực tế bên dưới nhé!

Share :