MeUtils 2025.1.4.11.4.46__py3-none-any.whl → 2025.1.10.20.14.42__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.1.4.11.4.46.dist-info → MeUtils-2025.1.10.20.14.42.dist-info}/METADATA +28 -28
- {MeUtils-2025.1.4.11.4.46.dist-info → MeUtils-2025.1.10.20.14.42.dist-info}/RECORD +71 -63
- examples/_openaisdk/openai_chatfire.py +11 -4
- examples/_openaisdk/openai_deepinfra.py +1 -1
- examples/_openaisdk/openai_images.py +6 -1
- examples/_openaisdk/openai_lingyi.py +59 -0
- examples/_openaisdk/openai_ppu.py +47 -0
- examples/_openaisdk/openai_test.py +2 -2
- examples/_openaisdk/openai_together.py +57 -0
- examples/_openaisdk/openai_zhipu.py +4 -3
- meutils/ai_audio/asr/openai_asr.py +2 -2
- meutils/apis/audio/deepinfra.py +2 -2
- meutils/apis/chatglm/glm_video_api.py +1 -1
- meutils/apis/common.py +5 -1
- meutils/apis/hailuoai/videos.py +14 -5
- meutils/apis/images/eidt.py +36 -0
- meutils/apis/images/gitee_kolors.py +49 -0
- meutils/apis/images/recraft.py +24 -6
- meutils/apis/niutrans.py +27 -8
- meutils/apis/oneapi/utils.py +24 -9
- meutils/apis/translator/deeplx.py +4 -3
- meutils/apis/vidu/vidu_video.py +6 -5
- meutils/caches/redis_cache.py +5 -0
- meutils/common.py +1 -0
- meutils/config_utils/lark_utils/common.py +0 -1
- meutils/data/VERSION +1 -1
- meutils/data/oneapi/NOTICE.md +5 -7
- meutils/io/files_utils.py +11 -5
- meutils/io/image.py +28 -2
- meutils/llm/clients.py +38 -0
- meutils/llm/completions/agents/file.py +124 -0
- meutils/llm/openai_utils/common.py +2 -2
- meutils/llm/utils.py +79 -0
- meutils/llm/x.py +75 -0
- meutils/notice/feishu.py +1 -0
- meutils/parsers/__init__.py +10 -0
- meutils/parsers/file_parsers.py +107 -0
- meutils/schemas/db/oneapi_types.py +3 -0
- meutils/schemas/image_types.py +28 -2
- meutils/schemas/kuaishou_types.py +1 -1
- meutils/schemas/oneapi/common.py +26 -16
- meutils/schemas/vidu_types.py +33 -12
- meutils/serving/fastapi/exceptions/http_error.py +2 -6
- meutils/str_utils/regular_expression.py +29 -6
- meutils/llm/completions/agents/files.py +0 -18
- meutils/llm/openai_client.py +0 -15
- {MeUtils-2025.1.4.11.4.46.dist-info → MeUtils-2025.1.10.20.14.42.dist-info}/LICENSE +0 -0
- {MeUtils-2025.1.4.11.4.46.dist-info → MeUtils-2025.1.10.20.14.42.dist-info}/WHEEL +0 -0
- {MeUtils-2025.1.4.11.4.46.dist-info → MeUtils-2025.1.10.20.14.42.dist-info}/entry_points.txt +0 -0
- {MeUtils-2025.1.4.11.4.46.dist-info → MeUtils-2025.1.10.20.14.42.dist-info}/top_level.txt +0 -0
- /meutils/{fileparser → parsers/fileparser}/PDF/346/212/275/345/217/226.py" +0 -0
- /meutils/{fileparser → parsers/fileparser}/__init__.py +0 -0
- /meutils/{fileparser → parsers/fileparser}/common.py +0 -0
- /meutils/{fileparser → parsers/fileparser}/demo.py +0 -0
- /meutils/{fileparser → parsers/fileparser}/filetype/__init__.py +0 -0
- /meutils/{fileparser → parsers/fileparser}/filetype/__main__.py +0 -0
- /meutils/{fileparser → parsers/fileparser}/filetype/filetype.py +0 -0
- /meutils/{fileparser → parsers/fileparser}/filetype/helpers.py +0 -0
- /meutils/{fileparser → parsers/fileparser}/filetype/match.py +0 -0
- /meutils/{fileparser → parsers/fileparser}/filetype/types/__init__.py +0 -0
- /meutils/{fileparser → parsers/fileparser}/filetype/types/application.py +0 -0
- /meutils/{fileparser → parsers/fileparser}/filetype/types/archive.py +0 -0
- /meutils/{fileparser → parsers/fileparser}/filetype/types/audio.py +0 -0
- /meutils/{fileparser → parsers/fileparser}/filetype/types/base.py +0 -0
- /meutils/{fileparser → parsers/fileparser}/filetype/types/document.py +0 -0
- /meutils/{fileparser → parsers/fileparser}/filetype/types/font.py +0 -0
- /meutils/{fileparser → parsers/fileparser}/filetype/types/image.py +0 -0
- /meutils/{fileparser → parsers/fileparser}/filetype/types/isobmff.py +0 -0
- /meutils/{fileparser → parsers/fileparser}/filetype/types/video.py +0 -0
- /meutils/{fileparser → parsers/fileparser}/filetype/utils.py +0 -0
- /meutils/{fileparser → parsers/fileparser}/filetype.py +0 -0
- /meutils/{fileparser → parsers/fileparser}/pdf.py +0 -0
- /meutils/{fileparser → parsers/fileparser}//350/241/250/346/240/274/346/212/275/345/217/226.py" +0 -0
meutils/apis/vidu/vidu_video.py
CHANGED
@@ -206,20 +206,21 @@ if __name__ == '__main__':
|
|
206
206
|
# arun(get_credits(token))
|
207
207
|
#
|
208
208
|
d = {
|
209
|
-
"
|
210
|
-
|
209
|
+
"model": 'vidu-1.5',
|
210
|
+
"prompt": "这个女人笑起来",
|
211
|
+
"url": "https://oss.ffire.cc/files/kling_watermark.png" # failed to save uploads
|
211
212
|
}
|
212
213
|
token = None
|
213
214
|
# print(bjson(ViduRequest(**d).payload))
|
214
|
-
|
215
|
+
arun(create_task(ViduRequest(**d)))
|
215
216
|
# arun(create_task(ViduRequest(**d), vip=False))
|
216
217
|
# # pass
|
217
218
|
# token = "sensorsdata2015jssdkcross=dfm-enc-%7B%22Va28a6y8_aV%22%3A%22sSsAAnHAInAGEtIG%22%2C%22gae28_aV%22%3A%22EGEuAnststSEirt-ARSAigSVHIiHVs-EtHsHnIR-sARInAA-EGEuAnststHsIti%22%2C%22OemO2%22%3A%7B%22%24ki8r28_8eiggay_2mbeyr_8cOr%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24ki8r28_2rieyz_lrcMmeV%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24ki8r28_ergreere%22%3A%22%22%7D%2C%22aVr68a8ar2%22%3A%22rc3liZ7ku67OV5kgPsGCiskkDskl3qmawFlJPq0swqfcpXNJPZKSBF0IQXLzWq7lQFQzQZNcBF1SQF3EQqwIBF3MQhwswX08wFlJPq0swqfcpXKcwhzz3aMax9klWZHAiD7HDsJCWskbDskl3qmawqNcwX0sQF0hQq0HwFfhp4xG%22%2C%22za28mec_kmfa6_aV%22%3A%7B%226ior%22%3A%22%24aVr68a8c_kmfa6_aV%22%2C%22Cikbr%22%3A%22sSsAAnHAInAGEtIG%22%7D%7D;_ga=GA1.1.2058758439.1724312077;_ga_ZJBV7VYP55=GS1.1.1727080335.38.1.1727080510.0.0.0;JWT=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MjgzNTAzODAsImlhdCI6MTcyNzA1NDM4MCwiaXNzIjoiaWFtIiwic3ViIjoiMjQyMDA2NTAzNjA5MTgzOSJ9.PkjQqjYB56vYetYwmlagnWn_6bSCwoxCjI7BjfelBOU;Shunt="
|
218
219
|
# # token = "_ga=GA1.1.2058758439.1724312077; JWT=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MjgzNTAzODAsImlhdCI6MTcyNzA1NDM4MCwiaXNzIjoiaWFtIiwic3ViIjoiMjQyMDA2NTAzNjA5MTgzOSJ9.PkjQqjYB56vYetYwmlagnWn_6bSCwoxCjI7BjfelBOU; Shunt=; sensorsdata2015jssdkcross=dfm-enc-%7B%22Va28a6y8_aV%22%3A%22sSsAAnHAInAGEtIG%22%2C%22gae28_aV%22%3A%22EGEuAnststSEirt-ARSAigSVHIiHVs-EtHsHnIR-sARInAA-EGEuAnststHsIti%22%2C%22OemO2%22%3A%7B%22%24ki8r28_8eiggay_2mbeyr_8cOr%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24ki8r28_2rieyz_lrcMmeV%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24ki8r28_ergreere%22%3A%22%22%7D%2C%22aVr68a8ar2%22%3A%22rc3liZ7ku67OV5kgPsGCiskkDskl3qmawFlJPq0swqfcpXNJPZKSBF0IQXLzWq7lQFQzQZNcBF1SQF3EQqwIBF3MQhwswX08wFlJPq0swqfcpXKcwhzz3aMax9klWZHAiD7HDsJCWskbDskl3qmawqNcwX0sQF0hQq0HwFfhp4xG%22%2C%22za28mec_kmfa6_aV%22%3A%7B%226ior%22%3A%22%24aVr68a8c_kmfa6_aV%22%2C%22Cikbr%22%3A%22sSsAAnHAInAGEtIG%22%7D%7D; _ga_ZJBV7VYP55=GS1.1.1727080335.38.1.1727080510.0.0.0"
|
219
220
|
# token = "JWT=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MjgzNDkyNzQsImlhdCI6MTcyNzA1MzI3NCwiaXNzIjoiaWFtIiwic3ViIjoiMjQyMDg5NjA4MTIwNTkwNyJ9.MRXmSr48PifQgRN1-yTTu8d7Sq1An4OS7G5WoYpJ_PU"
|
220
221
|
|
221
|
-
token = "_ga=GA1.1.1191408146.1725443726; Shunt=; JWT=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzY0NzgzODIsImlhdCI6MTczNTE4MjM4MiwiaXNzIjoiaWFtIiwic3ViIjoiMjU3NTg1MzI5MDUyNzYwNiJ9.AJBuQH0B9aQ2znnczYoqBw9YvHkLh0uZF0QQx5xdxrc; sensorsdata2015jssdkcross=dfm-enc-%7B%22Va28a6y8_aV%22%3A%22sHRHtHIsGAHsRnAn%22%2C%22gae28_aV%22%3A%22EGEuyRHVigIEtAG-AGRuSsHrVAGRuS-EtHsHnIR-sARInAA-EGEuyRHVigSEuIR%22%2C%22OemO2%22%3A%7B%22%24ki8r28_8eiggay_2mbeyr_8cOr%22%3A%22%E8%87%AA%E7%84%B6%E6%90%9C%E7%B4%A2%E6%B5%81%E9%87%8F%22%2C%22%24ki8r28_2rieyz_lrcMmeV%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC%22%2C%22%24ki8r28_ergreere%22%3A%22z88O2%3A%2F%2Fiyymb682.fmmfkr.ymo%2F%22%7D%2C%22aVr68a8ar2%22%3A%22rc3liZ7ku67OV5kgPsGCiskkDskl3qmawFlJPowIQZ7zWqwJpX0HBF0HQs3AwqdkWX0HQs3ABF1SQF3EQqwIBF3MQhwswX08wFlJPowIQZ7zWqNJPqwI3aMax9klWZHAiD7HDsJCWskbDskl3qmawqKIQFfEwh3HwXKcQhPMQaxG%22%2C%22za28mec_kmfa6_aV%22%3A%7B%226ior%22%3A%22%24aVr68a8c_kmfa6_aV%22%2C%22Cikbr%22%3A%22sHRHtHIsGAHsRnAn%22%7D%7D; _ga_ZJBV7VYP55=GS1.1.1735182278.4.1.1735182405.26.0.0"
|
222
|
-
arun(check_token(token))
|
222
|
+
# token = "_ga=GA1.1.1191408146.1725443726; Shunt=; JWT=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzY0NzgzODIsImlhdCI6MTczNTE4MjM4MiwiaXNzIjoiaWFtIiwic3ViIjoiMjU3NTg1MzI5MDUyNzYwNiJ9.AJBuQH0B9aQ2znnczYoqBw9YvHkLh0uZF0QQx5xdxrc; sensorsdata2015jssdkcross=dfm-enc-%7B%22Va28a6y8_aV%22%3A%22sHRHtHIsGAHsRnAn%22%2C%22gae28_aV%22%3A%22EGEuyRHVigIEtAG-AGRuSsHrVAGRuS-EtHsHnIR-sARInAA-EGEuyRHVigSEuIR%22%2C%22OemO2%22%3A%7B%22%24ki8r28_8eiggay_2mbeyr_8cOr%22%3A%22%E8%87%AA%E7%84%B6%E6%90%9C%E7%B4%A2%E6%B5%81%E9%87%8F%22%2C%22%24ki8r28_2rieyz_lrcMmeV%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC%22%2C%22%24ki8r28_ergreere%22%3A%22z88O2%3A%2F%2Fiyymb682.fmmfkr.ymo%2F%22%7D%2C%22aVr68a8ar2%22%3A%22rc3liZ7ku67OV5kgPsGCiskkDskl3qmawFlJPowIQZ7zWqwJpX0HBF0HQs3AwqdkWX0HQs3ABF1SQF3EQqwIBF3MQhwswX08wFlJPowIQZ7zWqNJPqwI3aMax9klWZHAiD7HDsJCWskbDskl3qmawqKIQFfEwh3HwXKcQhPMQaxG%22%2C%22za28mec_kmfa6_aV%22%3A%7B%226ior%22%3A%22%24aVr68a8c_kmfa6_aV%22%2C%22Cikbr%22%3A%22sHRHtHIsGAHsRnAn%22%7D%7D; _ga_ZJBV7VYP55=GS1.1.1735182278.4.1.1735182405.26.0.0"
|
223
|
+
# arun(check_token(token))
|
223
224
|
#
|
224
225
|
# FEISHU_URL = "https://xchatllm.feishu.cn/sheets/GYCHsvI4qhnDPNtI4VPcdw2knEd?sheet=rxldsA"
|
225
226
|
# FEISHU_URL="https://xchatllm.feishu.cn/sheets/GYCHsvI4qhnDPNtI4VPcdw2knEd?sheet=Hcr2i8"
|
meutils/caches/redis_cache.py
CHANGED
@@ -11,6 +11,7 @@
|
|
11
11
|
|
12
12
|
|
13
13
|
import hermes.backend.redis
|
14
|
+
import hermes.backend.inprocess
|
14
15
|
|
15
16
|
from meutils.db.redis_db import pool
|
16
17
|
|
@@ -19,6 +20,10 @@ cache = hermes.Hermes(
|
|
19
20
|
connection_pool=pool
|
20
21
|
)
|
21
22
|
|
23
|
+
cache_inmemory = hermes.Hermes(
|
24
|
+
backend=hermes.backend.inprocess.Backend,
|
25
|
+
)
|
26
|
+
|
22
27
|
if __name__ == '__main__':
|
23
28
|
from meutils.pipe import *
|
24
29
|
|
meutils/common.py
CHANGED
meutils/data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2025.01.
|
1
|
+
2025.01.10.20.14.42
|
meutils/data/oneapi/NOTICE.md
CHANGED
@@ -32,16 +32,15 @@
|
|
32
32
|
</details>
|
33
33
|
|
34
34
|
<details markdown="1">
|
35
|
-
<summary><b
|
35
|
+
<summary><b>大额充值优惠</b></summary>
|
36
36
|
|
37
|
-
-
|
38
|
-
- 充值100-200 增送5%
|
39
|
-
- 充值200-500 增送10%
|
40
|
-
- 充值500-1000 增送15%
|
41
|
-
- 充值1000-2000 增送20%
|
37
|
+
- 充值1000-2000 增送10%
|
42
38
|
|
43
39
|
</details>
|
44
40
|
|
41
|
+
## 2025-01-04
|
42
|
+
- 增加模型配额 gemini-2.0-flash-exp、gemini-2.0-flash-thinking-exp-1219
|
43
|
+
|
45
44
|
## 2024-12-31
|
46
45
|
|
47
46
|
- 上线新模型
|
@@ -49,7 +48,6 @@
|
|
49
48
|
在不显著降低通用任务能力的情况下,在专家任务能力方面表现大幅提升。其在 AIME 2024、MATH500 和 LiveCodeBench 评测中,效果与
|
50
49
|
OpenAI-o1-Preview 相当。
|
51
50
|
- 兼容SparkAI客户端,文件问答&图片问答:baseurl改为`https://api.chatfire.cn/sparkai/v1`
|
52
|
-

|
53
51
|
|
54
52
|
## 2024-12-27
|
55
53
|
|
meutils/io/files_utils.py
CHANGED
@@ -18,6 +18,13 @@ from starlette.datastructures import UploadFile
|
|
18
18
|
from contextlib import asynccontextmanager
|
19
19
|
|
20
20
|
|
21
|
+
def guess_mime_type(file):
|
22
|
+
mime_type = None
|
23
|
+
if isinstance(file, str):
|
24
|
+
mime_type, _ = mimetypes.guess_type(file)
|
25
|
+
return mime_type or "application/octet-stream"
|
26
|
+
|
27
|
+
|
21
28
|
def file_append_firstline(line):
|
22
29
|
with open('untitled.txt', "r+") as f:
|
23
30
|
old = f.read()
|
@@ -37,7 +44,6 @@ def base64_to_bytes(base64_image_string):
|
|
37
44
|
return base64.b64decode(base64_image_string.split(",", 1)[-1])
|
38
45
|
|
39
46
|
|
40
|
-
@retrying()
|
41
47
|
async def to_bytes(file: Union[UploadFile, str, bytes], headers: Optional[dict] = None): # plus
|
42
48
|
"""
|
43
49
|
|
@@ -97,11 +103,10 @@ async def to_url_fal(
|
|
97
103
|
"""对象存储"""
|
98
104
|
if not file: return
|
99
105
|
|
100
|
-
if file.startswith("http"): # 转存: todo: base64
|
106
|
+
if isinstance(file, str) and file.startswith("http"): # 转存: todo: base64
|
101
107
|
content_type = mimetypes.guess_type(file)[0] or content_type
|
102
108
|
|
103
|
-
|
104
|
-
|
109
|
+
file = await to_bytes(file, headers=headers)
|
105
110
|
content_type = (
|
106
111
|
mimetypes.guess_type(filename or '')[0]
|
107
112
|
or mimetypes.guess_type(f"x.{content_type}")[0] # format: image/png
|
@@ -218,4 +223,5 @@ if __name__ == '__main__':
|
|
218
223
|
# "https://cdn.hailuoai.video/moss/prod/2024-11-11-09/video/1731287464150180347-video_raw_8ba15c5c206f8d393a9248f4f9215ed8_312186282087260162.mp4",
|
219
224
|
# content_type=None))
|
220
225
|
|
221
|
-
arun(to_url_fal(url))
|
226
|
+
# arun(to_url_fal(url))
|
227
|
+
print(guess_mime_type("base64xxxxxxxxxxxxxxxxxx.png"))
|
meutils/io/image.py
CHANGED
@@ -13,7 +13,31 @@ import mimetypes
|
|
13
13
|
from PIL import Image, ImageDraw
|
14
14
|
|
15
15
|
from meutils.pipe import *
|
16
|
-
from meutils.io.files_utils import to_url
|
16
|
+
from meutils.io.files_utils import to_url, to_bytes
|
17
|
+
|
18
|
+
|
19
|
+
async def describe_image(image: Union[str, bytes]):
|
20
|
+
"""
|
21
|
+
图片转base64
|
22
|
+
:param image: 图片路径或图片对象
|
23
|
+
:return: base64字符串
|
24
|
+
"""
|
25
|
+
_ = await to_bytes(image)
|
26
|
+
img = Image.open(io.BytesIO(_))
|
27
|
+
|
28
|
+
info = {
|
29
|
+
'format': img.format, # 图片格式
|
30
|
+
'mode': img.mode, # 颜色模式
|
31
|
+
|
32
|
+
'width': img.width, # 宽度
|
33
|
+
'height': img.height, # 高度
|
34
|
+
'size': img.size, # (宽度, 高度)
|
35
|
+
|
36
|
+
'is_animated': getattr(img, 'is_animated', False), # 是否是动图
|
37
|
+
'n_frames': getattr(img, 'n_frames', 1), # 帧数
|
38
|
+
'info': img.info, # 图片附加信息
|
39
|
+
}
|
40
|
+
return info
|
17
41
|
|
18
42
|
|
19
43
|
def crop_polygon(image: Union[str, bytes], outline_points, inline_points):
|
@@ -199,4 +223,6 @@ if __name__ == '__main__':
|
|
199
223
|
|
200
224
|
url = "https://s22-def.ap4r.com/bs2/upload-ylab-stunt-sgp/se/ai_portal_sgp_queue_mmu_img2img_aiweb/7de17faa-cc11-48a6-b94a-e80fe7a34841/1.png"
|
201
225
|
|
202
|
-
arun(image2nowatermark_image(url, picinfo=PICINFO2_RIGHT_BOTTOM))
|
226
|
+
# arun(image2nowatermark_image(url, picinfo=PICINFO2_RIGHT_BOTTOM))
|
227
|
+
with timer():
|
228
|
+
arun(describe_image("https://oss.ffire.cc/files/kling_watermark.png"))
|
meutils/llm/clients.py
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Project : AI. @by PyCharm
|
4
|
+
# @File : chat
|
5
|
+
# @Time : 2024/8/19 14:23
|
6
|
+
# @Author : betterme
|
7
|
+
# @WeChat : meutils
|
8
|
+
# @Software : PyCharm
|
9
|
+
# @Description :
|
10
|
+
from openai import Client, AsyncClient, AsyncStream, APIStatusError
|
11
|
+
|
12
|
+
from meutils.pipe import *
|
13
|
+
|
14
|
+
OpenAI = lru_cache(Client)
|
15
|
+
AsyncOpenAI = lru_cache(AsyncClient)
|
16
|
+
|
17
|
+
moonshot_client = AsyncOpenAI(
|
18
|
+
api_key=os.getenv("MOONSHOT_API_KEY"),
|
19
|
+
base_url=os.getenv("MOONSHOT_BASE_URL")
|
20
|
+
)
|
21
|
+
zhipuai_client = AsyncOpenAI(
|
22
|
+
api_key=os.getenv("ZHIPUAI_API_KEY"),
|
23
|
+
base_url=os.getenv("ZHIPUAI_BASE_URL")
|
24
|
+
)
|
25
|
+
|
26
|
+
if __name__ == '__main__':
|
27
|
+
from meutils.pipe import *
|
28
|
+
|
29
|
+
# OpenAI().chat.completions.create(messages=[{"role": "user", "content": "hi"}], model='glm-4-flash')
|
30
|
+
|
31
|
+
# arun(zhipuai_client.chat.completions.create(messages=[{"role": "user", "content": "hi"}], model='glm-4-flash'))
|
32
|
+
|
33
|
+
# web-search-pro
|
34
|
+
|
35
|
+
arun(zhipuai_client.chat.completions.create(
|
36
|
+
messages=[{"role": "user", "content": "中国队奥运会拿了多少奖牌"}],
|
37
|
+
model='web-search-pro')
|
38
|
+
)
|
@@ -0,0 +1,124 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Project : AI. @by PyCharm
|
4
|
+
# @File : files
|
5
|
+
# @Time : 2025/1/3 15:38
|
6
|
+
# @Author : betterme
|
7
|
+
# @WeChat : meutils
|
8
|
+
# @Software : PyCharm
|
9
|
+
# @Description : 支持文档、图片、音频、视频问答
|
10
|
+
"""单一智能体
|
11
|
+
任意模型支持文档、图片、音频、视频问答
|
12
|
+
api形式
|
13
|
+
- /agents/v1
|
14
|
+
- /v1 前缀区分 agents-{model}【底层调用 /agents/v1】
|
15
|
+
|
16
|
+
"""
|
17
|
+
|
18
|
+
from meutils.pipe import *
|
19
|
+
from meutils.parsers.file_parsers import file_extract
|
20
|
+
|
21
|
+
from meutils.llm.clients import AsyncOpenAI
|
22
|
+
from meutils.llm.openai_utils import to_openai_params
|
23
|
+
|
24
|
+
from meutils.str_utils.regular_expression import parse_url
|
25
|
+
|
26
|
+
from meutils.schemas.openai_types import chat_completion, chat_completion_chunk, ChatCompletionRequest, CompletionUsage
|
27
|
+
|
28
|
+
|
29
|
+
class Completions(object):
|
30
|
+
|
31
|
+
def __init__(self, api_key: Optional[str] = None):
|
32
|
+
self.api_key = api_key
|
33
|
+
|
34
|
+
async def create(self, request: ChatCompletionRequest):
|
35
|
+
"""[{'role': 'user', 'content': 'hi'}]
|
36
|
+
{"type": "file_url", "file_url": {"url": "https://oss.ffire.cc/files/招标文件备案表(第二次).pdf", "detai": "auto"}}"""
|
37
|
+
|
38
|
+
if urls := parse_url(str(request.messages)):
|
39
|
+
logger.debug(urls)
|
40
|
+
|
41
|
+
file_reponse = await file_extract(urls[-1])
|
42
|
+
if file_reponse: # 仅关注最后一个
|
43
|
+
request.system_messages.append({
|
44
|
+
"role": "system",
|
45
|
+
"content": json.dumps(file_reponse, ensure_ascii=False),
|
46
|
+
})
|
47
|
+
|
48
|
+
request.messages = request.system_messages + request.messages
|
49
|
+
|
50
|
+
logger.debug(request)
|
51
|
+
|
52
|
+
data = to_openai_params(request)
|
53
|
+
return await AsyncOpenAI(api_key=self.api_key).chat.completions.create(**data)
|
54
|
+
|
55
|
+
|
56
|
+
# data: {"event": "message", "task_id": "900bbd43-dc0b-4383-a372-aa6e6c414227", "id": "663c5084-a254-4040-8ad3-51f2a3c1a77c", "answer": "Hi", "created_at": 1705398420}\n\n
|
57
|
+
if __name__ == '__main__':
|
58
|
+
c = Completions()
|
59
|
+
|
60
|
+
request = ChatCompletionRequest(
|
61
|
+
# model="qwen-turbo-2024-11-01",
|
62
|
+
# model="claude-3-5-sonnet-20241022",
|
63
|
+
model="gpt-4o-mini",
|
64
|
+
|
65
|
+
messages=[
|
66
|
+
{
|
67
|
+
'role': 'system',
|
68
|
+
'content': '你是一个文件问答助手'
|
69
|
+
},
|
70
|
+
# {
|
71
|
+
# 'role': 'user',
|
72
|
+
# # 'content': {
|
73
|
+
# # "type": "file_url",
|
74
|
+
# # "file_url": {"url": "https://oss.ffire.cc/files/招标文件备案表(第二次).pdf", "detai": "auto"}
|
75
|
+
# # },
|
76
|
+
# 'content': [
|
77
|
+
# {
|
78
|
+
# "type": "text",
|
79
|
+
# "text": "这个文件讲了什么?"
|
80
|
+
# },
|
81
|
+
# # 多轮的时候要剔除
|
82
|
+
# {
|
83
|
+
# "type": "file_url",
|
84
|
+
# "file_url": {"url": "https://oss.ffire.cc/files/招标文件备案表(第二次).pdf", "detai": "auto"}
|
85
|
+
# }
|
86
|
+
# ]
|
87
|
+
# },
|
88
|
+
|
89
|
+
{
|
90
|
+
'role': 'user',
|
91
|
+
# 'content': {
|
92
|
+
# "type": "file_url",
|
93
|
+
# "file_url": {"url": "https://oss.ffire.cc/files/招标文件备案表(第二次).pdf", "detai": "auto"}
|
94
|
+
# },
|
95
|
+
# 'content': "https://oss.ffire.cc/files/%E6%8B%9B%E6%A0%87%E6%96%87%E4%BB%B6%E5%A4%87%E6%A1%88%E8%A1%A8%EF%BC%88%E7%AC%AC%E4%BA%8C%E6%AC%A1%EF%BC%89.pdf 这个文件讲了什么?",
|
96
|
+
# 'content': "https://translate.google.com/?sl=zh-CN&tl=en&text=%E6%8F%90%E4%BE%9B%E6%96%B9&op=tr1anslate 这个文件讲了什么?",
|
97
|
+
|
98
|
+
"content": "总结下 https://oss.ffire.cc/files/百炼系列手机产品介绍.docx"
|
99
|
+
|
100
|
+
},
|
101
|
+
|
102
|
+
# {'role': 'assistant', 'content': "好的"},
|
103
|
+
# {
|
104
|
+
# 'role': 'user',
|
105
|
+
# # 'content': {
|
106
|
+
# # "type": "file_url",
|
107
|
+
# # "file_url": {"url": "https://oss.ffire.cc/files/招标文件备案表(第二次).pdf", "detai": "auto"}
|
108
|
+
# # },
|
109
|
+
# 'content': [
|
110
|
+
# {
|
111
|
+
# "type": "text",
|
112
|
+
# "text": "错了 继续回答"
|
113
|
+
# },
|
114
|
+
# # {
|
115
|
+
# # "type": "file_url",
|
116
|
+
# # "file_url": {"url": "https://oss.ffire.cc/files/招标文件备案表(第二次).pdf", "detai": "auto"}
|
117
|
+
# # }
|
118
|
+
# ]
|
119
|
+
# }
|
120
|
+
]
|
121
|
+
|
122
|
+
)
|
123
|
+
|
124
|
+
arun(c.create(request))
|
@@ -7,11 +7,11 @@
|
|
7
7
|
# @WeChat : meutils
|
8
8
|
# @Software : PyCharm
|
9
9
|
# @Description :
|
10
|
-
import time
|
11
10
|
|
12
11
|
import tiktoken
|
13
12
|
from contextlib import asynccontextmanager
|
14
13
|
from openai import AsyncOpenAI, OpenAI, AsyncStream
|
14
|
+
from meutils.llm.clients import AsyncOpenAI, OpenAI, AsyncStream
|
15
15
|
|
16
16
|
from meutils.pipe import *
|
17
17
|
from meutils.async_utils import achain, async_to_sync
|
@@ -266,7 +266,7 @@ if __name__ == '__main__':
|
|
266
266
|
with timer():
|
267
267
|
try:
|
268
268
|
async with ppu_flow(api_key="sk-OYK4YxtTlWauT2TdGR5FTAJpkRmSnDwPly4cve0cAvMcrBkZ", post="api-oss",
|
269
|
-
n=
|
269
|
+
n=1):
|
270
270
|
logger.debug("消费了哦")
|
271
271
|
|
272
272
|
except Exception as e:
|
meutils/llm/utils.py
CHANGED
@@ -8,7 +8,66 @@
|
|
8
8
|
# @Software : PyCharm
|
9
9
|
# @Description :
|
10
10
|
|
11
|
+
from contextlib import asynccontextmanager
|
12
|
+
|
11
13
|
from meutils.pipe import *
|
14
|
+
from meutils.llm.clients import AsyncOpenAI, OpenAI, AsyncStream
|
15
|
+
from meutils.schemas.oneapi import MODEL_PRICE
|
16
|
+
from meutils.notice.feishu import send_message
|
17
|
+
from meutils.apis.oneapi.utils import get_user_quota
|
18
|
+
|
19
|
+
|
20
|
+
async def ppu(
|
21
|
+
model: str = 'ppu',
|
22
|
+
api_key: Optional[str] = None,
|
23
|
+
base_url: Optional[str] = None,
|
24
|
+
):
|
25
|
+
if model not in MODEL_PRICE:
|
26
|
+
send_message(f"模型未找到{model},ppu-1默认", title=__name__)
|
27
|
+
model = "ppu-1"
|
28
|
+
|
29
|
+
client = AsyncOpenAI(api_key=api_key, base_url=base_url)
|
30
|
+
r = await client.chat.completions.create(messages=[{'role': 'user', 'content': 'hi'}], model=model)
|
31
|
+
|
32
|
+
|
33
|
+
@asynccontextmanager
|
34
|
+
async def ppu_flow(
|
35
|
+
api_key: str,
|
36
|
+
base_url: Optional[str] = None,
|
37
|
+
|
38
|
+
model: str = "ppu-1", # 后计费
|
39
|
+
|
40
|
+
n: float = 1, # 计费次数
|
41
|
+
|
42
|
+
**kwargs
|
43
|
+
):
|
44
|
+
"""
|
45
|
+
查余额
|
46
|
+
失败,先扣费
|
47
|
+
成功,充足,后扣费
|
48
|
+
成功,不足,报错
|
49
|
+
"""
|
50
|
+
n = int(np.ceil(n)) # 0 不计费
|
51
|
+
|
52
|
+
if n: # 计费
|
53
|
+
try:
|
54
|
+
money = await get_user_quota(api_key)
|
55
|
+
logger.debug(f"PREPAY: USER 余额 {money}")
|
56
|
+
except Exception as e:
|
57
|
+
logger.error(e)
|
58
|
+
money = None
|
59
|
+
|
60
|
+
if money and money > MODEL_PRICE.get(model, 0.1):
|
61
|
+
yield # 先执行
|
62
|
+
|
63
|
+
# 执行计费逻辑
|
64
|
+
await asyncio.gather(*[ppu(model, api_key=api_key, base_url=base_url) for _ in range(n)])
|
65
|
+
|
66
|
+
if money is None:
|
67
|
+
yield # 后执行
|
68
|
+
|
69
|
+
else: # 不计费
|
70
|
+
yield
|
12
71
|
|
13
72
|
|
14
73
|
def oneturn2multiturn(messages, template: Optional[str] = None):
|
@@ -52,3 +111,23 @@ def oneturn2multiturn(messages, template: Optional[str] = None):
|
|
52
111
|
context += f"{role}:\n{content}\n\n"
|
53
112
|
context += "assistant:\n"
|
54
113
|
return context
|
114
|
+
|
115
|
+
|
116
|
+
if __name__ == '__main__':
|
117
|
+
async def main():
|
118
|
+
with timer():
|
119
|
+
try:
|
120
|
+
async with ppu_flow(
|
121
|
+
api_key="sk-OYK4YxtTlWauT2TdGR5FTAJpkRmSnDwPly4cve0cAvMcrBkZ",
|
122
|
+
model="api-oss",
|
123
|
+
n=1):
|
124
|
+
logger.debug("消费了哦")
|
125
|
+
|
126
|
+
except Exception as e:
|
127
|
+
pass
|
128
|
+
logger.error(e)
|
129
|
+
# logger.debug(e.response.status_code)
|
130
|
+
# logger.debug(e.response.text)
|
131
|
+
|
132
|
+
|
133
|
+
arun(main())
|
meutils/llm/x.py
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
import os
|
2
|
+
|
3
|
+
# !/usr/bin/env python
|
4
|
+
# -*- coding: utf-8 -*-
|
5
|
+
# @Project : AI. @by PyCharm
|
6
|
+
# @File : x
|
7
|
+
# @Time : 2025/1/7 17:31
|
8
|
+
# @Author : betterme
|
9
|
+
# @WeChat : meutils
|
10
|
+
# @Software : PyCharm
|
11
|
+
# @Description :
|
12
|
+
|
13
|
+
from meutils.pipe import *
|
14
|
+
from meutils.llm.clients import zhipuai_client
|
15
|
+
from meutils.schemas.openai_types import _ChatCompletion
|
16
|
+
|
17
|
+
import requests
|
18
|
+
import uuid
|
19
|
+
|
20
|
+
api_key = os.getenv("ZHIPUAI_API_KEY")
|
21
|
+
|
22
|
+
msg = [
|
23
|
+
{
|
24
|
+
"role": "user",
|
25
|
+
"content": "中国队奥运会拿了多少奖牌"
|
26
|
+
}
|
27
|
+
]
|
28
|
+
|
29
|
+
tool = "web-search-pro"
|
30
|
+
|
31
|
+
|
32
|
+
async def run_v4_sync():
|
33
|
+
url = "https://open.bigmodel.cn/api/paas/v4/tools"
|
34
|
+
request_id = str(uuid.uuid4())
|
35
|
+
data = {
|
36
|
+
"request_id": request_id,
|
37
|
+
"tool": tool,
|
38
|
+
"stream": False,
|
39
|
+
"messages": msg
|
40
|
+
}
|
41
|
+
|
42
|
+
# resp = requests.post(
|
43
|
+
# url,
|
44
|
+
# json=data,
|
45
|
+
# headers={'Authorization': api_key},
|
46
|
+
# timeout=300
|
47
|
+
# )
|
48
|
+
# print(resp.content.decode())
|
49
|
+
|
50
|
+
resp = await zhipuai_client.post(
|
51
|
+
"/tools",
|
52
|
+
body={
|
53
|
+
"request_id": str(uuid.uuid4()),
|
54
|
+
"tool": tool,
|
55
|
+
"stream": False,
|
56
|
+
"messages": msg
|
57
|
+
},
|
58
|
+
cast_to=object
|
59
|
+
)
|
60
|
+
return resp
|
61
|
+
|
62
|
+
|
63
|
+
file_object = zhipuai_client.files.create(file=Path("/Users/betterme/PycharmProjects/AI/MeUtils/meutils/llm/completions/rag/百炼系列手机产品介绍.docx"), purpose="file-extract")
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
if __name__ == '__main__':
|
68
|
+
# r = arun(run_v4_sync())
|
69
|
+
# arun(file_object)
|
70
|
+
|
71
|
+
file_id = "1736243045_3771f3dfb394424885f24c3dc0583741"
|
72
|
+
|
73
|
+
file_content = json.loads(zhipuai_client.files.content(file_id=file_id).content)["content"]
|
74
|
+
|
75
|
+
file_content = json.loads(r.content)["content"]
|
meutils/notice/feishu.py
CHANGED
@@ -19,6 +19,7 @@ LLM_REVERSE = "https://open.feishu.cn/open-apis/bot/v2/hook/cd5c9126-a882-4a24-9
|
|
19
19
|
Vison = ""
|
20
20
|
# AUDIOS_TTS = "https://open.feishu.cn/open-apis/bot/v2/hook/ff7d4b86-d238-436c-9447-f88cf603454d"
|
21
21
|
AUDIO = "https://open.feishu.cn/open-apis/bot/v2/hook/80c2a700-adfa-4b9b-8e3f-00b78f2f5c8b"
|
22
|
+
FILES = "https://open.feishu.cn/open-apis/bot/v2/hook/075fb2fa-a559-4a7e-89ac-3ab9934ff15c"
|
22
23
|
|
23
24
|
|
24
25
|
@background_task
|
@@ -0,0 +1,107 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Project : AI. @by PyCharm
|
4
|
+
# @File : fileparser
|
5
|
+
# @Time : 2025/1/7 17:48
|
6
|
+
# @Author : betterme
|
7
|
+
# @WeChat : meutils
|
8
|
+
# @Software : PyCharm
|
9
|
+
# @Description : https://bigmodel.cn/dev/activities/freebie/fileextracion
|
10
|
+
import asyncio
|
11
|
+
|
12
|
+
from meutils.pipe import *
|
13
|
+
from meutils.io.files_utils import to_bytes, guess_mime_type
|
14
|
+
from meutils.llm.clients import moonshot_client, zhipuai_client, APIStatusError
|
15
|
+
from meutils.notice.feishu import send_message as _send_message, FILES
|
16
|
+
from meutils.caches.redis_cache import cache
|
17
|
+
|
18
|
+
send_message = partial(
|
19
|
+
_send_message,
|
20
|
+
title=__name__,
|
21
|
+
url=FILES
|
22
|
+
)
|
23
|
+
"""
|
24
|
+
|
25
|
+
# 智谱
|
26
|
+
# 格式限制:.PDF .DOCX .DOC .XLS .XLSX .PPT .PPTX .PNG .JPG .JPEG .CSV .PY .TXT .MD .BMP .GIF
|
27
|
+
|
28
|
+
# kimi todo: 定期删除文件
|
29
|
+
文件接口与 Kimi 智能助手中上传文件功能所使用的相同,支持相同的文件格式,它们包括
|
30
|
+
.pdf .txt .csv .doc .docx .xls .xlsx .ppt .pptx .md .jpeg .png .bmp .gif .svg .svgz .webp .ico .xbm .dib .pjp .tif
|
31
|
+
.pjpeg .avif .dot .apng .epub .tiff .jfif .html .json .mobi .log .go .h .c .cpp .cxx .cc .cs .java .js .css .jsp .php
|
32
|
+
.py .py3 .asp .yaml .yml .ini .conf .ts .tsx 等格式。
|
33
|
+
|
34
|
+
"""
|
35
|
+
|
36
|
+
|
37
|
+
@cache(ttl=24 * 3600)
|
38
|
+
async def file_extract(
|
39
|
+
file,
|
40
|
+
provider: Union[str, Literal['kimi', 'moonshot', 'zhipu']] = 'moonshot'
|
41
|
+
):
|
42
|
+
"""todo 定时删除文件
|
43
|
+
todo: 兼容下 url bytes path
|
44
|
+
|
45
|
+
# moonshot_client.files.
|
46
|
+
|
47
|
+
# len(moonshot_client.files.list().data)
|
48
|
+
|
49
|
+
"""
|
50
|
+
mime_type = guess_mime_type(file)
|
51
|
+
if mime_type == "application/octet-stream": return # 不解析
|
52
|
+
|
53
|
+
logger.debug(f"file_extract: {mime_type}")
|
54
|
+
|
55
|
+
if provider == "zhipu":
|
56
|
+
client = zhipuai_client
|
57
|
+
else:
|
58
|
+
client = moonshot_client # 默认
|
59
|
+
|
60
|
+
filename = Path(file).name
|
61
|
+
file_bytes: bytes = await to_bytes(file)
|
62
|
+
|
63
|
+
# todo: zhipu兜底
|
64
|
+
try:
|
65
|
+
file_object = await client.files.create(
|
66
|
+
# file=file,
|
67
|
+
# file=("filename.pdf", file),
|
68
|
+
file=(filename, file_bytes, mime_type),
|
69
|
+
purpose="file-extract"
|
70
|
+
)
|
71
|
+
|
72
|
+
if file_object.status and file_object.status != "ok":
|
73
|
+
if isinstance(file, str) and file.startswith('http'):
|
74
|
+
file_object.url = file
|
75
|
+
send_message(file_object)
|
76
|
+
|
77
|
+
response = await client.files.content(file_id=file_object.id) # 抛错处理
|
78
|
+
return response.json()
|
79
|
+
except APIStatusError as e:
|
80
|
+
logger.debug(e)
|
81
|
+
_ = e.response.json()
|
82
|
+
if isinstance(file, str) and file.startswith('http'):
|
83
|
+
_['url'] = file
|
84
|
+
send_message(_)
|
85
|
+
return _
|
86
|
+
|
87
|
+
|
88
|
+
if __name__ == '__main__':
|
89
|
+
# file = "https://oss.ffire.cc/files/招标文件备案表(第二次).pdf"
|
90
|
+
file = "https://oss.ffire.cc/files/%E6%8B%9B%E6%A0%87%E6%96%87%E4%BB%B6%E5%A4%87%E6%A1%88%E8%A1%A8%EF%BC%88%E7%AC%AC%E4%BA%8C%E6%AC%A1%EF%BC%89.pdf"
|
91
|
+
"https://oss.ffire.cc/files/%E6%8B%9B%E6%A0%87%E6%96%87%E4%BB%B6%E5%A4%87%E6%A1%88%E8%A1%A8%EF%BC%88%E7%AC%AC%E4%BA%8C%E6%AC%A1%EF%BC%89.pdf 这个文件讲了什么?"
|
92
|
+
# file = "https://oss.ffire.cc/files/百炼系列手机产品介绍.docx"
|
93
|
+
# file = Path("/Users/betterme/PycharmProjects/AI/MeUtils/meutils/llm/completions/rag/百炼系列手机产品介绍.docx")
|
94
|
+
|
95
|
+
# file = "/Users/betterme/PycharmProjects/AI/MeUtils/meutils/io/img_1.png"
|
96
|
+
|
97
|
+
# openai.BadRequestError: Error code: 400 - {'error': {'message': 'text extract error: 没有解析出内容', 'type': 'invalid_request_error'}}
|
98
|
+
# file = "https://oss.ffire.cc/files/kling_watermark.png"
|
99
|
+
|
100
|
+
# with timer():
|
101
|
+
# r = arun(file_extract(file, moonshot_client))
|
102
|
+
|
103
|
+
# with timer():
|
104
|
+
# r = arun(file_extract(file, provider='kimi'))
|
105
|
+
|
106
|
+
with timer():
|
107
|
+
arun(file_extract(file))
|