MeUtils 2025.1.6.14.2.0__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.6.14.2.0.dist-info → MeUtils-2025.1.10.20.14.42.dist-info}/METADATA +28 -28
- {MeUtils-2025.1.6.14.2.0.dist-info → MeUtils-2025.1.10.20.14.42.dist-info}/RECORD +67 -59
- examples/_openaisdk/openai_chatfire.py +11 -4
- examples/_openaisdk/openai_images.py +3 -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/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/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 +22 -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.6.14.2.0.dist-info → MeUtils-2025.1.10.20.14.42.dist-info}/LICENSE +0 -0
- {MeUtils-2025.1.6.14.2.0.dist-info → MeUtils-2025.1.10.20.14.42.dist-info}/WHEEL +0 -0
- {MeUtils-2025.1.6.14.2.0.dist-info → MeUtils-2025.1.10.20.14.42.dist-info}/entry_points.txt +0 -0
- {MeUtils-2025.1.6.14.2.0.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/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))
|
@@ -101,7 +101,10 @@ class OneapiToken(SQLModel, table=True):
|
|
101
101
|
id: Optional[int] = Field(default=None, primary_key=True)
|
102
102
|
user_id: Optional[int] = Field(default=None)
|
103
103
|
key: Optional[str] = Field(default=None)
|
104
|
+
|
104
105
|
used_quota: Optional[int] = Field(default=None)
|
106
|
+
remain_quota: Optional[int] = Field(default=None)
|
107
|
+
unlimited_quota: Optional[bool] = Field(default=False)
|
105
108
|
|
106
109
|
class Config:
|
107
110
|
arbitrary_types_allowed = True
|
meutils/schemas/image_types.py
CHANGED
@@ -10,6 +10,7 @@
|
|
10
10
|
|
11
11
|
from meutils.pipe import *
|
12
12
|
|
13
|
+
from pydantic import constr
|
13
14
|
from openai.types import ImagesResponse as _ImagesResponse, Image
|
14
15
|
|
15
16
|
ASPECT_RATIOS = {
|
@@ -58,7 +59,7 @@ class ImagesResponse(_ImagesResponse):
|
|
58
59
|
|
59
60
|
|
60
61
|
class ImageRequest(BaseModel): # openai
|
61
|
-
prompt:
|
62
|
+
prompt: constr(min_length=1, max_length=1000) = ""
|
62
63
|
negative_prompt: Optional[str] = None
|
63
64
|
|
64
65
|
model: str = ""
|
@@ -215,6 +216,31 @@ class KlingImageRequest(ImageRequest):
|
|
215
216
|
self.size = "1:1" if self.size not in {"1:1", "2:3", "3:2", "3:4", "4:3", "9:16", "16:9"} else self.size
|
216
217
|
|
217
218
|
|
219
|
+
class KolorsRequest(ImageRequest):
|
220
|
+
model: Literal["kolors-1.0", "kolors-1.5"] = "kolors-1.0"
|
221
|
+
n: Optional[int] = 4
|
222
|
+
|
223
|
+
"""
|
224
|
+
1:1(1024*1024)
|
225
|
+
4:3(1152*896)
|
226
|
+
3:4(768*1024)
|
227
|
+
16:9(1024 576)
|
228
|
+
9:16(576 1024)
|
229
|
+
3:2(1024*640)
|
230
|
+
2:3(640*1024)
|
231
|
+
"""
|
232
|
+
size: Literal[
|
233
|
+
"1024x1024", "1152x896", "768x1024", "1024x576", "576x1024", "1024x640", "640x1024"
|
234
|
+
] = "1024x1024"
|
235
|
+
|
236
|
+
# 图生图
|
237
|
+
image: Optional[str] = None
|
238
|
+
image_fidelity: Optional[float] = None
|
239
|
+
|
240
|
+
def __init__(self, /, **data: Any):
|
241
|
+
super().__init__(**data)
|
242
|
+
|
243
|
+
|
218
244
|
class CogviewImageRequest(ImageRequest):
|
219
245
|
model: str = "cogview-3"
|
220
246
|
size: Optional[Literal["1024x1024", "768x1344", "864x1152", "1344x768", "1152x864", "1440x720", "720x1440"]] = None
|
@@ -440,4 +466,4 @@ if __name__ == '__main__':
|
|
440
466
|
|
441
467
|
# print(ImagesResponse(data=[{'url': 1}]))
|
442
468
|
|
443
|
-
print(
|
469
|
+
print(RecraftImageRequest(prompt="").model_dump_json())
|
@@ -113,7 +113,7 @@ class KlingaiImageRequest(BaseModel):
|
|
113
113
|
{'name': 'imageCount', 'value': self.n},
|
114
114
|
{"name": "fidelity", "value": self.image_fidelity or 0.5},
|
115
115
|
{'name': 'biz', 'value': 'klingai'},
|
116
|
-
{"name": "kolors_version", "value": "1.
|
116
|
+
{"name": "kolors_version", "value": "1.0"} ####### 1.5
|
117
117
|
]
|
118
118
|
self.payload = {
|
119
119
|
'arguments': arguments,
|