pycoze 0.1.402__py3-none-any.whl → 0.1.403__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.
- pycoze/ai/__init__.py +0 -4
- pycoze/bot/chat_base.py +24 -8
- {pycoze-0.1.402.dist-info → pycoze-0.1.403.dist-info}/METADATA +1 -1
- {pycoze-0.1.402.dist-info → pycoze-0.1.403.dist-info}/RECORD +7 -8
- pycoze/ai/vram_reserve.py +0 -144
- {pycoze-0.1.402.dist-info → pycoze-0.1.403.dist-info}/LICENSE +0 -0
- {pycoze-0.1.402.dist-info → pycoze-0.1.403.dist-info}/WHEEL +0 -0
- {pycoze-0.1.402.dist-info → pycoze-0.1.403.dist-info}/top_level.txt +0 -0
pycoze/ai/__init__.py
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
from .vram_reserve import reserve_vram, reserve_vram_retry, unreserve_vram
|
2
1
|
from .llm import (
|
3
2
|
chat,
|
4
3
|
chat_stream,
|
@@ -11,9 +10,6 @@ from .llm import (
|
|
11
10
|
)
|
12
11
|
|
13
12
|
__all__ = [
|
14
|
-
reserve_vram,
|
15
|
-
reserve_vram_retry,
|
16
|
-
unreserve_vram,
|
17
13
|
chat,
|
18
14
|
chat_stream,
|
19
15
|
chat_async,
|
pycoze/bot/chat_base.py
CHANGED
@@ -86,6 +86,8 @@ def dumps_markdown_json(data):
|
|
86
86
|
|
87
87
|
|
88
88
|
|
89
|
+
import re
|
90
|
+
|
89
91
|
async def stream_openai_response(conversation_history, start_new_stream):
|
90
92
|
"""
|
91
93
|
异步流式传输 OpenAI 聊天完成响应并处理结构化输出
|
@@ -118,24 +120,38 @@ async def stream_openai_response(conversation_history, start_new_stream):
|
|
118
120
|
if start_new_stream["value"]:
|
119
121
|
break # 退出当前的 async for 循环,进入下一次 while 循环
|
120
122
|
|
121
|
-
# 处理 buffer
|
122
|
-
while
|
123
|
-
line, buffer = buffer.split("\n", 1)
|
123
|
+
# 处理 buffer 中的内容
|
124
|
+
while buffer:
|
124
125
|
if not in_json_block:
|
125
|
-
|
126
|
-
|
126
|
+
# 查找 JSON 代码块的起始标记
|
127
|
+
json_start_match = re.search(r"```json", buffer, re.IGNORECASE)
|
128
|
+
if json_start_match:
|
129
|
+
# 提取 JSON 代码块之前的文本
|
130
|
+
text_content += buffer[:json_start_match.start()]
|
131
|
+
if text_content.strip():
|
127
132
|
yield ("text", text_content.strip())
|
128
133
|
text_content = ""
|
134
|
+
# 进入 JSON 代码块模式
|
129
135
|
in_json_block = True
|
136
|
+
buffer = buffer[json_start_match.end():]
|
130
137
|
else:
|
131
|
-
|
138
|
+
# 如果没有找到 JSON 代码块,直接处理为普通文本
|
139
|
+
text_content += buffer
|
140
|
+
buffer = ""
|
132
141
|
else:
|
133
|
-
|
142
|
+
# 查找 JSON 代码块的结束标记
|
143
|
+
json_end_match = re.search(r"```", buffer)
|
144
|
+
if json_end_match:
|
145
|
+
# 提取 JSON 代码块内容
|
146
|
+
json_block_content += buffer[:json_end_match.start()]
|
134
147
|
yield ("json", json_block_content.strip())
|
135
148
|
json_block_content = ""
|
136
149
|
in_json_block = False
|
150
|
+
buffer = buffer[json_end_match.end():]
|
137
151
|
else:
|
138
|
-
|
152
|
+
# 如果没有找到结束标记,继续累积 JSON 内容
|
153
|
+
json_block_content += buffer
|
154
|
+
buffer = ""
|
139
155
|
|
140
156
|
# 如果流正常结束,退出 while 循环
|
141
157
|
break
|
@@ -1,6 +1,5 @@
|
|
1
1
|
pycoze/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
pycoze/ai/__init__.py,sha256=
|
3
|
-
pycoze/ai/vram_reserve.py,sha256=DRxKzqf89fLAts0DzU8e19z9kecIF8OdMkQnJlCKZV0,4244
|
2
|
+
pycoze/ai/__init__.py,sha256=e8cRzp4bLXILIUVtOPqwpiV-szD2eKtaWIodYIuw-7s,312
|
4
3
|
pycoze/ai/llm/__init__.py,sha256=7qmligvCSneLx5AFCjKYfGURIiI4KlB4hE19SxIr-Xk,342
|
5
4
|
pycoze/ai/llm/chat.py,sha256=sQZT0ImvRW81fXdlKG0ZrHdDB8g5M4iudaWdG4Kpd6Q,6373
|
6
5
|
pycoze/ai/llm/text_to_image_prompt.py,sha256=0bx2C_YRvjAo7iphHGp1-pmGKsKqwur7dM0t3SiA8kA,3398
|
@@ -12,7 +11,7 @@ pycoze/api/lib/web.py,sha256=GWgtiTJOolKOX2drXcwuyqTcbo5FQVxa1NuBGcNyjyc,223
|
|
12
11
|
pycoze/api/lib/window.py,sha256=dkzWfLwn5pE_L0DfQ38K8nx9tQyT5KO-GYyXi0rytFc,2073
|
13
12
|
pycoze/bot/__init__.py,sha256=rL3Q-ycczRpSFfKn84fg3QBl5k22WpyeIU5qOEjEby8,79
|
14
13
|
pycoze/bot/chat.py,sha256=qEuMxH0cVFU9QSU36FrOsjhRAxtsvOv7CQtuXvM3F6Y,6446
|
15
|
-
pycoze/bot/chat_base.py,sha256=
|
14
|
+
pycoze/bot/chat_base.py,sha256=d9obNsYR0RRSILGy0m2lrKKzSJzy_NFI0fvjkxDyVkw,11209
|
16
15
|
pycoze/bot/lib.py,sha256=_bQ52mKsWgFGAogFHnmRBJbvK_tPOwsAJ8NqJNMR5K4,7210
|
17
16
|
pycoze/bot/message.py,sha256=udnIi-h4QgGzkbr_5VcAsVGjoLp9wXJSfBCeuOz7_Bk,802
|
18
17
|
pycoze/bot/prompt.md,sha256=t7NQdiiNe-jCDVfeVbvTPfq5WK5nF8CxFUQUFMyXJlo,13880
|
@@ -32,8 +31,8 @@ pycoze/utils/arg.py,sha256=jop1tBfe5hYkHW1NSpCeaZBEznkgguBscj_7M2dWfrs,503
|
|
32
31
|
pycoze/utils/env.py,sha256=5pWlXfM1F5ZU9hhv1rHlDEanjEW5wf0nbyez9bNRqqA,559
|
33
32
|
pycoze/utils/socket.py,sha256=bZbFFRH4mfThzRqt55BAAGQ6eICx_ja4x8UGGrUdAm8,2428
|
34
33
|
pycoze/utils/text_or_file.py,sha256=gpxZVWt2DW6YiEg_MnMuwg36VNf3TX383QD_1oZNB0Y,551
|
35
|
-
pycoze-0.1.
|
36
|
-
pycoze-0.1.
|
37
|
-
pycoze-0.1.
|
38
|
-
pycoze-0.1.
|
39
|
-
pycoze-0.1.
|
34
|
+
pycoze-0.1.403.dist-info/LICENSE,sha256=QStd_Qsd0-kAam_-sOesCIp_uKrGWeoKwt9M49NVkNU,1090
|
35
|
+
pycoze-0.1.403.dist-info/METADATA,sha256=oPdn1ujLGfPS5rhAADa_mOOngNcVlVybdrZwDVAsO4A,854
|
36
|
+
pycoze-0.1.403.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
37
|
+
pycoze-0.1.403.dist-info/top_level.txt,sha256=76dPeDhKvOCleL3ZC5gl1-y4vdS1tT_U1hxWVAn7sFo,7
|
38
|
+
pycoze-0.1.403.dist-info/RECORD,,
|
pycoze/ai/vram_reserve.py
DELETED
@@ -1,144 +0,0 @@
|
|
1
|
-
import subprocess
|
2
|
-
import sqlite3
|
3
|
-
import atexit
|
4
|
-
import time
|
5
|
-
import os
|
6
|
-
import psutil
|
7
|
-
import sys
|
8
|
-
from pycoze import utils
|
9
|
-
|
10
|
-
# 定义数据库连接和初始化
|
11
|
-
params = utils.params
|
12
|
-
if params:
|
13
|
-
DATABASE_PATH = params["appPath"] + "/vram_usage.db"
|
14
|
-
else:
|
15
|
-
DATABASE_DIR = os.path.expanduser("~/pycoze")
|
16
|
-
os.makedirs(DATABASE_DIR, exist_ok=True)
|
17
|
-
DATABASE_PATH = os.path.join(DATABASE_DIR, "vram_usage.db")
|
18
|
-
|
19
|
-
TABLE_NAME = "vram_usage"
|
20
|
-
|
21
|
-
|
22
|
-
def initialize_db():
|
23
|
-
conn = sqlite3.connect(DATABASE_PATH)
|
24
|
-
cursor = conn.cursor()
|
25
|
-
cursor.execute(
|
26
|
-
f"""
|
27
|
-
CREATE TABLE IF NOT EXISTS {TABLE_NAME} (
|
28
|
-
id INTEGER PRIMARY KEY,
|
29
|
-
uid TEXT NOT NULL,
|
30
|
-
reserved_gb REAL NOT NULL
|
31
|
-
)
|
32
|
-
"""
|
33
|
-
)
|
34
|
-
conn.commit()
|
35
|
-
conn.close()
|
36
|
-
|
37
|
-
|
38
|
-
def get_vram_resources():
|
39
|
-
try:
|
40
|
-
# 使用nvidia-smi命令获取VRAM信息
|
41
|
-
result = subprocess.run(
|
42
|
-
["nvidia-smi", "--query-gpu=memory.total", "--format=csv,noheader,nounits"],
|
43
|
-
stdout=subprocess.PIPE,
|
44
|
-
text=True,
|
45
|
-
)
|
46
|
-
total_memory_list = result.stdout.strip().split("\n")
|
47
|
-
total_memory = 0
|
48
|
-
for mem in total_memory_list:
|
49
|
-
try:
|
50
|
-
total_memory += float(mem)
|
51
|
-
except:
|
52
|
-
pass
|
53
|
-
return round(total_memory / 1024, 2)
|
54
|
-
except Exception as e:
|
55
|
-
print(f"Error getting VRAM resources: {e}")
|
56
|
-
return 0.0
|
57
|
-
|
58
|
-
|
59
|
-
def reserve_vram(gb, uid=None):
|
60
|
-
if uid is None:
|
61
|
-
uid = f"pid:{os.getpid()}"
|
62
|
-
with sqlite3.connect(DATABASE_PATH) as conn:
|
63
|
-
cursor = conn.cursor()
|
64
|
-
cursor.execute(f"SELECT SUM(reserved_gb) FROM {TABLE_NAME}")
|
65
|
-
total_reserved = cursor.fetchone()[0]
|
66
|
-
if total_reserved is None:
|
67
|
-
total_reserved = 0.0
|
68
|
-
available_gb = get_vram_resources() - total_reserved
|
69
|
-
if available_gb >= gb:
|
70
|
-
cursor.execute(
|
71
|
-
f"INSERT INTO {TABLE_NAME} (uid, reserved_gb) VALUES (?, ?)",
|
72
|
-
(uid, gb),
|
73
|
-
)
|
74
|
-
conn.commit()
|
75
|
-
print(f"预留成功,剩余VRAM大小: {available_gb - gb} GB")
|
76
|
-
return True
|
77
|
-
else:
|
78
|
-
print(f"预留失败,剩余VRAM大小: {available_gb} GB")
|
79
|
-
return False
|
80
|
-
|
81
|
-
|
82
|
-
def reserve_vram_retry(gb, retry=None, uid=None):
|
83
|
-
if retry is None:
|
84
|
-
# 接近无限重试,python中允许无限大的整数,尽管sys.maxsize不是真正的无限大,但足够大
|
85
|
-
retry = sys.maxsize
|
86
|
-
for i in range(retry):
|
87
|
-
time.sleep(1)
|
88
|
-
if i % 10 == 0 or i < 10 and i != 0:
|
89
|
-
print(f"重试第{i}次")
|
90
|
-
if reserve_vram(gb, uid):
|
91
|
-
return True
|
92
|
-
return False
|
93
|
-
|
94
|
-
|
95
|
-
def unreserve_vram(uid=None):
|
96
|
-
if uid is None:
|
97
|
-
uid = f"pid:{os.getpid()}"
|
98
|
-
with sqlite3.connect(DATABASE_PATH) as conn:
|
99
|
-
cursor = conn.cursor()
|
100
|
-
cursor.execute(f"DELETE FROM {TABLE_NAME} WHERE uid = ?", (uid,))
|
101
|
-
conn.commit()
|
102
|
-
|
103
|
-
|
104
|
-
# 注册退出时的清理函数
|
105
|
-
def cleanup():
|
106
|
-
unreserve_vram()
|
107
|
-
|
108
|
-
|
109
|
-
def initialize_and_check():
|
110
|
-
initialize_db()
|
111
|
-
with sqlite3.connect(DATABASE_PATH) as conn:
|
112
|
-
cursor = conn.cursor()
|
113
|
-
cursor.execute(f"SELECT uid, reserved_gb FROM {TABLE_NAME}")
|
114
|
-
rows = cursor.fetchall()
|
115
|
-
for row in rows:
|
116
|
-
uid, reserved_gb = row
|
117
|
-
try:
|
118
|
-
# 检查进程是否存在
|
119
|
-
if uid.startswith("pid:"):
|
120
|
-
pid = int(uid.split(":")[1])
|
121
|
-
psutil.Process(pid)
|
122
|
-
except psutil.NoSuchProcess:
|
123
|
-
# 进程不存在,删除对应的记录
|
124
|
-
cursor.execute(f"DELETE FROM {TABLE_NAME} WHERE uid = ?", (uid,))
|
125
|
-
print(f"进程 {uid} 不存在,已删除对应的预留记录")
|
126
|
-
conn.commit()
|
127
|
-
|
128
|
-
|
129
|
-
# 在模块加载时执行初始化检查
|
130
|
-
initialize_and_check()
|
131
|
-
|
132
|
-
# 注册清理函数
|
133
|
-
atexit.register(cleanup)
|
134
|
-
|
135
|
-
if __name__ == "__main__":
|
136
|
-
if reserve_vram_retry(5):
|
137
|
-
print("(1)VRAM资源预留成功")
|
138
|
-
if reserve_vram_retry(5):
|
139
|
-
print("(2)VRAM资源预留成功")
|
140
|
-
time.sleep(100)
|
141
|
-
release_vram()
|
142
|
-
print("VRAM资源释放成功")
|
143
|
-
else:
|
144
|
-
print("VRAM资源不足,无法预留")
|
File without changes
|
File without changes
|
File without changes
|