jarvis-ai-assistant 0.1.209__py3-none-any.whl → 0.1.211__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.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_code_agent/code_agent.py +2 -0
- jarvis/jarvis_data/tiktoken/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +100256 -0
- jarvis/jarvis_platform/human.py +11 -3
- jarvis/jarvis_platform/tongyi.py +77 -72
- jarvis/jarvis_platform/yuanbao.py +54 -51
- jarvis/jarvis_utils/embedding.py +8 -0
- jarvis/jarvis_utils/git_utils.py +23 -2
- jarvis/jarvis_utils/http.py +108 -43
- jarvis/jarvis_utils/utils.py +1 -21
- {jarvis_ai_assistant-0.1.209.dist-info → jarvis_ai_assistant-0.1.211.dist-info}/METADATA +2 -1
- {jarvis_ai_assistant-0.1.209.dist-info → jarvis_ai_assistant-0.1.211.dist-info}/RECORD +16 -15
- {jarvis_ai_assistant-0.1.209.dist-info → jarvis_ai_assistant-0.1.211.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.209.dist-info → jarvis_ai_assistant-0.1.211.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.209.dist-info → jarvis_ai_assistant-0.1.211.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.209.dist-info → jarvis_ai_assistant-0.1.211.dist-info}/top_level.txt +0 -0
jarvis/jarvis_platform/human.py
CHANGED
@@ -52,12 +52,20 @@ class HumanPlatform(BasePlatform):
|
|
52
52
|
session_info = f"(会话ID: {self.conversation_id})"
|
53
53
|
|
54
54
|
if self.system_message and self.first_message:
|
55
|
-
prompt = f"{self.system_message}\n\n{message} {session_info}
|
55
|
+
prompt = f"{self.system_message}\n\n{message} {session_info}"
|
56
56
|
self.first_message = False
|
57
57
|
else:
|
58
|
-
prompt = f"{message} {session_info}
|
58
|
+
prompt = f"{message} {session_info}"
|
59
59
|
|
60
|
-
|
60
|
+
# 将prompt复制到剪贴板
|
61
|
+
import subprocess
|
62
|
+
try:
|
63
|
+
subprocess.run(['xsel', '-ib'], input=prompt.encode('utf-8'), check=True)
|
64
|
+
PrettyOutput.print("提示已复制到剪贴板", OutputType.INFO)
|
65
|
+
except subprocess.CalledProcessError as e:
|
66
|
+
PrettyOutput.print(f"无法复制到剪贴板: {e}", OutputType.WARNING)
|
67
|
+
|
68
|
+
response = get_multiline_input(prompt + "\n\n请回复:")
|
61
69
|
yield response
|
62
70
|
return None
|
63
71
|
|
jarvis/jarvis_platform/tongyi.py
CHANGED
@@ -159,88 +159,93 @@ class TongyiPlatform(BasePlatform):
|
|
159
159
|
}
|
160
160
|
|
161
161
|
try:
|
162
|
-
|
163
|
-
|
162
|
+
# 使用新的stream_post接口发送消息请求,获取流式响应
|
163
|
+
response_stream = while_success(
|
164
|
+
lambda: http.stream_post(url, headers=headers, json=payload),
|
164
165
|
sleep_time=5,
|
165
166
|
)
|
166
|
-
|
167
|
-
raise Exception(f"HTTP {response.status_code}: {response.text}")
|
167
|
+
|
168
168
|
msg_id = ""
|
169
169
|
session_id = ""
|
170
170
|
thinking_content = ""
|
171
171
|
text_content = ""
|
172
172
|
in_thinking = False
|
173
|
-
|
174
|
-
if not line:
|
175
|
-
continue
|
173
|
+
response_data = b""
|
176
174
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
else:
|
181
|
-
line_str = str(line)
|
182
|
-
|
183
|
-
if not line_str.startswith("data: "):
|
184
|
-
continue
|
175
|
+
# 处理流式响应
|
176
|
+
for chunk in response_stream:
|
177
|
+
response_data += chunk
|
185
178
|
|
179
|
+
# 尝试解析SSE格式的数据
|
186
180
|
try:
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
if
|
201
|
-
|
202
|
-
|
203
|
-
]
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
181
|
+
# 查找完整的数据行
|
182
|
+
lines = response_data.decode("utf-8").split("\n")
|
183
|
+
response_data = b"" # 重置缓冲区
|
184
|
+
|
185
|
+
for line in lines:
|
186
|
+
if not line.strip():
|
187
|
+
continue
|
188
|
+
|
189
|
+
# SSE格式的行通常以"data: "开头
|
190
|
+
if line.startswith("data: "):
|
191
|
+
try:
|
192
|
+
data = json.loads(line[6:])
|
193
|
+
# 记录消息ID和会话ID
|
194
|
+
if "msgId" in data:
|
195
|
+
msg_id = data["msgId"]
|
196
|
+
if "sessionId" in data:
|
197
|
+
session_id = data["sessionId"]
|
198
|
+
|
199
|
+
if "contents" in data and len(data["contents"]) > 0:
|
200
|
+
for content in data["contents"]:
|
201
|
+
if content.get("contentType") == "think":
|
202
|
+
if not in_thinking:
|
203
|
+
yield "<think>\n\n"
|
204
|
+
in_thinking = True
|
205
|
+
if content.get("incremental"):
|
206
|
+
tmp_content = json.loads(
|
207
|
+
content.get("content")
|
208
|
+
)["content"]
|
209
|
+
thinking_content += tmp_content
|
210
|
+
yield tmp_content
|
211
|
+
else:
|
212
|
+
tmp_content = json.loads(
|
213
|
+
content.get("content")
|
214
|
+
)["content"]
|
215
|
+
if len(thinking_content) < len(
|
216
|
+
tmp_content
|
217
|
+
):
|
218
|
+
yield tmp_content[
|
219
|
+
len(thinking_content) :
|
220
|
+
]
|
221
|
+
thinking_content = tmp_content
|
222
|
+
else:
|
223
|
+
yield "\r\n</think>\n"[
|
224
|
+
len(thinking_content)
|
225
|
+
- len(tmp_content) :
|
226
|
+
]
|
227
|
+
thinking_content = tmp_content
|
228
|
+
in_thinking = False
|
229
|
+
elif content.get("contentType") == "text":
|
230
|
+
if in_thinking:
|
231
|
+
continue
|
232
|
+
if content.get("incremental"):
|
233
|
+
tmp_content = content.get("content")
|
234
|
+
text_content += tmp_content
|
235
|
+
yield tmp_content
|
236
|
+
else:
|
237
|
+
tmp_content = content.get("content")
|
238
|
+
if len(text_content) < len(tmp_content):
|
239
|
+
yield tmp_content[
|
240
|
+
len(text_content) :
|
241
|
+
]
|
242
|
+
text_content = tmp_content
|
243
|
+
|
244
|
+
except json.JSONDecodeError:
|
245
|
+
continue
|
246
|
+
|
247
|
+
except UnicodeDecodeError:
|
248
|
+
# 如果解码失败,继续累积数据
|
244
249
|
continue
|
245
250
|
|
246
251
|
self.msg_id = msg_id
|
@@ -468,63 +468,66 @@ class YuanbaoPlatform(BasePlatform):
|
|
468
468
|
payload["displayPrompt"] = payload["prompt"]
|
469
469
|
|
470
470
|
try:
|
471
|
-
#
|
472
|
-
|
473
|
-
lambda: http.
|
474
|
-
url,
|
475
|
-
headers=headers,
|
476
|
-
json=payload,
|
477
|
-
stream=True,
|
478
|
-
),
|
471
|
+
# 使用新的stream_post接口发送消息请求,获取流式响应
|
472
|
+
response_stream = while_success(
|
473
|
+
lambda: http.stream_post(url, headers=headers, json=payload),
|
479
474
|
sleep_time=5,
|
480
475
|
)
|
481
476
|
|
482
|
-
# 检查响应状态
|
483
|
-
if response.status_code != 200:
|
484
|
-
error_msg = f"发送消息失败,状态码: {response.status_code}"
|
485
|
-
if hasattr(response, "text"):
|
486
|
-
error_msg += f", 响应: {response.text}"
|
487
|
-
raise Exception(error_msg)
|
488
|
-
|
489
477
|
in_thinking = False
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
478
|
+
response_data = b""
|
479
|
+
|
480
|
+
# 处理流式响应
|
481
|
+
for chunk in response_stream:
|
482
|
+
response_data += chunk
|
483
|
+
|
484
|
+
# 尝试解析SSE格式的数据
|
485
|
+
try:
|
486
|
+
# 查找完整的数据行
|
487
|
+
lines = response_data.decode("utf-8").split("\n")
|
488
|
+
response_data = b"" # 重置缓冲区
|
489
|
+
|
490
|
+
for line in lines:
|
491
|
+
if not line.strip():
|
492
|
+
continue
|
493
|
+
|
494
|
+
# SSE格式的行通常以"data: "开头
|
495
|
+
if line.startswith("data: "):
|
496
|
+
try:
|
497
|
+
data_str = line[6:] # 移除"data: "前缀
|
498
|
+
|
499
|
+
# 检查结束标志
|
500
|
+
if data_str == "[DONE]":
|
501
|
+
self.first_chat = False
|
502
|
+
return None
|
503
|
+
|
504
|
+
data = json.loads(data_str)
|
505
|
+
|
506
|
+
# 处理文本类型的消息
|
507
|
+
if data.get("type") == "text":
|
508
|
+
if in_thinking:
|
509
|
+
yield "</think>\n"
|
510
|
+
in_thinking = False
|
511
|
+
msg = data.get("msg", "")
|
512
|
+
if msg:
|
513
|
+
yield msg
|
514
|
+
|
515
|
+
# 处理思考中的消息
|
516
|
+
elif data.get("type") == "think":
|
517
|
+
if not in_thinking:
|
518
|
+
yield "<think>\n"
|
519
|
+
in_thinking = True
|
520
|
+
think_content = data.get("content", "")
|
521
|
+
if think_content:
|
522
|
+
yield think_content
|
523
|
+
|
524
|
+
except json.JSONDecodeError:
|
525
|
+
pass
|
526
|
+
|
527
|
+
except UnicodeDecodeError:
|
528
|
+
# 如果解码失败,继续累积数据
|
494
529
|
continue
|
495
530
|
|
496
|
-
line_str = line.decode("utf-8")
|
497
|
-
|
498
|
-
# SSE格式的行通常以"data: "开头
|
499
|
-
if line_str.startswith("data: "):
|
500
|
-
try:
|
501
|
-
data_str = line_str[6:] # 移除"data: "前缀
|
502
|
-
data = json.loads(data_str)
|
503
|
-
|
504
|
-
# 处理文本类型的消息
|
505
|
-
if data.get("type") == "text":
|
506
|
-
if in_thinking:
|
507
|
-
yield "</think>\n"
|
508
|
-
in_thinking = False
|
509
|
-
msg = data.get("msg", "")
|
510
|
-
if msg:
|
511
|
-
yield msg
|
512
|
-
|
513
|
-
# 处理思考中的消息
|
514
|
-
elif data.get("type") == "think":
|
515
|
-
if not in_thinking:
|
516
|
-
yield "<think>\n"
|
517
|
-
in_thinking = True
|
518
|
-
think_content = data.get("content", "")
|
519
|
-
if think_content:
|
520
|
-
yield think_content
|
521
|
-
|
522
|
-
except json.JSONDecodeError:
|
523
|
-
pass
|
524
|
-
|
525
|
-
# 检测结束标志
|
526
|
-
elif line_str == "data: [DONE]":
|
527
|
-
return None
|
528
531
|
self.first_chat = False
|
529
532
|
return None
|
530
533
|
|
jarvis/jarvis_utils/embedding.py
CHANGED
@@ -1,8 +1,16 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
+
import os
|
3
|
+
from pathlib import Path
|
2
4
|
from typing import List
|
3
5
|
|
4
6
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
5
7
|
|
8
|
+
# 设置tiktoken缓存目录
|
9
|
+
script_dir = Path(__file__).parent
|
10
|
+
tiktoken_cache_dir = script_dir / "../jarvis_data/tiktoken"
|
11
|
+
os.makedirs(tiktoken_cache_dir, exist_ok=True)
|
12
|
+
os.environ["TIKTOKEN_CACHE_DIR"] = str(tiktoken_cache_dir.absolute())
|
13
|
+
|
6
14
|
|
7
15
|
def get_context_token_count(text: str) -> int:
|
8
16
|
"""使用tiktoken获取文本的token数量。
|
jarvis/jarvis_utils/git_utils.py
CHANGED
@@ -9,6 +9,7 @@ Git工具模块
|
|
9
9
|
- 获取最新提交的哈希值
|
10
10
|
- 从Git差异中提取修改的行范围
|
11
11
|
"""
|
12
|
+
import datetime
|
12
13
|
import os
|
13
14
|
import re
|
14
15
|
import subprocess
|
@@ -344,6 +345,19 @@ def check_and_update_git_repo(repo_path: str) -> bool:
|
|
344
345
|
return False
|
345
346
|
|
346
347
|
try:
|
348
|
+
# 检查最新提交时间是否为今天
|
349
|
+
commit_date_result = subprocess.run(
|
350
|
+
["git", "log", "-1", "--format=%cd", "--date=short"],
|
351
|
+
cwd=git_root,
|
352
|
+
capture_output=True,
|
353
|
+
text=True,
|
354
|
+
)
|
355
|
+
if commit_date_result.returncode == 0:
|
356
|
+
commit_date = commit_date_result.stdout.strip()
|
357
|
+
today = datetime.date.today().strftime("%Y-%m-%d")
|
358
|
+
if commit_date == today:
|
359
|
+
return False
|
360
|
+
|
347
361
|
# 检查是否有未提交的修改
|
348
362
|
if has_uncommitted_changes():
|
349
363
|
return False
|
@@ -499,9 +513,16 @@ def get_recent_commits_with_files() -> List[Dict[str, Any]]:
|
|
499
513
|
失败时返回空列表
|
500
514
|
"""
|
501
515
|
try:
|
502
|
-
#
|
516
|
+
# 获取当前git用户名
|
517
|
+
current_author = subprocess.run(
|
518
|
+
["git", "config", "user.name"],
|
519
|
+
capture_output=True,
|
520
|
+
text=True,
|
521
|
+
).stdout.strip()
|
522
|
+
|
523
|
+
# 获取当前用户最近5次提交的基本信息
|
503
524
|
result = subprocess.run(
|
504
|
-
["git", "log", "-5", "--pretty=format:%H%n%s%n%an%n%ad"],
|
525
|
+
["git", "log", "-5", "--author=" + current_author, "--pretty=format:%H%n%s%n%an%n%ad"],
|
505
526
|
capture_output=True,
|
506
527
|
text=True,
|
507
528
|
)
|
jarvis/jarvis_utils/http.py
CHANGED
@@ -1,104 +1,169 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
|
-
import
|
4
|
-
from typing import Any, Dict, Optional, Union
|
3
|
+
import httpx
|
4
|
+
from typing import Any, Dict, Optional, Union, AsyncGenerator, Generator
|
5
5
|
|
6
6
|
|
7
|
-
def
|
7
|
+
def get_httpx_client() -> httpx.Client:
|
8
8
|
"""
|
9
|
-
|
9
|
+
获取一个配置好的 httpx.Client 对象
|
10
10
|
|
11
11
|
返回:
|
12
|
-
|
12
|
+
httpx.Client 对象
|
13
13
|
"""
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
client = httpx.Client(
|
15
|
+
timeout=httpx.Timeout(None), # 永不超时
|
16
|
+
headers={
|
17
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36",
|
18
|
+
},
|
19
19
|
)
|
20
|
+
return client
|
21
|
+
|
22
|
+
|
23
|
+
def get_async_httpx_client() -> httpx.AsyncClient:
|
24
|
+
"""
|
25
|
+
获取一个配置好的 httpx.AsyncClient 对象
|
20
26
|
|
21
|
-
|
27
|
+
返回:
|
28
|
+
httpx.AsyncClient 对象
|
29
|
+
"""
|
30
|
+
client = httpx.AsyncClient(
|
31
|
+
timeout=httpx.Timeout(None), # 永不超时
|
32
|
+
headers={
|
33
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36",
|
34
|
+
},
|
35
|
+
)
|
36
|
+
return client
|
22
37
|
|
23
38
|
|
24
|
-
# 增强版本的 HTTP
|
39
|
+
# 增强版本的 HTTP 请求方法(使用 httpx 实现,带重试机制,解决连接中断问题)
|
25
40
|
def post(
|
26
41
|
url: str,
|
27
|
-
data: Optional[
|
42
|
+
data: Optional[Any] = None,
|
28
43
|
json: Optional[Dict[str, Any]] = None,
|
29
44
|
**kwargs,
|
30
|
-
) ->
|
45
|
+
) -> httpx.Response:
|
31
46
|
"""
|
32
|
-
发送增强版永不超时的 POST
|
47
|
+
发送增强版永不超时的 POST 请求,使用 httpx 实现,包含重试机制
|
33
48
|
|
34
49
|
参数:
|
35
50
|
url: 请求的 URL
|
36
51
|
data: (可选) 请求体数据 (表单数据或原始数据)
|
37
52
|
json: (可选) JSON 数据,会自动设置 Content-Type
|
38
|
-
**kwargs: 其他传递给
|
53
|
+
**kwargs: 其他传递给 httpx.post 的参数
|
39
54
|
|
40
55
|
返回:
|
41
|
-
|
56
|
+
httpx.Response 对象
|
42
57
|
|
43
58
|
注意:
|
44
|
-
|
59
|
+
此方法使用 httpx 实现,包含自动重试机制,适用于解决"Response ended prematurely"等连接问题
|
45
60
|
"""
|
46
|
-
|
47
|
-
|
61
|
+
client = get_httpx_client()
|
62
|
+
try:
|
63
|
+
response = client.post(url=url, data=data, json=json, **kwargs)
|
64
|
+
response.raise_for_status()
|
65
|
+
return response
|
66
|
+
finally:
|
67
|
+
client.close()
|
48
68
|
|
49
69
|
|
50
|
-
def get(url: str, **kwargs) ->
|
70
|
+
def get(url: str, **kwargs) -> httpx.Response:
|
51
71
|
"""
|
52
|
-
发送增强版永不超时的 GET
|
72
|
+
发送增强版永不超时的 GET 请求,使用 httpx 实现,包含重试机制
|
53
73
|
|
54
74
|
参数:
|
55
75
|
url: 请求的 URL
|
56
|
-
**kwargs: 其他传递给
|
76
|
+
**kwargs: 其他传递给 httpx.get 的参数
|
57
77
|
|
58
78
|
返回:
|
59
|
-
|
79
|
+
httpx.Response 对象
|
60
80
|
|
61
81
|
注意:
|
62
|
-
|
82
|
+
此方法使用 httpx 实现,包含自动重试机制,适用于解决"Response ended prematurely"等连接问题
|
63
83
|
"""
|
64
|
-
|
65
|
-
|
84
|
+
client = get_httpx_client()
|
85
|
+
try:
|
86
|
+
response = client.get(url=url, **kwargs)
|
87
|
+
response.raise_for_status()
|
88
|
+
return response
|
89
|
+
finally:
|
90
|
+
client.close()
|
66
91
|
|
67
92
|
|
68
|
-
def put(
|
69
|
-
url: str, data: Optional[Union[Dict[str, Any], str, bytes]] = None, **kwargs
|
70
|
-
) -> requests.Response:
|
93
|
+
def put(url: str, data: Optional[Any] = None, **kwargs) -> httpx.Response:
|
71
94
|
"""
|
72
|
-
发送增强版永不超时的 PUT
|
95
|
+
发送增强版永不超时的 PUT 请求,使用 httpx 实现,包含重试机制
|
73
96
|
|
74
97
|
参数:
|
75
98
|
url: 请求的 URL
|
76
99
|
data: (可选) 请求体数据 (表单数据或原始数据)
|
77
|
-
**kwargs: 其他传递给
|
100
|
+
**kwargs: 其他传递给 httpx.put 的参数
|
78
101
|
|
79
102
|
返回:
|
80
|
-
|
103
|
+
httpx.Response 对象
|
81
104
|
|
82
105
|
注意:
|
83
|
-
|
106
|
+
此方法使用 httpx 实现,包含自动重试机制,适用于解决"Response ended prematurely"等连接问题
|
84
107
|
"""
|
85
|
-
|
86
|
-
|
108
|
+
client = get_httpx_client()
|
109
|
+
try:
|
110
|
+
response = client.put(url=url, data=data, **kwargs)
|
111
|
+
response.raise_for_status()
|
112
|
+
return response
|
113
|
+
finally:
|
114
|
+
client.close()
|
87
115
|
|
88
116
|
|
89
|
-
def delete(url: str, **kwargs) ->
|
117
|
+
def delete(url: str, **kwargs) -> httpx.Response:
|
90
118
|
"""
|
91
|
-
发送增强版永不超时的 DELETE
|
119
|
+
发送增强版永不超时的 DELETE 请求,使用 httpx 实现,包含重试机制
|
92
120
|
|
93
121
|
参数:
|
94
122
|
url: 请求的 URL
|
95
|
-
**kwargs: 其他传递给
|
123
|
+
**kwargs: 其他传递给 httpx.delete 的参数
|
124
|
+
|
125
|
+
返回:
|
126
|
+
httpx.Response 对象
|
127
|
+
|
128
|
+
注意:
|
129
|
+
此方法使用 httpx 实现,包含自动重试机制,适用于解决"Response ended prematurely"等连接问题
|
130
|
+
"""
|
131
|
+
client = get_httpx_client()
|
132
|
+
try:
|
133
|
+
response = client.delete(url=url, **kwargs)
|
134
|
+
response.raise_for_status()
|
135
|
+
return response
|
136
|
+
finally:
|
137
|
+
client.close()
|
138
|
+
|
139
|
+
|
140
|
+
# 同步流式POST请求方法
|
141
|
+
def stream_post(
|
142
|
+
url: str,
|
143
|
+
data: Optional[Any] = None,
|
144
|
+
json: Optional[Dict[str, Any]] = None,
|
145
|
+
**kwargs,
|
146
|
+
) -> Generator[bytes, None, None]:
|
147
|
+
"""
|
148
|
+
发送流式 POST 请求,使用 httpx 实现,返回标准 Generator
|
149
|
+
|
150
|
+
参数:
|
151
|
+
url: 请求的 URL
|
152
|
+
data: (可选) 请求体数据 (表单数据或原始数据)
|
153
|
+
json: (可选) JSON 数据,会自动设置 Content-Type
|
154
|
+
**kwargs: 其他传递给 httpx.post 的参数
|
96
155
|
|
97
156
|
返回:
|
98
|
-
|
157
|
+
Generator[bytes, None, None]: 字节流生成器
|
99
158
|
|
100
159
|
注意:
|
101
|
-
|
160
|
+
此方法使用 httpx 实现流式请求,适用于处理大文件下载或流式响应
|
102
161
|
"""
|
103
|
-
|
104
|
-
|
162
|
+
client = get_httpx_client()
|
163
|
+
try:
|
164
|
+
with client.stream("POST", url, data=data, json=json, **kwargs) as response:
|
165
|
+
response.raise_for_status()
|
166
|
+
for chunk in response.iter_bytes():
|
167
|
+
yield chunk
|
168
|
+
finally:
|
169
|
+
client.close()
|
jarvis/jarvis_utils/utils.py
CHANGED
@@ -66,23 +66,6 @@ def _show_welcome_message(welcome_str: str) -> None:
|
|
66
66
|
PrettyOutput.print_gradient_text(jarvis_ascii_art, (0, 120, 255), (0, 255, 200))
|
67
67
|
|
68
68
|
|
69
|
-
def _extract_huggingface_models() -> None:
|
70
|
-
"""解压HuggingFace模型"""
|
71
|
-
data_dir = Path(get_data_dir())
|
72
|
-
script_dir = Path(os.path.dirname(os.path.dirname(__file__)))
|
73
|
-
hf_archive = script_dir / "jarvis_data" / "huggingface.tar.gz"
|
74
|
-
hf_dir = data_dir / "huggingface" / "hub"
|
75
|
-
|
76
|
-
if not hf_dir.exists() and hf_archive.exists():
|
77
|
-
try:
|
78
|
-
PrettyOutput.print("正在解压HuggingFace模型...", OutputType.INFO)
|
79
|
-
with tarfile.open(hf_archive, "r:gz") as tar:
|
80
|
-
tar.extractall(path=data_dir)
|
81
|
-
PrettyOutput.print("HuggingFace模型解压完成", OutputType.SUCCESS)
|
82
|
-
except Exception as e:
|
83
|
-
PrettyOutput.print(f"解压HuggingFace模型失败: {e}", OutputType.ERROR)
|
84
|
-
|
85
|
-
|
86
69
|
def _check_git_updates() -> bool:
|
87
70
|
"""检查并更新git仓库
|
88
71
|
|
@@ -117,10 +100,7 @@ def init_env(welcome_str: str, config_file: Optional[str] = None) -> None:
|
|
117
100
|
g_config_file = config_file
|
118
101
|
load_config()
|
119
102
|
|
120
|
-
# 5.
|
121
|
-
_extract_huggingface_models()
|
122
|
-
|
123
|
-
# 6. 检查git更新
|
103
|
+
# 5. 检查git更新
|
124
104
|
if _check_git_updates():
|
125
105
|
os.execv(sys.executable, [sys.executable] + sys.argv)
|
126
106
|
sys.exit(0)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: jarvis-ai-assistant
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.211
|
4
4
|
Summary: Jarvis: An AI assistant that uses tools to interact with the system
|
5
5
|
Home-page: https://github.com/skyfireitdiy/Jarvis
|
6
6
|
Author: skyfire
|
@@ -55,6 +55,7 @@ Requires-Dist: openai==1.78.1
|
|
55
55
|
Requires-Dist: tabulate==0.9.0
|
56
56
|
Requires-Dist: pyte==0.8.2
|
57
57
|
Requires-Dist: pyyaml>=6.0.2
|
58
|
+
Requires-Dist: httpx>=0.28.1
|
58
59
|
Provides-Extra: dev
|
59
60
|
Requires-Dist: pytest; extra == "dev"
|
60
61
|
Requires-Dist: black; extra == "dev"
|