Spaces:
Runtime error
Runtime error
File size: 6,290 Bytes
b1060b0 f1368c4 b5fafa1 b1060b0 b5fafa1 b1060b0 b5fafa1 b1060b0 b5fafa1 b1060b0 b5fafa1 b1060b0 b5fafa1 b1060b0 b5fafa1 7c1f478 b5fafa1 7c1f478 b5fafa1 7c1f478 b5fafa1 7c1f478 b5fafa1 7c1f478 b5fafa1 7c1f478 b5fafa1 7c1f478 b5fafa1 f1368c4 b1060b0 b5fafa1 b1060b0 b5fafa1 f1368c4 b1060b0 b5fafa1 b1060b0 f1368c4 b1060b0 b5fafa1 b1060b0 b5fafa1 b1060b0 b5fafa1 b1060b0 b5fafa1 b1060b0 b5fafa1 b1060b0 84c66cd b1060b0 b5fafa1 b1060b0 f1368c4 b1060b0 b5fafa1 b1060b0 f1368c4 b1060b0 b5fafa1 b1060b0 b5fafa1 b1060b0 b5fafa1 f1368c4 b1060b0 f1368c4 b5fafa1 f1368c4 b5fafa1 f1368c4 b5fafa1 f1368c4 b5fafa1 f1368c4 b1060b0 b5fafa1 |
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 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
import os
from enum import Enum
from typing import Literal
import requests
from linkup import LinkupClient, LinkupSourcedAnswer
from pydantic import BaseModel, Field
from tavily import AsyncTavilyClient
class SearchResult(BaseModel):
"""Represents a single search result from any search API."""
title: str = Field(..., description="Title of the search result")
url: str = Field(..., description="URL of the result")
content: str = Field(..., description="Summary/snippet of content")
raw_content: str | None = Field(None, description="Full page content if available")
class SearchResponse(BaseModel):
"""Represents a search response from any search API."""
query: str = Field(..., description="The original search query")
answer: str | None = Field(
None, description="Direct answer from the search API if available"
)
search_results: list[SearchResult] = Field(
default_factory=list, description="List of search results"
)
def to_string(self):
"""Convert search response to a formatted string suitable for LLM consumption."""
result_parts = []
# Add the query
result_parts.append(f"Search Query: {self.query}\n")
# Add the direct answer if available
if self.answer:
result_parts.append(f"Direct Answer: {self.answer}\n")
# Add search results
if self.search_results:
result_parts.append(f"Found {len(self.search_results)} search results:\n")
for i, result in enumerate(self.search_results, 1):
result_parts.append(f"\n--- Result {i} ---")
result_parts.append(f"Title: {result.title}")
result_parts.append(f"URL: {result.url}")
result_parts.append(f"Content: {result.content[:2000]}...")
result_parts.append("") # Empty line for separation
else:
result_parts.append("No search results found.")
return "\n".join(result_parts)
class ScientificDomains(str, Enum):
wikipedia = "wikipedia.org"
arxiv = "arxiv.org"
pubmed = "pubmed.ncbi.nlm.nih.gov"
sciencedirect = "sciencedirect.com"
def get_tavily_usage():
url = "https://api.tavily.com/usage"
headers = {"Authorization": f"Bearer {os.getenv('TAVILY_API_KEY')}"}
response = requests.request("GET", url, headers=headers)
response_json = response.json()
usage = int(response_json["key"]["usage"])
return usage
async def tavily_search_async(
search_query: str,
max_results: int = 10,
include_answer: Literal["basic", "advanced"] | None = "advanced",
include_raw_content: Literal["text", "markdown"] | None = "markdown",
include_images: bool = False,
search_depth: Literal["basic", "advanced"] | None = "basic",
include_domains: list[ScientificDomains] = None,
) -> SearchResponse:
"""
Performs concurrent web searches with the Tavily API
"""
tavily_async_client = AsyncTavilyClient()
search_response = await tavily_async_client.search(
query=search_query,
search_depth=search_depth,
include_answer=include_answer,
include_raw_content=include_raw_content,
max_results=max_results,
include_images=include_images,
include_domains=include_domains,
)
search_results = [
SearchResult(
title=result.get("title", ""),
url=result.get("url", ""),
content=result.get("content", ""),
raw_content=result.get("raw_content"),
)
for result in search_response.get("results", [])
]
# Convert to our Pydantic models
responses: SearchResponse = SearchResponse(
query=search_query,
answer=search_response.get("answer", None),
search_results=search_results,
)
return responses
def get_linkup_balance():
url = "https://api.linkup.so/v1/credits/balance"
headers = {"Authorization": f"Bearer {os.getenv('LINKUP_API_KEY')}"}
response = requests.request("GET", url, headers=headers)
response_json = response.json()
balance = float(response_json["balance"])
return balance
async def linkup_search_async(
search_query: str,
depth: Literal["standard", "deep"] = "standard",
output_type: Literal[
"searchResults", "sourcedAnswer", "structured"
] = "sourcedAnswer",
include_images: bool = False,
include_domains: list[ScientificDomains] = None,
) -> SearchResponse:
"""
Performs concurrent web searches using the Linkup API.
"""
client = LinkupClient()
search_response: LinkupSourcedAnswer = await client.async_search(
query=search_query,
depth=depth,
output_type=output_type,
include_images=include_images,
include_domains=include_domains,
)
search_results = [
SearchResult(
title=result.name,
url=result.url,
content=result.snippet,
raw_content=None,
)
for result in search_response.sources
]
# Convert to our Pydantic models
responses: SearchResponse = SearchResponse(
query=search_query, answer=search_response.answer, search_results=search_results
)
return responses
async def arxiv_search_async(
search_query: str,
) -> SearchResponse:
response = await linkup_search_async(
search_query, include_domains=[ScientificDomains.arxiv]
)
return response
async def pubmed_search_async(
search_query: str,
) -> SearchResponse:
response = await linkup_search_async(
search_query, include_domains=[ScientificDomains.pubmed]
)
return response
async def sciencedirect_search_async(
search_query: str,
) -> SearchResponse:
response = await linkup_search_async(
search_query, include_domains=[ScientificDomains.sciencedirect]
)
return response
async def scientific_search_async(
search_query: str,
) -> SearchResponse:
response = await linkup_search_async(
search_query,
include_domains=[
ScientificDomains.wikipedia,
ScientificDomains.arxiv,
ScientificDomains.pubmed,
ScientificDomains.sciencedirect,
],
)
return response
|