SearchableToolset

SearchableToolset

키워드 기반 검색으로 에이전트가 대규모 툴 카탈로그에서 툴을 동적으로 발견하게 해 주는 컴포넌트예요.

출처: 문서

본문

항목 내용
필수 init 변수 catalog: Tool 및/또는 Toolset 목록, 또는 단일 Toolset
API reference SearchableToolset
GitHub 링크 searchable_toolset.py
패키지 이름 haystack-ai

개요

SearchableToolset은 대규모 툴 카탈로그를 다룰 때 사용하도록 설계되었어요. 모든 툴을 한꺼번에 노출하면 LLM 컨텍스트가 부담될 수 있으니, 대신 단일 search_tools 부트스트랩 툴을 제공해요. 에이전트는 이 툴을 사용해 BM25 키워드 검색으로 카탈로그에서 특정 툴을 찾고 로드하죠.

에이전트가 search_tools를 호출하면 일치하는 툴이 즉시 사용 가능해지고, 이후 반복에서 그 툴을 호출할 수 있어요.

동작 모드

SearchableToolset은 카탈로그 크기에 따라 두 가지 모드 중 하나로 동작해요:

  • 검색 모드(대규모 카탈로그의 기본값): 에이전트는 search_tools 부트스트랩 툴만으로 시작하고, 다른 툴은 필요할 때 발견해요. 카탈로그 크기가 search_threshold 이상일 때 활성화되죠.
  • 통과 모드(passthrough, 소규모 카탈로그): 모든 툴을 직접 노출하며 발견 단계가 필요 없어요. 카탈로그에 search_threshold보다 적은 툴이 있을 때 자동으로 활성화돼요.

파라미터

  • catalog (필수): 툴의 소스 — Tool 및/또는 Toolset 인스턴스 목록, 또는 단일 Toolset. MCPTool과 MCPToolset 인스턴스를 포함해요.
  • top_k (선택): 각 search_tools 호출이 반환하는 기본 툴 수. 기본값은 3이에요.
  • search_threshold (선택): 검색 모드를 활성화할 최소 카탈로그 크기. 이 값보다 작은 카탈로그는 통과 모드를 사용해요. 기본값은 8이에요.

참고: SearchableToolset은 초기화 후 새 툴을 추가하거나 다른 툴셋과 병합하는 것을 지원하지 않아요. 모든 툴을 미리 catalog로 제공하세요.

워밍업

SearchableToolset은 warm_up() 중에 검색 인덱스를 구축해요. Agent와 함께 사용할 때, Agent를 생성하는 것만으로는 이 과정이 트리거되지 않아요. 워밍업은 Agent.warm_up()을 호출하거나 런타임에 자동으로 일어나죠.

카탈로그의 모든 툴 이름은 고유해야 해요. 카탈로그에 이름이 중복된 툴이 있으면 warm_up()이 ValueError를 발생시켜요. 검색 히트가 잘못된 툴로 해석될 수 있기 때문이죠.

Agent는 런타임에 exit_conditions를 평가하므로, 종료 조건은 에이전트가 아직 발견하지 못한 툴을 포함해 카탈로그의 어떤 툴이든 지목할 수 있어요.

사용법

Agent와의 기본 사용법

from typing import Annotated
from haystack.components.agents import Agent
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.dataclasses import ChatMessage
from haystack.tools import create_tool_from_function, SearchableToolset

def get_weather(city: Annotated[str, "The city to get the weather for"]) -> str:
    """Get current weather for a city."""
    return f"Sunny, 22°C in {city}"

def search_web(query: Annotated[str, "The search query"]) -> str:
    """Search the web for information."""
    return f"Results for: {query}"

# Build a catalog from tools
catalog = [
    create_tool_from_function(get_weather),
    create_tool_from_function(search_web),
    # ... many more tools
]

toolset = SearchableToolset(catalog=catalog)
agent = Agent(
    chat_generator=OpenAIChatGenerator(),
    tools=toolset,
)

# The agent initially sees only `search_tools`. It will call it to find relevant tools,
# then use the discovered tools to answer the question.
result = agent.run(messages=[ChatMessage.from_user("What's the weather in Milan?")])
print(result["messages"][-1].text)

부트스트랩 툴 커스터마이징

search_tools 부트스트랩 툴의 이름, 설명, 파라미터 설명을 커스터마이즈할 수 있어요:

  • search_tool_name: 부트스트랩 툴의 커스텀 이름. 기본값은 "search_tools"예요.
  • search_tool_description: 부트스트랩 툴의 커스텀 설명.
  • search_tool_parameters_description: 부트스트랩 툴 파라미터의 커스텀 설명. 키는 {"tool_keywords", "k"}의 부분 집합이어야 해요.
toolset = SearchableToolset(
    catalog=catalog,
    search_tool_name="find_tools",
    search_tool_description="Search for tools in the catalog by keyword.",
    search_tool_parameters_description={
        "tool_keywords": "Keywords to find tools, e.g. 'email send'",
        "k": "Max number of tools to return",
    },
)

여러 에이전트 실행에 걸쳐 툴셋 재사용

같은 SearchableToolset 인스턴스를 동시 실행을 포함해 여러 에이전트 실행에 걸쳐 안전하게 재사용할 수 있어요. 각 Agent 실행은 툴셋의 격리된, 실행 범위(scope) 복사본(spawn()으로 생성)으로 동작하므로, 한 실행에서 발견된 툴이 다른 실행에 남거나 충돌하지 않아요. 모든 실행은 카탈로그에서 새로 시작하죠:

agent = Agent(
    chat_generator=OpenAIChatGenerator(),
    tools=toolset,
)
result1 = agent.run(messages=[ChatMessage.from_user("What's the weather in Milan?")])

# The next run starts fresh: tools discovered in the previous run are not carried over
result2 = agent.run(messages=[ChatMessage.from_user("Search for news about AI.")])

(Agent 밖에서) 툴셋을 직접 사용한다면, 발견된 툴을 직접 재설정하려고 clear()를 호출할 수 있어요.

더 알아보기 (Learn more)