beswarm 0.3.1__py3-none-any.whl → 0.3.3__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.
- beswarm/agents/planact.py +1 -2
- beswarm/aient/aient/architext/architext/core.py +56 -2
- beswarm/aient/aient/architext/test/test.py +164 -0
- beswarm/aient/aient/core/request.py +4 -2
- beswarm/aient/aient/core/response.py +3 -2
- beswarm/aient/aient/core/utils.py +44 -1
- beswarm/aient/aient/models/audio.py +2 -2
- beswarm/aient/aient/models/base.py +2 -2
- beswarm/aient/aient/models/chatgpt.py +49 -30
- beswarm/aient/aient/plugins/image.py +2 -2
- beswarm/aient/aient/utils/prompt.py +0 -4
- beswarm/aient/aient/utils/scripts.py +0 -8
- beswarm/aient/test/test_whisper.py +1 -1
- {beswarm-0.3.1.dist-info → beswarm-0.3.3.dist-info}/METADATA +1 -1
- {beswarm-0.3.1.dist-info → beswarm-0.3.3.dist-info}/RECORD +18 -20
- beswarm/aient/test/test_search.py +0 -18
- beswarm/aient/test/test_yjh.py +0 -21
- {beswarm-0.3.1.dist-info → beswarm-0.3.3.dist-info}/WHEEL +0 -0
- {beswarm-0.3.1.dist-info → beswarm-0.3.3.dist-info}/entry_points.txt +0 -0
- {beswarm-0.3.1.dist-info → beswarm-0.3.3.dist-info}/top_level.txt +0 -0
beswarm/agents/planact.py
CHANGED
@@ -204,8 +204,7 @@ class WorkerAgent(BaseAgent):
|
|
204
204
|
self.broker.publish(message, self.error_topic)
|
205
205
|
else:
|
206
206
|
self.broker.publish({"status": "new_message", "result": "\n✅ 工作智能体:\n" + response}, self.status_topic)
|
207
|
-
|
208
|
-
self.agent.conversation["default"].pop(-1)
|
207
|
+
self.agent.conversation["default"][-1].rstrip(Texts)
|
209
208
|
self.broker.publish({
|
210
209
|
"conversation": self.agent.conversation["default"]
|
211
210
|
}, self.publish_topic)
|
@@ -104,9 +104,10 @@ class ContextProvider(ABC):
|
|
104
104
|
return NotImplemented
|
105
105
|
|
106
106
|
class Texts(ContextProvider):
|
107
|
-
def __init__(self, text: Optional[Union[str, Callable[[], str]]] = None, name: Optional[str] = None, visible: bool = True):
|
107
|
+
def __init__(self, text: Optional[Union[str, Callable[[], str]]] = None, name: Optional[str] = None, visible: bool = True, newline: bool = False):
|
108
108
|
if text is None and name is None:
|
109
109
|
raise ValueError("Either 'text' or 'name' must be provided.")
|
110
|
+
self.newline = newline
|
110
111
|
|
111
112
|
# Ensure that non-callable inputs are treated as strings
|
112
113
|
if not callable(text):
|
@@ -127,6 +128,11 @@ class Texts(ContextProvider):
|
|
127
128
|
else:
|
128
129
|
_name = name
|
129
130
|
super().__init__(_name, visible=visible)
|
131
|
+
if not self._is_dynamic:
|
132
|
+
self._cached_content = self.content
|
133
|
+
# The content is cached, but it's still "stale" from the perspective
|
134
|
+
# of the async refresh cycle. Let the first refresh formalize it.
|
135
|
+
self._is_stale = True
|
130
136
|
|
131
137
|
async def refresh(self):
|
132
138
|
if self._is_dynamic:
|
@@ -190,6 +196,10 @@ class Tools(ContextProvider):
|
|
190
196
|
def __init__(self, tools_json: Optional[List[Dict]] = None, name: str = "tools", visible: bool = True):
|
191
197
|
super().__init__(name, visible=visible)
|
192
198
|
self._tools_json = tools_json or []
|
199
|
+
# Pre-render and cache the content, but leave it stale for the first refresh
|
200
|
+
if self._tools_json:
|
201
|
+
self._cached_content = f"<tools>{str(self._tools_json)}</tools>"
|
202
|
+
self._is_stale = True
|
193
203
|
def update(self, tools_json: List[Dict]):
|
194
204
|
self._tools_json = tools_json
|
195
205
|
self.mark_stale()
|
@@ -288,6 +298,9 @@ class Images(ContextProvider):
|
|
288
298
|
def __init__(self, url: str, name: Optional[str] = None, visible: bool = True):
|
289
299
|
super().__init__(name or url, visible=visible)
|
290
300
|
self.url = url
|
301
|
+
if self.url.startswith("data:"):
|
302
|
+
self._cached_content = self.url
|
303
|
+
self._is_stale = True
|
291
304
|
def update(self, url: str):
|
292
305
|
self.url = url
|
293
306
|
self.mark_stale()
|
@@ -315,6 +328,8 @@ class Message(ABC):
|
|
315
328
|
self.role = role
|
316
329
|
processed_items = []
|
317
330
|
for item in initial_items:
|
331
|
+
if item is None:
|
332
|
+
continue
|
318
333
|
if isinstance(item, str):
|
319
334
|
# Check if the string contains placeholders from f-string rendering
|
320
335
|
import re
|
@@ -371,8 +386,11 @@ class Message(ABC):
|
|
371
386
|
for item in self._items:
|
372
387
|
block = item.get_content_block()
|
373
388
|
if block and block.content is not None:
|
389
|
+
# Check if it's a Texts provider with newline=True
|
390
|
+
# and it's not the very first item with content.
|
391
|
+
if isinstance(item, Texts) and hasattr(item, 'newline') and item.newline and final_parts:
|
392
|
+
final_parts.append("\n\n")
|
374
393
|
final_parts.append(block.content)
|
375
|
-
|
376
394
|
return "".join(final_parts)
|
377
395
|
|
378
396
|
def pop(self, name: str) -> Optional[ContextProvider]:
|
@@ -466,11 +484,47 @@ class Message(ABC):
|
|
466
484
|
# and our custom __eq__ on ContextProvider handles the comparison logic.
|
467
485
|
return item in self._items
|
468
486
|
|
487
|
+
def has(self, provider_type: type) -> bool:
|
488
|
+
"""Checks if the message contains a provider of a specific type."""
|
489
|
+
if not isinstance(provider_type, type) or not issubclass(provider_type, ContextProvider):
|
490
|
+
raise TypeError("provider_type must be a subclass of ContextProvider")
|
491
|
+
return any(isinstance(p, provider_type) for p in self._items)
|
492
|
+
|
493
|
+
def lstrip(self, provider_type: type):
|
494
|
+
"""
|
495
|
+
从消息的左侧(开头)移除所有指定类型的 provider。
|
496
|
+
移除操作会一直持续,直到遇到一个不同类型的 provider 为止。
|
497
|
+
"""
|
498
|
+
while self._items and type(self._items[0]) is provider_type:
|
499
|
+
self.pop(self._items[0].name)
|
500
|
+
|
501
|
+
def rstrip(self, provider_type: type):
|
502
|
+
"""
|
503
|
+
从消息的右侧(末尾)移除所有指定类型的 provider。
|
504
|
+
移除操作会一直持续,直到遇到一个不同类型的 provider 为止。
|
505
|
+
"""
|
506
|
+
while self._items and type(self._items[-1]) is provider_type:
|
507
|
+
self.pop(self._items[-1].name)
|
508
|
+
|
509
|
+
def strip(self, provider_type: type):
|
510
|
+
"""
|
511
|
+
从消息的两侧移除所有指定类型的 provider。
|
512
|
+
"""
|
513
|
+
self.lstrip(provider_type)
|
514
|
+
self.rstrip(provider_type)
|
515
|
+
|
469
516
|
def __bool__(self) -> bool:
|
470
517
|
return bool(self._items)
|
471
518
|
def get(self, key: str, default: Any = None) -> Any:
|
472
519
|
"""提供类似字典的 .get() 方法来访问属性。"""
|
473
520
|
return getattr(self, key, default)
|
521
|
+
|
522
|
+
async def render_latest(self) -> Optional[Dict[str, Any]]:
|
523
|
+
"""Refreshes all providers in the message and returns the rendered dictionary."""
|
524
|
+
tasks = [provider.refresh() for provider in self._items]
|
525
|
+
await asyncio.gather(*tasks)
|
526
|
+
return self.to_dict()
|
527
|
+
|
474
528
|
def to_dict(self) -> Optional[Dict[str, Any]]:
|
475
529
|
is_multimodal = any(isinstance(p, Images) for p in self._items)
|
476
530
|
|
@@ -1434,6 +1434,170 @@ Files: {Files(visible=True, name="files")}
|
|
1434
1434
|
self.assertTrue(message in messages_collection)
|
1435
1435
|
self.assertFalse(UserMessage("not in collection") in messages_collection)
|
1436
1436
|
|
1437
|
+
async def test_zz_none_input_ignored(self):
|
1438
|
+
"""测试在Message初始化时,None值是否被自动忽略"""
|
1439
|
+
# 1. 在初始化列表中包含 None
|
1440
|
+
message = UserMessage("Hello", None, "World")
|
1441
|
+
self.assertEqual(len(message.provider()), 2)
|
1442
|
+
self.assertIsInstance(message.provider()[0], Texts)
|
1443
|
+
self.assertIsInstance(message.provider()[1], Texts)
|
1444
|
+
rendered = await message.render_latest()
|
1445
|
+
self.assertEqual(rendered['content'], "HelloWorld")
|
1446
|
+
|
1447
|
+
# 2. 测试只有 None
|
1448
|
+
message_none = SystemMessage(None)
|
1449
|
+
self.assertEqual(len(message_none.provider()), 0)
|
1450
|
+
self.assertFalse(message_none)
|
1451
|
+
|
1452
|
+
# 3. 测试混合 provider 和 None
|
1453
|
+
message_mixed = SystemMessage(Texts("hi"), None)
|
1454
|
+
self.assertEqual(len(message_mixed.provider()), 1)
|
1455
|
+
self.assertIsInstance(message_mixed.provider()[0], Texts)
|
1456
|
+
|
1457
|
+
async def test_zaa_has_method_for_provider_type_check(self):
|
1458
|
+
"""测试 Message.has(type) 方法是否能正确检查 provider 类型"""
|
1459
|
+
# 1. 创建一个混合类型的消息
|
1460
|
+
message_with_text = UserMessage(Texts("hi"), Images("url"))
|
1461
|
+
|
1462
|
+
# 2. 测试存在的情况
|
1463
|
+
# This line is expected to fail with an AttributeError before implementation
|
1464
|
+
self.assertTrue(message_with_text.has(Texts))
|
1465
|
+
self.assertTrue(message_with_text.has(Images))
|
1466
|
+
|
1467
|
+
# 3. 测试不存在的情况
|
1468
|
+
self.assertFalse(message_with_text.has(Tools))
|
1469
|
+
|
1470
|
+
# 4. 测试空消息
|
1471
|
+
empty_message = UserMessage()
|
1472
|
+
self.assertFalse(empty_message.has(Texts))
|
1473
|
+
|
1474
|
+
# 5. 测试传入无效类型
|
1475
|
+
with self.assertRaises(TypeError):
|
1476
|
+
message_with_text.has(str)
|
1477
|
+
|
1478
|
+
with self.assertRaises(TypeError):
|
1479
|
+
# Also test with a class that is not a subclass of ContextProvider
|
1480
|
+
class NotAProvider: pass
|
1481
|
+
message_with_text.has(NotAProvider)
|
1482
|
+
|
1483
|
+
async def test_zab_lstrip_and_rstrip(self):
|
1484
|
+
"""测试 lstrip, rstrip, 和 strip 方法是否能正确移除两侧的特定类型的 provider"""
|
1485
|
+
# 1. 定义一个用于测试的子类
|
1486
|
+
class SpecialTexts(Texts):
|
1487
|
+
pass
|
1488
|
+
url = "data:image/png;base64,FAKE_IMG"
|
1489
|
+
|
1490
|
+
# 2. 创建一个复杂的测试消息
|
1491
|
+
message = UserMessage(
|
1492
|
+
Texts("leading1"),
|
1493
|
+
Texts("leading2"),
|
1494
|
+
Images(url, name="image1"),
|
1495
|
+
Texts("middle"),
|
1496
|
+
SpecialTexts("special_middle"),
|
1497
|
+
Images(url, name="image2"),
|
1498
|
+
Texts("trailing1"),
|
1499
|
+
SpecialTexts("special_trailing"), # rstrip(Texts) should stop here
|
1500
|
+
Texts("trailing2")
|
1501
|
+
)
|
1502
|
+
|
1503
|
+
# 3. 测试 rstrip(Texts)
|
1504
|
+
r_stripped_message = UserMessage(*message.provider()) # 创建副本
|
1505
|
+
r_stripped_message.rstrip(Texts)
|
1506
|
+
# 应移除 "trailing2",但在 "special_trailing" 处停止
|
1507
|
+
self.assertEqual(len(r_stripped_message), 8)
|
1508
|
+
self.assertIs(type(r_stripped_message[-1]), SpecialTexts)
|
1509
|
+
|
1510
|
+
# 4. 测试 lstrip(Texts)
|
1511
|
+
l_stripped_message = UserMessage(*message.provider()) # 创建副本
|
1512
|
+
l_stripped_message.lstrip(Texts)
|
1513
|
+
# 应移除 "leading1" 和 "leading2",但在 "image1" 处停止
|
1514
|
+
self.assertEqual(len(l_stripped_message), 7)
|
1515
|
+
self.assertIs(type(l_stripped_message[0]), Images)
|
1516
|
+
|
1517
|
+
# 5. 测试 strip(Texts)
|
1518
|
+
stripped_message = UserMessage(*message.provider()) # 创建副本
|
1519
|
+
stripped_message.strip(Texts)
|
1520
|
+
# 应同时移除 "leading1", "leading2", 和 "trailing2"
|
1521
|
+
self.assertEqual(len(stripped_message), 6)
|
1522
|
+
self.assertIs(type(stripped_message[0]), Images)
|
1523
|
+
self.assertIs(type(stripped_message[-1]), SpecialTexts)
|
1524
|
+
|
1525
|
+
# 6. 测试在一个只包含一种类型的消息上进行剥离
|
1526
|
+
only_texts = UserMessage(Texts("a"), Texts("b"))
|
1527
|
+
only_texts.strip(Texts)
|
1528
|
+
self.assertEqual(len(only_texts), 0)
|
1529
|
+
|
1530
|
+
# 7. 测试剥离一个不包含目标类型的消息
|
1531
|
+
only_images = UserMessage(Images("url1"), Images("url2"))
|
1532
|
+
only_images.strip(Texts)
|
1533
|
+
self.assertEqual(len(only_images), 2) # 不应改变
|
1534
|
+
|
1535
|
+
# 8. 测试在一个空消息上进行剥离
|
1536
|
+
empty_message = UserMessage()
|
1537
|
+
empty_message.strip(Texts)
|
1538
|
+
self.assertEqual(len(empty_message), 0)
|
1539
|
+
|
1540
|
+
# 9. 测试剥离子类
|
1541
|
+
message_ending_with_special = UserMessage(Texts("a"), SpecialTexts("b"))
|
1542
|
+
message_ending_with_special.rstrip(SpecialTexts)
|
1543
|
+
self.assertEqual(len(message_ending_with_special), 1)
|
1544
|
+
self.assertIsInstance(message_ending_with_special[0], Texts)
|
1545
|
+
|
1546
|
+
async def test_zac_texts_join_parameter(self):
|
1547
|
+
"""测试 Texts provider 是否支持通过参数控制拼接方式"""
|
1548
|
+
# 1. 测试默认行为:直接拼接
|
1549
|
+
message_default = UserMessage(
|
1550
|
+
Texts("First line."),
|
1551
|
+
Texts("Second line.")
|
1552
|
+
)
|
1553
|
+
rendered_default = await message_default.render_latest()
|
1554
|
+
self.assertEqual(rendered_default['content'], "First line.Second line.")
|
1555
|
+
|
1556
|
+
# 2. 测试新功能:使用 \n\n 拼接
|
1557
|
+
# 假设新参数为 `newline=True`
|
1558
|
+
message_newline = UserMessage(
|
1559
|
+
Texts("First paragraph."),
|
1560
|
+
Texts("Second paragraph.", newline=True)
|
1561
|
+
)
|
1562
|
+
rendered_newline = await message_newline.render_latest()
|
1563
|
+
self.assertEqual(rendered_newline['content'], "First paragraph.\n\nSecond paragraph.")
|
1564
|
+
|
1565
|
+
# 3. 测试多个 provider 的情况
|
1566
|
+
message_multiple = UserMessage(
|
1567
|
+
Texts("First."),
|
1568
|
+
Texts("Second.", newline=True),
|
1569
|
+
Texts("Third.", newline=True)
|
1570
|
+
)
|
1571
|
+
rendered_multiple = await message_multiple.render_latest()
|
1572
|
+
self.assertEqual(rendered_multiple['content'], "First.\n\nSecond.\n\nThird.")
|
1573
|
+
|
1574
|
+
# 4. 测试只有一个 provider 的情况
|
1575
|
+
message_single = UserMessage(
|
1576
|
+
Texts("Only one.", newline=True)
|
1577
|
+
)
|
1578
|
+
rendered_single = await message_single.render_latest()
|
1579
|
+
self.assertEqual(rendered_single['content'], "Only one.")
|
1580
|
+
|
1581
|
+
async def test_zad_simple_render_without_refresh(self):
|
1582
|
+
"""测试 Messages(UserMessage('hi')).render() 是否能直接同步渲染"""
|
1583
|
+
# This test checks if a simple message can be rendered synchronously
|
1584
|
+
# without an explicit `await refresh()` or `await render_latest()`.
|
1585
|
+
# Calling the synchronous render method directly on a new instance
|
1586
|
+
rendered = Messages(UserMessage("hi", Images(url="data:image/png;base64,FAKE"))).render()
|
1587
|
+
|
1588
|
+
# The current implementation will likely fail here, returning []
|
1589
|
+
self.assertEqual(len(rendered), 1)
|
1590
|
+
self.assertEqual(rendered[0]['role'], 'user')
|
1591
|
+
|
1592
|
+
# Now we expect a list for multimodal content
|
1593
|
+
content = rendered[0]['content']
|
1594
|
+
self.assertIsInstance(content, list)
|
1595
|
+
self.assertEqual(len(content), 2)
|
1596
|
+
self.assertEqual(content[0]['type'], 'text')
|
1597
|
+
self.assertEqual(content[0]['text'], 'hi')
|
1598
|
+
self.assertEqual(content[1]['type'], 'image_url')
|
1599
|
+
self.assertEqual(content[1]['image_url']['url'], "data:image/png;base64,FAKE")
|
1600
|
+
|
1437
1601
|
|
1438
1602
|
# ==============================================================================
|
1439
1603
|
# 6. 演示
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import re
|
2
2
|
import json
|
3
|
+
import copy
|
3
4
|
import httpx
|
4
5
|
import base64
|
5
6
|
import asyncio
|
@@ -57,7 +58,7 @@ async def get_gemini_payload(request, engine, provider, api_key=None):
|
|
57
58
|
try:
|
58
59
|
request_messages = [Message(role="user", content=request.prompt)]
|
59
60
|
except:
|
60
|
-
request_messages = request.messages
|
61
|
+
request_messages = copy.deepcopy(request.messages)
|
61
62
|
for msg in request_messages:
|
62
63
|
if msg.role == "assistant":
|
63
64
|
msg.role = "model"
|
@@ -399,7 +400,8 @@ async def get_vertex_gemini_payload(request, engine, provider, api_key=None):
|
|
399
400
|
systemInstruction = None
|
400
401
|
system_prompt = ""
|
401
402
|
function_arguments = None
|
402
|
-
|
403
|
+
request_messages = copy.deepcopy(request.messages)
|
404
|
+
for msg in request_messages:
|
403
405
|
if msg.role == "assistant":
|
404
406
|
msg.role = "model"
|
405
407
|
tool_calls = None
|
@@ -8,7 +8,7 @@ from datetime import datetime
|
|
8
8
|
|
9
9
|
from .log_config import logger
|
10
10
|
|
11
|
-
from .utils import safe_get, generate_sse_response, generate_no_stream_response, end_of_line, parse_json_safely
|
11
|
+
from .utils import safe_get, generate_sse_response, generate_no_stream_response, end_of_line, parse_json_safely, upload_image_to_0x0st
|
12
12
|
|
13
13
|
async def check_response(response, error_log):
|
14
14
|
if response and not (200 <= response.status_code < 300):
|
@@ -277,7 +277,8 @@ async def fetch_gpt_response_stream(client, url, headers, payload, timeout):
|
|
277
277
|
openrouter_reasoning = safe_get(line, "choices", 0, "delta", "reasoning", default="")
|
278
278
|
openrouter_base64_image = safe_get(line, "choices", 0, "delta", "images", 0, "image_url", "url", default="")
|
279
279
|
if openrouter_base64_image:
|
280
|
-
|
280
|
+
image_url = await upload_image_to_0x0st(openrouter_base64_image)
|
281
|
+
sse_string = await generate_sse_response(timestamp, payload["model"], content=f"\n\n")
|
281
282
|
yield sse_string
|
282
283
|
continue
|
283
284
|
azure_databricks_claude_summary_content = safe_get(line, "choices", 0, "delta", "content", 0, "summary", 0, "text", default="")
|
@@ -228,7 +228,12 @@ async def update_initial_model(provider):
|
|
228
228
|
def safe_get(data, *keys, default=None):
|
229
229
|
for key in keys:
|
230
230
|
try:
|
231
|
-
|
231
|
+
if isinstance(data, (dict, list)):
|
232
|
+
data = data[key]
|
233
|
+
elif isinstance(key, str) and hasattr(data, key):
|
234
|
+
data = getattr(data, key)
|
235
|
+
else:
|
236
|
+
data = data.get(key)
|
232
237
|
except (KeyError, IndexError, AttributeError, TypeError):
|
233
238
|
return default
|
234
239
|
if not data:
|
@@ -797,6 +802,44 @@ def parse_json_safely(json_str):
|
|
797
802
|
# 两种方法都失败,抛出异常
|
798
803
|
raise Exception(f"无法解析JSON字符串: {e}, {json_str}")
|
799
804
|
|
805
|
+
async def upload_image_to_0x0st(base64_image: str):
|
806
|
+
"""
|
807
|
+
Uploads a base64 encoded image to 0x0.st.
|
808
|
+
|
809
|
+
Args:
|
810
|
+
base64_image: The base64 encoded image string.
|
811
|
+
|
812
|
+
Returns:
|
813
|
+
The URL of the uploaded image.
|
814
|
+
"""
|
815
|
+
if "," in base64_image:
|
816
|
+
base64_image_split = base64_image.split(",")[1]
|
817
|
+
|
818
|
+
image_data = base64.b64decode(base64_image_split)
|
819
|
+
|
820
|
+
img_format = get_image_format(image_data)
|
821
|
+
if not img_format:
|
822
|
+
img_format = 'png' # 如果无法检测到格式,则默认为 png
|
823
|
+
|
824
|
+
content_type = f'image/{img_format}'
|
825
|
+
file_name = f'image.{img_format}'
|
826
|
+
|
827
|
+
files = {'file': (file_name, image_data, content_type)}
|
828
|
+
data = {'expires': '24', 'secret': '123456'}
|
829
|
+
|
830
|
+
async with httpx.AsyncClient() as client:
|
831
|
+
try:
|
832
|
+
response = await client.post("https://0x0.st", files=files, data=data)
|
833
|
+
response.raise_for_status()
|
834
|
+
return response.text.strip()
|
835
|
+
except httpx.RequestError as e:
|
836
|
+
logger.error(f"请求 0x0.st 时出错: {e}")
|
837
|
+
# raise HTTPException(status_code=500, detail="上传图片到 0x0.st 失败")
|
838
|
+
except httpx.HTTPStatusError as e:
|
839
|
+
logger.error(f"上传图片到 0x0.st 时发生 HTTP 错误: {e.response.status_code}")
|
840
|
+
# raise HTTPException(status_code=e.response.status_code, detail=f"上传图片到 0x0.st 失败: {e.response.text}")
|
841
|
+
return base64_image
|
842
|
+
|
800
843
|
if __name__ == "__main__":
|
801
844
|
provider = {
|
802
845
|
"base_url": "https://gateway.ai.cloudflare.com/v1/%7Baccount_id%7D/%7Bgateway_id%7D/google-vertex-ai",
|
@@ -4,13 +4,13 @@ import json
|
|
4
4
|
from .base import BaseLLM
|
5
5
|
|
6
6
|
API = os.environ.get('API', None)
|
7
|
-
|
7
|
+
BASE_URL = os.environ.get('BASE_URL', None)
|
8
8
|
|
9
9
|
class whisper(BaseLLM):
|
10
10
|
def __init__(
|
11
11
|
self,
|
12
12
|
api_key: str,
|
13
|
-
api_url: str = (os.environ.get("
|
13
|
+
api_url: str = (os.environ.get("BASE_URL") or "https://api.openai.com/v1/audio/transcriptions"),
|
14
14
|
timeout: float = 20,
|
15
15
|
):
|
16
16
|
super().__init__(api_key, api_url=api_url, timeout=timeout)
|
@@ -11,8 +11,8 @@ class BaseLLM:
|
|
11
11
|
def __init__(
|
12
12
|
self,
|
13
13
|
api_key: str = None,
|
14
|
-
engine: str = os.environ.get("
|
15
|
-
api_url: str = (os.environ.get("
|
14
|
+
engine: str = os.environ.get("MODEL") or "gpt-3.5-turbo",
|
15
|
+
api_url: str = (os.environ.get("BASE_URL", None) or "https://api.openai.com/v1/chat/completions"),
|
16
16
|
system_prompt: str = prompt.chatgpt_system_prompt,
|
17
17
|
proxy: str = None,
|
18
18
|
timeout: float = 600,
|
@@ -6,6 +6,7 @@ import httpx
|
|
6
6
|
import asyncio
|
7
7
|
import logging
|
8
8
|
import inspect
|
9
|
+
from collections import defaultdict
|
9
10
|
from typing import Union, Optional, Callable
|
10
11
|
|
11
12
|
from .base import BaseLLM
|
@@ -16,6 +17,21 @@ from ..core.request import prepare_request_payload
|
|
16
17
|
from ..core.response import fetch_response_stream, fetch_response
|
17
18
|
from ..architext.architext import Messages, SystemMessage, UserMessage, AssistantMessage, ToolCalls, ToolResults, Texts, RoleMessage, Images, Files
|
18
19
|
|
20
|
+
class ToolResult(Texts):
|
21
|
+
def __init__(self, tool_name: str, tool_args: str, tool_response: str, name: Optional[str] = None, visible: bool = True, newline: bool = True):
|
22
|
+
super().__init__(text=tool_response, name=name or f"tool_result_{tool_name}", visible=visible, newline=newline)
|
23
|
+
self.tool_name = tool_name
|
24
|
+
self.tool_args = tool_args
|
25
|
+
|
26
|
+
async def render(self) -> Optional[str]:
|
27
|
+
tool_response = await super().render()
|
28
|
+
if tool_response is None:
|
29
|
+
tool_response = ""
|
30
|
+
if self.tool_args:
|
31
|
+
return f"[{self.tool_name}({self.tool_args}) Result]:\n\n{tool_response}"
|
32
|
+
else:
|
33
|
+
return f"[{self.tool_name} Result]:\n\n{tool_response}"
|
34
|
+
|
19
35
|
class APITimeoutError(Exception):
|
20
36
|
"""Custom exception for API timeout errors."""
|
21
37
|
pass
|
@@ -73,8 +89,8 @@ class chatgpt(BaseLLM):
|
|
73
89
|
def __init__(
|
74
90
|
self,
|
75
91
|
api_key: str = None,
|
76
|
-
engine: str = os.environ.get("
|
77
|
-
api_url: str = (os.environ.get("
|
92
|
+
engine: str = os.environ.get("MODEL") or "gpt-4o",
|
93
|
+
api_url: str = (os.environ.get("BASE_URL") or "https://api.openai.com/v1/chat/completions"),
|
78
94
|
system_prompt: str = "You are ChatGPT, a large language model trained by OpenAI. Respond conversationally",
|
79
95
|
proxy: str = None,
|
80
96
|
timeout: float = 600,
|
@@ -97,9 +113,7 @@ class chatgpt(BaseLLM):
|
|
97
113
|
Initialize Chatbot with API key (from https://platform.openai.com/account/api-keys)
|
98
114
|
"""
|
99
115
|
super().__init__(api_key, engine, api_url, system_prompt, proxy, timeout, max_tokens, temperature, top_p, presence_penalty, frequency_penalty, reply_count, truncate_limit, use_plugins=use_plugins, print_log=print_log)
|
100
|
-
self.conversation: dict[str, Messages] =
|
101
|
-
"default": Messages(SystemMessage(self.system_prompt)),
|
102
|
-
}
|
116
|
+
self.conversation: dict[str, Messages] = defaultdict(lambda: Messages(SystemMessage(self.system_prompt)))
|
103
117
|
if cache_messages:
|
104
118
|
self.conversation["default"] = cache_messages
|
105
119
|
self.function_calls_counter = {}
|
@@ -111,8 +125,12 @@ class chatgpt(BaseLLM):
|
|
111
125
|
else:
|
112
126
|
# 如果没有提供 logger,创建一个默认的,它只会打印到控制台
|
113
127
|
self.logger = logging.getLogger("chatgpt_default")
|
128
|
+
self.logger.propagate = False
|
114
129
|
if not self.logger.handlers: # 防止重复添加 handler
|
115
|
-
|
130
|
+
handler = logging.StreamHandler()
|
131
|
+
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
132
|
+
handler.setFormatter(formatter)
|
133
|
+
self.logger.addHandler(handler)
|
116
134
|
self.logger.setLevel(logging.INFO if print_log else logging.WARNING)
|
117
135
|
|
118
136
|
# 注册和处理传入的工具
|
@@ -173,8 +191,8 @@ class chatgpt(BaseLLM):
|
|
173
191
|
self.conversation[convo_id].append(ToolCalls(tool_calls))
|
174
192
|
self.conversation[convo_id].append(ToolResults(tool_call_id=function_call_id, content=message))
|
175
193
|
else:
|
176
|
-
last_user_message = self.conversation[convo_id][-1]
|
177
|
-
if last_user_message != message:
|
194
|
+
last_user_message = self.conversation[convo_id][-1]
|
195
|
+
if last_user_message != UserMessage(message):
|
178
196
|
image_message_list = UserMessage()
|
179
197
|
if isinstance(function_arguments, str):
|
180
198
|
functions_list = json.loads(function_arguments)
|
@@ -268,7 +286,7 @@ class chatgpt(BaseLLM):
|
|
268
286
|
"messages": await self.conversation[convo_id].render_latest() if pass_history else Messages(
|
269
287
|
SystemMessage(self.system_prompt, self.conversation[convo_id].provider("files")),
|
270
288
|
UserMessage(prompt)
|
271
|
-
),
|
289
|
+
).render(),
|
272
290
|
"stream": stream,
|
273
291
|
"temperature": kwargs.get("temperature", self.temperature)
|
274
292
|
}
|
@@ -565,7 +583,7 @@ class chatgpt(BaseLLM):
|
|
565
583
|
tool_calls = function_parameter
|
566
584
|
|
567
585
|
# 处理所有工具调用
|
568
|
-
all_responses =
|
586
|
+
all_responses = UserMessage()
|
569
587
|
|
570
588
|
for tool_info in tool_calls:
|
571
589
|
tool_name = tool_info['function_name']
|
@@ -585,27 +603,28 @@ class chatgpt(BaseLLM):
|
|
585
603
|
tool_response = chunk.replace("function_response:", "")
|
586
604
|
else:
|
587
605
|
yield chunk
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
606
|
+
final_tool_response = tool_response
|
607
|
+
if "<tool_error>" not in tool_response:
|
608
|
+
if tool_name == "read_file":
|
609
|
+
self.conversation[convo_id].provider("files").update(tool_info['parameter']["file_path"], tool_response)
|
610
|
+
final_tool_response = "Read file successfully! The file content has been updated in the tag <latest_file_content>."
|
611
|
+
elif tool_name == "get_knowledge_graph_tree":
|
612
|
+
self.conversation[convo_id].provider("knowledge_graph").visible = True
|
613
|
+
final_tool_response = "Get knowledge graph tree successfully! The knowledge graph tree has been updated in the tag <knowledge_graph_tree>."
|
614
|
+
elif tool_name == "write_to_file":
|
615
|
+
tool_args = None
|
616
|
+
elif tool_name == "read_image":
|
617
|
+
tool_info["base64_image"] = tool_response
|
618
|
+
final_tool_response = "Read image successfully!"
|
619
|
+
elif tool_response.startswith("data:image/") and ";base64," in tool_response:
|
620
|
+
tool_info["base64_image"] = tool_response
|
621
|
+
final_tool_response = "Read image successfully!"
|
622
|
+
all_responses.append(ToolResult(tool_name, tool_args, final_tool_response))
|
604
623
|
|
605
624
|
# 合并所有工具响应
|
606
|
-
function_response =
|
625
|
+
function_response = all_responses
|
607
626
|
if missing_required_params:
|
608
|
-
function_response
|
627
|
+
function_response.append(Texts("\n\n".join(missing_required_params)))
|
609
628
|
|
610
629
|
# 使用第一个工具的名称和参数作为历史记录
|
611
630
|
function_call_name = tool_calls[0]['function_name']
|
@@ -673,7 +692,7 @@ class chatgpt(BaseLLM):
|
|
673
692
|
# 准备会话
|
674
693
|
self.system_prompt = system_prompt or self.system_prompt
|
675
694
|
if convo_id not in self.conversation or pass_history <= 2:
|
676
|
-
self.reset(convo_id=convo_id, system_prompt=system_prompt)
|
695
|
+
self.reset(convo_id=convo_id, system_prompt=self.system_prompt)
|
677
696
|
self.add_to_conversation(prompt, role, convo_id=convo_id, function_name=function_name, total_tokens=total_tokens, function_arguments=function_arguments, pass_history=pass_history, function_call_id=function_call_id)
|
678
697
|
|
679
698
|
# 获取请求体
|
@@ -930,7 +949,7 @@ class chatgpt(BaseLLM):
|
|
930
949
|
"""
|
931
950
|
self.system_prompt = system_prompt or self.system_prompt
|
932
951
|
self.conversation[convo_id] = Messages(
|
933
|
-
SystemMessage(
|
952
|
+
SystemMessage(self.system_prompt, self.conversation[convo_id].provider("files")),
|
934
953
|
)
|
935
954
|
self.tokens_usage[convo_id] = 0
|
936
955
|
self.current_tokens[convo_id] = 0
|
@@ -5,13 +5,13 @@ from ..models.base import BaseLLM
|
|
5
5
|
from .registry import register_tool
|
6
6
|
|
7
7
|
API = os.environ.get('API', None)
|
8
|
-
|
8
|
+
BASE_URL = os.environ.get('BASE_URL', None)
|
9
9
|
|
10
10
|
class dalle3(BaseLLM):
|
11
11
|
def __init__(
|
12
12
|
self,
|
13
13
|
api_key: str,
|
14
|
-
api_url: str = (os.environ.get("
|
14
|
+
api_url: str = (os.environ.get("BASE_URL") or "https://api.openai.com/v1/images/generations"),
|
15
15
|
timeout: float = 20,
|
16
16
|
):
|
17
17
|
super().__init__(api_key, api_url=api_url, timeout=timeout)
|
@@ -90,10 +90,6 @@ chatgpt_system_prompt = (
|
|
90
90
|
"You are ChatGPT, a large language model trained by OpenAI. Use simple characters to represent mathematical symbols. Do not use LaTeX commands. Respond conversationally"
|
91
91
|
)
|
92
92
|
|
93
|
-
claude_system_prompt = (
|
94
|
-
"You are Claude, a large language model trained by Anthropic. Use simple characters to represent mathematical symbols. Do not use LaTeX commands. Respond conversationally in {}."
|
95
|
-
)
|
96
|
-
|
97
93
|
search_system_prompt = (
|
98
94
|
"You are ChatGPT, a large language model trained by OpenAI. Respond conversationally in {}."
|
99
95
|
"You can break down the task into multiple steps and search the web to answer my questions one by one."
|
@@ -134,14 +134,6 @@ def is_surrounded_by_chinese(text, index):
|
|
134
134
|
def replace_char(string, index, new_char):
|
135
135
|
return string[:index] + new_char + string[index+1:]
|
136
136
|
|
137
|
-
def claude_replace(text):
|
138
|
-
Punctuation_mapping = {",": ",", ":": ":", "!": "!", "?": "?", ";": ";"}
|
139
|
-
key_list = list(Punctuation_mapping.keys())
|
140
|
-
for i in range(len(text)):
|
141
|
-
if is_surrounded_by_chinese(text, i) and (text[i] in key_list):
|
142
|
-
text = replace_char(text, i, Punctuation_mapping[text[i]])
|
143
|
-
return text
|
144
|
-
|
145
137
|
def safe_get(data, *keys, default=None):
|
146
138
|
for key in keys:
|
147
139
|
try:
|
@@ -7,33 +7,33 @@ beswarm/prompt.py,sha256=45onnyoY9plKM86KQefbPw5z9QJMn-mVnjlFQZcrjz0,34373
|
|
7
7
|
beswarm/taskmanager.py,sha256=2Uz_cthW9rWkQMJdzgsXAMlfN8Ni2Qj_DOq_L-p6XZc,12662
|
8
8
|
beswarm/utils.py,sha256=0J-b38P5QGT-A_38co7FjzaUNJykaskI7mbbcQ4w_68,8215
|
9
9
|
beswarm/agents/chatgroup.py,sha256=PzrmRcDKAbB7cxL16nMod_CzPosDV6bfTmXxQVuv-AQ,12012
|
10
|
-
beswarm/agents/planact.py,sha256=
|
10
|
+
beswarm/agents/planact.py,sha256=wYIyrAsBY6Z_Hc8rx76vbfUTsagqYFIBOfPi43ze708,18361
|
11
11
|
beswarm/aient/aient/__init__.py,sha256=SRfF7oDVlOOAi6nGKiJIUK6B_arqYLO9iSMp-2IZZps,21
|
12
12
|
beswarm/aient/aient/architext/architext/__init__.py,sha256=79Ih1151rfcqZdr7F8HSZSTs_iT2SKd1xCkehMsXeXs,19
|
13
|
-
beswarm/aient/aient/architext/architext/core.py,sha256=
|
13
|
+
beswarm/aient/aient/architext/architext/core.py,sha256=XKMYDLdaTP6OWmNZLEF-b24KVDkMeM-xyVptmpXoBsU,33112
|
14
14
|
beswarm/aient/aient/architext/test/openai_client.py,sha256=Dqtbmubv6vwF8uBqcayG0kbsiO65of7sgU2-DRBi-UM,4590
|
15
|
-
beswarm/aient/aient/architext/test/test.py,sha256=
|
15
|
+
beswarm/aient/aient/architext/test/test.py,sha256=jxmEfZaeJWh3dq0f67TBTPMgT0FMK7eiTs9XcyAtFFg,73944
|
16
16
|
beswarm/aient/aient/architext/test/test_save_load.py,sha256=o8DqH6gDYZkFkQy-a7blqLtJTRj5e4a-Lil48pJ0V3g,3260
|
17
17
|
beswarm/aient/aient/core/__init__.py,sha256=NxjebTlku35S4Dzr16rdSqSTWUvvwEeACe8KvHJnjPg,34
|
18
18
|
beswarm/aient/aient/core/log_config.py,sha256=kz2_yJv1p-o3lUQOwA3qh-LSc3wMHv13iCQclw44W9c,274
|
19
19
|
beswarm/aient/aient/core/models.py,sha256=KMlCRLjtq1wQHZTJGqnbWhPS2cHq6eLdnk7peKDrzR8,7490
|
20
|
-
beswarm/aient/aient/core/request.py,sha256
|
21
|
-
beswarm/aient/aient/core/response.py,sha256=
|
22
|
-
beswarm/aient/aient/core/utils.py,sha256=
|
20
|
+
beswarm/aient/aient/core/request.py,sha256=-KEBd4jWLVC9QYUhb1ZfgkLf4nKE7HKL0A58iULkY7o,76757
|
21
|
+
beswarm/aient/aient/core/response.py,sha256=Z9geTfh2LkGHKAqjelgeleQtfOAYIyM82t9AVB4xsgE,36407
|
22
|
+
beswarm/aient/aient/core/utils.py,sha256=Z8vTH9w3uS8uubBa65c_aJ11A3OKGYEzm4q0brNZDSk,31594
|
23
23
|
beswarm/aient/aient/core/test/test_base_api.py,sha256=pWnycRJbuPSXKKU9AQjWrMAX1wiLC_014Qc9hh5C2Pw,524
|
24
24
|
beswarm/aient/aient/core/test/test_geminimask.py,sha256=HFX8jDbNg_FjjgPNxfYaR-0-roUrOO-ND-FVsuxSoiw,13254
|
25
25
|
beswarm/aient/aient/core/test/test_image.py,sha256=_T4peNGdXKBHHxyQNx12u-NTyFE8TlYI6NvvagsG2LE,319
|
26
26
|
beswarm/aient/aient/core/test/test_payload.py,sha256=8jBiJY1uidm1jzL-EiK0s6UGmW9XkdsuuKFGrwFhFkw,2755
|
27
27
|
beswarm/aient/aient/models/__init__.py,sha256=ZTiZgbfBPTjIPSKURE7t6hlFBVLRS9lluGbmqc1WjxQ,43
|
28
|
-
beswarm/aient/aient/models/audio.py,sha256=
|
29
|
-
beswarm/aient/aient/models/base.py,sha256
|
30
|
-
beswarm/aient/aient/models/chatgpt.py,sha256=
|
28
|
+
beswarm/aient/aient/models/audio.py,sha256=FNW4lxG1IhxOU7L8mvcbaeC1nXk_lpUZQlg9ijQ0h_Q,1937
|
29
|
+
beswarm/aient/aient/models/base.py,sha256=HWIGfa2A7OTccvHK0wG1-UlHB-yaWRC7hbi4oR1Mu1Y,7228
|
30
|
+
beswarm/aient/aient/models/chatgpt.py,sha256=cRz_6ocQbEoXREAlr9HteddfIRicE0c8lV_fnWhTXcA,43574
|
31
31
|
beswarm/aient/aient/plugins/__init__.py,sha256=p3KO6Aa3Lupos4i2SjzLQw1hzQTigOAfEHngsldrsyk,986
|
32
32
|
beswarm/aient/aient/plugins/arXiv.py,sha256=yHjb6PS3GUWazpOYRMKMzghKJlxnZ5TX8z9F6UtUVow,1461
|
33
33
|
beswarm/aient/aient/plugins/config.py,sha256=TGgZ5SnNKZ8MmdznrZ-TEq7s2ulhAAwTSKH89bci3dA,7079
|
34
34
|
beswarm/aient/aient/plugins/excute_command.py,sha256=b-rxsyFN6_HnZJAhUi9Qsp8iJ6XTf-zU-CIUIxeQO98,10869
|
35
35
|
beswarm/aient/aient/plugins/get_time.py,sha256=Ih5XIW5SDAIhrZ9W4Qe5Hs1k4ieKPUc_LAd6ySNyqZk,654
|
36
|
-
beswarm/aient/aient/plugins/image.py,sha256=
|
36
|
+
beswarm/aient/aient/plugins/image.py,sha256=JR4iJ--uUk1abICwQjd9tVIk0-Vs8qMxn6z2lJwuQ4U,2075
|
37
37
|
beswarm/aient/aient/plugins/list_directory.py,sha256=V_uKkLx_fQDL5z__bSDC-PqAP-o32KmQW6Pdhx0Fx0s,1433
|
38
38
|
beswarm/aient/aient/plugins/read_file.py,sha256=qHAhdesOr1VMOCDkeHNvI8UV2ZI98HmJl6GhN4Aq9dU,9183
|
39
39
|
beswarm/aient/aient/plugins/read_image.py,sha256=4FbIiMNVFUQpNyiH5ApGSRvOD9ujcXGyuqlGTJMd7ac,4017
|
@@ -43,17 +43,15 @@ beswarm/aient/aient/plugins/run_python.py,sha256=MohvdtZUTDLrHBDtJ9L2_Qu1pWAGrkb
|
|
43
43
|
beswarm/aient/aient/plugins/websearch.py,sha256=aPsBjUQ3zQ4gzNrbVq7BMh28ENj9h_fSAeJFF2h9TNk,15334
|
44
44
|
beswarm/aient/aient/plugins/write_file.py,sha256=Jt8fOEwqhYiSWpCbwfAr1xoi_BmFnx3076GMhuL06uI,3949
|
45
45
|
beswarm/aient/aient/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
46
|
-
beswarm/aient/aient/utils/prompt.py,sha256=
|
47
|
-
beswarm/aient/aient/utils/scripts.py,sha256=
|
46
|
+
beswarm/aient/aient/utils/prompt.py,sha256=ZvGAt_ImJ_CGbDnWgpsWskfSV5fCkpFKRpNQjYL7M7s,11100
|
47
|
+
beswarm/aient/aient/utils/scripts.py,sha256=Q0tS7E9AmdikO7GeDBd_3Ii5opXHCvKjDGqHsXen6_A,40622
|
48
48
|
beswarm/aient/test/test_Web_crawler.py,sha256=l-DY0xwVPBfeEitUASkcIf19b4XwGrN-Ql_p7Dsbg_A,11410
|
49
49
|
beswarm/aient/test/test_ddg_search.py,sha256=HnM72mwi4Yp87BymMmQ0eRd0-OJtyWEIUvJvN9QBhdg,1498
|
50
50
|
beswarm/aient/test/test_google_search.py,sha256=rPaKqD_N3ogHYE5DrMfRmKumcVAHKC7LcYw5euR_zGM,1035
|
51
51
|
beswarm/aient/test/test_ollama.py,sha256=ywy9l06S1g1AnWQvlBbhpac7i-hBB9bpwi-pk0Afivc,1325
|
52
52
|
beswarm/aient/test/test_plugin.py,sha256=0sBwpf1YdKba-IVPZwBMKbLR7buHfudLS9NOETm7BTc,779
|
53
|
-
beswarm/aient/test/test_search.py,sha256=-SRNOo2PvAAVmqIASFVq8WYmXqjLRonmHVEcBZkJAek,1171
|
54
53
|
beswarm/aient/test/test_url.py,sha256=ASE3kT2-ooaX6Flw4botjXnuqaBgutqRWPx3fow5nLg,1894
|
55
|
-
beswarm/aient/test/test_whisper.py,sha256=
|
56
|
-
beswarm/aient/test/test_yjh.py,sha256=MsHuBLNOqi3fyX-uboBKmTevkZW_KVv12p-pkF5ir3Y,787
|
54
|
+
beswarm/aient/test/test_whisper.py,sha256=f1Crge_EfKW3OpaCqfHApYGUtPFlFkxQTzqtJuM6MVo,379
|
57
55
|
beswarm/bemcp/bemcp/__init__.py,sha256=Ss6bDXiZJgVIZS6KWytcGwXmIFu7SsagIXa5NpeWJ7c,140
|
58
56
|
beswarm/bemcp/bemcp/decorator.py,sha256=23bNgwLjuUkpod5VcRv-UqlJTf91_wfztf8ls7-Gg08,3218
|
59
57
|
beswarm/bemcp/bemcp/main.py,sha256=gtl3oyjAM_rwFw3kR-m-cUpS0FFTASnUOB8-fMrVT7g,8608
|
@@ -123,8 +121,8 @@ beswarm/tools/search_web.py,sha256=0fTeczXiOX_LJQGaLEGbuJtIPzofeuquGWEt3yDMtVw,1
|
|
123
121
|
beswarm/tools/subtasks.py,sha256=NHDnmUhUPgDQKBACnpgErpFJRcsH0w_Q9VsyQjNvNHA,12658
|
124
122
|
beswarm/tools/worker.py,sha256=mQ1qdrQ8MgL99byAbTvxfEByFFGN9mty3UHqHjARMQ8,2331
|
125
123
|
beswarm/tools/write_csv.py,sha256=u0Hq18Ksfheb52MVtyLNCnSDHibITpsYBPs2ub7USYA,1466
|
126
|
-
beswarm-0.3.
|
127
|
-
beswarm-0.3.
|
128
|
-
beswarm-0.3.
|
129
|
-
beswarm-0.3.
|
130
|
-
beswarm-0.3.
|
124
|
+
beswarm-0.3.3.dist-info/METADATA,sha256=hOAbWEDzDcl3ihVRJam3X0Tkbt91fsK-Nitu3JPceKA,3877
|
125
|
+
beswarm-0.3.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
126
|
+
beswarm-0.3.3.dist-info/entry_points.txt,sha256=URK7Y4PDzBgxIecQnxsWTu4O-eaFa1CoAcNTWh5R7LM,45
|
127
|
+
beswarm-0.3.3.dist-info/top_level.txt,sha256=pJw4O87wvt5882smuSO6DfByJz7FJ8SxxT8h9fHCmpo,8
|
128
|
+
beswarm-0.3.3.dist-info/RECORD,,
|
@@ -1,18 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
from aient.models import chatgpt
|
3
|
-
|
4
|
-
API = os.environ.get('API', None)
|
5
|
-
API_URL = os.environ.get('API_URL', None)
|
6
|
-
GPT_ENGINE = os.environ.get('GPT_ENGINE', 'gpt-4o')
|
7
|
-
|
8
|
-
systemprompt = (
|
9
|
-
"You are ChatGPT, a large language model trained by OpenAI. Respond conversationally"
|
10
|
-
)
|
11
|
-
bot = chatgpt(api_key=API, api_url=API_URL, engine=GPT_ENGINE, system_prompt=systemprompt, print_log=True)
|
12
|
-
for text in bot.ask_stream("搜索上海的天气"):
|
13
|
-
# for text in bot.ask_stream("我在广州市,想周一去香港,周四早上回来,是去游玩,请你帮我规划整个行程。包括细节,如交通,住宿,餐饮,价格,等等,最好细节到每天各个部分的时间,花费,等等,尽量具体,用户一看就能直接执行的那种"):
|
14
|
-
# for text in bot.ask_stream("上海有哪些好玩的地方?"):
|
15
|
-
# for text in bot.ask_stream("just say test"):
|
16
|
-
# for text in bot.ask_stream("我在上海想去重庆旅游,我只有2000元预算,我想在重庆玩一周,你能帮我规划一下吗?"):
|
17
|
-
# for text in bot.ask_stream("我在上海想去重庆旅游,我有一天的时间。你能帮我规划一下吗?"):
|
18
|
-
print(text, end="")
|
beswarm/aient/test/test_yjh.py
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
from datetime import datetime
|
3
|
-
|
4
|
-
from aient.models import chatgpt
|
5
|
-
from aient.utils import prompt
|
6
|
-
|
7
|
-
API = os.environ.get('API', None)
|
8
|
-
API_URL = os.environ.get('API_URL', None)
|
9
|
-
GPT_ENGINE = os.environ.get('GPT_ENGINE', 'gpt-4o')
|
10
|
-
LANGUAGE = os.environ.get('LANGUAGE', 'Simplified Chinese')
|
11
|
-
|
12
|
-
current_date = datetime.now()
|
13
|
-
Current_Date = current_date.strftime("%Y-%m-%d")
|
14
|
-
|
15
|
-
systemprompt = os.environ.get('SYSTEMPROMPT', prompt.system_prompt.format(LANGUAGE, Current_Date))
|
16
|
-
|
17
|
-
bot = chatgpt(api_key=API, api_url=API_URL, engine=GPT_ENGINE, system_prompt=systemprompt)
|
18
|
-
for text in bot.ask_stream("arXiv:2210.10716 这篇文章讲了啥"):
|
19
|
-
# for text in bot.ask_stream("今天的微博热搜有哪些?"):
|
20
|
-
# for text in bot.ask_stream("你现在是什么版本?"):
|
21
|
-
print(text, end="")
|
File without changes
|
File without changes
|
File without changes
|