beswarm 0.1.12__py3-none-any.whl → 0.1.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. beswarm/aient/main.py +50 -0
  2. beswarm/aient/setup.py +15 -0
  3. beswarm/aient/src/aient/__init__.py +1 -0
  4. beswarm/aient/src/aient/core/__init__.py +1 -0
  5. beswarm/aient/src/aient/core/log_config.py +6 -0
  6. beswarm/aient/src/aient/core/models.py +232 -0
  7. beswarm/aient/src/aient/core/request.py +1665 -0
  8. beswarm/aient/src/aient/core/response.py +617 -0
  9. beswarm/aient/src/aient/core/test/test_base_api.py +18 -0
  10. beswarm/aient/src/aient/core/test/test_image.py +15 -0
  11. beswarm/aient/src/aient/core/test/test_payload.py +92 -0
  12. beswarm/aient/src/aient/core/utils.py +715 -0
  13. beswarm/aient/src/aient/models/__init__.py +9 -0
  14. beswarm/aient/src/aient/models/audio.py +63 -0
  15. beswarm/aient/src/aient/models/base.py +251 -0
  16. beswarm/aient/src/aient/models/chatgpt.py +938 -0
  17. beswarm/aient/src/aient/models/claude.py +640 -0
  18. beswarm/aient/src/aient/models/duckduckgo.py +241 -0
  19. beswarm/aient/src/aient/models/gemini.py +357 -0
  20. beswarm/aient/src/aient/models/groq.py +268 -0
  21. beswarm/aient/src/aient/models/vertex.py +420 -0
  22. beswarm/aient/src/aient/plugins/__init__.py +33 -0
  23. beswarm/aient/src/aient/plugins/arXiv.py +48 -0
  24. beswarm/aient/src/aient/plugins/config.py +172 -0
  25. beswarm/aient/src/aient/plugins/excute_command.py +35 -0
  26. beswarm/aient/src/aient/plugins/get_time.py +19 -0
  27. beswarm/aient/src/aient/plugins/image.py +72 -0
  28. beswarm/aient/src/aient/plugins/list_directory.py +50 -0
  29. beswarm/aient/src/aient/plugins/read_file.py +79 -0
  30. beswarm/aient/src/aient/plugins/registry.py +116 -0
  31. beswarm/aient/src/aient/plugins/run_python.py +156 -0
  32. beswarm/aient/src/aient/plugins/websearch.py +394 -0
  33. beswarm/aient/src/aient/plugins/write_file.py +51 -0
  34. beswarm/aient/src/aient/prompt/__init__.py +1 -0
  35. beswarm/aient/src/aient/prompt/agent.py +280 -0
  36. beswarm/aient/src/aient/utils/__init__.py +0 -0
  37. beswarm/aient/src/aient/utils/prompt.py +143 -0
  38. beswarm/aient/src/aient/utils/scripts.py +721 -0
  39. beswarm/aient/test/chatgpt.py +161 -0
  40. beswarm/aient/test/claude.py +32 -0
  41. beswarm/aient/test/test.py +2 -0
  42. beswarm/aient/test/test_API.py +6 -0
  43. beswarm/aient/test/test_Deepbricks.py +20 -0
  44. beswarm/aient/test/test_Web_crawler.py +262 -0
  45. beswarm/aient/test/test_aiwaves.py +25 -0
  46. beswarm/aient/test/test_aiwaves_arxiv.py +19 -0
  47. beswarm/aient/test/test_ask_gemini.py +8 -0
  48. beswarm/aient/test/test_class.py +17 -0
  49. beswarm/aient/test/test_claude.py +23 -0
  50. beswarm/aient/test/test_claude_zh_char.py +26 -0
  51. beswarm/aient/test/test_ddg_search.py +50 -0
  52. beswarm/aient/test/test_download_pdf.py +56 -0
  53. beswarm/aient/test/test_gemini.py +97 -0
  54. beswarm/aient/test/test_get_token_dict.py +21 -0
  55. beswarm/aient/test/test_google_search.py +35 -0
  56. beswarm/aient/test/test_jieba.py +32 -0
  57. beswarm/aient/test/test_json.py +65 -0
  58. beswarm/aient/test/test_langchain_search_old.py +235 -0
  59. beswarm/aient/test/test_logging.py +32 -0
  60. beswarm/aient/test/test_ollama.py +55 -0
  61. beswarm/aient/test/test_plugin.py +16 -0
  62. beswarm/aient/test/test_py_run.py +26 -0
  63. beswarm/aient/test/test_requests.py +162 -0
  64. beswarm/aient/test/test_search.py +18 -0
  65. beswarm/aient/test/test_tikitoken.py +19 -0
  66. beswarm/aient/test/test_token.py +94 -0
  67. beswarm/aient/test/test_url.py +33 -0
  68. beswarm/aient/test/test_whisper.py +14 -0
  69. beswarm/aient/test/test_wildcard.py +20 -0
  70. beswarm/aient/test/test_yjh.py +21 -0
  71. {beswarm-0.1.12.dist-info → beswarm-0.1.13.dist-info}/METADATA +1 -1
  72. beswarm-0.1.13.dist-info/RECORD +131 -0
  73. beswarm-0.1.12.dist-info/RECORD +0 -61
  74. {beswarm-0.1.12.dist-info → beswarm-0.1.13.dist-info}/WHEEL +0 -0
  75. {beswarm-0.1.12.dist-info → beswarm-0.1.13.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,156 @@
1
+ import os
2
+ import ast
3
+ import asyncio
4
+ import logging
5
+ import tempfile
6
+ from .registry import register_tool
7
+
8
+ def get_dangerous_attributes(node):
9
+ # 简单的代码审查,检查是否包含某些危险关键词
10
+ dangerous_keywords = ['os', 'subprocess', 'sys', 'import', 'eval', 'exec', 'open']
11
+ if isinstance(node, ast.Name):
12
+ return node.id in dangerous_keywords
13
+ elif isinstance(node, ast.Attribute):
14
+ return node.attr in dangerous_keywords
15
+ return False
16
+
17
+ def check_code_safety(code):
18
+ try:
19
+ # 解析代码为 AST
20
+ tree = ast.parse(code)
21
+
22
+ # 检查所有节点
23
+ for node in ast.walk(tree):
24
+ # 检查危险属性访问
25
+ if get_dangerous_attributes(node):
26
+ return False
27
+
28
+ # 检查危险的调用
29
+ if isinstance(node, ast.Call):
30
+ if isinstance(node.func, (ast.Name, ast.Attribute)):
31
+ if get_dangerous_attributes(node.func):
32
+ return False
33
+
34
+ # 检查字符串编码/解码操作
35
+ if isinstance(node, ast.Call) and isinstance(node.func, ast.Attribute):
36
+ if node.func.attr in ('encode', 'decode'):
37
+ return False
38
+
39
+ return True
40
+ except SyntaxError:
41
+ return False
42
+
43
+ @register_tool()
44
+ async def run_python_script(code):
45
+ """
46
+ 执行 Python 代码
47
+
48
+ 参数:
49
+ code: 要执行的 Python 代码字符串
50
+
51
+ 返回:
52
+ 执行结果字符串
53
+ """
54
+
55
+ timeout = 10
56
+ # 检查代码安全性
57
+ if not check_code_safety(code):
58
+ return "Code contains potentially dangerous operations.\n\n"
59
+
60
+ # 添加一段捕获代码,确保最后表达式的值会被输出
61
+ # 这种方式比 ast 解析更可靠
62
+ wrapper_code = """
63
+ import sys
64
+ _result = None
65
+
66
+ def _capture_last_result(code_to_run):
67
+ global _result
68
+ namespace = {{}}
69
+ exec(code_to_run, namespace)
70
+ if "_last_expr" in namespace:
71
+ _result = namespace["_last_expr"]
72
+
73
+ # 用户代码
74
+ _user_code = '''
75
+ {}
76
+ '''
77
+
78
+ # 处理用户代码,尝试提取最后一个表达式
79
+ lines = _user_code.strip().split('\\n')
80
+ if lines:
81
+ # 检查最后一行是否是表达式
82
+ last_line = lines[-1].strip()
83
+ if last_line and not last_line.startswith(('def ', 'class ', 'if ', 'for ', 'while ', 'try:', 'with ')):
84
+ if not any(last_line.startswith(kw) for kw in ['return', 'print', 'raise', 'assert', 'import', 'from ']):
85
+ if not last_line.endswith(':') and not last_line.endswith('='):
86
+ # 可能是表达式,修改它
87
+ lines[-1] = "_last_expr = " + last_line
88
+ _user_code = '\\n'.join(lines)
89
+
90
+ _capture_last_result(_user_code)
91
+
92
+ # 输出结果
93
+ if _result is not None:
94
+ print("\\nResult:", repr(_result))
95
+ """.format(code)
96
+
97
+ with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as temp_file:
98
+ temp_file.write(wrapper_code)
99
+ temp_file_name = temp_file.name
100
+
101
+ try:
102
+ process = await asyncio.create_subprocess_exec(
103
+ 'python', temp_file_name,
104
+ stdout=asyncio.subprocess.PIPE,
105
+ stderr=asyncio.subprocess.PIPE
106
+ )
107
+
108
+ try:
109
+ stdout, stderr = await asyncio.wait_for(process.communicate(), timeout=timeout)
110
+ stdout = stdout.decode()
111
+ stderr = stderr.decode()
112
+ return_code = process.returncode
113
+ except asyncio.TimeoutError:
114
+ # 使用 SIGTERM 信号终止进程
115
+ process.terminate()
116
+ await asyncio.sleep(0.1) # 给进程一点时间来终止
117
+ if process.returncode is None:
118
+ # 如果进程还没有终止,使用 SIGKILL
119
+ process.kill()
120
+ return "Process execution timed out."
121
+
122
+ mess = (
123
+ f"Execution result:\n{stdout}\n",
124
+ f"Stderr:\n{stderr}\n" if stderr else "",
125
+ f"Return Code: {return_code}\n" if return_code else "",
126
+ )
127
+ mess = "".join(mess)
128
+ return mess
129
+
130
+ except Exception as e:
131
+ logging.error(f"Error executing code: {str(e)}")
132
+ return f"Error: {str(e)}"
133
+
134
+ finally:
135
+ try:
136
+ os.unlink(temp_file_name)
137
+ except Exception as e:
138
+ logging.error(f"Error deleting temporary file: {str(e)}")
139
+
140
+ # 使用示例
141
+ async def main():
142
+ code = """
143
+ print("Hello, World!")
144
+ """
145
+ code = """
146
+ def add(a, b):
147
+ return a + b
148
+
149
+ result = add(5, 3)
150
+ print(result)
151
+ """
152
+ result = await run_python_script(code)
153
+ print(result)
154
+
155
+ if __name__ == "__main__":
156
+ asyncio.run(main())
@@ -0,0 +1,394 @@
1
+ import os
2
+ import re
3
+ import datetime
4
+ import requests
5
+ import threading
6
+ import time as record_time
7
+ from itertools import islice
8
+ from bs4 import BeautifulSoup
9
+ from duckduckgo_search import DDGS
10
+ from .registry import register_tool
11
+
12
+ class ThreadWithReturnValue(threading.Thread):
13
+ def run(self):
14
+ if self._target is not None:
15
+ self._return = self._target(*self._args, **self._kwargs)
16
+
17
+ def join(self):
18
+ super().join()
19
+ return self._return
20
+
21
+ import re
22
+ import httpx
23
+ import lxml.html
24
+ from lxml_html_clean import Cleaner
25
+ from html2text import HTML2Text
26
+ from textwrap import dedent
27
+
28
+ def url_to_markdown(url):
29
+ # 获取并清理网页内容
30
+ def get_body(url):
31
+ try:
32
+ text = httpx.get(url, verify=False, timeout=5).text
33
+ if text == "":
34
+ return "抱歉,目前无法访问该网页。"
35
+ # body = lxml.html.fromstring(text).xpath('//body')
36
+
37
+ doc = lxml.html.fromstring(text)
38
+ # 检查是否是GitHub raw文件格式(body > pre)
39
+ if doc.xpath('//body/pre'):
40
+ return text # 直接返回原始文本,保留格式
41
+
42
+ body = doc.xpath('//body')
43
+ if body == [] and text != "":
44
+ body = text
45
+ return f'<pre>{body}</pre>'
46
+ # return body
47
+ else:
48
+ body = body[0]
49
+ body = Cleaner(javascript=True, style=True).clean_html(body)
50
+ return ''.join(lxml.html.tostring(c, encoding='unicode') for c in body)
51
+ except Exception as e:
52
+ # print('\033[31m')
53
+ # print("error: url_to_markdown url", url)
54
+ # print("error", e)
55
+ # print('\033[0m')
56
+ return "抱歉,目前无法访问该网页。"
57
+
58
+ # 将HTML转换为Markdown
59
+ def get_md(cts):
60
+ h2t = HTML2Text(bodywidth=5000)
61
+ h2t.ignore_links = True
62
+ h2t.mark_code = True
63
+ h2t.ignore_images = True
64
+ res = h2t.handle(cts)
65
+
66
+ def _f(m):
67
+ return f'```\n{dedent(m.group(1))}\n```'
68
+
69
+ return re.sub(r'\[code]\s*\n(.*?)\n\[/code]', _f, res or '', flags=re.DOTALL).strip()
70
+
71
+ # 获取网页内容
72
+ body_content = get_body(url)
73
+
74
+ # 转换为Markdown
75
+ markdown_content = get_md(body_content)
76
+
77
+ return "URL Source: " + url + "\n\ntext: " + markdown_content
78
+
79
+ def jina_ai_Web_crawler(url: str, isSearch=False) -> str:
80
+ """返回链接网址url正文内容,必须是合法的网址"""
81
+ headers = {
82
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"
83
+ }
84
+ result = ''
85
+ try:
86
+ requests.packages.urllib3.disable_warnings()
87
+ url = "https://r.jina.ai/" + url
88
+ response = requests.get(url, headers=headers, verify=False, timeout=5, stream=True)
89
+ if response.status_code == 404:
90
+ print("Page not found:", url)
91
+ return "抱歉,网页不存在,目前无法访问该网页。@Trash@"
92
+ content_length = int(response.headers.get('Content-Length', 0))
93
+ if content_length > 5000000:
94
+ print("Skipping large file:", url)
95
+ return result
96
+
97
+ # 检查内容是否为HTML
98
+ content_type = response.headers.get('Content-Type', '')
99
+ if 'text/html' in content_type or 'application/xhtml+xml' in content_type:
100
+ # 使用html.parser而不是lxml可能会更宽松一些
101
+ soup = BeautifulSoup(response.content, 'html.parser')
102
+ else:
103
+ # 对于非HTML内容,直接提取文本
104
+ return response.text # 限制长度
105
+
106
+ table_contents = ""
107
+ tables = soup.find_all('table')
108
+ for table in tables:
109
+ table_contents += table.get_text()
110
+ table.decompose()
111
+ body = "".join(soup.find('body').get_text().split('\n'))
112
+ result = table_contents + body
113
+ if result == '' and not isSearch:
114
+ result = "抱歉,可能反爬虫策略,目前无法访问该网页。@Trash@"
115
+ if result.count("\"") > 1000:
116
+ result = ""
117
+ except Exception as e:
118
+ # print('\033[31m')
119
+ # print("error: jina_ai_Web_crawler url", url)
120
+ # print("error", e)
121
+ # print('\033[0m')
122
+ pass
123
+ # print(result + "\n\n")
124
+ return result
125
+
126
+ @register_tool()
127
+ def get_url_content(url: str) -> str:
128
+ """
129
+ 获取 url 的网页内容,以 markdown 格式返回给用户
130
+
131
+ :param url: 要爬取的网页URL
132
+ :return: 网页内容
133
+ """
134
+ markdown_content = url_to_markdown(url)
135
+ # print(markdown_content)
136
+ # print('-----------------------------')
137
+ jina_content = jina_ai_Web_crawler(url)
138
+ # print('-----------------------------')
139
+
140
+ # 定义评分函数
141
+ def score_content(content):
142
+ # 1. 内容长度
143
+ length_score = len(content)
144
+
145
+ # 2. 是否包含错误信息
146
+ error_penalty = 1000 if "抱歉" in content or "@Trash@" in content else 0
147
+
148
+ # 3. 内容的多样性(可以通过不同类型的字符来粗略估计)
149
+ diversity_score = len(set(content))
150
+
151
+ # 4. 特殊字符比例(过高可能意味着格式问题)
152
+ special_char_ratio = len(re.findall(r'[^a-zA-Z0-9\u4e00-\u9fff\s]', content)) / len(content)
153
+ special_char_penalty = 500 if special_char_ratio > 0.1 else 0
154
+
155
+ return length_score + diversity_score - error_penalty - special_char_penalty
156
+
157
+ if markdown_content == "":
158
+ markdown_score = -2000
159
+ else:
160
+ markdown_score = score_content(markdown_content)
161
+ if jina_content == "":
162
+ jina_score = -2000
163
+ else:
164
+ jina_score = score_content(jina_content)
165
+
166
+ # print(f"url_to_markdown 得分: {markdown_score}")
167
+ # print(f"jina_ai_Web_crawler 得分: {jina_score}")
168
+
169
+ if markdown_score > jina_score:
170
+ # print("choose: 选择 url_to_markdown 的结果")
171
+ return markdown_content
172
+ elif markdown_score == jina_score and jina_score < 0:
173
+ print("choose: 两者都无法访问")
174
+ return ""
175
+ else:
176
+ # print("choose: 选择 jina_ai_Web_crawler 的结果")
177
+ return jina_content
178
+
179
+ def getddgsearchurl(query, max_results=4):
180
+ try:
181
+ results = []
182
+ with DDGS() as ddgs:
183
+ ddgs_gen = ddgs.text(query, safesearch='Off', timelimit='y', backend="lite")
184
+ for r in islice(ddgs_gen, max_results):
185
+ results.append(r)
186
+ urls = [result['href'] for result in results]
187
+ except Exception as e:
188
+ print('\033[31m')
189
+ print("duckduckgo error", e)
190
+ print('\033[0m')
191
+ urls = []
192
+ return urls
193
+
194
+ def getgooglesearchurl(result, numresults=3):
195
+ urls = []
196
+ try:
197
+ url = "https://www.googleapis.com/customsearch/v1"
198
+ params = {
199
+ 'q': result,
200
+ 'key': os.environ.get('GOOGLE_API_KEY', None),
201
+ 'cx': os.environ.get('GOOGLE_CSE_ID', None)
202
+ }
203
+ response = requests.get(url, params=params)
204
+ # print(response.text)
205
+ results = response.json()
206
+ link_list = [item['link'] for item in results.get('items', [])]
207
+ urls = link_list[:numresults]
208
+ except Exception as e:
209
+ print('\033[31m')
210
+ print("error", e)
211
+ print('\033[0m')
212
+ if "rateLimitExceeded" in str(e):
213
+ print("Google API 每日调用频率已达上限,请明日再试!")
214
+ # print("google urls", urls)
215
+ return urls
216
+
217
+ def sort_by_time(urls):
218
+ def extract_date(url):
219
+ match = re.search(r'[12]\d{3}.\d{1,2}.\d{1,2}', url)
220
+ if match is not None:
221
+ match = re.sub(r'([12]\d{3}).(\d{1,2}).(\d{1,2})', "\\1/\\2/\\3", match.group())
222
+ print(match)
223
+ if int(match[:4]) > datetime.datetime.now().year:
224
+ match = "1000/01/01"
225
+ else:
226
+ match = "1000/01/01"
227
+ try:
228
+ return datetime.datetime.strptime(match, '%Y/%m/%d')
229
+ except:
230
+ match = "1000/01/01"
231
+ return datetime.datetime.strptime(match, '%Y/%m/%d')
232
+
233
+ # 提取日期并创建一个包含日期和URL的元组列表
234
+ date_url_pairs = [(extract_date(url), url) for url in urls]
235
+
236
+ # 按日期排序
237
+ date_url_pairs.sort(key=lambda x: x[0], reverse=True)
238
+
239
+ # 获取排序后的URL列表
240
+ sorted_urls = [url for _, url in date_url_pairs]
241
+
242
+ return sorted_urls
243
+
244
+ async def get_search_url(keywords, search_url_num):
245
+ yield "message_search_stage_2"
246
+
247
+ search_threads = []
248
+ if os.environ.get('GOOGLE_API_KEY', None) and os.environ.get('GOOGLE_CSE_ID', None):
249
+ search_thread = ThreadWithReturnValue(target=getgooglesearchurl, args=(keywords[0],search_url_num,))
250
+ keywords.pop(0)
251
+ search_thread.start()
252
+ search_threads.append(search_thread)
253
+
254
+ urls_set = []
255
+ urls_set += getddgsearchurl(keywords[0], search_url_num)
256
+
257
+ for t in search_threads:
258
+ tmp = t.join()
259
+ urls_set += tmp
260
+ url_set_list = sorted(set(urls_set), key=lambda x: urls_set.index(x))
261
+ url_set_list = sort_by_time(url_set_list)
262
+
263
+ url_pdf_set_list = [item for item in url_set_list if item.endswith(".pdf")]
264
+ url_set_list = [item for item in url_set_list if not item.endswith(".pdf")]
265
+ # cut_num = int(len(url_set_list) * 1 / 3)
266
+ yield url_set_list[:6], url_pdf_set_list
267
+ # return url_set_list[:6], url_pdf_set_list
268
+ # return url_set_list, url_pdf_set_list
269
+
270
+ def concat_url(threads):
271
+ url_result = []
272
+ for t in threads:
273
+ tmp = t.join()
274
+ if tmp:
275
+ url_result.append(tmp)
276
+ return url_result
277
+
278
+ async def get_url_text_list(keywords, search_url_num):
279
+ start_time = record_time.time()
280
+
281
+ async for chunk in get_search_url(keywords, search_url_num):
282
+ if type(chunk) == str:
283
+ yield chunk
284
+ else:
285
+ url_set_list, url_pdf_set_list = chunk
286
+ # url_set_list, url_pdf_set_list = yield from get_search_url(keywords, search_url_num)
287
+
288
+ yield "message_search_stage_3"
289
+ threads = []
290
+ for url in url_set_list:
291
+ # url_search_thread = ThreadWithReturnValue(target=jina_ai_Web_crawler, args=(url,True,))
292
+ url_search_thread = ThreadWithReturnValue(target=get_url_content, args=(url,))
293
+ # url_search_thread = ThreadWithReturnValue(target=Web_crawler, args=(url,True,))
294
+ url_search_thread.start()
295
+ threads.append(url_search_thread)
296
+
297
+ url_text_list = concat_url(threads)
298
+
299
+ yield "message_search_stage_4"
300
+ end_time = record_time.time()
301
+ run_time = end_time - start_time
302
+ print("urls", url_set_list)
303
+ print(f"搜索用时:{run_time}秒")
304
+
305
+ yield url_text_list
306
+ # return url_text_list
307
+
308
+ # Plugins 搜索入口
309
+ @register_tool()
310
+ async def get_search_results(query):
311
+ """
312
+ 执行网络搜索并返回搜索结果文本
313
+
314
+ 参数:
315
+ query: 查询语句,包含用户想要搜索的内容
316
+
317
+ 返回:
318
+ 异步生成器,依次产生:
319
+ - 搜索状态消息 ("message_search_stage_2", "message_search_stage_3", "message_search_stage_4")
320
+ - 最终的搜索结果文本列表
321
+
322
+ 说明:
323
+ - 根据查询语句自动搜索结果
324
+ - 使用多线程并行抓取网页内容
325
+ - 在搜索过程中通过yield返回状态更新
326
+ """
327
+ keywords = query
328
+ if len(keywords) == 3:
329
+ search_url_num = 4
330
+ if len(keywords) == 2:
331
+ search_url_num = 6
332
+ if len(keywords) == 1:
333
+ search_url_num = 12
334
+
335
+ url_text_list = []
336
+ async for chunk in get_url_text_list(keywords, search_url_num):
337
+ if type(chunk) == str:
338
+ yield chunk
339
+ else:
340
+ url_text_list = chunk
341
+ yield url_text_list
342
+
343
+ if __name__ == "__main__":
344
+ os.system("clear")
345
+ # from aient.models import chatgpt
346
+ # print(get_search_results("今天的微博热搜有哪些?", chatgpt.chatgpt_api_url.v1_url))
347
+
348
+ # # 搜索
349
+
350
+ # for i in search_web_and_summary("今天的微博热搜有哪些?"):
351
+ # for i in search_web_and_summary("给出清华铊中毒案时间线,并作出你的评论。"):
352
+ # for i in search_web_and_summary("红警hbk08是谁"):
353
+ # for i in search_web_and_summary("国务院 2024 放假安排"):
354
+ # for i in search_web_and_summary("中国最新公布的游戏政策,对游戏行业和其他相关行业有什么样的影响?"):
355
+ # for i in search_web_and_summary("今天上海的天气怎么样?"):
356
+ # for i in search_web_and_summary("阿里云24核96G的云主机价格是多少"):
357
+ # for i in search_web_and_summary("话说葬送的芙莉莲动漫是半年番还是季番?完结没?"):
358
+ # for i in search_web_and_summary("周海媚事件进展"):
359
+ # for i in search_web_and_summary("macos 13.6 有什么新功能"):
360
+ # for i in search_web_and_summary("用python写个网络爬虫给我"):
361
+ # for i in search_web_and_summary("消失的她主要讲了什么?"):
362
+ # for i in search_web_and_summary("奥巴马的全名是什么?"):
363
+ # for i in search_web_and_summary("华为mate60怎么样?"):
364
+ # for i in search_web_and_summary("慈禧养的猫叫什么名字?"):
365
+ # for i in search_web_and_summary("民进党当初为什么支持柯文哲选台北市长?"):
366
+ # for i in search_web_and_summary("Has the United States won the china US trade war?"):
367
+ # for i in search_web_and_summary("What does 'n+2' mean in Huawei's 'Mate 60 Pro' chipset? Please conduct in-depth analysis."):
368
+ # for i in search_web_and_summary("AUTOMATIC1111 是什么?"):
369
+ # for i in search_web_and_summary("python telegram bot 怎么接收pdf文件"):
370
+ # for i in search_web_and_summary("中国利用外资指标下降了 87% ?真的假的。"):
371
+ # for i in search_web_and_summary("How much does the 'zeabur' software service cost per month? Is it free to use? Any limitations?"):
372
+ # for i in search_web_and_summary("英国脱欧没有好处,为什么英国人还是要脱欧?"):
373
+ # for i in search_web_and_summary("2022年俄乌战争为什么发生?"):
374
+ # for i in search_web_and_summary("卡罗尔与星期二讲的啥?"):
375
+ # for i in search_web_and_summary("金砖国家会议有哪些决定?"):
376
+ # for i in search_web_and_summary("iphone15有哪些新功能?"):
377
+ # for i in search_web_and_summary("python函数开头:def time(text: str) -> str:每个部分有什么用?"):
378
+ # print(i, end="")
379
+
380
+ # 问答
381
+ # result = asyncio.run(docQA("/Users/yanyuming/Downloads/GitHub/wiki/docs", "ubuntu 版本号怎么看?"))
382
+ # result = asyncio.run(docQA("https://yym68686.top", "说一下HSTL pipeline"))
383
+ # result = asyncio.run(docQA("https://wiki.yym68686.top", "PyTorch to MindSpore翻译思路是什么?"))
384
+ # print(result['answer'])
385
+ # result = asyncio.run(pdfQA("https://api.telegram.org/file/bot5569497961:AAHobhUuydAwD8SPkXZiVFybvZJOmGrST_w/documents/file_1.pdf", "HSTL的pipeline详细讲一下"))
386
+ # print(result)
387
+ # source_url = set([i.metadata['source'] for i in result["source_documents"]])
388
+ # source_url = "\n".join(source_url)
389
+ # message = (
390
+ # f"{result['result']}\n\n"
391
+ # f"参考链接:\n"
392
+ # f"{source_url}"
393
+ # )
394
+ # print(message)
@@ -0,0 +1,51 @@
1
+ from .registry import register_tool
2
+
3
+ import os
4
+
5
+ @register_tool()
6
+ def write_to_file(path, content, mode='w'):
7
+ """
8
+ ## write_to_file
9
+ Description: Request to write full content to a file at the specified path. If the file exists, it will be overwritten with the provided content. If the file doesn't exist, it will be created. This tool will automatically create any directories needed to write the file.
10
+ Parameters:
11
+ - path: (required) The path of the file to write to (relative to the current working directory ${args.cwd})
12
+ - content: (required) The content to write to the file. ALWAYS provide the COMPLETE intended content of the file, without any truncation or omissions. You MUST include ALL parts of the file, even if they haven't been modified. Do NOT include the line numbers in the content though, just the actual content of the file.
13
+ - mode: (optional) The mode to write to the file. Default is 'w'. 'w' for write, 'a' for append.
14
+ Usage:
15
+ <write_to_file>
16
+ <path>File path here</path>
17
+ <content>
18
+ Your file content here
19
+ </content>
20
+ <mode>w</mode>
21
+ </write_to_file>
22
+
23
+ Example: Requesting to write to frontend-config.json
24
+ <write_to_file>
25
+ <path>frontend-config.json</path>
26
+ <content>
27
+ {
28
+ "apiEndpoint": "https://api.example.com",
29
+ "theme": {
30
+ "primaryColor": "#007bff",
31
+ "secondaryColor": "#6c757d",
32
+ "fontFamily": "Arial, sans-serif"
33
+ },
34
+ "features": {
35
+ "darkMode": true,
36
+ "notifications": true,
37
+ "analytics": false
38
+ },
39
+ "version": "1.0.0"
40
+ }
41
+ </content>
42
+ </write_to_file>
43
+ """
44
+ # 确保目录存在
45
+ os.makedirs(os.path.dirname(path) or '.', exist_ok=True)
46
+
47
+ # 写入文件
48
+ with open(path, mode, encoding='utf-8') as file:
49
+ file.write(content)
50
+
51
+ return f"文件已成功写入:{path}"
@@ -0,0 +1 @@
1
+ from .agent import *