0Pricing
AI Agents · Pelajaran

Desain Putaran Riset Multi-Langkah

Rencanakan → cari → baca → ekstrak → sintesis → ulangi hingga kedalaman yang memadai.

Desain Putaran Riset Multi-Langkah adalah pelajaran AI Agents gratis di CoddyKit. Ini adalah pelajaran 1 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.

Apa Itu Siklus Riset?

Siklus riset adalah pola agenik ketika LLM merencanakan, mencari, membaca, mengekstrak, mengidentifikasi kesenjangan, dan mengulanginya sampai tujuan riset terpenuhi.

Berbeda dari pencarian sekali jalan, siklus ini beradaptasi berdasarkan hasil yang ditemukan — menindaklanjuti petunjuk tak terduga dan membuang jalan buntu.

Tahap 1: Penguraian Pertanyaan

Langkah pertama adalah memecah pertanyaan riset menjadi subpertanyaan. Hal ini membuat rencana pencarian terarah dan mencegah agen menjelajah tanpa tujuan.

import openai, json

client = openai.OpenAI(api_key='YOUR_OPENAI_KEY')

def decompose_question(question: str) -> list[str]:
    prompt = (
        f'Break this research question into 3-5 focused sub-questions.\n'
        f'Each sub-question should be independently searchable.\n'
        f'Question: "{question}"\n'
        f'Return JSON: {{"sub_questions": ["..."]}}'
    )
    resp = client.chat.completions.create(
        model='gpt-4o',
        messages=[{'role': 'user', 'content': prompt}],
        response_format={'type': 'json_object'}
    )
    return json.loads(resp.choices[0].message.content)['sub_questions']

questions = decompose_question('What are the main causes of inflation in 2024?')
print(questions)

Tahap 2: Pencarian Web

Untuk setiap subpertanyaan, lakukan pencarian web. Gunakan API pencarian (Serper, Brave, Bing) untuk mendapatkan daftar URL dan cuplikan. Jangan membaca semua halaman — prioritaskan sumber berkualitas tinggi terlebih dahulu.

import requests

SERPER_KEY = 'YOUR_SERPER_API_KEY'

def search_web(query: str, num_results: int = 5) -> list[dict]:
    resp = requests.post(
        'https://google.serper.dev/search',
        headers={'X-API-KEY': SERPER_KEY, 'Content-Type': 'application/json'},
        json={'q': query, 'num': num_results}
    )
    resp.raise_for_status()
    results = resp.json().get('organic', [])
    return [
        {'title': r['title'], 'url': r['link'], 'snippet': r.get('snippet', '')}
        for r in results
    ]

Tahap 3: Membaca dan Mengekstrak Fakta

Ambil setiap URL dan ekstrak fakta utama yang relevan dengan subpertanyaan. Gunakan LLM untuk membaca artikel dan menghasilkan daftar fakta beserta URL sumbernya.

import httpx
from bs4 import BeautifulSoup

def fetch_text(url: str, max_chars: int = 4000) -> str:
    try:
        resp = httpx.get(url, timeout=10, follow_redirects=True,
                         headers={'User-Agent': 'ResearchAgent/1.0'})
        soup = BeautifulSoup(resp.text, 'html.parser')
        for tag in soup(['script', 'style', 'nav', 'footer']):
            tag.decompose()
        return soup.get_text(separator=' ', strip=True)[:max_chars]
    except Exception:
        return ''

def extract_facts(text: str, question: str, url: str) -> list[dict]:
    prompt = (
        f'Extract key facts from the text that answer: "{question}"\n'
        f'Return JSON: {{"facts": ["fact1", ...]}}\n\n'
        f'TEXT:\n{text[:3000]}'
    )
    resp = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': prompt}],
        response_format={'type': 'json_object'}
    )
    facts = json.loads(resp.choices[0].message.content).get('facts', [])
    return [{'fact': f, 'source': url} for f in facts]

Tahap 4: Mengidentifikasi Kesenjangan Pengetahuan

Setelah membaca, minta LLM meninjau fakta yang telah terkumpul dan mengidentifikasi hal-hal yang masih belum diketahui. Kesenjangan ini menjadi kueri pencarian pada putaran berikutnya.

def identify_gaps(original_question: str, facts: list[dict]) -> list[str]:
    fact_text = '\n'.join(f'- {f["fact"]}' for f in facts[:20])
    prompt = (
        f'Original question: "{original_question}"\n'
        f'Facts gathered so far:\n{fact_text}\n\n'
        f'What key aspects are still unanswered? '
        f'Return 0-3 follow-up search queries (0 if research is complete).\n'
        f'JSON: {{"gaps": ["search query 1", ...]}}'
    )
    resp = client.chat.completions.create(
        model='gpt-4o',
        messages=[{'role': 'user', 'content': prompt}],
        response_format={'type': 'json_object'}
    )
    return json.loads(resp.choices[0].message.content).get('gaps', [])

Kondisi Penghentian

Siklus memerlukan kondisi berhenti yang jelas agar tidak berjalan selamanya. Berhentilah ketika:

  • Tidak ada kesenjangan baru yang teridentifikasi
  • Tidak ada fakta baru yang ditambahkan pada iterasi terakhir
  • Jumlah maksimum iterasi telah tercapai (batas keselamatan)
  • Total fakta melampaui ambang batas (kedalaman sudah memadai)
def should_continue(gaps: list[str], new_facts_this_round: int,
                    iteration: int, total_facts: int) -> bool:
    if iteration >= 5:
        return False          # Hard cap: 5 iterations
    if new_facts_this_round == 0:
        return False          # No new information found
    if not gaps:
        return False          # LLM says research is complete
    if total_facts >= 50:
        return False          # Sufficient depth reached
    return True

if __name__ == '__main__':
    print('Continue (has gaps, new facts)?', should_continue(['gap1'], 4, iteration=1, total_facts=10))
    print('Continue (no new facts)?', should_continue(['gap1'], 0, iteration=1, total_facts=10))

Menghapus Duplikasi Fakta

Beberapa sumber sering melaporkan fakta yang sama. Hapus duplikat dengan meminta LLM menggabungkan fakta yang setara secara semantik, sambil mempertahankan versi dengan sumber terbaik.

def deduplicate_facts(facts: list[dict]) -> list[dict]:
    if len(facts) <= 3:
        return facts
    fact_text = '\n'.join(
        f'{i}: {f["fact"]} (source: {f["source"]})' for i, f in enumerate(facts)
    )
    prompt = (
        f'Remove duplicate or near-duplicate facts. Keep the most informative version.\n'
        f'Return JSON: {{"keep_indices": [0, 1, ...]}}\n\n'
        f'FACTS:\n{fact_text}'
    )
    resp = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': prompt}],
        response_format={'type': 'json_object'}
    )
    indices = json.loads(resp.choices[0].message.content).get('keep_indices', [])
    return [facts[i] for i in indices if i < len(facts)]

Siklus Riset Lengkap

Gabungkan semua tahap ke dalam satu fungsi research() yang menjalankan siklus hingga penghentian.

def research(question: str) -> dict:
    all_facts = []
    iteration = 0

    # Phase 1: Decompose into sub-questions
    queries = decompose_question(question)

    while True:
        new_facts_this_round = 0

        for query in queries:
            results = search_web(query, num_results=3)
            for result in results:
                text = fetch_text(result['url'])
                if not text:
                    continue
                facts = extract_facts(text, query, result['url'])
                all_facts.extend(facts)
                new_facts_this_round += len(facts)

        all_facts = deduplicate_facts(all_facts)
        gaps = identify_gaps(question, all_facts)
        iteration += 1

        if not should_continue(gaps, new_facts_this_round, iteration, len(all_facts)):
            break

        queries = gaps  # next iteration searches for the gaps

    return {'facts': all_facts, 'iterations': iteration}

Melacak Asal-Usul

Setiap fakta harus menyertakan URL sumbernya agar laporan akhir dapat memuat sitasi. Jangan pernah menghapus metadata sumber selama pemrosesan — metadata tersebut diperlukan oleh lapisan sitasi.

def add_fact(fact_list: list, fact_text: str, source_url: str, iteration: int):
    fact_list.append({
        'fact':      fact_text,
        'source':    source_url,
        'iteration': iteration,
        'verified':  False   # set to True after cross-referencing
    })

# Example:
facts_store = []
add_fact(facts_store, 'Global inflation peaked at 9.1% in June 2022',
         'https://bls.gov/news.release/cpi.htm', iteration=1)

print(f'Logged {len(facts_store)} fact(s):')
for f in facts_store:
    print(f"  - {f['fact']} (source: {f['source']})")

Pencarian Paralel untuk Kecepatan

Pencarian berurutan berjalan lambat — 5 kueri × 3 URL × 1 pengambilan masing-masing = 15 panggilan HTTP berurutan. Gunakan concurrent.futures untuk menjalankan pengambilan secara paralel dalam setiap iterasi.

from concurrent.futures import ThreadPoolExecutor, as_completed

def parallel_research_round(queries: list[str]) -> list[dict]:
    collected = []

    def process_query(query):
        results = search_web(query, num_results=3)
        facts = []
        for r in results:
            text = fetch_text(r['url'])
            if text:
                facts.extend(extract_facts(text, query, r['url']))
        return facts

    with ThreadPoolExecutor(max_workers=4) as ex:
        futures = {ex.submit(process_query, q): q for q in queries}
        for future in as_completed(futures):
            collected.extend(future.result())

    return collected

Memantau Kemajuan Siklus

Catat setiap iterasi agar Anda dapat men-debug alasan siklus berhenti atau berjalan lebih lama dari yang diharapkan. Sertakan jumlah kueri, fakta yang ditambahkan, dan kesenjangan yang teridentifikasi.

import logging

log = logging.getLogger('research_loop')
import sys
logging.basicConfig(level=logging.INFO, stream=sys.stdout)

def log_iteration(iteration: int, queries: list[str],
                  new_facts: int, total_facts: int, gaps: list[str]):
    log.info(
        'Iteration %d | Queries: %d | New facts: %d | Total: %d | Gaps: %d',
        iteration, len(queries), new_facts, total_facts, len(gaps)
    )
    if gaps:
        for g in gaps:
            log.debug('  Gap query: %s', g)

if __name__ == '__main__':
    log_iteration(iteration=2, queries=['who are our top competitors?'], new_facts=4, total_facts=12, gaps=['pricing data'])

Apa yang menghentikan siklus riset ketika tidak ada informasi baru yang ditemukan?

Memahami kondisi penghentian mencegah siklus tak terbatas dan memastikan agen memberikan hasil dalam jangka waktu yang wajar.

Ringkasan Desain Siklus Riset

Siklus riset multi-langkah mengikuti urutan: urai → cari → baca → ekstrak → identifikasi kesenjangan → ulangi. Berhentilah ketika kesenjangan sudah habis, tidak ada fakta baru yang ditemukan, atau batas keras iterasi tercapai.

Selalu lacak URL sumber bersama setiap fakta, jalankan pencarian secara paralel untuk mempercepat proses, dan hapus duplikasi fakta sebelum melakukan sintesis.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Desain Putaran Riset Multi-Langkah” gratis?

Ya — teks lengkap “Desain Putaran Riset Multi-Langkah” 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 “Desain Putaran Riset Multi-Langkah”?

Rencanakan → cari → baca → ekstrak → sintesis → ulangi hingga kedalaman yang memadai. 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 1 dari 4.

Berapa lama pelajaran “Desain Putaran Riset Multi-Langkah” 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. Desain Putaran Riset Multi-Langkah
  2. Verifikasi Sumber dan Sitasi
  3. Pembuatan Laporan Terstruktur
  4. Pemeriksaan Fakta dan Pencegahan Halusinasi
← Kembali ke AI Agents