File size: 1,858 Bytes
cb505ff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76962bf
 
 
cb505ff
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
from typing import List

import requests
from bs4 import BeautifulSoup
from langchain_core.tools import tool


DUCKDUCKGO_HTML_URL = "https://html.duckduckgo.com/html/"
MAX_RESULTS = 5
REQUEST_TIMEOUT_SECONDS = 10
FALLBACK_MESSAGE = (
    "External search returned no results or is unavailable. "
    "Answer using the available medical knowledge and clearly state "
    "that no external source was retrieved."
)


def _search_duckduckgo(query: str) -> str:
    response = requests.get(
        DUCKDUCKGO_HTML_URL,
        params={"q": query, "kl": "us-en", "kp": "-1"},
        headers={"User-Agent": "dmChatbot/1.0"},
        timeout=REQUEST_TIMEOUT_SECONDS,
    )
    response.raise_for_status()

    soup = BeautifulSoup(response.text, "html.parser")
    results: List[str] = []
    for result in soup.select(".result")[:MAX_RESULTS]:
        link = result.select_one(".result__a")
        if not link:
            continue

        title = link.get_text(" ", strip=True)
        url = link.get("href", "").strip()
        snippet_element = result.select_one(".result__snippet")
        snippet = snippet_element.get_text(" ", strip=True) if snippet_element else ""
        details = [title]
        if snippet:
            details.append(snippet)
        if url:
            details.append(url)
        results.append("\n".join(details))

    if not results:
        raise ValueError("DuckDuckGo returned no search results")
    return "\n\n".join(results)


@tool
def web_search_tool(query: str) -> str:
    """Search the web for medical information or nutritional data."""
    try:
        return _search_duckduckgo(query)
    except Exception:
        return FALLBACK_MESSAGE


def search_web(query: str) -> str:
    """Useful for searching the web for medical information or nutritional data."""
    return web_search_tool.invoke({"query": query})