คำตอบสั้น
จะเพิ่มการค้นหาเว็บแบบเรียลไทม์ให้ LangChain หรือ LlamaIndex ได้อย่างไร?
ห่อการเรียก /search ของ LLMWebSearch ด้วย LangChain @tool, LangChain retriever หรือ LlamaIndex FunctionTool แต่ละแบบจะคืนแหล่งที่มาจัดอันดับ พร้อม 3 หน้าแรกเป็น Markdown และ URL พร้อมสำหรับการอ้างอิง ไม่ต้องติดตั้งแพ็กเกจของเรา โค้ดด้านล่างคือการเชื่อมต่อทั้งหมด การค้นหา 1 ครั้งใช้ 1 เครดิต เริ่มต้นที่ US$1.20/1K การค้นหา ณ เดือนตุลาคม 2026 ไม่ต้อง KYC จ่ายด้วยคริปโต
แต่ละ wrapper ใช้ทำอะไร
| LangChain tool | agent จะเรียก search_web เมื่อเห็นว่าตนต้องการเว็บ |
|---|---|
| LangChain retriever | chain จะดึงเอกสารใหม่สำหรับทุกคำถามโดยไม่ต้องสั่ง |
| LlamaIndex FunctionTool | ฟังก์ชัน search_web เดียวกัน สำหรับ agent ของ LlamaIndex |
| แพ็กเกจ | langchain-core หรือ llama-index-core พร้อม requests |
| Key | LLMWEBSEARCH_API_KEY ใน environment |
| การเรียกเก็บเงิน | หนึ่งเครดิตจ่ายสำหรับการค้นหาหนึ่งครั้ง: ผลลัพธ์แบบจัดอันดับสูงสุด 20 รายการ โดยอ่านหน้าเว็บของ 3 รายการแรกและส่งกลับเป็น Markdown การอ่าน 4 ถึง 10 หน้าใช้ 2 เครดิต การเรียกที่จบลงด้วยข้อผิดพลาดไม่มีค่าใช้จ่าย |
จะสร้างเครื่องมือค้นหาสำหรับ LangChain agent ได้อย่างไร?
ตกแต่งฟังก์ชันด้วย @tool จาก langchain_core.tools LangChain จะอ่านชื่อ อาร์กิวเมนต์ที่มีชนิดข้อมูล และ docstring เพื่ออธิบาย tool ให้โมเดล จึงควรเขียน docstring ให้สั้นและชัดเจน ฟังก์ชันจะคืนสตริงเดียวพร้อมแหล่งที่มาที่มีหมายเลข ซึ่งเข้ากับแชตโมเดลทุกตัวและเก็บ URL ไว้ข้างข้อความ
เรียกใช้โดยตรงด้วย .invoke() เพื่อทดสอบ จากนั้นส่งเข้าในลิสต์ tools ของ agent
import os
import requests
from langchain_core.tools import tool
API = "https://llmwebsearch.com/api/v1/search"
HEADERS = {"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]}
@tool
def search_web(query: str, read: int = 3) -> str:
"""Search the live web. Returns numbered sources with URLs; the first `read` include page text."""
body = {"q": query, "max_results": 5, "read": max(0, min(read, 10)), "max_chars": 5000}
resp = requests.post(API, headers=HEADERS, json=body, timeout=60)
resp.raise_for_status()
parts = []
for i, r in enumerate(resp.json()["results"], start=1):
text = r["content"] if r["content_status"] == "ok" else "(snippet only) " + r["snippet"]
parts.append(f"[{i}] {r['title']} - {r['url']}\n{text}")
return "\n\n".join(parts)
print(search_web.invoke({"query": "postgres connection pool size"})[:500])
จะใช้เว็บแบบเรียลไทม์เป็น retriever ได้อย่างไร?
สร้าง subclass ของ BaseRetriever และคืน Document หนึ่งรายการต่อหน้าที่อ่าน ข้อความของหน้าจะอยู่ใน page_content ส่วน URL, title, rank และวันที่อยู่ใน metadata ซึ่ง chain ที่อ้างอิงแหล่งที่มาจะค้นหาข้อมูลเหล่านี้ ผลลัพธ์ที่ไม่มีเนื้อหาจะถูกข้าม เพราะ retriever ควรส่งข้อความที่โมเดลนำไปอ้างอิงได้
retriever ทำงานทุกคำถาม เหมาะกับ chain ตอบคำถามเกี่ยวกับหัวข้อปัจจุบัน แต่สิ้นเปลืองในแชตที่ส่วนใหญ่ไม่ต้องค้นหา ในกรณีนั้นให้ใช้ tool
import os
from typing import List
import requests
from langchain_core.callbacks import CallbackManagerForRetrieverRun
from langchain_core.documents import Document
from langchain_core.retrievers import BaseRetriever
class LLMWebSearchRetriever(BaseRetriever):
"""Live web search results as Documents, one per page that was read."""
max_results: int = 5
read: int = 3
max_chars: int = 6000
def _get_relevant_documents(self, query: str, *, run_manager: CallbackManagerForRetrieverRun) -> List[Document]:
resp = requests.post(
"https://llmwebsearch.com/api/v1/search",
headers={"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]},
json={"q": query, "max_results": self.max_results, "read": self.read, "max_chars": self.max_chars},
timeout=60,
)
resp.raise_for_status()
docs = []
for r in resp.json()["results"]:
if r["content_status"] != "ok":
continue
meta = {"source": r["url"], "title": r["title"], "position": r["position"], "published_at": r.get("published_at")}
docs.append(Document(page_content=r["content"], metadata=meta))
return docs
retriever = LLMWebSearchRetriever(read=3)
for doc in retriever.invoke("pgbouncer transaction mode limitations"):
print(doc.metadata["position"], doc.metadata["source"], len(doc.page_content))
จะให้การค้นหาเดียวกันกับ agent ของ LlamaIndex ได้อย่างไร?
เขียนฟังก์ชันธรรมดาแล้วห่อด้วย FunctionTool.from_defaults จาก llama_index.core.tools LlamaIndex จะสร้างชื่อและคำอธิบายของ tool จากชื่อฟังก์ชัน signature และ docstring การเรียก tool จะคืน ToolOutput ที่มี content เป็นข้อความที่ agent จะอ่าน
ฟังก์ชันนี้เหมือนกับของ LangChain ทีมที่ใช้ทั้งสองเฟรมเวิร์กจึงแชร์ฟังก์ชันนี้ได้
import os
import requests
from llama_index.core.tools import FunctionTool
def search_web(query: str, read: int = 3) -> str:
"""Search the live web and return numbered sources; the first `read` include their page text."""
resp = requests.post(
"https://llmwebsearch.com/api/v1/search",
headers={"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]},
json={"q": query, "max_results": 5, "read": max(0, min(read, 10)), "max_chars": 5000},
timeout=60,
)
resp.raise_for_status()
parts = []
for i, r in enumerate(resp.json()["results"], start=1):
text = r["content"] if r["content_status"] == "ok" else "(snippet only) " + r["snippet"]
parts.append(f"[{i}] {r['title']} - {r['url']}\n{text}")
return "\n\n".join(parts)
search_tool = FunctionTool.from_defaults(fn=search_web)
print(search_tool.metadata.name)
print(search_tool.call(query="postgres connection pool size").content[:300])
ฉันจะควบคุม context window ได้อย่างไร?
ตั้งค่า max_chars ตอนเรียก API แทนที่จะมาตัดทีหลัง: ข้อมูลที่ส่งไปน้อยกว่า และ framework จะไม่ถือเวอร์ชันยาวไว้เลย 5,000 ตัวอักษรต่อหน้าและ 3 หน้า คิดเป็นประมาณ 4,000 tokens ซึ่งสบายสำหรับโมเดลส่วนใหญ่
สำหรับ retrieval chain ที่รวมเว็บสดเข้ากับเอกสารของคุณเอง ให้ให้น้ำหนักเอกสารจากเว็บต่ำลงหรือแยกส่วน prompt ต่างหาก หน้าเว็บเปลี่ยนได้และอาจผิดพลาด ส่วนเอกสารของคุณเองมักเป็นข้อมูลอ้างอิง
ฉันเก็บสิ่งที่ retriever ส่งคืนไว้ใน vector database ได้ไหม?
ได้ เท่าที่เราเกี่ยวข้องนะ เราไม่ฝึกโมเดลใดๆ ด้วยคำค้นหาของคุณหรือข้อมูลที่ API ส่งกลับ และเราไม่เพิ่มกฎของเราเองต่อต้านการจัดเก็บผลลัพธ์; สิทธิ์ของเว็บไซต์ที่คุณอ่านหน้ายังคงมีผล เก็บ URL และ published_at ไว้กับทุก chunk เพื่อให้ agent อ้างอิงหน้าเว็บได้ และคุณลบ chunk ที่เก่าเกินไปได้
ทีมส่วนใหญ่แคชผลการค้นหาเว็บของคำถามที่ถามบ่อยไว้หนึ่งวันหรือหนึ่งสัปดาห์ ช่วยลดการค้นหาซ้ำ และทุกการค้นหาที่เลี่ยงได้คือเครดิตที่ประหยัด
LangChain และ LlamaIndex: คำถามที่พบบ่อย
มีแพ็กเกจ langchain-llmwebsearch ไหม?
ไม่มี เราไม่ได้เผยแพร่แพ็กเกจใดๆ โค้ดในหน้านี้สั้นพอที่จะเป็นของคุณเอง: คัดลอกไป เปลี่ยนค่า default และเก็บไว้ใน repository ของคุณ
ฉันทำให้ tool เป็น async ได้ไหม?
ได้ แทนที่ requests ด้วย httpx.AsyncClient และนิยามฟังก์ชันด้วย async def decorator @tool ของ LangChain ใช้กับฟังก์ชัน async ได้โดยตรง ส่วนใน LlamaIndex ให้ส่งเวอร์ชัน async ไปยัง FunctionTool.from_defaults เป็น async_fn
ฉันจะอ่านหน้าเว็บที่ agent เจอมาจากที่อื่นได้อย่างไร?
เพิ่ม tool ที่สองที่ส่ง URL ไปยัง https://llmwebsearch.com/api/v1/extract การอ่านหน้าเว็บที่คุณมี URL อยู่แล้วใช้ 1 เครดิตต่อกลุ่ม 3 หน้าที่เริ่มอ่านและส่งกลับพร้อมเนื้อหา สูงสุด 20 URL ต่อการเรียก; URL ที่ถูกปฏิเสธหรือล้มเหลวไม่ถูกนับ เอกสารอ้างอิง extract แสดงตัวอย่าง request