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.
Files changed (69) hide show
  1. {MeUtils-2025.1.6.14.2.0.dist-info → MeUtils-2025.1.10.20.14.42.dist-info}/METADATA +28 -28
  2. {MeUtils-2025.1.6.14.2.0.dist-info → MeUtils-2025.1.10.20.14.42.dist-info}/RECORD +67 -59
  3. examples/_openaisdk/openai_chatfire.py +11 -4
  4. examples/_openaisdk/openai_images.py +3 -1
  5. examples/_openaisdk/openai_lingyi.py +59 -0
  6. examples/_openaisdk/openai_ppu.py +47 -0
  7. examples/_openaisdk/openai_test.py +2 -2
  8. examples/_openaisdk/openai_together.py +57 -0
  9. examples/_openaisdk/openai_zhipu.py +4 -3
  10. meutils/ai_audio/asr/openai_asr.py +2 -2
  11. meutils/apis/audio/deepinfra.py +2 -2
  12. meutils/apis/chatglm/glm_video_api.py +1 -1
  13. meutils/apis/common.py +5 -1
  14. meutils/apis/hailuoai/videos.py +14 -5
  15. meutils/apis/images/eidt.py +36 -0
  16. meutils/apis/images/gitee_kolors.py +49 -0
  17. meutils/apis/images/recraft.py +24 -6
  18. meutils/apis/niutrans.py +27 -8
  19. meutils/apis/oneapi/utils.py +24 -9
  20. meutils/apis/translator/deeplx.py +4 -3
  21. meutils/caches/redis_cache.py +5 -0
  22. meutils/common.py +1 -0
  23. meutils/config_utils/lark_utils/common.py +0 -1
  24. meutils/data/VERSION +1 -1
  25. meutils/io/files_utils.py +11 -5
  26. meutils/io/image.py +28 -2
  27. meutils/llm/clients.py +38 -0
  28. meutils/llm/completions/agents/file.py +124 -0
  29. meutils/llm/openai_utils/common.py +2 -2
  30. meutils/llm/utils.py +79 -0
  31. meutils/llm/x.py +75 -0
  32. meutils/notice/feishu.py +1 -0
  33. meutils/parsers/__init__.py +10 -0
  34. meutils/parsers/file_parsers.py +107 -0
  35. meutils/schemas/db/oneapi_types.py +3 -0
  36. meutils/schemas/image_types.py +28 -2
  37. meutils/schemas/kuaishou_types.py +1 -1
  38. meutils/schemas/oneapi/common.py +22 -12
  39. meutils/serving/fastapi/exceptions/http_error.py +2 -6
  40. meutils/str_utils/regular_expression.py +29 -6
  41. meutils/llm/completions/agents/files.py +0 -18
  42. meutils/llm/openai_client.py +0 -15
  43. {MeUtils-2025.1.6.14.2.0.dist-info → MeUtils-2025.1.10.20.14.42.dist-info}/LICENSE +0 -0
  44. {MeUtils-2025.1.6.14.2.0.dist-info → MeUtils-2025.1.10.20.14.42.dist-info}/WHEEL +0 -0
  45. {MeUtils-2025.1.6.14.2.0.dist-info → MeUtils-2025.1.10.20.14.42.dist-info}/entry_points.txt +0 -0
  46. {MeUtils-2025.1.6.14.2.0.dist-info → MeUtils-2025.1.10.20.14.42.dist-info}/top_level.txt +0 -0
  47. /meutils/{fileparser → parsers/fileparser}/PDF/346/212/275/345/217/226.py" +0 -0
  48. /meutils/{fileparser → parsers/fileparser}/__init__.py +0 -0
  49. /meutils/{fileparser → parsers/fileparser}/common.py +0 -0
  50. /meutils/{fileparser → parsers/fileparser}/demo.py +0 -0
  51. /meutils/{fileparser → parsers/fileparser}/filetype/__init__.py +0 -0
  52. /meutils/{fileparser → parsers/fileparser}/filetype/__main__.py +0 -0
  53. /meutils/{fileparser → parsers/fileparser}/filetype/filetype.py +0 -0
  54. /meutils/{fileparser → parsers/fileparser}/filetype/helpers.py +0 -0
  55. /meutils/{fileparser → parsers/fileparser}/filetype/match.py +0 -0
  56. /meutils/{fileparser → parsers/fileparser}/filetype/types/__init__.py +0 -0
  57. /meutils/{fileparser → parsers/fileparser}/filetype/types/application.py +0 -0
  58. /meutils/{fileparser → parsers/fileparser}/filetype/types/archive.py +0 -0
  59. /meutils/{fileparser → parsers/fileparser}/filetype/types/audio.py +0 -0
  60. /meutils/{fileparser → parsers/fileparser}/filetype/types/base.py +0 -0
  61. /meutils/{fileparser → parsers/fileparser}/filetype/types/document.py +0 -0
  62. /meutils/{fileparser → parsers/fileparser}/filetype/types/font.py +0 -0
  63. /meutils/{fileparser → parsers/fileparser}/filetype/types/image.py +0 -0
  64. /meutils/{fileparser → parsers/fileparser}/filetype/types/isobmff.py +0 -0
  65. /meutils/{fileparser → parsers/fileparser}/filetype/types/video.py +0 -0
  66. /meutils/{fileparser → parsers/fileparser}/filetype/utils.py +0 -0
  67. /meutils/{fileparser → parsers/fileparser}/filetype.py +0 -0
  68. /meutils/{fileparser → parsers/fileparser}/pdf.py +0 -0
  69. /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=100):
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,10 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ # @Project : AI. @by PyCharm
4
+ # @File : __init__.py
5
+ # @Time : 2025/1/10 15:45
6
+ # @Author : betterme
7
+ # @WeChat : meutils
8
+ # @Software : PyCharm
9
+ # @Description :
10
+
@@ -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
@@ -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: str = ""
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(Recraft(prompt="一条猫").model_dump_json())
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.5"}
116
+ {"name": "kolors_version", "value": "1.0"} ####### 1.5
117
117
  ]
118
118
  self.payload = {
119
119
  'arguments': arguments,