mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-04-20 18:09:56 +00:00
fix(web-search): fix Jina search format and fallback
This commit is contained in:
parent
acf652358c
commit
f422de8084
@ -8,7 +8,7 @@ import json
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import quote, urlparse
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
@ -182,10 +182,10 @@ class WebSearchTool(Tool):
|
|||||||
return await self._search_duckduckgo(query, n)
|
return await self._search_duckduckgo(query, n)
|
||||||
try:
|
try:
|
||||||
headers = {"Accept": "application/json", "Authorization": f"Bearer {api_key}"}
|
headers = {"Accept": "application/json", "Authorization": f"Bearer {api_key}"}
|
||||||
|
encoded_query = quote(query, safe="")
|
||||||
async with httpx.AsyncClient(proxy=self.proxy) as client:
|
async with httpx.AsyncClient(proxy=self.proxy) as client:
|
||||||
r = await client.get(
|
r = await client.get(
|
||||||
f"https://s.jina.ai/",
|
f"https://s.jina.ai/{encoded_query}",
|
||||||
params={"q": query},
|
|
||||||
headers=headers,
|
headers=headers,
|
||||||
timeout=15.0,
|
timeout=15.0,
|
||||||
)
|
)
|
||||||
@ -197,7 +197,8 @@ class WebSearchTool(Tool):
|
|||||||
]
|
]
|
||||||
return _format_results(query, items, n)
|
return _format_results(query, items, n)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return f"Error: {e}"
|
logger.warning("Jina search failed ({}), falling back to DuckDuckGo", e)
|
||||||
|
return await self._search_duckduckgo(query, n)
|
||||||
|
|
||||||
async def _search_duckduckgo(self, query: str, n: int) -> str:
|
async def _search_duckduckgo(self, query: str, n: int) -> str:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@ -160,3 +160,70 @@ async def test_searxng_invalid_url():
|
|||||||
tool = _tool(provider="searxng", base_url="not-a-url")
|
tool = _tool(provider="searxng", base_url="not-a-url")
|
||||||
result = await tool.execute(query="test")
|
result = await tool.execute(query="test")
|
||||||
assert "Error" in result
|
assert "Error" in result
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_jina_422_falls_back_to_duckduckgo(monkeypatch):
|
||||||
|
class MockDDGS:
|
||||||
|
def __init__(self, **kw):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def text(self, query, max_results=5):
|
||||||
|
return [{"title": "Fallback", "href": "https://ddg.example", "body": "DuckDuckGo fallback"}]
|
||||||
|
|
||||||
|
async def mock_get(self, url, **kw):
|
||||||
|
assert "s.jina.ai" in str(url)
|
||||||
|
raise httpx.HTTPStatusError(
|
||||||
|
"422 Unprocessable Entity",
|
||||||
|
request=httpx.Request("GET", str(url)),
|
||||||
|
response=httpx.Response(422, request=httpx.Request("GET", str(url))),
|
||||||
|
)
|
||||||
|
|
||||||
|
monkeypatch.setattr(httpx.AsyncClient, "get", mock_get)
|
||||||
|
monkeypatch.setattr("ddgs.DDGS", MockDDGS)
|
||||||
|
|
||||||
|
tool = _tool(provider="jina", api_key="jina-key")
|
||||||
|
result = await tool.execute(query="test")
|
||||||
|
assert "DuckDuckGo fallback" in result
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_jina_search_uses_path_encoded_query(monkeypatch):
|
||||||
|
calls = {}
|
||||||
|
|
||||||
|
async def mock_get(self, url, **kw):
|
||||||
|
calls["url"] = str(url)
|
||||||
|
calls["params"] = kw.get("params")
|
||||||
|
return _response(json={
|
||||||
|
"data": [{"title": "Jina Result", "url": "https://jina.ai", "content": "AI search"}]
|
||||||
|
})
|
||||||
|
|
||||||
|
monkeypatch.setattr(httpx.AsyncClient, "get", mock_get)
|
||||||
|
tool = _tool(provider="jina", api_key="jina-key")
|
||||||
|
await tool.execute(query="hello world")
|
||||||
|
assert calls["url"].rstrip("/") == "https://s.jina.ai/hello%20world"
|
||||||
|
assert calls["params"] in (None, {})
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_jina_422_falls_back_to_duckduckgo(monkeypatch):
|
||||||
|
class MockDDGS:
|
||||||
|
def __init__(self, **kw):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def text(self, query, max_results=5):
|
||||||
|
return [{"title": "Fallback", "href": "https://ddg.example", "body": "DuckDuckGo fallback"}]
|
||||||
|
|
||||||
|
async def mock_get(self, url, **kw):
|
||||||
|
raise httpx.HTTPStatusError(
|
||||||
|
"422 Unprocessable Entity",
|
||||||
|
request=httpx.Request("GET", str(url)),
|
||||||
|
response=httpx.Response(422, request=httpx.Request("GET", str(url))),
|
||||||
|
)
|
||||||
|
|
||||||
|
monkeypatch.setattr(httpx.AsyncClient, "get", mock_get)
|
||||||
|
monkeypatch.setattr("ddgs.DDGS", MockDDGS)
|
||||||
|
|
||||||
|
tool = _tool(provider="jina", api_key="jina-key")
|
||||||
|
result = await tool.execute(query="test")
|
||||||
|
assert "DuckDuckGo fallback" in result
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user