KYC 없이 — 신분증, 셀피, 서류가 필요 없습니다. 암호화폐로 결제하세요: BTC, USDT, USDC, ETH, SOL, LTC
언어: 한국어
API 키 받기

가이드 · Python · 약 60줄, 모든 LLM

웹 검색 API로 Python에서 딥 리서치 에이전트 구축하기

딥 리서치는 모델이 아니라 루프입니다. 이 가이드는 몇 분 만에 읽을 수 있는 하나를 구축합니다: 검색 쿼리를 계획하고, 페이지 텍스트가 포함된 웹 검색을 하고, 각 소스를 한 번만 유지하고, 빈틈을 찾고, 번호가 매겨진 인용이 포함된 답변을 작성합니다.

마지막 업데이트: · 4 분 소요

빠른 답변

Python으로 딥 리서치 에이전트를 어떻게 구축하나요?

LLM에 검색 쿼리를 요청하고, 각 쿼리를 페이지 텍스트를 반환하는 웹 검색 API로 실행하고, 각 소스를 한 번만 유지하고, 후속 검색 쿼리를 요청한 다음, 인용이 포함된 답변을 작성하는 루프를 작성하세요. LLMWebSearch에서는 각 검색이 첫 3페이지를 Markdown으로 반환하며 1크레딧입니다. 아래 스크립트는 질문당 여섯 번의 검색을 실행합니다. US$1.20/1K 검색부터, KYC 없이, 암호화폐 결제.

에이전트는 무엇을 하나요?

  1. 요금제

    모델에 질문을 함께 커버하는 네 개의 짧은 검색 쿼리를 요청합니다.

  2. 검색

    각 검색 쿼리를 read=3로 실행하여 처음 세 페이지가 Markdown으로 반환되게 합니다.

  3. 소스를 한 번만 유지

    URL을 기준으로 결과를 저장하고 이미 수집된 페이지나 텍스트가 없는 페이지는 건너뜁니다.

  4. 빈틈 찾기

    지금까지 찾은 제목을 모델에 보여주고 빠진 부분에 대한 두 개의 검색 쿼리를 요청합니다.

  5. 작성

    최대 12개의 소스에 번호를 매기고 [1], [2]로 인용하는 답변을 요청합니다.

시작하기 전에 무엇이 필요한가요?

세 가지입니다:

  • LLMWebSearch API 키를 환경 변수 LLMWEBSEARCH_API_KEY에 설정합니다. 키는 첫 팩 결제 후 대시보드에 표시됩니다.
  • 모든 OpenAI 호환 chat endpoint를 LLM_BASE_URL, LLM_API_KEY, LLM_MODEL로 설정합니다. 호스팅 모델과 로컬 서버 모두 작동합니다.
  • Python 3.9 이상과 requests 패키지.

스크립트는 두 서비스 모두에 일반 HTTP를 사용하므로 검색 코드를 변경하지 않고 모델을 교체할 수 있습니다.

Python: deep_research.py
import os

import requests

SEARCH = "https://llmwebsearch.com/api/v1/search"
SEARCH_HEADERS = {"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]}
# Any OpenAI-compatible chat endpoint works here: set your own base URL, key and model name.
LLM_URL = os.environ.get("LLM_BASE_URL", "https://llm.example.com/v1") + "/chat/completions"
LLM_HEADERS = {"Authorization": "Bearer " + os.environ.get("LLM_API_KEY", "")}
MODEL = os.environ.get("LLM_MODEL", "your-model-name")


def ask_llm(prompt):
    body = {"model": MODEL, "messages": [{"role": "user", "content": prompt}]}
    resp = requests.post(LLM_URL, headers=LLM_HEADERS, json=body, timeout=120)
    resp.raise_for_status()
    return resp.json()["choices"][0]["message"]["content"]


def plan_queries(question, n=4):
    text = ask_llm(f"Write {n} short web search queries, one per line, to answer: {question}")
    queries = [line.strip("-*0123456789. ").strip() for line in text.splitlines()]
    return [q for q in queries if q][:n]


def search(query):
    body = {"q": query, "max_results": 5, "read": 3, "max_chars": 5000}
    resp = requests.post(SEARCH, headers=SEARCH_HEADERS, json=body, timeout=60)
    resp.raise_for_status()
    return resp.json()["results"]


def research(question, rounds=2):
    sources = {}  # url -> result, so the same page is never cited twice
    queries = plan_queries(question)
    for _ in range(rounds):
        for query in queries:
            for r in search(query):
                if r.get("content_status") == "ok" and r["url"] not in sources:
                    sources[r["url"]] = r
        notes = "\n".join(f"- {r['title']}" for r in sources.values())
        queries = plan_queries(f"{question}\nAlready found:\n{notes}\nWhat is still missing?", n=2)
    numbered = list(sources.values())[:12]
    context = "\n\n".join(
        f"[{i}] {r['title']} ({r['url']})\n{r['content']}" for i, r in enumerate(numbered, 1)
    )
    prompt = (
        "Answer the question using only the sources below. Cite them as [1], [2]. "
        "Say so when the sources disagree or do not cover a point.\n\n"
        f"Question: {question}\n\nSources:\n{context}"
    )
    return ask_llm(prompt), [r["url"] for r in numbered]


if __name__ == "__main__":
    answer, urls = research("What changed in the EU rules for general-purpose AI models in 2025?")
    print(answer)
    for i, url in enumerate(urls, 1):
        print(f"[{i}] {url}")

각 부분은 어떻게 작동하나요?

plan_queries은 모델에 한 줄에 하나씩 짧은 검색 쿼리를 요청하고 목록 표시를 제거합니다. 짧은 검색 쿼리는 전체 질문보다 검색 엔진이 페이지 순위를 매기는 방식과 더 잘 맞습니다.

search는 max_results=5, read=3, max_chars=5000과 함께 POST https://llmwebsearch.com/api/v1/search를 호출합니다. 응답은 다섯 개의 결과를 나열하며, 처음 세 개는 content에 페이지 텍스트를 담고 있습니다.

research은 라운드를 실행합니다. URL을 키로 하는 딕셔너리에 소스를 유지하므로 두 개의 검색 쿼리로 찾은 페이지는 한 번만 계산됩니다. 답변이 모델이 읽을 수 있는 텍스트에 기반해야 하므로 content_status가 ok인 결과만 유지됩니다.

각 라운드 후에 모델은 지금까지 수집된 제목을 보고 빠진 부분에 대한 두 개의 새 검색 쿼리를 제안합니다. 최종 프롬프트는 최대 열두 개의 소스에 번호를 매기고 인용 규칙을 설정합니다.

보고서 하나에 비용이 얼마나 드나요?

기본 설정으로 질문당 여섯 번의 검색: 첫 라운드에 네 번, 두 번째 라운드에 두 번. read을 3으로 설정하면 6크레딧입니다. 따라서 검색 25,000회이 US$41.25에서는 4,000건 이상의 보고서를 커버합니다.

모델 호출은 LLM 청구서에 추가 비용이 듭니다: 보고서당 세 번의 계획 호출과 한 번의 긴 답변 호출. 답변 호출은 최대 12페이지의 5,000자 분량을 처리하므로 모델이 비싸다면 max_chars을 낮추세요.

더 깊게 들어가려면 어떻게 하나요?

구조는 그대로 두고 숫자를 바꾸세요:

  • 라운드 늘리기. rounds=4를 사용하면 모델이 두 세트의 빈틈을 더 추적합니다.
  • 라운드당 검색 쿼리 늘리기. 빈틈 찾기 호출에서 n을 2에서 4로 올리세요.
  • 소스 좁히기. 검색 본문에 include_domains을 추가해 공식 또는 학술 사이트로 한정하세요.
  • 최신 자료만. "time_range": "month" 또는 "topic": "news"을 추가하세요.
  • 검색 쿼리당 페이지 늘리기. read=5는 검색 1회당 2 크레딧으로 다섯 페이지를 읽습니다.

한도를 올리기 전에 중지 규칙을 먼저 추가하세요: 한 라운드에서 새 소스가 두 개 미만으로 나오면 루프를 끝내도록 하세요.

에이전트를 안전하고 예의 바르게 유지하려면 어떻게 하나요?

모든 페이지를 신뢰할 수 없는 텍스트로 취급하세요. 최종 프롬프트는 모델에게 소스를 근거로만 사용하라고 지시하며, 소스 안의 지시는 무시해야 한다는 줄을 명시적으로 추가하세요. 소스가 도구 호출이나 파일 쓰기를 절대 유발하지 않도록 하세요.

웹 쪽에서는 저희 리더는 robots.txt를 준수합니다. 자신을 LLMWebSearch로 소개하고, 사이트가 리더를 위해 또는 모든 로봇을 위해 작성한 규칙을 따르며, 읽기가 허용되지 않은 페이지의 콘텐츠는 제외합니다. 접근을 거부하는 페이지는 내용 없이 돌아오고 스크립트는 그냥 건너뜁니다. 사이트가 저희 리더를 거부하면, 결과는 콘텐츠 없이 해당 사이트의 상태와 함께 반환됩니다. 저희는 CAPTCHA를 풀거나 계정에 로그인하거나 차단 또는 페이월을 우회하지 않습니다.

무엇이 잘못될 수 있나요?

테스트에서 세 가지가 나타납니다:

  • 모호한 검색 쿼리. 계획이 약하면 매 라운드 같은 페이지를 찾습니다. 모델에게 구체적인 이름과 날짜를 사용한 검색 쿼리를 요청하세요.
  • 텍스트가 있는 소스 부족. 일부 주제는 유료 장벽 뒤에 있습니다. 검색 쿼리를 넓히거나 결과를 더 허용하세요.
  • 너무 긴 프롬프트. 긴 페이지 12개는 작은 모델의 컨텍스트를 초과할 수 있습니다. max_chars을 낮추거나 소스를 8개로 유지하세요.

각 검색 쿼리와 그것이 반환한 URL을 로그로 남기세요. 그 로그를 읽는 것이 계획 프롬프트를 개선하는 가장 빠른 방법입니다.

딥 리서치 에이전트: 자주 묻는 질문

로컬 모델로 실행할 수 있나요?

네, 로컬 서버가 OpenAI chat-completions 형식을 지원한다면 가능합니다. LLM_BASE_URL을 그 주소로, LLM_MODEL을 모델 이름으로 설정하세요.

MCP 도구로 바꿀 수 있나요?

네. research()을 MCP 도구로 감싸거나, 에이전트에게 MCP 페이지의 일반 검색 도구를 주고 루프를 직접 실행하게 하세요.

검색 API에 직접 답변을 요청하면 안 되나요?

LLMWebSearch은 답변을 작성하지 않기 때문입니다. API는 작성된 답변이 아니라 출처를 반환합니다. 자체 모델이 페이지를 읽고 답변을 작성하며 URL을 인용합니다.

각 검색에 얼마가 들었는지 어떻게 볼 수 있나요?

모든 응답에는 credits_used이 포함되며, GET https://llmwebsearch.com/api/v1/credits는 남은 잔액을 비용 없이 보여줍니다.

US$1.20/1K 검색부터 · KYC 없이

API 키 받기