Agent Web Search (Outline)

Agent 為什麼需要 Web Search?

LLM 的知識有 training cutoff,無法得知最新資訊。
Web Search 讓 Agent 能在推理時動態拉取即時資料。

使用者問「最新的 GPT-5 規格是什麼?」
    ↓
LLM 本身不知道(cutoff 之後的資訊)
    ↓
呼叫 Web Search tool → 拿到即時搜尋結果
    ↓
結果放進 context → LLM 生成回答

這個模式稱為 Tool-Augmented Generation,是 RAG 的即時網路版本


三種主流方案

工具 定位 詳細筆記
Tavily 專為 LLM 設計的官方商用 Search API Tavily
SearXNG 開源自架 metasearch engine SearXNG
ddgs 非官方 Python metasearch library DuckDuckGo

完整比較

比較 ddgs Tavily SearXNG
官方 API ❌ 非官方 ✅ 官方 ✅ 自架
API Key ✅(tvly-...
費用 免費 Free 1,000 credits/月 免費(自架成本)
AI 合成回答 include_answer
結果格式 title + href + body 摘要/chunks + score title + url + content + engine
Rate limit 風險 中(取決於上游)
LLM 優化
授權 MIT 商用 API AGPL-3.0
穩定性 低(非官方) 高(SLA) 中(上游不穩定)
適合情境 快速 prototype 正式 RAG / Agent 隱私優先、自架

各工具核心特性

Tavily

/search → 摘要 / chunks,可開 include_answer
search_depth: ultra-fast / fast / basic / advanced(1–2 credits)
topic: general / news / finance
/extract → 完整網頁正文(markdown)
/research → 多輪迭代搜尋,回傳完整 report

SearXNG

GET /search?q=...&format=json
同時查詢 251 個上游來源(Google / Bing / DDG / Wikipedia...)
自架 Docker,只改 settings.yml
回傳:title + url + content + engine + score

ddgs

from ddgs import DDGS
DDGS().text(query=..., timelimit="w", max_results=5)
方法:text / news / images / videos / books / extract
回傳:title + href + body

決策流程

需要即時網路資料
    ↓
是否在乎隱私 / 不想用第三方 API?
    ├─ 是 → SearXNG(自架)
    └─ 否
         ↓
    是否是正式產品 / 需要穩定性?
         ├─ 是 → Tavily(Official API)
         └─ 否 → ddgs(prototype 快速驗證)

常見使用模式

RAG with Web Search

# Tavily 版
from tavily import TavilyClient

def retrieve(query: str) -> list[str]:
    results = TavilyClient(api_key="tvly-...").search(
        query=query, search_depth="basic", max_results=5
    )
    return [r["content"] for r in results["results"]]

context = "\n".join(retrieve("HNSW 的時間複雜度"))
prompt = f"根據以下資料回答問題:\n{context}\n\n問題:HNSW 的時間複雜度?"

LangChain Agent with Web Search Tool

from langchain_tavily import TavilySearch
from langchain_community.tools import DuckDuckGoSearchRun

# 選一個掛進 agent
tools = [TavilySearch(max_results=3)]
# 或
tools = [DuckDuckGoSearchRun()]

SearXNG HTTP call

import requests

def searxng_search(query: str, n: int = 5) -> list[dict]:
    resp = requests.get(
        "http://localhost:8080/search",
        params={"q": query, "format": "json", "pageno": 1}
    )
    return resp.json()["results"][:n]

Powered by Forestry.md