MeUtils 2025.8.16.19.17.25__py3-none-any.whl → 2025.8.20.17.32.39__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,6 +9,7 @@
9
9
  # @Description :
10
10
 
11
11
  from openai import AsyncOpenAI
12
+ from openai import APIStatusError
12
13
 
13
14
  from meutils.pipe import *
14
15
  from meutils.io.files_utils import to_base64, to_url
@@ -111,19 +112,30 @@ async def generate(request: ImageRequest, api_key: Optional[str] = None):
111
112
  data = to_openai_images_params(request)
112
113
  # logger.debug(data)
113
114
 
114
- # 代理
115
- http_client = None
116
- if request.user == 'proxy':
117
- http_client = httpx.AsyncClient(proxy=await get_one_proxy(), timeout=60)
118
-
119
- client = AsyncOpenAI(base_url=BASE_URL, api_key=api_key, http_client=http_client, timeout=60)
120
- response = await client.images.generate(**data)
121
- response.model = ""
122
- # logger.debug(response)
115
+ try:
116
+ client = AsyncOpenAI(base_url=BASE_URL, api_key=api_key)
117
+ response = await client.images.generate(**data)
118
+ # logger.debug(response)
119
+
120
+ except APIStatusError as e:
121
+ logger.debug(e)
122
+ # logger.debug(e.response.json())
123
+ # logger.debug(e.response.status_code)
124
+
125
+ if e.response.status_code > 403 and any(i in BASE_URL for i in {"siliconflow", "modelscope"}):
126
+ proxy = await get_one_proxy()
127
+ client = AsyncOpenAI(
128
+ base_url=BASE_URL,
129
+ api_key=api_key,
130
+ http_client=httpx.AsyncClient(proxy=proxy, timeout=100)
131
+ )
132
+ response = await client.images.generate(**data)
133
+ raise e
123
134
 
124
135
  # response.data[0].url = response.data[0].url.replace(r'\u0026', '&')
125
- send_message(f"request: {request.model}\n{request.prompt}\nresponse: {response.data[0].url}",)
136
+ send_message(f"request: {request.model}\n{request.prompt}\nresponse: {response.data[0].url}", )
126
137
 
138
+ response.model = ""
127
139
  response.data[0].url = await to_url(response.data[0].url, content_type="image/png")
128
140
  if request.response_format == "b64_json":
129
141
  b64_json = await to_base64(response.data[0].url)
@@ -140,10 +152,11 @@ if __name__ == '__main__':
140
152
  from meutils.pipe import *
141
153
 
142
154
  data = {
143
- # "model": "flux-schnell",
144
- "model": "black-forest-labs/FLUX.1-Krea-dev",
155
+ "model": "flux-schnell",
156
+ # "model": "black-forest-labs/FLUX.1-Krea-dev",
145
157
 
146
- "prompt": "(Chinese dragon soaring through the clouds).(majestic, colorful, mythical, powerful, ancient).(DSLR camera).(wide-angle lens).(dawn)(fantasy photography).(Kodak Ektar 100)",
158
+ "prompt": "a dog",
159
+ # "prompt": "(Chinese dragon soaring through the clouds).(majestic, colorful, mythical, powerful, ancient).(DSLR camera).(wide-angle lens).(dawn)(fantasy photography).(Kodak Ektar 100)",
147
160
  "negative_prompt": "",
148
161
  "n": 1,
149
162
  # "response_format": "url",
@@ -173,8 +186,11 @@ if __name__ == '__main__':
173
186
  # request = FluxImageRequest(model="flux", prompt="a dog", size="1024x1024", num_inference_steps=1)
174
187
  # request = FluxImageRequest(model="flux-pro", prompt="a dog", size="10x10", num_inference_steps=1)
175
188
 
176
- data = {'model': 'black-forest-labs/FLUX.1-Krea-dev', 'prompt': '画一个2025年电脑如何一键重装系统win10教程详解的封面图', 'n': 1,
177
- 'size': '680x400'}
189
+ # data = {
190
+ # 'model': 'black-forest-labs/FLUX.1-Krea-dev',
191
+ # 'prompt': '画一个2025年电脑如何一键重装系统win10教程详解的封面图', 'n': 1,
192
+ # 'size': '1024x1024'
193
+ # }
178
194
  request = FluxImageRequest(**data)
179
195
 
180
196
  print(request)
meutils/data/VERSION CHANGED
@@ -1 +1 @@
1
- 2025.08.16.19.17.25
1
+ 2025.08.20.17.32.39
@@ -286,7 +286,7 @@ async def check_token_for_zhipu(api_key, threshold: float = 1, resource_package_
286
286
  try:
287
287
  client = AsyncOpenAI(base_url="https://bigmodel.cn/api/biz/tokenAccounts/list", api_key=api_key)
288
288
  data = await client.get("", cast_to=object)
289
- logger.debug(bjson(data))
289
+ # logger.debug(bjson(data))
290
290
 
291
291
  if resource_package_name:
292
292
  # print(str(data))
@@ -298,8 +298,8 @@ async def check_token_for_zhipu(api_key, threshold: float = 1, resource_package_
298
298
  # "resourcePackageName": "【新用户专享】200万GLM-Z1-Air推理资源包",
299
299
  # "resourcePackageName": "【新用户专享】30次Vidu系列视频生成次包",
300
300
  for d in data["rows"]:
301
- if resource_package_name.lower() in d["resourcePackageName"].lower():
302
- # logger.debug(bjson(d))
301
+ if resource_package_name.lower() in d["resourcePackageName"].lower() and d['status'] != "EXPIRED":
302
+ logger.debug(bjson(d))
303
303
  return d["tokenBalance"] >= threshold
304
304
  else:
305
305
  logger.debug(bjson(data))
@@ -7,12 +7,13 @@
7
7
  # @WeChat : meutils
8
8
  # @Software : PyCharm
9
9
  # @Description :
10
- import json
10
+ from aiostream import stream
11
11
 
12
12
  from meutils.pipe import *
13
13
  from meutils.io.files_utils import to_url, to_url_fal
14
14
  from meutils.str_utils.json_utils import json_path
15
- from meutils.schemas.openai_types import CompletionRequest
15
+ from meutils.llm.openai_utils import create_chat_completion
16
+ from meutils.schemas.openai_types import CompletionRequest, ChatCompletion
16
17
  from meutils.schemas.image_types import ImageRequest
17
18
  from meutils.llm.openai_utils import chat_completion, chat_completion_chunk, create_chat_completion_chunk
18
19
 
@@ -39,6 +40,18 @@ async def chat_for_image(
39
40
  chat_completion.choices[0].message.content = "请设置`stream=True`"
40
41
  return chat_completion
41
42
 
43
+ # request.stream = True # 流转非流
44
+ # response = await chat_for_image(generate, request, api_key)
45
+ # chunks = await stream.list(response)
46
+ #
47
+ # logger.debug(chunks)
48
+ #
49
+ # if chunks and isinstance(chunks[0], ChatCompletion):
50
+ # response = chunks[0]
51
+ # else:
52
+ # response = create_chat_completion(chunks)
53
+ # return response
54
+
42
55
  prompt = request.last_user_content
43
56
  if request.last_urls: # image_url
44
57
  urls = await to_url_fal(request.last_urls["image_url"], content_type="image/png")
@@ -65,7 +78,6 @@ async def chat_for_image(
65
78
  return chunks
66
79
 
67
80
 
68
-
69
81
  async def chat_for_video(
70
82
  get_task: Callable, # response
71
83
  taskid: str,
@@ -100,7 +112,7 @@ async def chat_for_video(
100
112
  else:
101
113
  yield "🚀"
102
114
 
103
- chunks = create_chat_completion_chunk(gen())
115
+ chunks = create_chat_completion_chunk(gen(), chat_id=taskid)
104
116
  return chunks
105
117
 
106
118
 
@@ -27,7 +27,7 @@ from meutils.schemas.openai_types import chat_completion, chat_completion_chunk,
27
27
 
28
28
  from meutils.schemas.image_types import ImageRequest, ImageEditRequest
29
29
 
30
- token_encoder = tiktoken.get_encoding('cl100k_base')
30
+ token_encoder = tiktoken.get_encoding('cl100k_base') # o200k_base
31
31
  token_encoder_with_cache = lru_cache(maxsize=1024)(token_encoder.encode)
32
32
 
33
33
  CHAT_COMPLETION_PARAMS = get_function_params()
@@ -320,4 +320,6 @@ if __name__ == '__main__':
320
320
  #
321
321
  # print(token_encoder.encode('hi'))
322
322
 
323
- logger.debug(IMAGES_EDIT_PARAMS)
323
+ # logger.debug(IMAGES_EDIT_PARAMS)
324
+
325
+ print(token_encoder_with_cache('hi'))
@@ -36,6 +36,8 @@ def calculate_min_resolution(w, h):
36
36
 
37
37
 
38
38
  def size2aspect_ratio(size):
39
+ if not size: return "1:1"
40
+
39
41
  if 'x' in size:
40
42
  w, h = size.split('x')
41
43
  w, h = calculate_min_resolution(w, h)
@@ -49,3 +51,4 @@ if __name__ == '__main__':
49
51
  print(size2aspect_ratio("1920x1080"))
50
52
  print(size2aspect_ratio("1920:1080"))
51
53
  print(size2aspect_ratio("1024x1024"))
54
+ print(size2aspect_ratio("16:9"))
meutils/oss/ali_oss.py CHANGED
@@ -11,6 +11,7 @@
11
11
  import oss2
12
12
 
13
13
  from meutils.pipe import *
14
+ from meutils.caches import rcache
14
15
  from meutils.io.files_utils import guess_mime_type
15
16
  from meutils.config_utils.lark_utils import get_next_token_for_polling
16
17
 
@@ -32,11 +33,10 @@ url = "https://chat.qwen.ai/api/v1/files/getstsToken"
32
33
 
33
34
 
34
35
  async def get_sts_token(filename, filetype: Optional[str] = None, token: Optional[str] = None):
35
- token = token or await get_next_token_for_polling(feishu_url=FEISHU_URL, from_redis=True)
36
+ token = token or await get_next_token_for_polling(feishu_url=FEISHU_URL)
36
37
 
37
38
  filetype = filetype or guess_mime_type(filename).split('/')[0]
38
39
 
39
-
40
40
  payload = {
41
41
  "filename": filename,
42
42
  "filetype": filetype, # file video audio
@@ -52,8 +52,8 @@ async def get_sts_token(filename, filetype: Optional[str] = None, token: Optiona
52
52
  return response.json()
53
53
 
54
54
 
55
- async def qwenai_upload(file, filetype: Optional[str] = None): # todo: 自动猜测类型
56
- params = await get_sts_token(file_name, filetype)
55
+ async def qwenai_upload(file, filetype: Optional[str] = None, token: Optional[str] = None): # todo: 自动猜测类型
56
+ params = await get_sts_token(file_name, filetype, token)
57
57
 
58
58
  access_key_id = params['access_key_id']
59
59
  access_key_secret = params['access_key_secret']
@@ -87,4 +87,3 @@ if __name__ == '__main__':
87
87
 
88
88
  # arun(get_sts_token(file_name))
89
89
  file_url = arun(qwenai_upload(file_name))
90
-
@@ -58,7 +58,13 @@ if __name__ == '__main__':
58
58
  url = "https://chat.tune.app/?id=7f268d94-d2d4-4bd4-a732-f196aa20dceb"
59
59
  url = "https://app.yinxiang.com/fx/8b8bba1e-b254-40ff-81e1-fa3427429efe"
60
60
 
61
- print(Crawler(url).xpath('//script//text()'))
61
+ # print(Crawler(url).xpath('//script//text()'))
62
+
63
+
64
+ url = "https://docs.bigmodel.cn/cn/guide/models/free"
65
+ print(Crawler(url).xpath('//*[@id="sidebar-group"]/li[8]//text()'))
66
+
67
+ # 'GLM-4.5-Flash', 'GLM-4.1V-Thinking-Flash', 'GLM-4-Flash-250414', 'GLM-4V-Flash', 'GLM-Z1-Flash', 'Cogview-3-Flash'
62
68
 
63
69
  # html_content = httpx.get(url).text
64
70
 
@@ -108,7 +108,7 @@ class ImageRequest(BaseModel): # openai
108
108
  guidance: Optional[float] = None
109
109
  steps: Optional[int] = None
110
110
 
111
- controls: Optional[dict] = None # 额外参数
111
+ controls: Optional[dict] = None # 额外参数
112
112
 
113
113
  safety_tolerance: Optional[int] = None
114
114
 
@@ -116,6 +116,9 @@ class ImageRequest(BaseModel): # openai
116
116
 
117
117
  user: Optional[str] = None # to_url_fal
118
118
 
119
+ image: Optional[str] = None # url b64
120
+ watermark: Optional[bool] = None
121
+
119
122
  def __init__(self, /, **data: Any):
120
123
  super().__init__(**data)
121
124
 
@@ -618,4 +621,4 @@ if __name__ == '__main__':
618
621
 
619
622
  r = ImageRequest(**data)
620
623
 
621
- print(ImagesResponse())
624
+ # print(ImagesResponse())
@@ -107,7 +107,7 @@ FAL_MODELS = {
107
107
  MODEL_PRICE = {
108
108
  **FAL_MODELS,
109
109
 
110
- "qwen-image": 0.1,
110
+ "qwen-image": 0.05,
111
111
 
112
112
  "wan-ai-wan2.1-t2v-14b": 1,
113
113
  "wan-ai-wan2.1-t2v-14b-turbo": 1,
@@ -198,6 +198,7 @@ MODEL_PRICE = {
198
198
  "minimax-i2v-01_6s_720p": 1 * MINIMAX_VIDEO,
199
199
  "minimax-i2v-01-director_6s_720p": 1 * MINIMAX_VIDEO,
200
200
  "minimax-i2v-01-live_6s_720p": 1 * MINIMAX_VIDEO,
201
+
201
202
  "minimax-s2v-01_6s_720p": 1.5 * MINIMAX_VIDEO,
202
203
  "minimax-hailuo-02_6s_512p": 0.3 * MINIMAX_VIDEO,
203
204
  "minimax-hailuo-02_10s_512p": 0.5 * MINIMAX_VIDEO,