MeUtils 2025.6.9.11.35.52__py3-none-any.whl → 2025.6.12.17.34.4__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.
@@ -9,7 +9,8 @@
9
9
  # @Description : todo: 通用比例适配
10
10
 
11
11
  from meutils.pipe import *
12
- from meutils.str_utils.regular_expression import parse_url
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
- if ':' in self.size:
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,16 @@ 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"
604
607
  }
605
608
 
606
- r = ImageRequest(**data)
609
+ dd = {
610
+ "model": "flux-kontext-pro",
611
+ "prompt": "a cat and a dog",
612
+ "size": "5121x1024",
613
+ # "aspect_ratio": "16:9"
614
+ }
607
615
 
616
+ r = ImageRequest(**data)
@@ -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
 
@@ -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=True, headers=headers)
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
- print(validate_url([url] * 3))
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
- 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 \nA young woman holding a lipstick tube with a black body and gold decorative rings, featuring a nude or light brown lipstick bullet. The lipstick product faces the camera, positioned slightly below her face. In the background, a close-up of lips coated with the same nude or light brown shade, creating a natural and soft effect.
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, for_image=True))
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)