0Pricing
AI Agents · 강의

에이전트 검색을 위한 Tavily 및 SerpAPI

웹 검색 도구를 위한 API 설정, 쿼리 구성, 결과 파싱을 알아봅니다.

에이전트 검색을 위한 Tavily 및 SerpAPI은(는) CoddyKit의 무료 AI Agents 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 AI Agents 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. AI Agents 강의에는 총 4개의 강의가 포함되어 있습니다.

에이전트에게 웹 검색이 필요한 이유

LLM에는 지식 기준일이 있습니다. 현재 사건, 실시간 가격, 최근 뉴스 또는 빠르게 변화하는 주제에 관한 질문에서는 모델의 학습 데이터가 오래되었을 수 있습니다.

Tavily 및 SerpApi와 같은 웹 검색 도구는 에이전트에 인터넷 실시간 접근을 제공하여 정적인 학습 데이터와 현재 현실 사이의 간극을 메웁니다.

Tavily: AI 에이전트에 맞게 설계된 도구

Tavily는 AI 에이전트를 위해 특별히 설계된 검색 API입니다. 일반적인 웹 데이터 수집과 달리 깔끔하고 구조화된 결과를 미리 추출된 콘텐츠와 함께 반환하므로 HTML 구문 분석이 필요하지 않습니다.

pip install tavily-python으로 설치하십시오. tavily.com에서 API 키를 받으십시오.

from tavily import TavilyClient
import os

client = TavilyClient(api_key=os.getenv('TAVILY_API_KEY'))

results = client.search(
    query='latest OpenAI GPT-5 release date',
    max_results=5
)

for r in results['results']:
    print(r['title'])
    print(r['url'])
    print(r['content'][:200])
    print('---')

Tavily 검색 매개변수

Tavily는 검색 동작을 제어할 수 있는 여러 매개변수를 제공합니다. 에이전트에 가장 유용한 매개변수는 max_results, search_depth, include_domains / exclude_domains입니다.

# Basic search
results = client.search(
    query='Python async best practices 2024',
    max_results=5,
    search_depth='basic'  # 'basic' (fast) or 'advanced' (slower, deeper)
)

# Domain-filtered search
results = client.search(
    query='machine learning papers',
    max_results=5,
    include_domains=['arxiv.org', 'papers.nips.cc', 'openreview.net']
)

# Exclude low-quality domains
results = client.search(
    query='stock market today',
    max_results=5,
    exclude_domains=['pinterest.com', 'quora.com']
)

Tavily 결과 구조

각 Tavily 결과에는 title, url, content(추출된 텍스트), score(관련성)가 포함되며, 선택적으로 published_date도 포함됩니다. content 필드는 HTML 태그가 없는 깔끔한 텍스트입니다.

results = client.search('Claude AI pricing 2024', max_results=3)

for r in results['results']:
    print(f"Title:   {r['title']}")
    print(f"URL:     {r['url']}")
    print(f"Score:   {r.get('score', 'N/A')}")
    print(f"Date:    {r.get('published_date', 'unknown')}")
    print(f"Content: {r['content'][:300]}")
    print()

# Tavily also returns 'answer' — a direct answer synthesized from results
if results.get('answer'):
    print('Direct answer:', results['answer'])

SerpApi: Google 검색 프로그래밍 방식 접근

SerpApi는 Google, Bing, YouTube 및 기타 검색 엔진에 구조화된 방식으로 접근할 수 있게 합니다. 자연 검색 결과, 지식 패널, 주요 검색 결과 요약문, 쇼핑 결과를 비롯한 풍부한 데이터를 반환합니다.

pip install google-search-results로 설치하십시오.

from serpapi import GoogleSearch
import os

params = {
    'q': 'best Python web frameworks 2024',
    'api_key': os.getenv('SERPAPI_KEY'),
    'num': 5,              # number of results
    'hl': 'en',            # language
    'gl': 'us',            # country
    'safe': 'active'       # safe search
}

search = GoogleSearch(params)
results = search.get_dict()

for r in results.get('organic_results', []):
    print(r['title'])
    print(r['link'])
    print(r.get('snippet', ''))
    print()

SerpApi 결과 구조

SerpApi는 Tavily보다 더 풍부한 구조화된 데이터를 반환합니다. organic_results의 주요 필드는 title, link, snippet, position입니다. 주요 검색 결과 요약문은 answer_box 아래에 별도로 표시됩니다.

def extract_serp_results(serp_data, max_results=5):
    results = []

    # Featured snippet / answer box (highest priority)
    if 'answer_box' in serp_data:
        box = serp_data['answer_box']
        results.append({
            'title': box.get('title', 'Featured Snippet'),
            'url':   box.get('link', ''),
            'snippet': box.get('answer') or box.get('snippet', ''),
            'is_featured': True
        })

    # Organic results
    for r in serp_data.get('organic_results', [])[:max_results]:
        results.append({
            'title':   r.get('title', ''),
            'url':     r.get('link', ''),
            'snippet': r.get('snippet', ''),
            'position': r.get('position', 0),
            'is_featured': False
        })

    return results

if __name__ == '__main__':
    demo_serp = {
        'answer_box': {'title': 'Python version', 'link': 'https://python.org', 'answer': '3.13'},
        'organic_results': [
            {'title': 'Python Docs', 'link': 'https://docs.python.org', 'snippet': 'Official docs', 'position': 1},
        ],
    }
    for r in extract_serp_results(demo_serp):
        print(f"{'[FEATURED] ' if r['is_featured'] else ''}{r['title']} - {r['url']}")

최신성 옵션 및 날짜 필터링

시간에 민감한 쿼리의 경우 게시 날짜로 결과를 필터링하십시오. Tavily는 days 매개변수를 지원하고, SerpApi는 tbs(시간 기반 검색) 매개변수를 지원합니다.

# Tavily: results from last 7 days
recent_results = client.search(
    query='AI news',
    max_results=5,
    days=7  # only results published in last 7 days
)

# SerpApi: results from last month
params = {
    'q': 'AI news',
    'api_key': os.getenv('SERPAPI_KEY'),
    'tbs': 'qdr:m',   # qdr:d=day, qdr:w=week, qdr:m=month, qdr:y=year
    'num': 5
}
search = GoogleSearch(params)
results = search.get_dict()

LangChain용 검색 도구 구축

LangChain 에이전트 안에서 Tavily 또는 SerpApi를 사용하려면 검색 함수를 Tool로 감싸십시오. 그러면 에이전트는 제공한 설명을 바탕으로 다른 도구와 마찬가지로 해당 도구를 호출할 수 있습니다.

from langchain.tools import Tool
from tavily import TavilyClient
import os

tavily = TavilyClient(api_key=os.getenv('TAVILY_API_KEY'))

def tavily_search(query: str) -> str:
    results = tavily.search(query=query, max_results=3, search_depth='basic')
    output = []
    for r in results['results']:
        output.append(f"Title: {r['title']}\nURL: {r['url']}\nContent: {r['content'][:500]}")
    return '\n\n'.join(output)

web_search_tool = Tool(
    name='web_search',
    func=tavily_search,
    description='Search the web for current information. Input: a search query string. Returns top results with title, URL, and content.'
)

품질 관리를 위한 도메인 필터링

모든 검색 결과를 신뢰할 수 있는 것은 아닙니다. 도메인 필터링을 사용하면 검색을 신뢰할 수 있는 출처로 제한하거나(연구 목적), 스팸이 많은 도메인을 제외할 수 있습니다(일반적인 질문의 경우).

TRUSTED_DOMAINS = {
    'medical':  ['nih.gov', 'who.int', 'mayoclinic.org', 'pubmed.ncbi.nlm.nih.gov'],
    'legal':    ['law.cornell.edu', 'supreme.justia.com', 'congress.gov'],
    'tech':     ['docs.python.org', 'developer.mozilla.org', 'stackoverflow.com'],
    'finance':  ['sec.gov', 'federalreserve.gov', 'bloomberg.com']
}

SPAM_DOMAINS = ['pinterest.com', 'quora.com', 'answers.yahoo.com', 'wikihow.com']

def domain_aware_search(query, domain_category=None):
    kwargs = {'query': query, 'max_results': 5, 'exclude_domains': SPAM_DOMAINS}
    if domain_category and domain_category in TRUSTED_DOMAINS:
        kwargs['include_domains'] = TRUSTED_DOMAINS[domain_category]
    return client.search(**kwargs)

검색 오류 및 요청 한도 처리

Tavily와 SerpApi 모두 요청 한도가 있습니다. 지수 백오프를 적용한 재시도 로직을 구현하고, 검색 결과가 없을 때도 정상적으로 처리하십시오.

import time

def robust_search(query, max_retries=3):
    for attempt in range(max_retries):
        try:
            results = client.search(query=query, max_results=5)
            if results and results.get('results'):
                return results['results']
            print(f'No results for: {query}')
            return []
        except Exception as e:
            if '429' in str(e) or 'rate' in str(e).lower():
                wait = 2 ** attempt  # 1s, 2s, 4s
                print(f'Rate limited. Waiting {wait}s...')
                time.sleep(wait)
            else:
                print(f'Search error: {e}')
                return []
    return []

검색 결과 요약문 길이 정규화

검색 결과 요약문의 길이는 크게 다릅니다. 어떤 것은 50자이고 다른 것은 2000자일 수 있습니다. 요약문 길이를 정규화하면 각 출처가 LLM 맥락에서 동일한 비중을 차지하게 됩니다.

MAX_SNIPPET_CHARS = 600
MIN_SNIPPET_CHARS = 100

def normalize_snippets(results):
    normalized = []
    for r in results:
        content = r.get('content') or r.get('snippet', '')
        # Truncate long snippets at sentence boundary
        if len(content) > MAX_SNIPPET_CHARS:
            # Find last sentence end before limit
            cutoff = content.rfind('. ', 0, MAX_SNIPPET_CHARS)
            content = content[:cutoff + 1] if cutoff > 0 else content[:MAX_SNIPPET_CHARS]
        # Skip very short snippets
        if len(content) < MIN_SNIPPET_CHARS:
            continue
        normalized.append({**r, 'content': content})
    return normalized

if __name__ == '__main__':
    demo_results = [
        {'content': 'Short.'},
        {'content': 'A' * 200 + '. ' + 'B' * 500},
    ]
    for r in normalize_snippets(demo_results):
        print(f"Length {len(r['content'])}: {r['content'][:60]}...")

지식 확인

AI 에이전트에 일반적인 웹 데이터 수집 방식보다 Tavily가 제공하는 핵심적인 이점은 무엇입니까?

복습: 에이전트 검색을 위한 Tavily 및 SerpApi

웹 검색 API를 사용하면 에이전트가 학습 기준일 이후의 최신 정보에 접근할 수 있습니다. Tavily는 깔끔한 콘텐츠 추출 기능을 갖춘 AI 에이전트 전용 도구이며, SerpApi는 주요 검색 결과 요약문과 지식 패널을 비롯한 더 풍부한 구조화된 Google 데이터를 제공합니다.

핵심 실천 방법은 다음과 같습니다. 품질 관리를 위해 도메인 필터링을 사용하고, 시간에 민감한 쿼리에는 최신성 필터를 적용하며, 검색 결과 요약문 길이를 정규화하고, 요청 한도를 처리할 수 있도록 백오프를 적용한 재시도 로직을 구현하십시오.

자주 묻는 질문

“에이전트 검색을 위한 Tavily 및 SerpAPI” 강의는 무료인가요?

네 — “에이전트 검색을 위한 Tavily 및 SerpAPI” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 AI Agents 강의 전체를 잠금 해제할 수 있습니다. AI Agents 강의에는 총 4개의 강의가 포함되어 있습니다.

“에이전트 검색을 위한 Tavily 및 SerpAPI”에서 뭘 배우나요?

웹 검색 도구를 위한 API 설정, 쿼리 구성, 결과 파싱을 알아봅니다. 브라우저에서 직접 실행하는 실습 코드로 AI Agents을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

AI Agents을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 AI Agents은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.

“에이전트 검색을 위한 Tavily 및 SerpAPI” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 AI Agents 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 AI Agents 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 에이전트 검색을 위한 Tavily 및 SerpAPI
  2. 검색 결과 순위 지정 및 필터링
  3. 심층 연구 반복 패턴
  4. 웹 검색과 RAG 결합
← AI Agents(으)로 돌아가기