-
Notifications
You must be signed in to change notification settings - Fork 174
Expand file tree
/
Copy pathtavily_search.py
More file actions
107 lines (85 loc) · 3.49 KB
/
Copy pathtavily_search.py
File metadata and controls
107 lines (85 loc) · 3.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import logging
from tavily import AsyncTavilyClient
from sgr_agent_core.agent_definition import SearchConfig
from sgr_agent_core.models import SourceData
logger = logging.getLogger(__name__)
class TavilySearchService:
def __init__(self, search_config: SearchConfig):
self._client = AsyncTavilyClient(
api_key=search_config.tavily_api_key, api_base_url=search_config.tavily_api_base_url
)
self._config = search_config
@staticmethod
def rearrange_sources(sources: list[SourceData], starting_number=1) -> list[SourceData]:
for i, source in enumerate(sources, starting_number):
source.number = i
return sources
async def search(
self,
query: str,
max_results: int | None = None,
include_raw_content: bool = True,
) -> list[SourceData]:
"""Perform search through Tavily API and return results with
SourceData.
Args:
query: Search query
max_results: Maximum number of results (default from config)
include_raw_content: Include raw page content
Returns:
Tuple with tavily answer and list of SourceData
"""
max_results = max_results or self._config.max_results
logger.info(f"🔍 Tavily search: '{query}' (max_results={max_results})")
# Execute search through Tavily
response = await self._client.search(
query=query,
max_results=max_results,
include_raw_content=include_raw_content,
)
# Convert results to SourceData
sources = self._convert_to_source_data(response)
return sources
async def extract(self, urls: list[str]) -> list[SourceData]:
"""Extract full content from specific URLs using Tavily Extract API.
Args:
urls: List of URLs to extract content from
Returns:
List of SourceData with extracted content
"""
logger.info(f"📄 Tavily extract: {len(urls)} URLs")
response = await self._client.extract(urls=urls)
sources = []
for i, result in enumerate(response.get("results", [])):
if not result.get("url"):
continue
source = SourceData(
number=i,
title=result.get("url", "").split("/")[-1] or "Extracted Content",
url=result.get("url", ""),
snippet="",
full_content=result.get("raw_content", ""),
char_count=len(result.get("raw_content", "")),
)
sources.append(source)
failed_urls = response.get("failed_results", [])
if failed_urls:
logger.warning(f"⚠️ Failed to extract {len(failed_urls)} URLs: {failed_urls}")
return sources
def _convert_to_source_data(self, response: dict) -> list[SourceData]:
"""Convert Tavily response to SourceData list."""
sources = []
for i, result in enumerate(response.get("results", [])):
if not result.get("url", ""):
continue
source = SourceData(
number=i,
title=result.get("title", ""),
url=result.get("url", ""),
snippet=result.get("content", ""),
)
if result.get("raw_content", ""):
source.full_content = result["raw_content"]
source.char_count = len(source.full_content)
sources.append(source)
return sources