MeUtils 2025.6.18.16.41.23__py3-none-any.whl → 2025.6.24.11.13.32__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.
Files changed (43) hide show
  1. {MeUtils-2025.6.18.16.41.23.dist-info → MeUtils-2025.6.24.11.13.32.dist-info}/METADATA +260 -260
  2. {MeUtils-2025.6.18.16.41.23.dist-info → MeUtils-2025.6.24.11.13.32.dist-info}/RECORD +40 -36
  3. examples/_openaisdk/openai_doubao.py +7 -7
  4. examples/_openaisdk/openai_edits.py +48 -0
  5. examples/_openaisdk/openai_images.py +10 -3
  6. examples/_openaisdk/openai_lingyi.py +44 -10
  7. examples/_openaisdk/openai_modelscope.py +1 -0
  8. examples/_openaisdk/openai_ppinfra.py +7 -2
  9. examples/_openaisdk/openai_siliconflow.py +3 -3
  10. meutils/apis/hailuoai/images.py +2 -2
  11. meutils/apis/hailuoai/videos.py +10 -0
  12. meutils/apis/oneapi/channel.py +57 -6
  13. meutils/apis/oneapi/user.py +3 -3
  14. meutils/apis/{veo → ppio}/__init__.py +1 -1
  15. meutils/apis/ppio/videos.py +142 -0
  16. meutils/apis/proxy/kdlapi.py +18 -14
  17. meutils/apis/transparent_transmission/__init__.py +10 -0
  18. meutils/apis/transparent_transmission/tasks.py +28 -0
  19. meutils/apis/utils.py +10 -9
  20. meutils/apis/videos/veo.py +68 -0
  21. meutils/apis/volcengine_apis/videos.py +5 -2
  22. meutils/config_utils/lark_utils/common.py +19 -3
  23. meutils/data/VERSION +1 -1
  24. meutils/llm/check_utils.py +26 -13
  25. meutils/llm/completions/qwenllm.py +5 -4
  26. meutils/llm/models_mapping.py +76 -0
  27. meutils/llm/openai_utils/usage_utils.py +19 -0
  28. meutils/llm/utils.py +1 -54
  29. meutils/schemas/hailuo_types.py +13 -4
  30. meutils/schemas/image_types.py +1 -1
  31. meutils/schemas/oneapi/_types.py +19 -7
  32. meutils/schemas/oneapi/common.py +20 -12
  33. meutils/serving/fastapi/dependencies/auth.py +2 -1
  34. meutils/serving/fastapi/dependencies/headers.py +19 -15
  35. meutils/str_utils/__init__.py +21 -0
  36. meutils/str_utils/regular_expression.py +8 -1
  37. examples/pyinstxtractor.py +0 -340
  38. meutils/apis/kuaidi.py +0 -32
  39. meutils/apis/veo/videos.py +0 -48
  40. {MeUtils-2025.6.18.16.41.23.dist-info → MeUtils-2025.6.24.11.13.32.dist-info}/LICENSE +0 -0
  41. {MeUtils-2025.6.18.16.41.23.dist-info → MeUtils-2025.6.24.11.13.32.dist-info}/WHEEL +0 -0
  42. {MeUtils-2025.6.18.16.41.23.dist-info → MeUtils-2025.6.24.11.13.32.dist-info}/entry_points.txt +0 -0
  43. {MeUtils-2025.6.18.16.41.23.dist-info → MeUtils-2025.6.24.11.13.32.dist-info}/top_level.txt +0 -0
@@ -74,14 +74,63 @@ async def edit_channel(models, token: Optional[str] = None):
74
74
  logger.debug(bjson(response.json()))
75
75
 
76
76
 
77
+ async def exist_channel(
78
+ request: ChannelInfo,
79
+
80
+ base_url: Optional[str] = None,
81
+ api_key: Optional[str] = None,
82
+ ):
83
+ if request.id is None:
84
+ return False
85
+ base_url = base_url or "https://api.chatfire.cn"
86
+ api_key = api_key or os.getenv("CHATFIRE_ONEAPI_TOKEN")
87
+
88
+ headers = {
89
+ 'authorization': f'Bearer {api_key}',
90
+ 'new-api-user': '1',
91
+ 'rix-api-user': '1',
92
+ }
93
+ async with httpx.AsyncClient(base_url=base_url, headers=headers, timeout=100) as client:
94
+ response = await client.get("/api/channel/", params={"channel_id": request.id})
95
+ response.raise_for_status()
96
+ logger.debug(response.json())
97
+
98
+ if items := response.json()['data']['items']:
99
+ return items[0]
100
+ else:
101
+ return False
102
+
103
+
77
104
  async def create_or_update_channel(
78
105
  request: ChannelInfo,
79
106
 
80
107
  base_url: Optional[str] = None,
81
108
  api_key: Optional[str] = None,
82
109
  ):
83
- method = "put" if request.id else "post"
84
- base_url = base_url or "https://api.chatfire.cn"
110
+ if request.id and isinstance(request.id, str): # 批量更新
111
+ ids = []
112
+ if "," in request.id:
113
+ ids = map(int, request.id.split(","))
114
+ elif ':' in request.id:
115
+ start, end = map(int, request.id.split(":"))
116
+ ids = range(start, end)
117
+
118
+ request_list = []
119
+ for i, k in zip(ids, request.key.split()): # api_key不为空
120
+ _request = request.copy()
121
+ _request.id = i
122
+ _request.key = k
123
+ request_list.append(_request)
124
+
125
+ tasks = [create_or_update_channel(r, base_url, api_key) for r in request_list]
126
+ return await asyncio.gather(*tasks)
127
+
128
+ base_url = base_url or "https://api.chatfire.cn"
129
+
130
+ method = "post"
131
+ if await exist_channel(request, base_url, api_key):
132
+ logger.debug(f"渠道已存在,跳过创建:{request.id}")
133
+ method = "put"
85
134
 
86
135
  # 新创建的优先级低,保证旧key刷的时间更长
87
136
  request.priority = request.priority or int(1000 - (time.time() - time.time() // 1000 * 1000))
@@ -93,7 +142,7 @@ async def create_or_update_channel(
93
142
  'rix-api-user': '1',
94
143
  }
95
144
  payload = request.model_dump(exclude_none=True)
96
- async with httpx.AsyncClient(base_url=base_url, headers=headers, timeout=60) as client:
145
+ async with httpx.AsyncClient(base_url=base_url, headers=headers, timeout=100) as client:
97
146
  response = await client.request(method, "/api/channel/", json=payload)
98
147
  response.raise_for_status()
99
148
  logger.debug(response.json())
@@ -187,11 +236,13 @@ if __name__ == '__main__':
187
236
  # arun(create_or_update_channel(tokens, base_url))
188
237
  # arun(create_or_update_channel(tokens))
189
238
  # # arun(delete_channel(range(10000, 20000)))
190
- key= "KEY"
239
+ key = "KEY"
191
240
  request = ChannelInfo(name='', key=key)
192
- request = ChannelInfo(key=key)
241
+ request = ChannelInfo(id=10010, key=key)
242
+
243
+ # arun(create_or_update_channel(request))
193
244
 
194
- arun(create_or_update_channel(request))
245
+ arun(exist_channel(request))
195
246
 
196
247
  """
197
248
  API_KEY=6c255307-7b4d-4be8-984b-5440a3e867eb
@@ -107,10 +107,10 @@ async def get_user_from_api_key(api_key):
107
107
  if __name__ == '__main__':
108
108
  # api-key => get_one_log => get_user => put_user
109
109
  # arun(get_user(814))
110
- # payload = arun(get_user(924))
110
+ payload = arun(get_user(1))
111
111
  # print(payload)
112
- # arun(put_user(payload, -1))
112
+ arun(put_user(payload['data'], -1))
113
113
 
114
114
  # arun(get_api_key_log('sk-gpoH1z3G6nHovD8MY40i6xx5tsC1vbh7B3Aao2jmejYNoKhv'))
115
115
  # arun(get_user_money("sk-LlB4W38z9kv5Wy1c3ceeu4PHeIWs6bbWsjr8Om31jYvsucRv"))
116
- arun(get_user_from_api_key('sk-blrcheysazcdqkyghaumetjhzscjedyppghmlujmzhuuyfeu'))
116
+ # arun(get_user_from_api_key('sk-blrcheysazcdqkyghaumetjhzscjedyppghmlujmzhuuyfeu'))
@@ -2,7 +2,7 @@
2
2
  # -*- coding: utf-8 -*-
3
3
  # @Project : AI. @by PyCharm
4
4
  # @File : __init__.py
5
- # @Time : 2025/6/18 16:34
5
+ # @Time : 2025/6/20 11:31
6
6
  # @Author : betterme
7
7
  # @WeChat : meutils
8
8
  # @Software : PyCharm
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ # @Project : AI. @by PyCharm
4
+ # @File : videos
5
+ # @Time : 2025/6/20 11:31
6
+ # @Author : betterme
7
+ # @WeChat : meutils
8
+ # @Software : PyCharm
9
+ # @Description :
10
+
11
+ from meutils.pipe import *
12
+ from meutils.db.redis_db import redis_aclient
13
+ from meutils.apis.utils import make_request
14
+ from meutils.schemas.hailuo_types import VideoRequest, VideoResponse
15
+
16
+ from fastapi import APIRouter, File, UploadFile, Query, Form, Depends, Request, HTTPException, status, BackgroundTasks
17
+
18
+ base_url = "https://api.ppinfra.com/v3"
19
+
20
+
21
+ # minimax-hailuo-02-6s-768p minimax-hailuo-02-6s-768p minimax-hailuo-02-6s-1080p
22
+ async def create_task(request: VideoRequest, api_key: Optional[str] = None):
23
+ api_key = api_key or "sk_fh6OykfJHgO_Hx2TWBRe2SJMC6quHvCN7g--fO5FfcQ"
24
+
25
+ payload = {
26
+
27
+ "prompt": request.prompt,
28
+ "image_url": request.first_frame_image,
29
+
30
+ "duration": request.duration,
31
+ "resolution": request.resolution.upper(),
32
+ "enable_prompt_expansion": request.prompt_optimizer
33
+ }
34
+ response = await make_request(
35
+ base_url=base_url,
36
+ api_key=api_key,
37
+
38
+ path="/async/minimax-hailuo-02",
39
+ payload=payload,
40
+ )
41
+
42
+ # return response # {'task_id': 'f97d3f93-bb29-47d9-9327-77e70982bd43'}
43
+
44
+ video_response = VideoResponse(
45
+ task_id=response['task_id'],
46
+ base_resp={
47
+ "status_code": 0,
48
+ "status_msg": "Processing"
49
+ }
50
+ )
51
+
52
+ await redis_aclient.set(video_response.task_id, api_key, ex=7 * 24 * 3600) # todo 装饰器
53
+ return video_response
54
+
55
+
56
+ async def get_task(task_id: str):
57
+ token = await redis_aclient.get(task_id) # 绑定对应的 token
58
+ token = token and token.decode()
59
+
60
+ logger.debug(f"token: {token}")
61
+ if not token:
62
+ raise HTTPException(status_code=404, detail="TaskID not found")
63
+
64
+ response = await make_request(
65
+ base_url=base_url,
66
+ api_key=token,
67
+
68
+ path=f"/async/task-result?task_id={task_id}",
69
+
70
+ method='GET'
71
+ )
72
+ logger.debug(bjson(response))
73
+ """
74
+ {
75
+ "audios": [],
76
+ "extra": {},
77
+ "images": [],
78
+ "task": {
79
+ "eta": 0,
80
+ "progress_percent": 0,
81
+ "reason": "",
82
+ "status": "TASK_STATUS_SUCCEED",
83
+ "task_id": "f97d3f93-bb29-47d9-9327-77e70982bd43",
84
+ "task_type": "MINIMAX_HAILUO_02_6S_768P"
85
+ },
86
+ "videos": [
87
+ {
88
+ "nsfw_detection_result": null,
89
+ "video_type": "mp4",
90
+ "video_url": "https://faas-minimax-video-1312767721.cos.ap-shanghai.myqcloud.com/prod/281961854701760-ceb3b321-0ed3-43a3-9bb8-ca579a8abd4f.mp4?q-sign-algorithm=sha1&q-ak=AKIDHOHvKVnrgHkyxhCTyOdeSjoiRxGPSJ0V&q-sign-time=1750392487%3B1750396087&q-key-time=1750392487%3B1750396087&q-header-list=host&q-url-param-list=&q-signature=202c563db2ab6385a7ebe3e4650ee01ed3376e06",
91
+ "video_url_ttl": "0"
92
+ }
93
+ ]
94
+ }
95
+ """
96
+ video_response = VideoResponse(
97
+ task_id=task_id,
98
+ status="Processing",
99
+ base_resp={
100
+ "status_code": 0,
101
+ "status_msg": "Processing"
102
+ }
103
+ )
104
+ if response['task']['status'] == 'TASK_STATUS_SUCCEED':
105
+ video_response.status = "Success"
106
+ video_response.base_resp.status_msg = "Success"
107
+ video_response.videos = response['videos']
108
+
109
+
110
+ elif any(i in response['task']['status'].lower() for i in {"fail", 'error'}):
111
+ video_response.status = "Failed"
112
+ video_response.base_resp.status_code = 1027
113
+ video_response.base_resp.status_msg = "Failed"
114
+
115
+ return video_response # {'task_id': 'f97d3f93-bb29-47d9-9327-77e70982bd43'}
116
+
117
+
118
+ if __name__ == '__main__':
119
+ api_key = os.getenv('PPIO_API_KEY')
120
+
121
+ payload = {
122
+ "image_url": "https://static.ppinfra.com/docs/assets/minimax-hailuo-video-02-input-image.jpg",
123
+ "prompt": "戴着太阳镜的毛茸茸的熊猫在日出时的雪山顶上跳舞,左移运镜",
124
+ "duration": 6,
125
+ "resolution": "768P",
126
+ "enable_prompt_expansion": True
127
+ }
128
+
129
+ request = VideoRequest(
130
+ prompt="戴着太阳镜的毛茸茸的熊猫在日出时的雪山顶上跳舞,左移运镜",
131
+ first_frame_image="https://static.ppinfra.com/docs/assets/minimax-hailuo-video-02-input-image.jpg",
132
+ duration=6,
133
+ resolution="768P",
134
+ )
135
+
136
+ # r = arun(create_task(request, api_key=api_key))
137
+
138
+ # arun(get_task("d8b048d0-5c54-42ef-a691-3feab31693fe"))
139
+
140
+ # print(request.model_dump_json(exclude_none=True))
141
+
142
+ arun(get_task("05f31694-fed2-4069-b6be-6c85b70fef2b"))
@@ -5,17 +5,17 @@ from meutils.pipe import *
5
5
  from meutils.caches import rcache
6
6
  from meutils.decorators.retry import retrying
7
7
 
8
- username = "d1999983904" # 包月
8
+ username = "d1982743732" # 包月
9
9
  password = "1h29rymg"
10
10
 
11
11
 
12
- @rcache(ttl=60 - 50)
12
+ @rcache(ttl=120)
13
13
  @retrying()
14
14
  async def get_proxy_list():
15
- secret_id = os.getenv("KDLAPI_SECRET_ID") or "owklc8tk3ypo00ohu80o"
16
- signature = os.getenv("KDLAPI_SIGNATURE") or "8gqqy7w64g7uunseaz9tcae7h8saa24p"
15
+ secret_id = os.getenv("KDLAPI_SECRET_ID")
16
+ signature = os.getenv("KDLAPI_SIGNATURE")
17
17
  url = f"https://dps.kdlapi.com/api/getdps/?secret_id={secret_id}&signature={signature}&num=1&pt=1&format=json&sep=1"
18
- async with httpx.AsyncClient() as client:
18
+ async with httpx.AsyncClient(timeout=30) as client:
19
19
  response = await client.get(url)
20
20
  response.raise_for_status()
21
21
  proxy_list = response.json().get('data').get('proxy_list')
@@ -32,25 +32,27 @@ if __name__ == '__main__':
32
32
  # arun(get_proxy_list())
33
33
 
34
34
  page_url = "https://icanhazip.com/" # 要访问的目标网页
35
- # page_url = "https://httpbin.org/ip"
36
35
 
37
36
 
37
+ # page_url = "https://httpbin.org/ip"
38
+
38
39
  async def fetch(url):
39
- # proxy = await get_one_proxy()
40
- proxy = "http://154.9.253.9:38443"
41
- # proxy="https://tinyproxy.chatfire.cn"
42
- # proxy="https://pp.chatfire.cn"
43
- proxy="http://110.42.51.201:38443"
44
- proxy="http://110.42.51.223:38443"
45
- proxy = "http://110.42.51.223:38443"
40
+ proxy = await get_one_proxy()
41
+ # proxy = "http://154.9.253.9:38443"
42
+ # # proxy="https://tinyproxy.chatfire.cn"
43
+ # # proxy="https://pp.chatfire.cn"
44
+ # proxy = "http://110.42.51.201:38443"
45
+ # proxy = "http://110.42.51.223:38443"
46
+ # proxy = "http://110.42.51.223:38443"
46
47
 
47
48
  # proxy=None
48
- proxy="https://npjdodcrxljt.ap-northeast-1.clawcloudrun.com"
49
+ # proxy = "https://npjdodcrxljt.ap-northeast-1.clawcloudrun.com"
49
50
 
50
51
  async with httpx.AsyncClient(proxy=proxy, timeout=30) as client:
51
52
  resp = await client.get(url)
52
53
  logger.debug((f"status_code: {resp.status_code}, content: {resp.text}"))
53
54
 
55
+
54
56
  def run():
55
57
  loop = asyncio.get_event_loop()
56
58
  # 异步发出5次请求
@@ -59,3 +61,5 @@ if __name__ == '__main__':
59
61
 
60
62
 
61
63
  run()
64
+
65
+ # arun(get_one_proxy())
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ # @Project : AI. @by PyCharm
4
+ # @File : transparent_transmission
5
+ # @Time : 2025/6/18 16:45
6
+ # @Author : betterme
7
+ # @WeChat : meutils
8
+ # @Software : PyCharm
9
+ # @Description : 透传
10
+
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ # @Project : AI. @by PyCharm
4
+ # @File : tasks
5
+ # @Time : 2025/6/18 16:51
6
+ # @Author : betterme
7
+ # @WeChat : meutils
8
+ # @Software : PyCharm
9
+ # @Description :
10
+
11
+
12
+ from meutils.pipe import *
13
+ from meutils.llm.clients import AsyncOpenAI
14
+
15
+
16
+ # dynamic_router
17
+ # async def create_task(
18
+ # request: dict,
19
+ # api_key: Optional[str] = None
20
+ # ):
21
+ # payload = request
22
+ # client = AsyncOpenAI(base_url=base_url, api_key=api_key)
23
+ # response = client.post(
24
+ # ,
25
+ # body=payload,
26
+ # cast_to=dict,
27
+ # )
28
+ # return response
meutils/apis/utils.py CHANGED
@@ -6,34 +6,35 @@
6
6
  # @Author : betterme
7
7
  # @WeChat : meutils
8
8
  # @Software : PyCharm
9
- # @Description : textinparsex
9
+ # @Description :
10
10
 
11
- from openai import AsyncClient
12
11
  from meutils.pipe import *
12
+ from openai import AsyncClient
13
13
 
14
14
 
15
- # upstream_base_url: Optional[str] = Header(None),
16
- # upstream_api_key: Optional[str] = Header(None),
17
-
18
15
  async def make_request(
19
16
  base_url: str,
20
- path: str,
21
17
  api_key: Optional[str] = None,
22
-
23
- method: str = "GET",
24
18
  headers: Optional[dict] = None,
25
19
 
20
+ path: Optional[str] = None,
21
+
26
22
  params: Optional[dict] = None,
27
23
  payload: Optional[dict] = None,
28
24
  files: Optional[dict] = None,
29
25
 
26
+ method: str = "POST",
27
+
28
+ timeout: Optional[int] = None,
30
29
  ):
31
- client = AsyncClient(base_url=base_url, api_key=api_key, default_headers=headers)
30
+ client = AsyncClient(base_url=base_url, api_key=api_key, default_headers=headers, timeout=timeout)
32
31
 
33
32
  options = {}
34
33
  if params:
35
34
  options["params"] = params
36
35
 
36
+ path = path or "/"
37
+
37
38
  if method.upper() == 'GET':
38
39
  response = await client.get(path, options=options, cast_to=object)
39
40
  return response
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ # @Project : AI. @by PyCharm
4
+ # @File : videos
5
+ # @Time : 2025/6/18 16:34
6
+ # @Author : betterme
7
+ # @WeChat : meutils
8
+ # @Software : PyCharm
9
+ # @Description :
10
+
11
+ from meutils.pipe import *
12
+ from meutils.db.redis_db import redis_aclient
13
+ from meutils.apis.utils import make_request
14
+ from fastapi import APIRouter, File, UploadFile, Query, Form, Depends, Request, HTTPException, status, BackgroundTasks
15
+
16
+ base_url = "https://api.gptgod.online"
17
+
18
+
19
+ async def create_task(
20
+ request: dict,
21
+ api_key: Optional[str] = None
22
+ ):
23
+ response = await make_request(
24
+ base_url=base_url,
25
+ api_key=api_key,
26
+ path="/v1/video/create",
27
+ payload=request,
28
+ )
29
+
30
+ if task_id := response.get('id'):
31
+ await redis_aclient.set(task_id, api_key, ex=7 * 24 * 3600)
32
+
33
+ return response
34
+
35
+
36
+ async def get_task(task_id: str):
37
+ token = await redis_aclient.get(task_id) # 绑定对应的 token
38
+ token = token and token.decode()
39
+ if not token:
40
+ raise HTTPException(status_code=404, detail="TaskID not found")
41
+
42
+ response = await make_request(
43
+ base_url=base_url,
44
+ api_key=token,
45
+ path=f"/v1/video/query?id={task_id}",
46
+ method="GET",
47
+ )
48
+ return response
49
+
50
+
51
+ if __name__ == '__main__':
52
+ api_key = "sk-h0Cgw9qeyotIUC9WnWSBEB0aO4RbjgEbhZmtg2Ja0kL5npDZ1"
53
+ payload = {
54
+ "prompt": "牛飞上天了",
55
+ "model": "veo3",
56
+ "images": [
57
+ "https://filesystem.site/cdn/20250612/VfgB5ubjInVt8sG6rzMppxnu7gEfde.png",
58
+ "https://filesystem.site/cdn/20250612/998IGmUiM2koBGZM3UnZeImbPBNIUL.png"
59
+ ],
60
+ "enhance_prompt": True
61
+ }
62
+
63
+ # arun(create_task(payload, api_key))
64
+
65
+ arun(get_task("veo3:2ba161ec-747f-4d5b-b58b-2a610bfc2c31"))
66
+
67
+
68
+
@@ -6,7 +6,8 @@
6
6
  # @Author : betterme
7
7
  # @WeChat : meutils
8
8
  # @Software : PyCharm
9
- # @Description :
9
+ # @Description :
10
+ import time
10
11
 
11
12
  from meutils.pipe import *
12
13
  from meutils.io.files_utils import to_url
@@ -27,14 +28,16 @@ FEISHU_URL = "https://xchatllm.feishu.cn/sheets/GYCHsvI4qhnDPNtI4VPcdw2knEd?shee
27
28
 
28
29
  async def get_valid_token(tokens: Optional[list] = None):
29
30
  tokens = tokens or await get_series(FEISHU_URL)
31
+
30
32
  for token in tokens:
31
33
  if await check(token):
34
+
32
35
  logger.debug(f"有效 {token}")
33
36
 
34
37
  return token
35
38
  else:
36
39
  logger.debug(f"无效 {token}")
37
- _ = f"{FEISHU_URL}\n\n所有token无效"
40
+ _ = f"{time.ctime()}\n\n{FEISHU_URL}\n\n所有token无效"
38
41
  logger.error(_)
39
42
  send_message(_, n=3)
40
43
 
@@ -10,14 +10,14 @@
10
10
 
11
11
  from meutils.pipe import *
12
12
  from meutils.caches import rcache
13
-
13
+ from meutils.str_utils import parse_slice
14
14
  from meutils.decorators.retry import retrying
15
15
  from meutils.decorators.contextmanagers import try_catcher
16
16
  from meutils.notice.feishu import send_message
17
17
  from meutils.db.redis_db import redis_client, redis_aclient
18
18
  from typing import Optional, Union
19
19
 
20
- from urllib.parse import urlparse, parse_qs
20
+ from urllib.parse import urlparse, parse_qs, unquote
21
21
 
22
22
  FEISHU_BASE_URL = "https://open.feishu.cn/open-apis/"
23
23
 
@@ -307,12 +307,22 @@ async def get_dataframe(iloc_tuple: Optional[tuple] = None, feishu_url: Optional
307
307
 
308
308
 
309
309
  async def get_series(feishu_url: str, index: int = 0, duplicated: bool = False): # 系统配置
310
+ # 前置处理
311
+ # https://xchatllm.feishu.cn/sheets/Bmjtst2f6hfMqFttbhLcdfRJnNf?sheet=Y7HVfo[:2]
312
+ slice_obj = None
313
+ if feishu_url.endswith(']') and '[' in feishu_url: # 是否解码
314
+ logger.debug(feishu_url)
315
+ feishu_url, slice_string = feishu_url.rsplit('[', maxsplit=1)
316
+ slice_obj = parse_slice(f"[{slice_string}")
317
+
310
318
  df = await aget_spreadsheet_values(feishu_url=feishu_url, to_dataframe=True)
311
319
  series = df[index]
312
320
  values = [i for i in series if i and isinstance(i, str)] # todo: 非标准字符串处理
313
321
  if duplicated: # 有序去重
314
322
  values = values | xUnique
315
323
 
324
+ if slice_obj:
325
+ values = values[slice_obj]
316
326
  return values
317
327
 
318
328
 
@@ -395,4 +405,10 @@ if __name__ == '__main__':
395
405
  # token = arun(get_next_token(feishu_url))
396
406
 
397
407
  # FEISHU_URL = "https://xchatllm.feishu.cn/sheets/XfjqszII3hZAEvtTOgecOgv2nye?sheet=c14b34"
398
- # print(arun(get_series(FEISHU_URL)))
408
+ FEISHU_URL="https://xchatllm.feishu.cn/sheets/RIv6sAUtFhlZYItyYa6ctdv1nvb?sheet=0bcf4a[:2]"
409
+ FEISHU_URL="https://xchatllm.feishu.cn/sheets/RIv6sAUtFhlZYItyYa6ctdv1nvb?sheet=0bcf4a"
410
+
411
+ # FEISHU_URL="https://xchatllm.feishu.cn/sheets/Bmjtst2f6hfMqFttbhLcdfRJnNf?sheet=Y7HVfo%5B%3A2%5D"
412
+
413
+ r = arun(get_series(FEISHU_URL))
414
+
meutils/data/VERSION CHANGED
@@ -1 +1 @@
1
- 2025.06.18.16.41.23
1
+ 2025.06.24.11.13.32
@@ -26,7 +26,7 @@ async def check_tokens(tokens, check_token: Callable):
26
26
 
27
27
 
28
28
  @retrying()
29
- @rcache(ttl=1 * 3600)
29
+ # @rcache(ttl=1 * 3600)
30
30
  async def check_token_for_siliconflow(api_key, threshold: float = 0):
31
31
  if not isinstance(api_key, str):
32
32
  return await check_tokens(api_key, check_token_for_siliconflow)
@@ -36,17 +36,29 @@ async def check_token_for_siliconflow(api_key, threshold: float = 0):
36
36
  "Accept": "application/json"
37
37
  }
38
38
  try:
39
- async with httpx.AsyncClient(headers=headers, timeout=60) as client:
40
- response: httpx.Response = await client.get("https://api.siliconflow.cn/v1/user/info")
41
- response.raise_for_status()
42
-
43
- logger.debug(response.text)
44
- logger.debug(response.status_code)
45
39
 
46
- if response.is_success:
47
- logger.debug(api_key)
48
- total_balance = response.json()['data']['totalBalance']
49
- return float(total_balance) >= threshold
40
+ client = AsyncOpenAI(base_url=os.getenv("SILICONFLOW_BASE_URL"), api_key=api_key)
41
+ # _ = await client.chat.completions.create(
42
+ # model="Qwen/Qwen3-8B",
43
+ # messages=[{'role': 'user', 'content': "hi"}],
44
+ # max_tokens=1)
45
+ # print(_)
46
+ if models := (await client.models.list()).data:
47
+ if threshold <= 0: return True # 有效key
48
+
49
+ async with httpx.AsyncClient(headers=headers, timeout=60) as client:
50
+ response: httpx.Response = await client.get("https://api.siliconflow.cn/v1/user/info")
51
+ response.raise_for_status()
52
+
53
+ logger.debug(response.text)
54
+ logger.debug(response.status_code)
55
+
56
+ if response.is_success:
57
+ logger.debug(api_key)
58
+ total_balance = response.json()['data']['totalBalance']
59
+ return float(total_balance) >= threshold
60
+ else:
61
+ return False
50
62
  except TimeoutException as e:
51
63
  # logger.error(traceback.format_exc().strip())
52
64
 
@@ -228,7 +240,7 @@ if __name__ == '__main__':
228
240
 
229
241
  check_valid_token = partial(check_token_for_siliconflow, threshold=-1)
230
242
 
231
- # arun(check_valid_token("sk-tythaoctwemlhkytdlmjcegtnufvhqgmwlncgmoxixdyqoxx"))
243
+ arun(check_valid_token("sk-ggskfnxtlufyriixuquivrrczguartklbykfavmroddasxoi"))
232
244
 
233
245
  pass
234
246
  # arun(check_valid_token("sk-LlB4W38z9kv5Wy1c3ceeu4PHeIWs6bbWsjr8Om31jYvsucRv", threshold=0.1))
@@ -258,4 +270,5 @@ if __name__ == '__main__':
258
270
 
259
271
  # arun(check_token_for_ppinfra("sk_F0kgPyCMTzmOH_-VCEJucOK8HIrbnLGYm_IWxBToHZQ"))
260
272
 
261
- arun(check_token_for_volc("07139a08-e360-44e2-ba31-07f379bf99ed"))
273
+ # arun(check_token_for_volc("07139a08-e360-44e2-ba31-07f379bf99ed"))
274
+ # arun(check_token_for_ppinfra("sk_mCb5sRGTi6GXkSRp5F679Rbs0V_Hfee3p85lccGXCOo"))
@@ -249,7 +249,7 @@ if __name__ == '__main__':
249
249
  # model="qwen-max-latest",
250
250
  # model="qvq-max-2025-03-25",
251
251
  # model="qvq-72b-preview-0310",
252
- # model="qwen2.5-omni-7b",
252
+ model="qwen2.5-omni-7b",
253
253
 
254
254
  # model="qwen-max-latest-search",
255
255
  # model="qwq-max",
@@ -259,7 +259,7 @@ if __name__ == '__main__':
259
259
  # model="qwen2.5-vl-72b-instruct",
260
260
 
261
261
  # model="qwen-plus-latest",
262
- model="qwen3-235b-a22b",
262
+ # model="qwen3-235b-a22b",
263
263
  # model="qwen3-30b-a3b",
264
264
  # model="qwen3-32b",
265
265
 
@@ -271,7 +271,8 @@ if __name__ == '__main__':
271
271
  'role': 'user',
272
272
  # 'content': '今天南京天气',
273
273
  # 'content': "9.8 9.11哪个大",
274
- 'content': 'https://oss.ffire.cc/files/AIGC.pdf 总结下',
274
+ # 'content': 'https://oss.ffire.cc/files/AIGC.pdf 总结下',
275
+ 'content': ' 总结下',
275
276
 
276
277
  # "chat_type": "search", deep_research
277
278
 
@@ -339,7 +340,7 @@ if __name__ == '__main__':
339
340
  )
340
341
  token = None
341
342
 
342
- token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjMxMGNiZGFmLTM3NTQtNDYxYy1hM2ZmLTllYzgwMDUzMjljOSIsImV4cCI6MTc0ODQ3OTE0M30.oAIE1K0XA0YYqlxB8Su-u0UJbY_BBZa4_tvZpFJKxGY"
343
+ # token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjMxMGNiZGFmLTM3NTQtNDYxYy1hM2ZmLTllYzgwMDUzMjljOSIsImV4cCI6MTc0ODQ3OTE0M30.oAIE1K0XA0YYqlxB8Su-u0UJbY_BBZa4_tvZpFJKxGY"
343
344
 
344
345
  arun(create(request, token))
345
346