Không cần KYC — không ID, không ảnh selfie, không giấy tờ. Thanh toán bằng crypto: BTC, USDT, USDC, ETH, SOL, LTC
Ngôn ngữ: Tiếng Việt
Lấy khóa API

Tài liệu · Python

Ví dụ Python: tìm kiếm, chạy truy vấn song song, trả lời kèm trích dẫn

Ba script bao quát những gì hầu hết agent Python cần: một lần tìm kiếm với requests, nhiều lần tìm kiếm cùng lúc với httpx và một semaphore, và một vòng lặp ngắn đưa các nguồn cho một mô hình ngôn ngữ và nhận lại câu trả lời kèm trích dẫn được đánh số.

Cập nhật lần cuối: · 6 phút đọc

Trả lời nhanh

Làm thế nào để gọi web search API cho AI agent từ Python?

POST truy vấn tới https://llmwebsearch.com/api/v1/search với requests hoặc httpx và một khóa Bearer. LLMWebSearch trả về kết quả đã xếp hạng với 3 trang đầu dưới dạng Markdown, mà bạn có thể đánh số và đưa cho bất kỳ LLM nào để trả lời kèm trích dẫn. Một lần tìm kiếm tốn 1 credit, từ 1,20 US$/1K lượt tìm kiếm tính đến tháng 10 năm 2026. Python 3.9+ và không cần SDK. Không cần KYC; thanh toán bằng crypto.

Những gì bạn cần

Python3.9 trở lên
Packagerequests cho script đơn giản, httpx cho script bất đồng bộ
KeyLLMWEBSEARCH_API_KEY trong môi trường của bạn
Cho vòng lặp trả lờiBất kỳ chat endpoint tương thích OpenAI nào: LLM_BASE_URL, LLM_API_KEY, LLM_MODEL
Thanh toánMột credit trả cho một lượt tìm kiếm: tối đa 20 kết quả được xếp hạng, với nội dung của 3 trang đầu được đọc và trả về dưới dạng Markdown. Đọc từ 4 đến 10 trang thì tính 2 credit. Lượt gọi kết thúc bằng lỗi không tốn gì

Làm thế nào để chạy một lần tìm kiếm với requests?

Tạo một body JSON với q và các tùy chọn bạn cần, post nó, rồi lặp qua results. Kiểm tra content_status trước khi chạm vào content: chỉ các kết quả được đánh dấu ok mới chứa nội dung trang. Script bên dưới lưu mỗi trang đã đọc thành một file Markdown đặt tên theo vị trí của nó, với URL nguồn ở dòng đầu tiên.

search_once.py
import os
import pathlib

import requests

resp = requests.post(
    "https://llmwebsearch.com/api/v1/search",
    headers={"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]},
    json={"q": "how to size a postgres connection pool", "max_results": 5, "read": 3},
    timeout=60,
)
resp.raise_for_status()
data = resp.json()
out = pathlib.Path("sources")
out.mkdir(exist_ok=True)
for r in data["results"]:
    if r["content_status"] != "ok":
        print("skip", r["position"], r["content_status"], r["url"])
        continue
    path = out / f"{r['position']:02d}.md"
    path.write_text("Source: " + r["url"] + "\n\n" + r["content"], encoding="utf-8")
    print("saved", path, r["word_count"], "words")
print("credits used:", data["credits_used"])

Làm thế nào để chạy nhiều lần tìm kiếm cùng lúc?

Dùng httpx.AsyncClient và một asyncio.Semaphore. Semaphore giới hạn số lần gọi đang thực hiện, giúp bạn không vượt giới hạn mỗi phút của tài khoản và phân tán tải. Bốn đến tám lần gọi đồng thời phù hợp với hầu hết agent nghiên cứu. Mỗi tài khoản có một giới hạn lượt gọi mỗi phút, hiển thị trong dashboard; hãy hỏi support và giới hạn đó có thể được nâng lên.

Ví dụ gửi một lần tìm kiếm cho mỗi câu hỏi con, một bước điển hình của agent nghiên cứu, và thu thập URL của các trang đã đọc. Mỗi lần gọi độc lập: một lần thất bại không dừng những lần khác.

many_searches.py
import asyncio
import os

import httpx

API = "https://llmwebsearch.com/api/v1/search"
HEADERS = {"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]}
QUESTIONS = [
    "what is connection pooling in postgres",
    "recommended pool size per cpu core",
    "pgbouncer transaction mode limitations",
    "connection pool exhaustion symptoms",
]


async def search(client, sem, q):
    async with sem:
        resp = await client.post(API, json={"q": q, "read": 2, "max_chars": 4000})
        if resp.status_code != 200:
            return q, resp.json().get("error", {}).get("code"), []
        data = resp.json()
        read = [r["url"] for r in data["results"] if r["content_status"] == "ok"]
        return q, "ok", read


async def main():
    sem = asyncio.Semaphore(4)
    async with httpx.AsyncClient(headers=HEADERS, timeout=60) as client:
        for q, status, urls in await asyncio.gather(*(search(client, sem, q) for q in QUESTIONS)):
            print(status, q, urls)


asyncio.run(main())

Làm thế nào để nhận câu trả lời kèm trích dẫn từ bất kỳ LLM nào?

Tìm kiếm trước, sau đó đưa cho mô hình các nguồn được đánh số và yêu cầu nó trích dẫn chúng. API trả về các nguồn, không phải một câu trả lời được viết sẵn: model của chính bạn đọc các trang, viết câu trả lời và trích dẫn các URL, nên bạn chọn mô hình và kiểu trích dẫn. Vòng lặp bên dưới hoạt động với bất kỳ chat endpoint nào hỗ trợ định dạng chat/completions tương thích OpenAI; đặt địa chỉ, khóa và mô hình của nó trong ba biến môi trường.

Giữ ngữ cảnh trong tầm kiểm soát. Script cắt bớt mỗi nguồn để tổng vẫn nằm trong ngân sách khoảng 6.000 token, tính khoảng bốn ký tự mỗi token. Một kết quả không có nội dung được truyền dưới dạng snippet của nó, có ghi nhãn như vậy, để mô hình không giả vờ rằng nó đã đọc trang.

answer_with_citations.py
import os

import requests

SEARCH = "https://llmwebsearch.com/api/v1/search"
KEY = os.environ["LLMWEBSEARCH_API_KEY"]
BUDGET_CHARS = 6000 * 4  # about 6,000 tokens of sources


def sources_for(question):
    resp = requests.post(SEARCH, headers={"Authorization": "Bearer " + KEY},
                         json={"q": question, "max_results": 5, "read": 3}, timeout=60)
    resp.raise_for_status()
    results = resp.json()["results"]
    share = BUDGET_CHARS // max(len(results), 1)
    blocks = []
    for i, r in enumerate(results, start=1):
        if r["content_status"] == "ok":
            body = r["content"][:share]
        else:
            body = "(snippet only) " + r["snippet"]
        blocks.append(f"[{i}] {r['title']} - {r['url']}\n{body}")
    return "\n\n".join(blocks)


def answer(question):
    prompt = ("Answer the question using only the sources below. "
              "Cite them as [1], [2] and so on. Say so if the sources do not answer it.\n\n"
              + sources_for(question) + "\n\nQuestion: " + question)
    resp = requests.post(
        os.environ["LLM_BASE_URL"].rstrip("/") + "/chat/completions",
        headers={"Authorization": "Bearer " + os.environ["LLM_API_KEY"]},
        json={"model": os.environ["LLM_MODEL"], "messages": [{"role": "user", "content": prompt}]},
        timeout=120,
    )
    resp.raise_for_status()
    return resp.json()["choices"][0]["message"]["content"]


print(answer("How should I size a Postgres connection pool?"))

Tôi nên gửi bao nhiêu văn bản cho mô hình?

Ít nhất đủ để trả lời câu hỏi. Ba trang được cắt bớt còn 2.000 token mỗi trang thường tốt hơn mười trang đầy đủ: mô hình tập trung tốt hơn và mỗi câu trả lời tốn ít hơn. Giảm max_chars trong chính lần tìm kiếm khi bạn biết mình sẽ cắt bớt, để ít dữ liệu được truyền đi hơn.

Cắt từ đầu trang phù hợp với hầu hết bài viết, vì ý chính thường xuất hiện trước. Với các trang tham khảo dài, hãy chia nội dung theo tiêu đề và giữ lại những phần có tiêu đề khớp với câu hỏi.

Đoạn code nên làm gì khi thiếu một trang?

Tiếp tục với các nguồn khác. Một trang được đánh dấu blocked_by_robots, blocked_by_site_policy hoặc target_refused sẽ không được đọc lại ở lần thử thứ hai, nên đừng lặp lại nó. Một trang fetch_timeout hoặc fetch_failed có thể hoạt động sau đó thông qua https://llmwebsearch.com/api/v1/extract.

Lỗi HTTP thì khác: 429, 502 và 504 xứng đáng được thử lại với khoảng dừng tăng dần. Trang lỗi có sẵn một helper thử lại.

Python: các câu hỏi thường gặp

Có gói pip cho LLMWebSearch không?

Không. API là HTTPS và JSON thuần, nên bạn chỉ cần requests hoặc httpx. Các script trên trang này chính là phần tích hợp: hãy sao chép chúng vào dự án của bạn và điều chỉnh cho phù hợp.

Tôi có thể dùng các script này với một model cục bộ không?

Có. Bất kỳ server nào cung cấp route chat/completions tương thích OpenAI đều hoạt động với vòng lặp trích dẫn: đặt LLM_BASE_URL thành địa chỉ của nó và LLM_MODEL thành tên model mà nó mong đợi.

Làm cách nào để đếm credit từ Python?

Cộng credits_used từ mỗi response, hoặc gọi GET https://llmwebsearch.com/api/v1/credits trước và sau một job; lệnh gọi đó miễn phí.

Từ 1,20 US$/1K lượt tìm kiếm · không cần KYC

Lấy khóa API