Spaces:
Runtime error
Runtime error
| 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 | |