MeUtils 2025.6.9.11.35.52__py3-none-any.whl → 2025.6.13.10.18.19__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.
- {MeUtils-2025.6.9.11.35.52.dist-info → MeUtils-2025.6.13.10.18.19.dist-info}/METADATA +261 -261
- {MeUtils-2025.6.9.11.35.52.dist-info → MeUtils-2025.6.13.10.18.19.dist-info}/RECORD +29 -24
- examples/_openaisdk/openai_chatfire_usa.py +32 -0
- examples/_openaisdk/openai_ppinfra.py +2 -1
- examples/_openaisdk/openai_zhipu.py +5 -2
- meutils/apis/fal/images.py +17 -15
- meutils/apis/google/chat.py +3 -3
- meutils/apis/images/generations.py +34 -0
- meutils/apis/jimeng/images.py +3 -2
- meutils/apis/oneapi/channel.py +31 -52
- meutils/apis/volcengine_apis/videos.py +146 -0
- meutils/data/VERSION +1 -1
- meutils/llm/check_utils.py +2 -2
- meutils/llm/openai_polling/chat.py +1 -0
- meutils/llm/openai_utils/adapters.py +3 -0
- meutils/llm/openai_utils/common.py +1 -1
- meutils/math_utils/__init__.py +11 -0
- meutils/math_utils/common.py +50 -0
- meutils/notice/feishu.py +5 -1
- meutils/schemas/image_types.py +53 -42
- meutils/schemas/oneapi/_types.py +39 -27
- meutils/schemas/oneapi/common.py +35 -0
- meutils/schemas/openai_types.py +2 -0
- meutils/str_utils/__init__.py +17 -4
- meutils/str_utils/regular_expression.py +16 -5
- {MeUtils-2025.6.9.11.35.52.dist-info → MeUtils-2025.6.13.10.18.19.dist-info}/LICENSE +0 -0
- {MeUtils-2025.6.9.11.35.52.dist-info → MeUtils-2025.6.13.10.18.19.dist-info}/WHEEL +0 -0
- {MeUtils-2025.6.9.11.35.52.dist-info → MeUtils-2025.6.13.10.18.19.dist-info}/entry_points.txt +0 -0
- {MeUtils-2025.6.9.11.35.52.dist-info → MeUtils-2025.6.13.10.18.19.dist-info}/top_level.txt +0 -0
meutils/llm/check_utils.py
CHANGED
@@ -218,7 +218,7 @@ if __name__ == '__main__':
|
|
218
218
|
|
219
219
|
check_valid_token = partial(check_token_for_siliconflow, threshold=-1)
|
220
220
|
|
221
|
-
arun(check_valid_token("sk-tythaoctwemlhkytdlmjcegtnufvhqgmwlncgmoxixdyqoxx"))
|
221
|
+
# arun(check_valid_token("sk-tythaoctwemlhkytdlmjcegtnufvhqgmwlncgmoxixdyqoxx"))
|
222
222
|
|
223
223
|
pass
|
224
224
|
# arun(check_valid_token("sk-LlB4W38z9kv5Wy1c3ceeu4PHeIWs6bbWsjr8Om31jYvsucRv", threshold=0.1))
|
@@ -248,4 +248,4 @@ if __name__ == '__main__':
|
|
248
248
|
|
249
249
|
# arun(check_token_for_ppinfra("sk_F0kgPyCMTzmOH_-VCEJucOK8HIrbnLGYm_IWxBToHZQ"))
|
250
250
|
|
251
|
-
|
251
|
+
arun(check_token_for_volc("07139a08-e360-44e2-ba31-07f379bf99ed"))
|
@@ -73,6 +73,7 @@ class Completions(object):
|
|
73
73
|
|
74
74
|
elif "deepseek-r" in request.model:
|
75
75
|
request.separate_reasoning = True # pp
|
76
|
+
"""Error code: 403 - {'code': 403, 'reason': 'NOT_ENOUGH_BALANCE', 'message': 'not enough balance', 'metadata': {}}"""
|
76
77
|
###########################################################################
|
77
78
|
|
78
79
|
data = to_openai_params(request)
|
@@ -22,7 +22,10 @@ async def stream_to_nostream(
|
|
22
22
|
async def chat_for_image(
|
23
23
|
generate: Callable,
|
24
24
|
request: CompletionRequest,
|
25
|
+
api_key: Optional[str] = None,
|
25
26
|
):
|
27
|
+
generate = partial(generate, api_key=api_key)
|
28
|
+
|
26
29
|
if not request.stream or request.last_user_content.startswith( # 跳过nextchat
|
27
30
|
(
|
28
31
|
"hi",
|
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Project : AI. @by PyCharm
|
4
|
+
# @File : __init__.py
|
5
|
+
# @Time : 2025/6/10 09:11
|
6
|
+
# @Author : betterme
|
7
|
+
# @WeChat : meutils
|
8
|
+
# @Software : PyCharm
|
9
|
+
# @Description :
|
10
|
+
|
11
|
+
from meutils.math_utils.common import *
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Project : AI. @by PyCharm
|
4
|
+
# @File : common
|
5
|
+
# @Time : 2025/6/10 09:11
|
6
|
+
# @Author : betterme
|
7
|
+
# @WeChat : meutils
|
8
|
+
# @Software : PyCharm
|
9
|
+
# @Description :
|
10
|
+
|
11
|
+
|
12
|
+
import math
|
13
|
+
|
14
|
+
|
15
|
+
def calculate_min_resolution(w, h):
|
16
|
+
"""
|
17
|
+
计算给定宽高比的最小像素公约数分辨率(宽高互质)
|
18
|
+
|
19
|
+
参数:
|
20
|
+
aspect_ratio (str): 宽高比字符串,例如"16:9"
|
21
|
+
|
22
|
+
返回:
|
23
|
+
tuple: (宽, 高) 的元组,整数类型
|
24
|
+
"""
|
25
|
+
# 分割字符串并转换为整数
|
26
|
+
w, h = map(int, (w, h))
|
27
|
+
|
28
|
+
# 计算最大公约数
|
29
|
+
gcd_val = math.gcd(w, h)
|
30
|
+
|
31
|
+
# 化简为互质的整数比
|
32
|
+
width = w // gcd_val
|
33
|
+
height = h // gcd_val
|
34
|
+
|
35
|
+
return width, height
|
36
|
+
|
37
|
+
|
38
|
+
def size2aspect_ratio(size):
|
39
|
+
if 'x' in size:
|
40
|
+
w, h = size.split('x')
|
41
|
+
w, h = calculate_min_resolution(w, h)
|
42
|
+
return f"{w}:{h}" # aspect_ratio
|
43
|
+
|
44
|
+
elif ':' in size:
|
45
|
+
return size
|
46
|
+
|
47
|
+
|
48
|
+
if __name__ == '__main__':
|
49
|
+
print(size2aspect_ratio("1920x1080"))
|
50
|
+
print(size2aspect_ratio("1920:1080"))
|
meutils/notice/feishu.py
CHANGED
@@ -22,6 +22,8 @@ AUDIO = "https://open.feishu.cn/open-apis/bot/v2/hook/80c2a700-adfa-4b9b-8e3f-00
|
|
22
22
|
FILES = "https://open.feishu.cn/open-apis/bot/v2/hook/075fb2fa-a559-4a7e-89ac-3ab9934ff15c"
|
23
23
|
KLING = "https://open.feishu.cn/open-apis/bot/v2/hook/e9a850c2-d171-4637-b976-ee93f7654c40"
|
24
24
|
|
25
|
+
VOLC = "https://open.feishu.cn/open-apis/bot/v2/hook/d487ce4f-3c2b-44db-a5b4-7ee4c5e03b4f"
|
26
|
+
|
25
27
|
|
26
28
|
@background_task
|
27
29
|
def send_message(
|
@@ -119,13 +121,15 @@ send_message_for_http = partial(send_message, url=http_feishu_url)
|
|
119
121
|
try_catch_feishu_url = "https://open.feishu.cn/open-apis/bot/v2/hook/887fe4d3-8bcd-4cfb-bac9-62f776091ca2"
|
120
122
|
send_message_for_try_catch = partial(send_message, url=try_catch_feishu_url)
|
121
123
|
|
124
|
+
send_message_for_volc = partial(send_message, url=VOLC)
|
125
|
+
|
122
126
|
if __name__ == '__main__':
|
123
127
|
# send_message("xxx", title=None)
|
124
128
|
send_message(None, title=None)
|
125
129
|
|
126
130
|
# send_message_for_images("xxxxxxxx", title=None)
|
127
131
|
|
128
|
-
|
132
|
+
send_message_for_volc("xxxxxxxx")
|
129
133
|
# @catch(task_name='这是一个任务名')
|
130
134
|
# def f():
|
131
135
|
# time.sleep(3)
|
meutils/schemas/image_types.py
CHANGED
@@ -9,7 +9,8 @@
|
|
9
9
|
# @Description : todo: 通用比例适配
|
10
10
|
|
11
11
|
from meutils.pipe import *
|
12
|
-
from meutils.str_utils
|
12
|
+
from meutils.str_utils import parse_url
|
13
|
+
from meutils.math_utils import size2aspect_ratio
|
13
14
|
|
14
15
|
from pydantic import constr
|
15
16
|
from openai.types import ImagesResponse as _ImagesResponse, Image
|
@@ -124,11 +125,7 @@ class ImageRequest(BaseModel): # openai
|
|
124
125
|
self.size = ASPECT_RATIOS.get(self.aspect_ratio, '1024x1024')
|
125
126
|
|
126
127
|
elif self.size: # 适配尺寸
|
127
|
-
|
128
|
-
self.aspect_ratio = self.size
|
129
|
-
|
130
|
-
else:
|
131
|
-
self.aspect_ratio = ASPECT_RATIOS.get(self.size, '1:1')
|
128
|
+
self.aspect_ratio = size2aspect_ratio(self.size)
|
132
129
|
|
133
130
|
self.size = self.size if 'x' in self.size else '512x512'
|
134
131
|
|
@@ -138,7 +135,7 @@ class ImageRequest(BaseModel): # openai
|
|
138
135
|
if len(prompts) == 2:
|
139
136
|
return prompts
|
140
137
|
else:
|
141
|
-
return prompts + [' ']
|
138
|
+
return prompts + [' '] # 只有 单url
|
142
139
|
|
143
140
|
elif "http" in self.prompt and (images := parse_url(self.prompt)):
|
144
141
|
return images[0], self.prompt.replace(images[0], "")
|
@@ -146,6 +143,11 @@ class ImageRequest(BaseModel): # openai
|
|
146
143
|
else:
|
147
144
|
return None, self.prompt
|
148
145
|
|
146
|
+
def prompt2aspect_ratio(self, aspect_ratios): # 提示词优先级最高:从支持的比例中选择匹配
|
147
|
+
for aspect_ratio in aspect_ratios:
|
148
|
+
if aspect_ratio in self.prompt:
|
149
|
+
return aspect_ratio
|
150
|
+
|
149
151
|
class Config:
|
150
152
|
extra = "allow"
|
151
153
|
|
@@ -162,6 +164,40 @@ class ImageRequest(BaseModel): # openai
|
|
162
164
|
}
|
163
165
|
|
164
166
|
|
167
|
+
class ImageEditRequest(BaseModel):
|
168
|
+
model: Union[str, Literal["dall-e-2", "dall-e-3", "gpt-image-1"]]
|
169
|
+
|
170
|
+
prompt: str
|
171
|
+
image: Any # 图片
|
172
|
+
|
173
|
+
mask: Optional[Any] = None # 图片
|
174
|
+
background: Optional[Literal["transparent", "opaque", "auto"]] = None
|
175
|
+
|
176
|
+
n: Optional[int] = 1
|
177
|
+
quality: Optional[Literal["standard", "low", "medium", "high", "auto"]] = None
|
178
|
+
size: Optional[
|
179
|
+
Union[str, Literal["256x256", "512x512", "1024x1024", "1536x1024", "1024x1536", "auto"]]] = "1024x1024"
|
180
|
+
response_format: Optional[Literal["url", "b64_json"]] = None
|
181
|
+
|
182
|
+
aspect_ratio: Optional[str] = None
|
183
|
+
|
184
|
+
user: Optional[str] = None
|
185
|
+
|
186
|
+
def __init__(self, /, **data: Any):
|
187
|
+
super().__init__(**data)
|
188
|
+
if not isinstance(self.image, list):
|
189
|
+
self.image = [self.image]
|
190
|
+
|
191
|
+
if self.aspect_ratio: # 适配比例
|
192
|
+
self.size = ASPECT_RATIOS.get(self.aspect_ratio, '1024x1024')
|
193
|
+
|
194
|
+
elif self.size: # 适配尺寸
|
195
|
+
|
196
|
+
self.aspect_ratio = size2aspect_ratio(self.size)
|
197
|
+
|
198
|
+
self.size = self.size if 'x' in self.size else '512x512'
|
199
|
+
|
200
|
+
|
165
201
|
class FalImageRequest(ImageRequest):
|
166
202
|
prompt: str
|
167
203
|
seed: Optional[int] = None
|
@@ -525,40 +561,6 @@ class ImageProcess(BaseModel):
|
|
525
561
|
# extra = "allow"
|
526
562
|
|
527
563
|
|
528
|
-
class ImageEditRequest(BaseModel):
|
529
|
-
model: Union[str, Literal["dall-e-2", "dall-e-3", "gpt-image-1"]]
|
530
|
-
|
531
|
-
prompt: str
|
532
|
-
image: Any # 图片
|
533
|
-
|
534
|
-
mask: Optional[Any] = None # 图片
|
535
|
-
background: Optional[Literal["transparent", "opaque", "auto"]] = None
|
536
|
-
|
537
|
-
n: Optional[int] = 1
|
538
|
-
quality: Optional[Literal["standard", "low", "medium", "high", "auto"]] = None
|
539
|
-
size: Optional[
|
540
|
-
Union[str, Literal["256x256", "512x512", "1024x1024", "1536x1024", "1024x1536", "auto"]]] = "1024x1024"
|
541
|
-
response_format: Optional[Literal["url", "b64_json"]] = None
|
542
|
-
|
543
|
-
aspect_ratio: Optional[str] = None
|
544
|
-
|
545
|
-
user: Optional[str] = None
|
546
|
-
|
547
|
-
def __init__(self, /, **data: Any):
|
548
|
-
super().__init__(**data)
|
549
|
-
if not isinstance(self.image, list):
|
550
|
-
self.image = [self.image]
|
551
|
-
|
552
|
-
if self.aspect_ratio: # 适配比例
|
553
|
-
self.size = ASPECT_RATIOS.get(self.aspect_ratio, '1024x1024')
|
554
|
-
|
555
|
-
elif self.size: # 适配尺寸
|
556
|
-
if ':' in self.size:
|
557
|
-
self.aspect_ratio = self.size
|
558
|
-
|
559
|
-
self.size = self.size if 'x' in self.size else '512x512'
|
560
|
-
|
561
|
-
|
562
564
|
if __name__ == '__main__':
|
563
565
|
# print(ASPECT_RATIOS.items())
|
564
566
|
|
@@ -599,9 +601,18 @@ if __name__ == '__main__':
|
|
599
601
|
|
600
602
|
data = {
|
601
603
|
"model": "flux-kontext-pro",
|
602
|
-
"prompt": "a cat",
|
604
|
+
"prompt": "a cat and a dog",
|
603
605
|
"size": "512x1024",
|
606
|
+
# "aspect_ratio": "16:9"
|
607
|
+
}
|
608
|
+
|
609
|
+
dd = {
|
610
|
+
"model": "flux-kontext-pro",
|
611
|
+
"prompt": "a cat and a dog",
|
612
|
+
"size": "5121x1024",
|
613
|
+
# "aspect_ratio": "16:9"
|
604
614
|
}
|
605
615
|
|
606
616
|
r = ImageRequest(**data)
|
607
617
|
|
618
|
+
print(ImagesResponse())
|
meutils/schemas/oneapi/_types.py
CHANGED
@@ -38,52 +38,64 @@ class ModelInfo(BaseModel):
|
|
38
38
|
|
39
39
|
|
40
40
|
class ChannelInfo(BaseModel):
|
41
|
+
id: Optional[int] = None # 不存在就新建
|
42
|
+
type: int = 1 # 枚举值 openai
|
43
|
+
|
44
|
+
name: str = ''
|
41
45
|
tag: str = ''
|
46
|
+
group: str = 'default'
|
47
|
+
|
48
|
+
base_url: str = ''
|
49
|
+
key: str
|
50
|
+
models: str = 'MODEL'
|
42
51
|
|
43
|
-
id: Optional[int] = None
|
44
|
-
type: int = 1 # 枚举值 openai
|
45
|
-
key: Optional[str] = None
|
46
52
|
access_token: str = ''
|
47
53
|
openai_organization: str = ''
|
48
54
|
test_model: str = ''
|
49
|
-
status: int =
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
response_time: int = '0'
|
55
|
-
base_url: Optional[str] = None
|
55
|
+
status: int = 1
|
56
|
+
weight: int = 0
|
57
|
+
created_time: int = Field(default_factory=lambda: int(time.time()))
|
58
|
+
test_time: int = 0
|
59
|
+
response_time: int = 0
|
56
60
|
other: str = ''
|
57
|
-
balance: int =
|
58
|
-
balance_updated_time: int =
|
61
|
+
balance: int = 0
|
62
|
+
balance_updated_time: int = 0
|
59
63
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
used_quota: Optional[int] = None
|
64
|
-
upstream_user_quota: int = '0'
|
64
|
+
used_quota: int = 0
|
65
|
+
upstream_user_quota: int = 0
|
65
66
|
|
66
|
-
model_mapping:
|
67
|
+
model_mapping: Union[str, dict] = "" # json
|
67
68
|
|
68
69
|
headers: str = '' # json
|
69
70
|
status_code_mapping: str = ''
|
70
|
-
priority: int =
|
71
|
-
auto_ban: int =
|
72
|
-
empty_response_retry: int =
|
73
|
-
not_use_key: int =
|
71
|
+
priority: int = 0
|
72
|
+
auto_ban: int = 1
|
73
|
+
empty_response_retry: int = 0
|
74
|
+
not_use_key: int = 0
|
74
75
|
remark: str = ''
|
75
|
-
mj_relax_limit: int =
|
76
|
-
mj_fast_limit: int =
|
77
|
-
mj_turbo_limit: int =
|
76
|
+
mj_relax_limit: int = 99
|
77
|
+
mj_fast_limit: int = 99
|
78
|
+
mj_turbo_limit: int = 99
|
78
79
|
other_info: str = ''
|
79
|
-
channel_ratio: int =
|
80
|
-
error_return_429: int =
|
80
|
+
channel_ratio: int = 1
|
81
|
+
error_return_429: int = 0
|
81
82
|
setting: str = ''
|
82
83
|
|
83
84
|
"""参数覆盖"""
|
84
85
|
param_override: str = '' # json
|
85
86
|
is_tools: bool = False
|
86
87
|
|
88
|
+
def __init__(self, /, **data: Any):
|
89
|
+
super().__init__(**data)
|
90
|
+
self.name = self.name or self.base_url or "NAME"
|
91
|
+
self.tag = self.tag or self.base_url or "TAG"
|
92
|
+
|
93
|
+
if self.base_url:
|
94
|
+
self.type = 8
|
95
|
+
|
96
|
+
if isinstance(self.model_mapping, dict):
|
97
|
+
self.model_mapping = json.dumps(self.model_mapping)
|
98
|
+
|
87
99
|
|
88
100
|
# https://oss.ffire.cc/images/qw.jpeg?x-oss-process=image/format,jpg/resize,w_512
|
89
101
|
if __name__ == '__main__':
|
meutils/schemas/oneapi/common.py
CHANGED
@@ -92,6 +92,19 @@ MODEL_PRICE = {
|
|
92
92
|
"sora-1:1-480p-5s": 1.2,
|
93
93
|
"dall-e-3": 0.03,
|
94
94
|
|
95
|
+
# rag
|
96
|
+
"qwen3-reranker-0.6b": 0.0011,
|
97
|
+
"qwen3-reranker-4b": 0.0011,
|
98
|
+
"qwen3-reranker-8b": 0.0011,
|
99
|
+
|
100
|
+
"qwen3-embedding-0.6b": 0.0011,
|
101
|
+
"qwen3-embedding-4b": 0.0011,
|
102
|
+
"qwen3-embedding-8b": 0.0011,
|
103
|
+
|
104
|
+
# 视频
|
105
|
+
"api-videos-3d": 0.01,
|
106
|
+
"api-videos-3d-1.5": 0.01,
|
107
|
+
|
95
108
|
# 智能体
|
96
109
|
"ppt": 0.1,
|
97
110
|
"ppt-islide": 0.1,
|
@@ -667,6 +680,10 @@ MODEL_RATIO = {
|
|
667
680
|
"meta-deepresearch": 2,
|
668
681
|
|
669
682
|
# 豆包
|
683
|
+
"doubao-seed-1-6-flash-250615": 0.075,
|
684
|
+
"doubao-seed-1-6-250615": 0.4,
|
685
|
+
"doubao-seed-1-6-thinking-250615": 0.4,
|
686
|
+
|
670
687
|
"doubao-1-5-ui-tars-250428": 1.75,
|
671
688
|
"ui-tars-72b": 1.75,
|
672
689
|
"doubao-1-5-pro-32k": 0.4,
|
@@ -725,6 +742,11 @@ MODEL_RATIO = {
|
|
725
742
|
"hunyuan-standard-256k": 60,
|
726
743
|
|
727
744
|
# 百度文心
|
745
|
+
"ernie-4.5-turbo-vl-32k": 0.45,
|
746
|
+
"ernie-4.5-turbo-128k": 0.12,
|
747
|
+
"ernie-x1-turbo-32k": 0.15,
|
748
|
+
"ernie-x1-32k-preview": 0.3,
|
749
|
+
|
728
750
|
"ERNIE-Speed-8K": 0.2858,
|
729
751
|
"ERNIE-Speed-128K": 0.2858,
|
730
752
|
|
@@ -912,6 +934,8 @@ MODEL_RATIO = {
|
|
912
934
|
"o3": 5,
|
913
935
|
"o3-2025-04-16": 5,
|
914
936
|
|
937
|
+
"o3-pro": 10,
|
938
|
+
|
915
939
|
# 硅基
|
916
940
|
"llama-3.1-8b-instruct": 0.01,
|
917
941
|
"meta-llama/Meta-Llama-3.1-8B-Instruct": 0.01,
|
@@ -1023,6 +1047,7 @@ COMPLETION_RATIO = {
|
|
1023
1047
|
|
1024
1048
|
"o3": 4,
|
1025
1049
|
"o3-2025-04-16": 4,
|
1050
|
+
"o3-pro": 4,
|
1026
1051
|
|
1027
1052
|
"gpt-4o-realtime-preview": 4,
|
1028
1053
|
"gpt-4o-realtime-preview-2024-10-01": 4,
|
@@ -1095,6 +1120,11 @@ COMPLETION_RATIO = {
|
|
1095
1120
|
"ERNIE-4.0-Turbo-8K": 3,
|
1096
1121
|
"ERNIE-4.0-8K": 3,
|
1097
1122
|
|
1123
|
+
"ernie-4.5-turbo-vl-32k": 4,
|
1124
|
+
"ernie-4.5-turbo-128k": 4,
|
1125
|
+
"ernie-x1-turbo-32k": 4,
|
1126
|
+
"ernie-x1-32k-preview": 4,
|
1127
|
+
|
1098
1128
|
"gemini-all": 5,
|
1099
1129
|
"gemini-1.5-pro-001": 4,
|
1100
1130
|
"gemini-1.5-pro-002": 4,
|
@@ -1193,6 +1223,11 @@ COMPLETION_RATIO = {
|
|
1193
1223
|
"deepseek-ai/deepseek-vl2": 4,
|
1194
1224
|
|
1195
1225
|
# 豆包
|
1226
|
+
"doubao-seed-1-6-flash-250615": 10,
|
1227
|
+
# doubao-seed-1-6-flash-250615,doubao-seed-1-6-250615,doubao-seed-1-6-thinking-250615
|
1228
|
+
"doubao-seed-1-6-250615": 10,
|
1229
|
+
"doubao-seed-1-6-thinking-250615": 10,
|
1230
|
+
|
1196
1231
|
"doubao-1-5-ui-tars-250428": 3.43,
|
1197
1232
|
"ui-tars-72b": 4,
|
1198
1233
|
|
meutils/schemas/openai_types.py
CHANGED
meutils/str_utils/__init__.py
CHANGED
@@ -6,8 +6,10 @@
|
|
6
6
|
# @Author : yuanjie
|
7
7
|
# @WeChat : meutils
|
8
8
|
# @Software : PyCharm
|
9
|
-
# @Description :
|
9
|
+
# @Description :
|
10
|
+
import re
|
10
11
|
|
12
|
+
import httpx
|
11
13
|
|
12
14
|
from meutils.pipe import *
|
13
15
|
# from meutils.str_utils.translater import translater
|
@@ -231,13 +233,13 @@ def validate_url(url):
|
|
231
233
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
|
232
234
|
}
|
233
235
|
|
234
|
-
response = requests.head(url, timeout=5, allow_redirects=
|
236
|
+
# response = requests.head(url, timeout=5, allow_redirects=False, headers=headers)
|
237
|
+
response = requests.head(url, timeout=5, headers=headers)
|
235
238
|
if response.status_code >= 400:
|
236
239
|
logger.error(f"URL 返回错误状态码: {response.status_code}")
|
237
240
|
|
238
241
|
return False
|
239
242
|
|
240
|
-
logger.error("URL 有效")
|
241
243
|
return True
|
242
244
|
except requests.exceptions.RequestException as e:
|
243
245
|
logger.error(f"连接错误: {str(e)}")
|
@@ -277,4 +279,15 @@ if __name__ == '__main__':
|
|
277
279
|
|
278
280
|
url = 'https://fal.ai/models/fal-ai/flux-pro/kontext/requests/de5f28be-2ca8-4bd4-8c42-c7fc32969801?output=0'
|
279
281
|
url = "https://5b0988e595225.cdn.sohucs.com/images/20190814/5ebb727f502545718c4a06f199cd848b.jpeg"
|
280
|
-
|
282
|
+
# url = "https://filesystem.site/cdn/20250609/1XPdqIyhHiOJ8SC68W4ZQGBrf7XRZD.png"
|
283
|
+
|
284
|
+
# url = "https://filesystem.site/cdn/20250609/1QUKzDHRQedraO15CXnUc22aBjvqEN.png"
|
285
|
+
|
286
|
+
# url = "https://photog.art/api/oss/R2yh8N"
|
287
|
+
|
288
|
+
url = "https://p3-bot-workflow-sign.byteimg.com/tos-cn-i-mdko3gqilj/1fe07cca46224208bfbed8c0f3c50ed8.png~tplv-mdko3gqilj-image.image?rk3s=81d4c505&x-expires=1780112531&x-signature=e7q1NOMjqCHvMz%2FC3dVAEVisAh4%3D&x-wf-file_name=9748f6214970f744fe7fd7a3699cfa2.png"
|
289
|
+
|
290
|
+
# print(validate_url([url] * 3))
|
291
|
+
print(validate_url(url))
|
292
|
+
|
293
|
+
print(re.findall("http", url*2))
|
@@ -8,6 +8,7 @@
|
|
8
8
|
# @Software : PyCharm
|
9
9
|
# @Description :
|
10
10
|
import json
|
11
|
+
import re
|
11
12
|
|
12
13
|
from meutils.pipe import *
|
13
14
|
from urllib.parse import unquote, unquote_plus
|
@@ -66,6 +67,9 @@ def get_parse_and_index(text, pattern):
|
|
66
67
|
|
67
68
|
@lru_cache()
|
68
69
|
def parse_url(text: str, for_image=False, fn: Optional[Callable] = None):
|
70
|
+
if text.strip().startswith("http") and len(re.findall("http", text)) == 1: # http开头且是单链接
|
71
|
+
return text.split(maxsplit=1)[:1]
|
72
|
+
|
69
73
|
fn = fn or (lambda x: x.removesuffix(")"))
|
70
74
|
|
71
75
|
# url_pattern = r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'
|
@@ -97,9 +101,7 @@ def parse_url(text: str, for_image=False, fn: Optional[Callable] = None):
|
|
97
101
|
|
98
102
|
valid_urls = []
|
99
103
|
for url in urls:
|
100
|
-
url = url.strip(r"\n")
|
101
|
-
if fn:
|
102
|
-
url = fn(url) # lambda x: x.removesuffix(")")
|
104
|
+
url = fn(url.strip(r"\n"))
|
103
105
|
|
104
106
|
valid_urls.append(url)
|
105
107
|
|
@@ -171,7 +173,16 @@ if __name__ == '__main__':
|
|
171
173
|
|
172
174
|
# print(parse_url(text, True))
|
173
175
|
text = """
|
174
|
-
|
176
|
+
https://p26-bot-workflow-sign.byteimg.com/tos-cn-i-mdko3gqilj/f13171faeed2447b8b9c301ba912f25c.jpg~tplv-mdko3gqilj-image.image?rk3s=81d4c505&x-expires=1779880356&x-signature=AJop4%2FM8VjCUfjqiEzUugprc0CI%3D&x-wf-file_name=B0DCGKG71N.MAIN.jpg
|
177
|
+
|
178
|
+
还有这种url,两个.jpg的也能兼容么
|
175
179
|
"""
|
176
|
-
print(parse_url(text
|
180
|
+
print(parse_url(text))
|
181
|
+
|
177
182
|
|
183
|
+
# print(parse_url(text, for_image=False))
|
184
|
+
|
185
|
+
# text = """https://photog.art/api/oss/R2yh8N Convert this portrait into a straight-on,front-facing ID-style headshot."""
|
186
|
+
# print(parse_url(text))
|
187
|
+
#
|
188
|
+
# valid_urls = parse_url(text, for_image=True)
|
File without changes
|
File without changes
|
{MeUtils-2025.6.9.11.35.52.dist-info → MeUtils-2025.6.13.10.18.19.dist-info}/entry_points.txt
RENAMED
File without changes
|
File without changes
|