mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-07-08 22:22:17 +02:00
feat(capabilities): add env-keyed searxng/linkup/baidu discover providers
This commit is contained in:
parent
adc39d1062
commit
329bc63b6c
6 changed files with 345 additions and 0 deletions
|
|
@ -0,0 +1,53 @@
|
|||
"""Baidu AI Search discover provider (env-keyed via ``BAIDU_API_KEY``)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import httpx
|
||||
|
||||
from app.capabilities.web.discover.schemas import DiscoverHit
|
||||
from app.config import config
|
||||
|
||||
_ENDPOINT = "https://qianfan.baidubce.com/v2/ai_search/chat/completions"
|
||||
_SNIPPET_MAX = 300
|
||||
|
||||
|
||||
class BaiduProvider:
|
||||
name = "baidu"
|
||||
|
||||
def is_available(self) -> bool:
|
||||
return bool(config.BAIDU_API_KEY)
|
||||
|
||||
async def search(self, query: str, top_k: int) -> list[DiscoverHit]:
|
||||
max_per_type = min(top_k, 20)
|
||||
payload = {
|
||||
"messages": [{"role": "user", "content": query}],
|
||||
"model": config.BAIDU_MODEL,
|
||||
"search_source": config.BAIDU_SEARCH_SOURCE,
|
||||
"resource_type_filter": [{"type": "web", "top_k": max_per_type}],
|
||||
"stream": False,
|
||||
}
|
||||
headers = {
|
||||
"X-Appbuilder-Authorization": f"Bearer {config.BAIDU_API_KEY}",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
async with httpx.AsyncClient(timeout=90.0) as client:
|
||||
response = await client.post(_ENDPOINT, headers=headers, json=payload)
|
||||
response.raise_for_status()
|
||||
|
||||
hits: list[DiscoverHit] = []
|
||||
for reference in response.json().get("references", []):
|
||||
url = reference.get("url", "")
|
||||
if not url:
|
||||
continue
|
||||
content = reference.get("content", "") or ""
|
||||
hits.append(
|
||||
DiscoverHit(
|
||||
url=url,
|
||||
title=reference.get("title") or url,
|
||||
snippet=content[:_SNIPPET_MAX] or None,
|
||||
provider=self.name,
|
||||
)
|
||||
)
|
||||
if len(hits) >= top_k:
|
||||
break
|
||||
return hits
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
"""Linkup discover provider (env-keyed via ``LINKUP_API_KEY``)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
|
||||
from linkup import LinkupClient
|
||||
|
||||
from app.capabilities.web.discover.schemas import DiscoverHit
|
||||
from app.config import config
|
||||
|
||||
|
||||
class LinkupProvider:
|
||||
name = "linkup"
|
||||
|
||||
def is_available(self) -> bool:
|
||||
return bool(config.LINKUP_API_KEY)
|
||||
|
||||
async def search(self, query: str, top_k: int) -> list[DiscoverHit]:
|
||||
client = LinkupClient(api_key=config.LINKUP_API_KEY)
|
||||
response = await asyncio.to_thread(
|
||||
client.search, query=query, depth="standard", output_type="searchResults"
|
||||
)
|
||||
hits: list[DiscoverHit] = []
|
||||
for result in getattr(response, "results", None) or []:
|
||||
url = getattr(result, "url", "") or ""
|
||||
if not url:
|
||||
continue
|
||||
content = getattr(result, "content", "") or ""
|
||||
hits.append(
|
||||
DiscoverHit(
|
||||
url=url,
|
||||
title=getattr(result, "name", "") or url,
|
||||
snippet=content or None,
|
||||
provider=self.name,
|
||||
)
|
||||
)
|
||||
if len(hits) >= top_k:
|
||||
break
|
||||
return hits
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
"""SearXNG discover provider, wrapping the platform-env SearXNG search service."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from app.capabilities.web.discover.schemas import DiscoverHit
|
||||
from app.services import web_search_service
|
||||
|
||||
|
||||
class SearxngProvider:
|
||||
"""Env-keyed via ``SEARXNG_DEFAULT_HOST`` (the platform SearXNG instance)."""
|
||||
|
||||
name = "searxng"
|
||||
|
||||
def is_available(self) -> bool:
|
||||
return web_search_service.is_available()
|
||||
|
||||
async def search(self, query: str, top_k: int) -> list[DiscoverHit]:
|
||||
result_object, _documents = await web_search_service.search(query, top_k)
|
||||
return [
|
||||
DiscoverHit(
|
||||
url=source["url"],
|
||||
title=source.get("title") or source["url"],
|
||||
snippet=source.get("description") or None,
|
||||
provider=self.name,
|
||||
)
|
||||
for source in result_object.get("sources", [])
|
||||
if source.get("url")
|
||||
]
|
||||
Loading…
Add table
Add a link
Reference in a new issue