0Pricing
AI Agents · Pelajaran

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 route

Menyiapkan 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/web

Pemeriksaan 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

  1. Tavily dan SerpAPI untuk Pencarian Agen
  2. Mengurutkan dan Menyaring Hasil Pencarian
  3. Pola Putaran Riset Mendalam
  4. Menggabungkan Pencarian Web dengan RAG
← Kembali ke AI Agents