Menggabungkan Pencarian Web dengan RAG
Pengambilan hibrida: penyimpanan vektor lokal + pencarian web langsung untuk jawaban terkini.
Menggabungkan Pencarian Web dengan RAG adalah pelajaran AI Agents gratis di CoddyKit. Ini adalah pelajaran 4 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar AI Agents, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus AI Agents mencakup 4 pelajaran total.
Tantangan Pengambilan Hibrida
Sebagian besar agen di dunia nyata membutuhkan dua jenis pengetahuan: pengetahuan domain statis (dokumen perusahaan, manual produk, kebijakan) dan informasi terkini (berita, harga langsung, peristiwa terbaru).
Penyimpanan vektor lokal menangani jenis pertama; pencarian internet menangani jenis kedua. Menggabungkan keduanya memberikan hasil terbaik dari kedua sumber.
Arsitektur: RAG Lokal + Pencarian Internet
Sistem hibrida mengarahkan setiap pertanyaan ke sumber pengambilan yang tepat:
- Penyimpanan vektor (RAG) — dokumen terindeks, pengetahuan stabil, data privat
- Pencarian internet — peristiwa terkini, rilis terbaru, data langsung
- Keduanya — ketika pertanyaan memerlukan konteks dari dokumen AND informasi terkini
class HybridRetrievalAgent:
def __init__(self, vector_store, search_client):
self.vector_store = vector_store # e.g., ChromaDB or FAISS
self.search_client = search_client # e.g., TavilyClient
def answer(self, question):
route = self.classify_question(question)
if route == 'static':
context = self.vector_store.query(question, n_results=5)
elif route == 'current':
context = self.web_search(question)
else: # 'both'
local = self.vector_store.query(question, n_results=3)
web = self.web_search(question)
context = local + web
return self.generate_answer(question, context)
if __name__ == '__main__':
class DemoAgent(HybridRetrievalAgent):
def classify_question(self, question):
return 'static' if 'company' in question.lower() else 'current'
def web_search(self, question):
return [('Web result about ' + question, {})]
def generate_answer(self, question, context):
return f'Answer using {len(context)} context item(s).'
class FakeVectorStore:
def query(self, question, n_results=5):
return [('Local doc snippet', {})]
agent = DemoAgent(FakeVectorStore(), search_client=None)
print(agent.answer('What is our company policy on refunds?'))
Pengklasifikasi Perutean
Pengklasifikasi menentukan sumber pengambilan yang akan digunakan. Anda dapat mengimplementasikannya sebagai pemanggilan LLM, sekumpulan aturan kata kunci, atau pengklasifikasi kecil yang telah dilatih. Perute berbasis LLM adalah yang paling fleksibel.
ROUTING_PROMPT = '''Classify this question into one of three categories:
- "static": answered from company documents, product docs, or stable technical knowledge
- "current": requires up-to-date information (news, prices, recent events, latest releases)
- "both": needs both company context and current information
Question: {question}
Respond with exactly one word: static, current, or both.'''
def classify_question(question):
response = llm_call(ROUTING_PROMPT.format(question=question))
route = response.strip().lower()
if route not in ('static', 'current', 'both'):
return 'both' # safe default
return routeMenyiapkan Penyimpanan Vektor Lokal
Untuk basis pengetahuan statis, gunakan ChromaDB — basis data vektor ringan yang berjalan di dalam proses. Indeks dokumen sekali; lakukan kueri saat program berjalan.
Instal dengan pip install chromadb openai.
import chromadb
from chromadb.utils import embedding_functions
import os
client = chromadb.PersistentClient(path='./vector_db')
ef = embedding_functions.OpenAIEmbeddingFunction(
api_key=os.getenv('OPENAI_API_KEY'),
model_name='text-embedding-3-small'
)
collection = client.get_or_create_collection(
name='company_docs',
embedding_function=ef
)
def index_document(doc_id, text, metadata=None):
collection.add(
ids=[doc_id],
documents=[text],
metadatas=[metadata or {}]
)
def local_retrieve(question, n_results=5):
results = collection.query(
query_texts=[question],
n_results=n_results
)
return list(zip(results['documents'][0], results['metadatas'][0]))Pengambilan melalui Pencarian Internet
Jalur pencarian internet menggunakan Tavily untuk mengambil informasi terkini. Format hasil secara konsisten agar hasil tersebut dapat digabungkan dengan hasil RAG lokal dalam struktur perintah yang sama.
from tavily import TavilyClient
import os
tavily = TavilyClient(api_key=os.getenv('TAVILY_API_KEY'))
def web_retrieve(question, n_results=3):
results = tavily.search(
query=question,
max_results=n_results,
search_depth='basic'
)
# Normalize to same format as local results
return [
(
r['content'][:600], # text
{'source': r['url'], 'title': r['title'], 'type': 'web'} # metadata
)
for r in results.get('results', [])
]Menggabungkan Hasil Lokal dan Internet
Jika kedua sumber digunakan, gabungkan hasil dan beri label pada masing-masing hasil berdasarkan asalnya. Dengan demikian, LLM dapat menimbangnya secara tepat — dokumen lokal untuk fakta khusus perusahaan, dan internet untuk data terkini.
def merge_results(local_results, web_results):
merged = []
for text, meta in local_results:
merged.append({
'content': text,
'source': meta.get('source', 'internal document'),
'type': 'local',
'title': meta.get('title', 'Company Document')
})
for text, meta in web_results:
merged.append({
'content': text,
'source': meta.get('source', 'web'),
'type': 'web',
'title': meta.get('title', 'Web Result')
})
return merged
def format_merged_for_prompt(merged_results):
parts = []
for i, r in enumerate(merged_results, 1):
tag = '[INTERNAL]' if r['type'] == 'local' else '[WEB]'
parts.append(f'[{i}] {tag} {r["title"]}\n{r["content"]}')
return '\n\n'.join(parts)
if __name__ == '__main__':
local = [('Refunds are processed within 5 business days.', {'source': 'handbook', 'title': 'Refund Policy'})]
web = [('Company X reported Q2 earnings today.', {'source': 'reuters.com', 'title': 'Q2 Earnings'})]
merged = merge_results(local, web)
print(format_merged_for_prompt(merged))
Mendeteksi Pertanyaan yang Memerlukan Informasi Terkini
Selain pengklasifikasi LLM, gunakan heuristik kata kunci untuk mendeteksi pertanyaan yang memerlukan informasi terkini. Cara ini lebih cepat dan menghindari pemanggilan LLM tambahan untuk kasus yang jelas.
CURRENT_EVENTS_SIGNALS = [
'latest', 'current', 'today', 'now', 'recent',
'this week', 'this month', 'this year',
'just released', 'new version', 'updated',
'price', 'stock', 'news', 'announcement',
'2024', '2025'
]
STATIC_SIGNALS = [
'how does', 'what is', 'explain', 'tutorial',
'documentation', 'our product', 'company policy',
'internal', 'handbook'
]
def fast_route(question):
lower = question.lower()
current_score = sum(1 for s in CURRENT_EVENTS_SIGNALS if s in lower)
static_score = sum(1 for s in STATIC_SIGNALS if s in lower)
if current_score > static_score:
return 'current'
elif static_score > current_score:
return 'static'
else:
return 'both'
if __name__ == '__main__':
for q in ['What is our company handbook policy on PTO?', 'What is the latest stock price today?']:
print(f'{fast_route(q)!r} <- "{q}"')
Menangani Konflik Antar-Sumber
Konflik terjadi ketika dokumen lokal menyatakan satu hal, sedangkan hasil internet menyatakan hal lain. Contohnya, dokumen harga internal Anda menyebutkan $50/bulan, tetapi hasil internet menyatakan bahwa harganya telah berubah menjadi $80/bulan.
Instruksikan LLM untuk menandai konflik dan lebih mengutamakan sumber internet untuk fakta yang sensitif terhadap waktu.
HYBRID_ANSWER_PROMPT = '''You are answering a question using two types of sources:
- [INTERNAL] sources: company documents (may be outdated)
- [WEB] sources: current web information
For factual claims about current state (prices, versions, availability):
PREFER [WEB] sources over [INTERNAL] ones.
For company-specific processes, policies, and architecture:
PREFER [INTERNAL] sources.
If sources conflict, note the discrepancy in your answer.
Sources:
{sources}
Question: {question}
Answer:'''
def generate_hybrid_answer(question, merged_results):
sources_text = format_merged_for_prompt(merged_results)
return llm_call(HYBRID_ANSWER_PROMPT.format(
sources=sources_text,
question=question
))Mendeteksi Keusangan Dokumen Lokal
Dokumen lokal menjadi usang seiring waktu. Tambahkan pemeriksaan keusangan: jika dokumen lokal lebih lama daripada ambang batas, lengkapi dokumen tersebut dengan pencarian internet meskipun perute mengklasifikasikan pertanyaan sebagai 'statis'.
from datetime import datetime, timedelta
STALENESS_THRESHOLD_DAYS = 90
def check_staleness(metadata):
indexed_at = metadata.get('indexed_at')
if not indexed_at:
return False # unknown age — assume fresh
indexed_date = datetime.fromisoformat(indexed_at)
age = datetime.now() - indexed_date
return age > timedelta(days=STALENESS_THRESHOLD_DAYS)
def smart_retrieve(question, route):
local_results = []
web_results = []
if route in ('static', 'both'):
local_results = local_retrieve(question, n_results=4)
# Check if any local results are stale
stale = any(check_staleness(meta) for _, meta in local_results)
if stale:
print('Stale local docs — adding web search')
web_results = web_retrieve(question, n_results=2)
if route in ('current', 'both'):
web_results = web_retrieve(question, n_results=3)
return merge_results(local_results, web_results)Penilaian Tingkat Keyakinan
Berikan skor keyakinan pada setiap bagian konteks yang diambil. Sumber dengan keyakinan tinggi (terkini, berasal dari domain tepercaya, dan memiliki kemiripan representasi vektor yang tinggi) mendapatkan bobot lebih besar dalam jawaban akhir.
def score_result(result, query_embedding):
score = 0.5 # base score
# Recency bonus for web results
if result.get('type') == 'web':
pub_date = result.get('published_date', '')
if '2024' in pub_date or '2025' in pub_date:
score += 0.2
# Embedding similarity to query
if result.get('content'):
result_emb = embed(result['content'][:500])
sim = cosine_similarity(query_embedding, result_emb)
score += sim * 0.3
# Domain authority
from urllib.parse import urlparse
domain = urlparse(result.get('source', '')).netloc
if any(auth in domain for auth in ['docs.', 'developer.', 'official.']):
score += 0.1
return min(score, 1.0)Alur Pengambilan Hibrida Lengkap
Jika semua bagian digabungkan: perutean cepat → pengambilan cerdas dari salah satu atau kedua sumber → pelengkapan untuk mengatasi keusangan → penggabungan → penilaian → pemformatan → pembuatan jawaban.
def hybrid_answer(question):
# 1. Route (fast heuristic first, LLM fallback for ambiguous)
route = fast_route(question)
if route == 'both':
route = classify_question(question) # LLM for ambiguous cases
print(f'Route: {route}')
# 2. Retrieve
merged = smart_retrieve(question, route)
if not merged:
return 'I could not find relevant information to answer your question.'
# 3. Generate
answer = generate_hybrid_answer(question, merged)
return answer
# Usage
print(hybrid_answer('What is our refund policy?')) # -> static/local
print(hybrid_answer('What is GPT-4 pricing today?')) # -> current/webPemeriksaan Pengetahuan
Kapan agen pengambilan hibrida harus lebih mengutamakan hasil pencarian internet daripada hasil dokumen lokal?
Rangkuman: Menggabungkan Pencarian Internet dengan RAG
Pengambilan hibrida menggabungkan penyimpanan vektor lokal (untuk pengetahuan statis, privat, atau khusus domain) dengan pencarian internet (untuk informasi publik terkini). Pengklasifikasi perutean mengarahkan setiap pertanyaan ke sumber yang tepat — atau ke keduanya bila diperlukan.
Teknik utama: perutean heuristik cepat dengan sinyal kata kunci, deteksi keusangan dokumen lokal, instruksi penyelesaian konflik dalam perintah, dan penilaian keyakinan untuk memberi bobot pada konteks yang diambil.
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Menggabungkan Pencarian Web dengan RAG” gratis?
Ya — teks lengkap “Menggabungkan Pencarian Web dengan RAG” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus AI Agents, upgrade ke CoddyKit PRO. Kursus AI Agents mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Menggabungkan Pencarian Web dengan RAG”?
Pengambilan hibrida: penyimpanan vektor lokal + pencarian web langsung untuk jawaban terkini. Kamu berlatih AI Agents dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai AI Agents?
Tidak diperlukan pengalaman sebelumnya. AI Agents di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 4 dari 4.
Berapa lama pelajaran “Menggabungkan Pencarian Web dengan RAG” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran AI Agents ini?
Ya. Setiap pelajaran AI Agents menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Tavily dan SerpAPI untuk Pencarian Agen
- Mengurutkan dan Menyaring Hasil Pencarian
- Pola Putaran Riset Mendalam
- Menggabungkan Pencarian Web dengan RAG