Jawaban singkat
Bagaimana cara memanggil web search API untuk agen AI dari Python?
POST kueri ke https://llmwebsearch.com/api/v1/search dengan requests atau httpx dan Bearer key. LLMWebSearch mengembalikan hasil berperingkat beserta 3 halaman teratas sebagai Markdown, yang bisa Anda beri nomor dan teruskan ke LLM apa pun untuk dijawab dengan sitasi. Satu pencarian berbiaya 1 kredit, mulai dari US$1,20/1K pencarian per Oktober 2026. Python 3.9+ dan tanpa SDK. Tanpa KYC; bayar dengan kripto.
Yang Anda butuhkan
| Python | 3.9 atau lebih baru |
|---|---|
| Paket | requests untuk skrip sederhana, httpx untuk yang async |
| Key | LLMWEBSEARCH_API_KEY di environment Anda |
| Untuk loop jawaban | Endpoint chat apa pun yang kompatibel dengan OpenAI: LLM_BASE_URL, LLM_API_KEY, LLM_MODEL |
| Penagihan | Satu kredit membayar satu pencarian: hingga 20 hasil berperingkat, dengan halaman dari 3 hasil teratas dibaca dan dikembalikan sebagai Markdown. Membaca 4 hingga 10 halaman menjadi 2 kredit. Panggilan yang berakhir dengan error tidak dikenakan biaya |
Bagaimana cara menjalankan satu pencarian dengan requests?
Susun body JSON dengan q dan opsi yang Anda butuhkan, POST, lalu loop atas results. Periksa content_status sebelum menyentuh content: hanya hasil yang ditandai ok yang membawa teks halaman. Skrip di bawah menyimpan setiap halaman yang dibaca sebagai file Markdown bernama sesuai posisinya, dengan URL sumber di baris pertama.
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"])
Bagaimana cara menjalankan banyak pencarian sekaligus?
Gunakan httpx.AsyncClient dan asyncio.Semaphore. Semaphore membatasi berapa banyak panggilan yang sedang berjalan, sehingga Anda tetap di bawah batas per menit akun Anda dan beban tersebar. Empat sampai delapan panggilan bersamaan cocok untuk sebagian besar agen riset. Setiap akun memiliki batas panggilan per menit yang ditampilkan di dashboard; hubungi support dan batas itu bisa dinaikkan.
Contoh mengirim satu pencarian per sub-pertanyaan, langkah khas agen riset, dan mengumpulkan URL halaman yang dibaca. Setiap panggilan independen: satu kegagalan tidak menghentikan yang lain.
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())
Bagaimana cara mendapatkan jawaban dengan sitasi dari LLM apa pun?
Cari dulu, lalu beri model sumber bernomor dan minta ia mengutipnya. API mengembalikan sumber, bukan jawaban tertulis: model Anda sendiri yang membaca halaman, menulis balasan, dan mengutip URL-nya, jadi Anda memilih model dan gaya sitasi. Loop di bawah berfungsi dengan endpoint chat apa pun yang berbicara dalam format chat/completions yang kompatibel dengan OpenAI; atur alamat, key, dan modelnya di tiga environment variable.
Jaga konteks tetap terkendali. Skrip memangkas setiap sumber agar totalnya tetap dalam anggaran sekitar 6.000 token, dengan hitungan kira-kira empat karakter per token. Hasil tanpa konten diteruskan sebagai snippet-nya, ditandai sebagai snippet, agar model tidak berpura-pura telah membaca halaman itu.
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?"))
Berapa banyak teks yang harus saya kirim ke model?
Sesedikit yang cukup untuk menjawab pertanyaan. Tiga halaman yang dipangkas menjadi 2.000 token masing-masing biasanya mengalahkan sepuluh halaman penuh: model lebih fokus dan setiap jawaban lebih murah. Turunkan max_chars pada pencarian itu sendiri bila Anda tahu akan memangkas, agar lebih sedikit data yang berpindah.
Memangkas dari awal halaman berhasil untuk sebagian besar artikel, karena poin utamanya cenderung muncul lebih dulu. Untuk halaman referensi yang panjang, pecah konten berdasarkan heading dan pertahankan bagian yang judulnya cocok dengan pertanyaan.
Apa yang harus dilakukan kode ketika sebuah halaman hilang?
Lanjutkan dengan sumber lain. Halaman yang ditandai blocked_by_robots, blocked_by_site_policy atau target_refused tidak akan dibaca pada percobaan kedua, jadi jangan loop di situ. Halaman fetch_timeout atau fetch_failed mungkin berhasil nanti melalui https://llmwebsearch.com/api/v1/extract.
Error HTTP berbeda: 429, 502 dan 504 layak dicoba ulang dengan jeda yang makin panjang. Halaman errors punya helper retry yang siap pakai.
Python: pertanyaan umum
Apakah ada paket pip untuk LLMWebSearch?
Tidak. API ini adalah HTTPS dan JSON biasa, jadi Anda hanya perlu requests atau httpx. Skrip di halaman ini adalah integrasinya: salin ke proyek Anda dan sesuaikan.
Bisakah saya menggunakan skrip ini dengan model lokal?
Bisa. Server apa pun yang menyediakan route chat/completions yang kompatibel dengan OpenAI berfungsi dengan loop sitasi: atur LLM_BASE_URL ke alamatnya dan LLM_MODEL ke nama model yang diharapkannya.
Bagaimana cara menghitung kredit dari Python?
Jumlahkan credits_used dari setiap respons, atau panggil GET https://llmwebsearch.com/api/v1/credits sebelum dan sesudah tugas; panggilan itu gratis.