Harness Academy
Tài liệu gốc 14 12 phútTiếng Việt + English
docs/exa-search.mdXem bản gốc
Ngôn ngữ bài đọc
Bản dịch tiếng Việt

Bản dịch đầy đủ theo đúng cấu trúc tài liệu; code, liên kết và định danh kỹ thuật được giữ nguyên.

Tìm kiếm Exa

ExaSearch cung cấp cho agent các công cụ nghiên cứu web được hỗ trợ bởi Exa API tìm kiếm: tìm kiếm trả về kết quả phù hợp nhất đoạn trích từ mỗi lần truy cập (có tóm tắt văn bản tổng hợp tùy chọn), toàn trang truy xuất để tìm hiểu sâu về một URL cụ thể và chọn tham gia tìm kiếm sâu tổng hợp một câu trả lời được trích dẫn trong một cuộc gọi. Sự riêng biệt ExaAgent khả năng ủy quyền nghiên cứu dài hạn cho API Exa Agent dưới dạng lệnh gọi công cụ bị trì hoãn.

Nguồn

Mặc dù Pydantic AI Harness có trên các bản phát hành 0.x nhưng API có thể thay đổi giữa các bản phát hành nhỏ; khi đó, cảnh báo ngừng sử dụng và hướng dẫn di chuyển ghi chú phát hành sẽ cho bạn (hoặc người đại diện của bạn) biết chính xác cách nâng cấp. Xem chính sách phiên bản.

vấn đề

Các công cụ tìm kiếm chỉ trả về tiêu đề và đoạn trích buộc phải thực hiện vòng thứ hai tìm nạp trước khi agent có thể đánh giá một nguồn, trong khi các công cụ tìm kiếm trả về văn bản toàn trang tràn ngập bối cảnh với các trang mà agent sẽ loại bỏ. Đấu dây một API tìm kiếm cùng với trình tìm nạp trang, lập ngân sách cho những gì mỗi công cụ trả về và thúc đẩy agent nghiên cứu một cách có phương pháp là bản soạn sẵn cho mọi nghiên cứu agent tái phát minh.

ExaSearch bó hệ thống ống nước thành một khả năng: công cụ nghiên cứu, mỗi công cụ ngân sách đầu ra và hướng dẫn nghiên cứu ngắn gọn trong lời nhắc hệ thống.

Cách sử dụng

Cài đặt exa thêm và thiết lập EXA_API_KEY biến môi trường (tạo một chìa khóa tại https://dashboard.exa.ai):

uv add "pydantic-ai-harness[exa]"

Sau đó vượt qua ExaSearch đến một Agent thông qua capabilities tham số:

from pydantic_ai import Agent
from pydantic_ai_harness import ExaSearch

agent = Agent('anthropic:claude-sonnet-4-6', capabilities=[ExaSearch()])

result = agent.run_sync('What changed in the latest stable Python release?')
print(result.output)

Công cụ

ExaSearch đóng góp những công cụ này cho agent:

Công cụMục đích
web_searchTìm kiếm trên web và trở về đầu num_results các trang, mỗi trang có tiêu đề, URL và các đoạn trích phù hợp nhất.
get_pageTruy xuất toàn bộ văn bản của một URL cụ thể -- một URL đầy hứa hẹn web_search lần truy cập hoặc URL mà người dùng đã cung cấp.
deep_searchChạy tìm kiếm sâu nhiều bước của Exa và trả về câu trả lời tổng hợp, được trích dẫn. Chọn tham gia qua include_deep_search=True.
exa_agentỦy thác nhiệm vụ nghiên cứu cho việc chạy agent Exa không đồng bộ. Được cung cấp bởi riêng biệt ExaAgent khả năng.

web_search trả về các đoạn trích ngắn (Exa nổi bật) thay vì toàn trang văn bản, tuân theo hướng dẫn riêng của Exa dành cho tổng đài viên, vì vậy việc khảo sát một số nguồn vẫn rẻ; agent đọc một trang đã chọn với get_page.

get_page văn bản được giới hạn ở max_text_chars ký tự, giữ đầu (dẫn đầu của một trang mang nội dung). Một ký tự của khoảng không phía trên nắp được yêu cầu từ Exa, vì vậy khi một trang vượt quá giới hạn, đầu ra sẽ kết thúc bằng [... page text truncated at N characters] điểm đánh dấu; ở mức trần API của 10.000 ký tự không tồn tại khoảng trống nên điểm đánh dấu không thể xuất hiện ở đó. các số kết quả được giới hạn theo cùng một cách: num_results được yêu cầu từ Exa và áp dụng lại cho câu trả lời.

URL hoặc câu hỏi không trả về nội dung, giới hạn tỷ lệ hoặc API tạm thời hoặc Lỗi mạng xuất hiện trong mô hình dưới dạng ModelRetry chứ không phải là một lỗi cứng: quá trình chạy tiếp tục và mô hình có thể sửa URL, diễn đạt lại hoặc thử lại. Lỗi xác thực (401/403) là lỗi cấu hình và tuyên truyền.

Tìm kiếm sâu

deep_search gọi tìm kiếm Exa với type='deep' và một đầu ra văn bản thuần túy lược đồ: Exa mở rộng câu hỏi thành nhiều truy vấn, tìm kiếm và trả về một câu trả lời dựa trên các trích dẫn -- tất cả đều có trong một lệnh gọi công cụ, với trích dẫn các nguồn được liệt kê dưới câu trả lời. Mỗi cuộc gọi đầu tư nhiều thời gian và độ sâu tìm kiếm hơn hơn web_search (Chế độ cấp độ nghiên cứu của Exa) và mô hình quyết định thời điểm thực hiện gọi các công cụ, do đó công cụ này bị tắt theo mặc định -- bật nó một cách rõ ràng:

from pydantic_ai_harness import ExaSearch

ExaSearch(include_deep_search=True)

Khi được bật, hướng dẫn của khả năng sẽ yêu cầu mô hình coi nó như một leo thang từ web_search, không phải là sự thay thế Câu trả lời tổng hợp là được trả về đầy đủ (nó được tạo bởi Exa và vốn đã bị giới hạn); max_text_chars chỉ áp dụng cho get_page.

Tóm tắt văn bản

Đặt text_summary có mọi thứ web_search gọi cũng yêu cầu Exa's lược đồ đầu ra văn bản thuần túy, do đó phản hồi mang một bản tóm tắt ngắn được tổng hợp từ các kết quả cho các truy vấn kiểu câu hỏi. Vượt qua True cho một không bị hạn chế tóm tắt hoặc một chuỗi mô tả định dạng mong muốn (được gửi dưới dạng description):

from pydantic_ai_harness import ExaSearch

ExaSearch(text_summary='One concise sentence with the requested facts.')

Hình dạng trả về của công cụ không thay đổi và tương thích ngược: danh sách kết quả được trả về như trước và khi Exa trả về một bản tóm tắt, nó được thêm vào trước dưới dạng Summary: dòng.

Trích dẫn có cấu trúc

Mỗi công cụ đều trả về một ToolReturn: return_value mang văn bản có thể đọc được mà mô hình nhìn thấy (không thay đổi từ phiên bản trước đó, bao gồm cả Sources: khối) và metadata mang theo các nguồn có cấu trúc ExaSource hồ sơ ({'url': ..., 'title': ...}) dưới 'sources' chìa khóa. Siêu dữ liệu không bao giờ được gửi đến mô hình; cái ứng dụng đọc nó từ ToolReturnPart trong lịch sử tin nhắn, vì vậy hiển thị trích dẫn không cần phân tích văn bản:

from pydantic_ai.messages import ModelRequest, ToolReturnPart

for message in result.all_messages():
    if isinstance(message, ModelRequest):
        for part in message.parts:
            if isinstance(part, ToolReturnPart) and part.metadata is not None:
                for source in part.metadata.get('sources', []):
                    print(source['url'], source['title'])

exa_agent kết quả còn mang ID chạy Exa trong siêu dữ liệu trong RUN_ID_METADATA_KEY.

Hướng dẫn

ExaSearch đóng góp hướng dẫn nghiên cứu ngắn vào lời nhắc của hệ thống: tìm kiếm rộng với web_search đầu tiên, hãy đọc đầy đủ những trang hứa hẹn nhất với get_page trước khi đưa ra kết luận, hãy ưu tiên các nguồn chính và trích dẫn URL dựa vào. Với include_deep_search=True, hướng dẫn cũng bao gồm khi leo thang đến deep_search. Đặt guidance để thay thế văn bản mặc định, hoặc để '' để đóng góp không có hướng dẫn nào cả.

Cấu hình

Mỗi lĩnh vực của ExaSearch với mặc định của nó:

from pydantic_ai_harness import ExaSearch

ExaSearch(
    num_results=5,              # results per web_search call (1 to 100)
    max_text_chars=10_000,      # get_page text cap, in characters (1 to 10,000)
    text_summary=False,         # web_search also returns a synthesized text summary
    include_deep_search=False,  # also expose the deep_search tool
    include_domains=[],         # only search these domains (allowlist)
    exclude_domains=[],         # never search these domains (denylist)
    guidance=None,              # None = default instructions, '' = none, str = custom
    client=None,                # ExaClient -- None builds exa_py.AsyncExa from EXA_API_KEY
)

include_domains và exclude_domains áp dụng cho web_search và deep_search, và loại trừ lẫn nhau -- đặt một, không phải cả hai. Giới hạn ngoài phạm vi và thiết lập cả danh sách tên miền nâng cao khi xây dựng.

agent exa chạy

Exa API agent thực hiện các nhiệm vụ nghiên cứu mở không đồng bộ: một lần chạy được tạo, di chuyển qua queued -> runningvà đạt đến trạng thái đầu cuối (completed, failedhoặc cancelled) sau đến một giờ. Sự riêng biệt ExaAgent khả năng ánh xạ vòng đời vào Pydantic Cuộc gọi công cụ bị trì hoãn của AI: nó exa_agent công cụ tạo lần chạy và trì hoãn, mang ID chạy Exa trong siêu dữ liệu của cuộc gọi bị trì hoãn.

from pydantic_ai import Agent
from pydantic_ai_harness import ExaAgent

agent = Agent('anthropic:claude-sonnet-4-6', capabilities=[ExaAgent()])

Theo mặc định (execution='inline') khả năng giải quyết sự trì hoãn của chính nó các cuộc gọi trong agent được điều hành bằng cách thăm dò quá trình chạy Exa để hoàn thành, vì vậy công cụ hoạt động giống như một công cụ thông thường (nếu chậm). Với execution='external' các cuộc gọi bong bóng lên như DeferredToolRequests đầu ra cho ứng dụng máy chủ giải quyết ngoài băng tần -- kể cả từ một quy trình khác, vì ID chạy Exa tồn tại trong siêu dữ liệu yêu cầu bên dưới RUN_ID_METADATA_KEY. của agent output_type phải bao gồm DeferredToolRequests, nếu không thì lượt chạy sẽ tăng thay vì trả lại các yêu cầu bị trì hoãn:

from pydantic_ai import Agent
from pydantic_ai.tools import DeferredToolRequests

from pydantic_ai_harness import ExaAgent

agent = Agent(
    'anthropic:claude-sonnet-4-6',
    output_type=[str, DeferredToolRequests],
    capabilities=[ExaAgent(execution='external')],
)

Kết xuất một lần chạy đã hoàn thành với agent_run_result người trợ giúp, đi ngang qua output_schema khả năng được xây dựng với độ phân giải bên ngoài áp dụng cùng một xác nhận và tạo ra hình dạng kết quả công cụ giống như nội tuyến thực thi, sau đó cung cấp kết quả và lịch sử tin nhắn ban đầu vào agent tiếp tục quá trình chạy bị trì hoãn:

from pydantic_ai.tools import DeferredToolResults

from pydantic_ai_harness.exa import RUN_ID_METADATA_KEY, agent_run_result


async def resolve(requests, runs, output_schema=None):  # e.g. in a worker process
    results = DeferredToolResults()
    for call in requests.calls:
        run_id = requests.metadata[call.tool_call_id][RUN_ID_METADATA_KEY]
        run = await runs.poll_until_finished(run_id)
        results.calls[call.tool_call_id] = agent_run_result(run, output_schema=output_schema)
    return results


async def resume(agent, messages, results):
    return await agent.run(message_history=messages, deferred_tool_results=results)

Mỗi lĩnh vực của ExaAgent với mặc định của nó:

from pydantic_ai_harness import ExaAgent

ExaAgent(
    effort=None,            # 'low' | 'medium' | 'high' | 'xhigh' | 'auto' -- None = API default
    execution='inline',     # 'inline' polls to completion; 'external' bubbles DeferredToolRequests
    output_schema=None,     # BaseModel class or dict schema for structured output
    system_prompt=None,     # forwarded to the Exa agent run
    poll_interval=1000,     # ms between polls when resolving inline
    timeout_ms=3_600_000,   # ms to wait for a run when resolving inline
    guidance=None,          # None = default instructions, '' = none, str = custom
    runs=None,              # ExaAgentRuns -- None builds AsyncExa().agent.runs from EXA_API_KEY
)

Một output_schema lớp mô hình được xác nhận dựa trên đầu ra có cấu trúc của lần chạy đã hoàn thành (bề mặt không khớp vì ModelRetry), trong khi lược đồ dict được chuyển tiếp mà không cần xác thực phía máy khách và là biểu mẫu đặc tả agent. Lỗi terminal (failed, cancelled) được trả về mô hình hóa như một thông điệp có cấu trúc thay vì được nêu ra, vì vậy agent có thể quyết định cách thức để tiếp tục. Mỗi kết quả bao gồm ID chạy mà mô hình có thể gửi lại dưới dạng previous_run_id để đặt câu hỏi tiếp theo trong bối cảnh của lần chạy trước.

Nhiều trường hợp

Hai phiên bản có cùng khả năng đăng ký cùng một tên công cụ, đó là một lỗi. Để chạy một số phiên bản được cấu hình khác nhau trong một agent (ví dụ: ví dụ một trang web mở ExaSearch và một được ghim vào các miền cụ thể), hãy gói các trường hợp bổ sung trong lõi PrefixTools khả năng, tiền tố công cụ của họ tên:

from pydantic_ai import Agent
from pydantic_ai.capabilities import PrefixTools

from pydantic_ai_harness import ExaSearch

agent = Agent(
    'anthropic:claude-sonnet-4-6',
    capabilities=[
        ExaSearch(),  # web_search, get_page
        PrefixTools(
            wrapped=ExaSearch(include_domains=['crunchbase.com'], guidance=''),
            prefix='cb',
        ),  # cb_web_search, cb_get_page
    ],
)

Đặt guidance='' trên phiên bản được bao bọc (hoặc thay thế nó bằng văn bản cho biết mô hình khi nào nên sử dụng các công cụ có tiền tố), vì mỗi trường hợp khác đóng góp hướng dẫn nghiên cứu mặc định tương tự.

Điều này cũng có tác dụng với ExaAgent: nó xác định các cuộc gọi bị trì hoãn bằng siêu dữ liệu nó được viết khi trì hoãn, không phải theo tên công cụ, vì vậy tiền tố exa_agent vẫn còn giải quyết nội tuyến và nhiều ExaAgent các trường hợp không bao giờ đòi hỏi của nhau cuộc gọi.

Khách hàng tùy chỉnh

Máy khách mặc định là exa_py.AsyncExa, được cấu hình từ EXA_API_KEY biến môi trường; khi biến bị thiếu, việc xây dựng không thành công với gợi ý thiết lập. Vượt qua bất kỳ đối tượng nào thỏa mãn ExaClient giao thức -- tập hợp con của AsyncExa lệnh gọi bộ công cụ -- để định cấu hình xác thực hoặc URL cơ sở một cách rõ ràng hoặc để thay thế hàng giả trong các thử nghiệm:

from exa_py import AsyncExa

from pydantic_ai_harness import ExaSearch

ExaSearch(client=AsyncExa(api_key='...'))

ExaSearch so với WebSearch cốt lõi

Lõi AI Pydantic cung cấp một thiết bị thích ứng với nhà cung cấp WebSearch khả năng: trên các kiểu máy có công cụ tìm kiếm gốc, nó sử dụng công cụ tìm kiếm của chính nhà cung cấp tìm kiếm, thực thi phía máy chủ; ở nơi khác nó rơi trở lại DuckDuckGo cục bộ công cụ. Hãy tiếp cận nó khi bạn muốn tìm kiếm theo mô hình.

Tiếp cận với ExaSearch khi bạn muốn hành vi tìm kiếm giống nhau trên mọi mô hình: một nhà cung cấp, các đoạn trích với mỗi lần truy cập, truy xuất trang rõ ràng, bộ lọc tên miền, và chọn tham gia tìm kiếm sâu.

Một lưu ý khi kết hợp chúng: trên mô hình Anthropic, tìm kiếm gốc của nhà cung cấp công cụ cũng được đặt tên web_search trên dây, vì vậy capabilities=[WebSearch(), ExaSearch()] đặt hai công cụ có cùng tên vào yêu cầu. Sử dụng một khả năng tìm kiếm cho mỗi agent trên các mô hình tìm kiếm gốc hoặc buộc dự phòng cục bộ với WebSearch(native=False) (công cụ DuckDuckGo của nó là đặt tên duckduckgo_search, không va chạm).

ExaSearch vs máy chủ MCP của Exa

Exa cũng vận chuyển một máy chủ MCP được lưu trữ chính thức tại https://mcp.exa.ai/mcp (exa-labs/exa-mcp-server). Bởi mặc định nó lộ ra web_search_exa và web_fetch_exa; danh mục đầy đủ bổ sung web_search_advanced_exa và một bộ do agent điều hành (agent_create_run, agent_wait_for_run, agent_get_run_output, agent_cancel_run).

ExaSearch là đường dẫn được sắp xếp, được nhập: đầu ra bị chặn, thử lại khi trống hợp đồng, hướng dẫn nghiên cứu đi kèm và mối liên hệ với khách hàng tạo nên nó có thể kiểm tra ngoại tuyến. Máy chủ MCP là cách bạn có được danh mục đầy đủ của Exa mà không cần tốn nhiều công sức mã bao bọc, thông qua khả năng MCP của lõi Pydantic AI. Hoạt động agent của họ là tạo-rồi-thăm dò ý kiến (agent_create_run trả về ID ngay lập tức; agent_wait_for_run thăm dò nó), ở đâu deep_search trả lại câu trả lời trong một cuộc gọi duy nhất. Cả hai sáng tác thành một capabilities danh sách và không có MCP nào tên công cụ va chạm với web_search, get_pagehoặc deep_search:

from pydantic_ai import Agent
from pydantic_ai.capabilities import MCP
from pydantic_ai_harness import ExaSearch

agent = Agent('anthropic:claude-sonnet-4-6', capabilities=[ExaSearch(), MCP('https://mcp.exa.ai/mcp')])

Thông số agent (YAML/JSON)

ExaSearch hoạt động với Pydantic AI thông số agent, vì vậy bạn có thể khai báo nó trong config tập tin thay vì Python:

# agent.yaml
model: anthropic:claude-sonnet-4-6
capabilities:
  - ExaSearch:
      num_results: 3
      include_deep_search: true
  - ExaAgent:
      effort: low
from pydantic_ai import Agent
from pydantic_ai_harness import ExaAgent, ExaSearch

agent = Agent.from_file('agent.yaml', custom_capability_types=[ExaSearch, ExaAgent])

Vượt qua custom_capability_types để trình tải thông số kỹ thuật biết cách khởi tạo khả năng. các client và runs các trường không được tuần tự hóa theo thông số kỹ thuật; các phiên bản được tải thông số kỹ thuật luôn xây dựng ứng dụng khách mặc định từ EXA_API_KEY. trong thông số kỹ thuật, output_schema có dạng chính tả lược đồ JSON; Mô hình Pydantic các lớp chỉ khả dụng khi xây dựng khả năng trong Python.

Đọc thêm

Tham chiếu API

::: pydantic_ai_harness.exa.ExaSearch

::: pydantic_ai_harness.exa.ExaAgent

::: pydantic_ai_harness.exa.agent_run_result

::: pydantic_ai_harness.exa.ExaSource

Mục lục nguồn