File size: 6,004 Bytes
45c8f2a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e2a0df8
80a0956
45c8f2a
 
 
80a0956
45c8f2a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7aad2b9
45c8f2a
 
 
 
 
1dd96fa
45c8f2a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import requests
from pydantic import BaseModel, Field
from typing import Callable, Any, Optional


class Valves(BaseModel):
    SEARXNG_URL: str = Field(
        default="https://search.ricky.cloudns.be/search",
        description="SearXNG search URL",
    )
    BAIDU_URL: str = Field(
        default="https://www.baidu.com/s", description="Baidu search URL"
    )
    # 添加 Bing 搜索 URL
    BING_URL: str = Field(
        default="https://www.bing.com/search", description="Bing search URL"
    )
    TIMEOUT: int = Field(default=30, description="Request timeout in seconds")


class Tools:
    def __init__(self):
        self.valves = Valves()
        self.reader_api = "https://r.jina.ai/"
        self.citation = True

    async def read_url(
        self, url: str, __event_emitter__: Optional[Callable[[dict], Any]] = None
    ) -> str:
        """
        Read and extract the main content from a given URL.
        :param url: The URL to read from.
        :return: The main content of the page in clean, LLM-friendly text.
        """
        try:
            if __event_emitter__:
                await __event_emitter__(
                    {
                        "type": "status",
                        "data": {
                            "description": f"Reading content from {url}",
                            "status": "in_progress",
                        },
                    }
                )

            data = {"url": url}
            response = requests.post(
                self.reader_api, data=data, timeout=self.valves.TIMEOUT
            )
            response.raise_for_status()
            content = response.text

            if __event_emitter__:
                await __event_emitter__(
                    {
                        "type": "status",
                        "data": {
                            "description": "Content retrieved",
                            "status": "complete",
                        },
                    }
                )

            result_presentation = """
Result Presentation
STRICTLY ADHERE TO THIS FORMAT:
### [Site Name - Title](URL) 
#### 核心内容(Key Insights):
- Point 1
- Point 2
...
#### 总结(Summary):
---"""

            return f"{content}\n---\n{result_presentation}"
        except Exception as e:
            if __event_emitter__:
                await __event_emitter__(
                    {
                        "type": "status",
                        "data": {
                            "description": f"Error reading URL: {str(e)}",
                            "status": "error",
                        },
                    }
                )
            return f"Error reading URL: {str(e)}"

    async def search(
        self,
        search_term: str,
        engine: str = "bing",
        __event_emitter__: Optional[Callable[[dict], Any]] = None,
    ) -> str:
        """
        Issues a query to a search engine and displays the results. (Note: Use this when the query requires gathering information from external sources, such as current events, unfamiliar terms, or when explicit browsing is requested.)
        :param search_term: The search term or phrase to look up. (Note: think the keywords most likely to help users retrieve information as the "search_term",don't include search engine)
        :param engine: The search engine to use ('bing', 'baidu', or 'google'). Note:bing(Default, suitable for most queries), baidu(Best for content about China), google(For backup use only)
        :return: The search results in text format.
        """
        try:
            if __event_emitter__:
                await __event_emitter__(
                    {
                        "type": "status",
                        "data": {
                            "description": f"Searching with {engine}: {search_term}",
                            "status": "in_progress",
                        },
                    }
                )

            if engine == "baidu":
                url = f"{self.reader_api}{self.valves.BAIDU_URL}?wd={search_term}"
                headers = {"X-Target-Selector": "#content_left"}
            elif engine == "bing":
                # 添加 Bing 搜索的处理
                url = f"{self.reader_api}{self.valves.BING_URL}?q={search_term}"
                headers = {"X-Target-Selector": "#b_results"}
            else:
                url = f"{self.reader_api}{self.valves.SEARXNG_URL}?q={search_term}"
                headers = {"X-Target-Selector": "#urls"}

            response = requests.get(url, headers=headers, timeout=self.valves.TIMEOUT)
            response.raise_for_status()
            content = response.text

            if __event_emitter__:
                await __event_emitter__(
                    {
                        "type": "status",
                        "data": {
                            "description": f"Search completed with {engine}",
                            "status": "complete",
                        },
                    }
                )

            search_result_processing = """
Search Result Processing:
- Identify 1-3 highly relevant results from the search.
- Focus on the most informative and reliable sources.
- Integrate the key points from these sources to formulate a comprehensive answer to the query.
- If applicable, mention additional relevant information inferred from visible snippets in the search results.
"""

            return f"{content}\n---\n{search_result_processing}"

        except Exception as e:
            if __event_emitter__:
                await __event_emitter__(
                    {
                        "type": "status",
                        "data": {
                            "description": f"Error during search: {str(e)}",
                            "status": "error",
                        },
                    }
                )
            return f"Error during search: {str(e)}"