MeUtils 2025.3.19.19.13.35__py3-none-any.whl → 2025.3.21.10.18.9__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.3.19.19.13.35.dist-info → MeUtils-2025.3.21.10.18.9.dist-info}/METADATA +264 -264
- {MeUtils-2025.3.19.19.13.35.dist-info → MeUtils-2025.3.21.10.18.9.dist-info}/RECORD +29 -27
- examples/_openaisdk/openai_audio.py +7 -2
- examples/_openaisdk/openai_images.py +6 -5
- meutils/apis/audio/fish.py +1 -1
- meutils/apis/baidu/bdaitpzs.py +1 -1
- meutils/apis/fal/images.py +7 -3
- meutils/apis/hunyuan/image_tools.py +1 -1
- meutils/apis/images/eidt.py +22 -12
- meutils/apis/images/recraft.py +5 -5
- meutils/apis/proxy/ips.py +4 -23
- meutils/apis/textin.py +1 -1
- meutils/config_utils/lark_utils/common.py +10 -6
- meutils/data/VERSION +1 -1
- meutils/io/files_utils.py +29 -19
- meutils/llm/check_api.py +3 -1
- meutils/llm/check_utils.py +4 -1
- meutils/llm/completions/chat_gemini.py +73 -6
- meutils/llm/completions/chat_plus.py +22 -14
- meutils/llm/completions/chat_videos.py +95 -0
- meutils/llm/completions/deep2x.py +100 -0
- meutils/oss/__init__.py +0 -6
- meutils/schemas/oneapi/common.py +5 -3
- meutils/schemas/openai_types.py +33 -7
- meutils/str_utils/regular_expression.py +4 -0
- {MeUtils-2025.3.19.19.13.35.dist-info → MeUtils-2025.3.21.10.18.9.dist-info}/LICENSE +0 -0
- {MeUtils-2025.3.19.19.13.35.dist-info → MeUtils-2025.3.21.10.18.9.dist-info}/WHEEL +0 -0
- {MeUtils-2025.3.19.19.13.35.dist-info → MeUtils-2025.3.21.10.18.9.dist-info}/entry_points.txt +0 -0
- {MeUtils-2025.3.19.19.13.35.dist-info → MeUtils-2025.3.21.10.18.9.dist-info}/top_level.txt +0 -0
@@ -6,12 +6,16 @@
|
|
6
6
|
# @Author : betterme
|
7
7
|
# @WeChat : meutils
|
8
8
|
# @Software : PyCharm
|
9
|
-
# @Description :
|
9
|
+
# @Description :
|
10
|
+
import asyncio
|
10
11
|
|
12
|
+
import shortuuid
|
11
13
|
|
12
14
|
from meutils.pipe import *
|
13
15
|
from meutils.llm.openai_utils import to_openai_params
|
14
16
|
from meutils.llm.clients import AsyncOpenAI
|
17
|
+
from meutils.str_utils.regular_expression import parse_url
|
18
|
+
from meutils.io.files_utils import to_url, markdown_base64_to_url
|
15
19
|
|
16
20
|
from meutils.schemas.openai_types import chat_completion, chat_completion_chunk, CompletionRequest, CompletionUsage
|
17
21
|
|
@@ -31,12 +35,18 @@ class Completions(object):
|
|
31
35
|
base_url: Optional[str] = None,
|
32
36
|
api_key: Optional[str] = None
|
33
37
|
):
|
38
|
+
|
39
|
+
base_url = "https://api.aiguoguo199.com/v1"
|
40
|
+
|
34
41
|
self.client = AsyncOpenAI(
|
35
42
|
base_url=base_url,
|
36
43
|
api_key=api_key,
|
37
44
|
)
|
38
45
|
|
39
46
|
async def create(self, request: CompletionRequest):
|
47
|
+
if request.model == "gemini-2.0-flash-exp-image-generation":
|
48
|
+
return await self.images_create(request)
|
49
|
+
|
40
50
|
urls = sum(request.last_urls.values(), [])
|
41
51
|
for url in urls:
|
42
52
|
request.messages[-1]["content"].append({"type": "image_url", "image_url": {"url": url}})
|
@@ -44,20 +54,74 @@ class Completions(object):
|
|
44
54
|
data = to_openai_params(request)
|
45
55
|
return await self.client.chat.completions.create(**data)
|
46
56
|
|
57
|
+
async def images_create(self, request: CompletionRequest):
|
58
|
+
|
59
|
+
if request.last_assistant_content and (urls := parse_url(request.last_assistant_content)):
|
60
|
+
for message in request.messages[::-1]:
|
61
|
+
if message.get("role") == "assistant":
|
62
|
+
message["content"] = [
|
63
|
+
{"type": "image_url", "image_url": {"url": url.removesuffix(")")}} for url in urls
|
64
|
+
]
|
65
|
+
|
66
|
+
if urls := parse_url(request.last_user_content): # 修正提问格式, 兼容 url
|
67
|
+
for message in request.messages[::-1]:
|
68
|
+
if message.get("role") == "user":
|
69
|
+
message["content"] = [
|
70
|
+
{"type": "image_url", "image_url": {"url": url.removesuffix(")")}} for url in urls
|
71
|
+
]
|
72
|
+
message["content"] += [{"type": "text", "text": request.last_user_content}]
|
73
|
+
|
74
|
+
# 调用模型
|
75
|
+
logger.debug(request.model_dump_json(indent=4))
|
76
|
+
|
77
|
+
data = to_openai_params(request)
|
78
|
+
response = await self.client.chat.completions.create(**data)
|
79
|
+
|
80
|
+
if request.stream:
|
81
|
+
return self.stream_create(response)
|
82
|
+
|
83
|
+
else:
|
84
|
+
content = response.choices[0].message.content
|
85
|
+
response.choices[0].message.content = await markdown_base64_to_url(content) # base64 转 url
|
86
|
+
|
87
|
+
if hasattr(response, "system_prompt"):
|
88
|
+
del response.system_prompt
|
89
|
+
|
90
|
+
return response
|
91
|
+
|
92
|
+
async def stream_create(self, chunks):
|
93
|
+
async for chunk in chunks:
|
94
|
+
if hasattr(chunk, "system_prompt"):
|
95
|
+
del chunk.system_prompt
|
96
|
+
|
97
|
+
if (content := chunk.choices[0].delta.content) and content.startswith("!["):
|
98
|
+
chunk.choices[0].delta.content = await markdown_base64_to_url(content)
|
99
|
+
|
100
|
+
yield chunk
|
101
|
+
else:
|
102
|
+
yield chunk
|
103
|
+
logger.debug(str(chunk))
|
104
|
+
|
47
105
|
|
48
106
|
if __name__ == '__main__':
|
49
107
|
url = "https://oss.ffire.cc/files/lipsync.mp3"
|
50
108
|
url = "https://lmdbk.com/5.mp4"
|
51
109
|
content = [
|
52
|
-
|
110
|
+
|
111
|
+
{"type": "text", "text": "https://oss.ffire.cc/files/nsfw.jpg 移除右下角的水印"},
|
112
|
+
|
113
|
+
# {"type": "text", "text": "总结下"},
|
53
114
|
# {"type": "image_url", "image_url": {"url": url}},
|
54
115
|
|
55
|
-
{"type": "video_url", "video_url": {"url": url}}
|
116
|
+
# {"type": "video_url", "video_url": {"url": url}}
|
56
117
|
|
57
118
|
]
|
119
|
+
|
120
|
+
#
|
58
121
|
request = CompletionRequest(
|
59
122
|
# model="qwen-turbo-2024-11-01",
|
60
|
-
model="gemini-all",
|
123
|
+
# model="gemini-all",
|
124
|
+
model="gemini-2.0-flash-exp-image-generation",
|
61
125
|
# model="qwen-plus-latest",
|
62
126
|
|
63
127
|
messages=[
|
@@ -68,6 +132,9 @@ if __name__ == '__main__':
|
|
68
132
|
},
|
69
133
|
|
70
134
|
],
|
71
|
-
stream=
|
135
|
+
stream=True,
|
72
136
|
)
|
73
|
-
|
137
|
+
|
138
|
+
api_key = "sk-Q2XxJBh3KM7bTptL6e96E8596fC74426BaA87528867aA77b"
|
139
|
+
|
140
|
+
arun(Completions(api_key=api_key).create(request))
|
@@ -76,7 +76,7 @@ class Completions(object):
|
|
76
76
|
}
|
77
77
|
]
|
78
78
|
data = to_openai_params(request)
|
79
|
-
return self.client.chat.completions.create(**data)
|
79
|
+
return await self.client.chat.completions.create(**data)
|
80
80
|
|
81
81
|
elif guess_mime_type(file_url).startswith(("video", "audio")): # 音频 视频
|
82
82
|
request.model = "gemini" # 果果
|
@@ -98,7 +98,7 @@ class Completions(object):
|
|
98
98
|
}
|
99
99
|
]
|
100
100
|
data = to_openai_params(request)
|
101
|
-
return self.client.chat.completions.create(**data)
|
101
|
+
return await self.client.chat.completions.create(**data)
|
102
102
|
|
103
103
|
else:
|
104
104
|
|
@@ -111,18 +111,18 @@ class Completions(object):
|
|
111
111
|
}
|
112
112
|
]
|
113
113
|
data = to_openai_params(request)
|
114
|
-
return self.client.chat.completions.create(**data)
|
114
|
+
return await self.client.chat.completions.create(**data)
|
115
115
|
|
116
116
|
if image_urls := request.last_urls.get("image_url"): # 识图
|
117
117
|
request.model = "glm-4v-flash"
|
118
118
|
data = to_openai_params(request)
|
119
|
-
return self.client.chat.completions.create(**data)
|
119
|
+
return await self.client.chat.completions.create(**data)
|
120
120
|
|
121
121
|
elif file_urls := request.last_urls.get("file_url"):
|
122
|
-
return self.chat_files(request)
|
122
|
+
return await self.chat_files(request)
|
123
123
|
|
124
124
|
data = to_openai_params(request)
|
125
|
-
return self.client.chat.completions.create(**data)
|
125
|
+
return await self.client.chat.completions.create(**data)
|
126
126
|
|
127
127
|
async def chat_files(self, request: CompletionRequest): # 多轮
|
128
128
|
for i, message in enumerate(request.messages[::-1], 1):
|
@@ -142,7 +142,7 @@ class Completions(object):
|
|
142
142
|
break # 截断:从最新的文件开始
|
143
143
|
|
144
144
|
data = to_openai_params(request)
|
145
|
-
return self.client.chat.completions.create(**data)
|
145
|
+
return await self.client.chat.completions.create(**data)
|
146
146
|
|
147
147
|
async def create_images(self, request: CompletionRequest):
|
148
148
|
|
@@ -153,7 +153,13 @@ class Completions(object):
|
|
153
153
|
)
|
154
154
|
image_url = response.data[0].url
|
155
155
|
tool_desc = """> images.generate\n\n"""
|
156
|
-
|
156
|
+
tool_desc += f""
|
157
|
+
if not request.stream:
|
158
|
+
chat_completion.choices[0].message.content = tool_desc
|
159
|
+
return chat_completion
|
160
|
+
return tool_desc
|
161
|
+
|
162
|
+
# chat_completion_chunk
|
157
163
|
|
158
164
|
# async def create_videos(self, request: CompletionRequest):
|
159
165
|
#
|
@@ -169,9 +175,9 @@ if __name__ == '__main__':
|
|
169
175
|
c = Completions()
|
170
176
|
|
171
177
|
request = CompletionRequest(
|
172
|
-
model="qwen-turbo-2024-11-01",
|
178
|
+
# model="qwen-turbo-2024-11-01",
|
173
179
|
# model="claude-3-5-sonnet-20241022",
|
174
|
-
|
180
|
+
model="gpt-4o-mini",
|
175
181
|
|
176
182
|
messages=[{
|
177
183
|
'role': 'user',
|
@@ -181,10 +187,12 @@ if __name__ == '__main__':
|
|
181
187
|
"text": "总结下"
|
182
188
|
},
|
183
189
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
190
|
+
{
|
191
|
+
"type": "file_url",
|
192
|
+
"file_url": {
|
193
|
+
"url": "https://oss.ffire.cc/files/招标文件备案表(第二次).pdf"
|
194
|
+
}
|
195
|
+
}
|
188
196
|
]
|
189
197
|
}])
|
190
198
|
|
@@ -0,0 +1,95 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Project : AI. @by PyCharm
|
4
|
+
# @File : chat_videos
|
5
|
+
# @Time : 2025/3/20 10:19
|
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
|
+
from meutils.apis.chatglm import glm_video_api # VideoRequest, create_task, get_task
|
15
|
+
from meutils.str_utils.regular_expression import parse_url
|
16
|
+
|
17
|
+
from meutils.schemas.openai_types import chat_completion, chat_completion_chunk, CompletionRequest, CompletionUsage
|
18
|
+
|
19
|
+
|
20
|
+
class Completions(object):
|
21
|
+
|
22
|
+
def __init__(self,
|
23
|
+
base_url: Optional[str] = None,
|
24
|
+
api_key: Optional[str] = None
|
25
|
+
):
|
26
|
+
self.client = AsyncOpenAI(
|
27
|
+
base_url=base_url,
|
28
|
+
api_key=api_key,
|
29
|
+
)
|
30
|
+
|
31
|
+
async def create(self, request: CompletionRequest):
|
32
|
+
|
33
|
+
image_url = None
|
34
|
+
prompt = request.last_user_content
|
35
|
+
if urls := parse_url(prompt):
|
36
|
+
image_url = urls[0]
|
37
|
+
prompt = prompt.replace(image_url, "")
|
38
|
+
|
39
|
+
# 创建任务
|
40
|
+
video_request = glm_video_api.VideoRequest(image_url=image_url, prompt=prompt)
|
41
|
+
response = await glm_video_api.create_task(video_request)
|
42
|
+
taskid = response.id
|
43
|
+
system_fingerprint = response.system_fingerprint
|
44
|
+
|
45
|
+
# 获取任务
|
46
|
+
for i in f"""> VideoTask(id={taskid.split('-')[-1]}, image_url={image_url}, prompt={prompt})\n""":
|
47
|
+
await asyncio.sleep(0.03)
|
48
|
+
yield i
|
49
|
+
|
50
|
+
yield f"[🤫 任务进度]("
|
51
|
+
for i in range(60):
|
52
|
+
await asyncio.sleep(3)
|
53
|
+
response = await glm_video_api.get_task(taskid, system_fingerprint)
|
54
|
+
|
55
|
+
logger.debug(response)
|
56
|
+
if response.task_status == "SUCCESS" or response.video_result:
|
57
|
+
yield ")🎉🎉🎉\n\n"
|
58
|
+
for video in response.video_result or []:
|
59
|
+
yield f"[^1]: [封面]({video.cover_image_url})\n\n"
|
60
|
+
yield f"[^2]: [视频]({video.url})\n\n"
|
61
|
+
|
62
|
+
yield f"[视频]({video.url})[^1][^2]\n\n"
|
63
|
+
yield f"[^1][^2]\n\n"
|
64
|
+
|
65
|
+
break
|
66
|
+
else:
|
67
|
+
yield "🔥"
|
68
|
+
|
69
|
+
|
70
|
+
if __name__ == '__main__':
|
71
|
+
url = "https://oss.ffire.cc/files/lipsync.mp3"
|
72
|
+
url = "https://lmdbk.com/5.mp4"
|
73
|
+
content = [
|
74
|
+
{"type": "text", "text": "总结下"},
|
75
|
+
# {"type": "image_url", "image_url": {"url": url}},
|
76
|
+
|
77
|
+
{"type": "video_url", "video_url": {"url": url}}
|
78
|
+
|
79
|
+
]
|
80
|
+
request = CompletionRequest(
|
81
|
+
# model="qwen-turbo-2024-11-01",
|
82
|
+
model="gemini-all",
|
83
|
+
# model="qwen-plus-latest",
|
84
|
+
|
85
|
+
messages=[
|
86
|
+
{
|
87
|
+
'role': 'user',
|
88
|
+
|
89
|
+
'content': content
|
90
|
+
},
|
91
|
+
|
92
|
+
],
|
93
|
+
stream=False,
|
94
|
+
)
|
95
|
+
arun(Completions().create(request))
|
@@ -0,0 +1,100 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Project : AI. @by PyCharm
|
4
|
+
# @File : deepx
|
5
|
+
# @Time : 2025/3/20 08:53
|
6
|
+
# @Author : betterme
|
7
|
+
# @WeChat : meutils
|
8
|
+
# @Software : PyCharm
|
9
|
+
# @Description :
|
10
|
+
"""
|
11
|
+
deep + claude
|
12
|
+
|
13
|
+
"""
|
14
|
+
|
15
|
+
from openai import AsyncOpenAI
|
16
|
+
|
17
|
+
from meutils.pipe import *
|
18
|
+
from meutils.decorators.retry import retrying
|
19
|
+
from meutils.io.files_utils import to_bytes
|
20
|
+
from meutils.io.openai_files import file_extract, guess_mime_type
|
21
|
+
from meutils.str_utils.json_utils import json_path
|
22
|
+
from meutils.apis.search import metaso
|
23
|
+
# from meutils.apis.chatglm import glm_video_api
|
24
|
+
|
25
|
+
from meutils.llm.clients import chatfire_client, zhipuai_client, AsyncOpenAI
|
26
|
+
from meutils.llm.openai_utils import to_openai_params
|
27
|
+
|
28
|
+
from meutils.schemas.openai_types import ChatCompletionRequest
|
29
|
+
from meutils.schemas.openai_types import chat_completion, chat_completion_chunk, CompletionRequest, ImageRequest
|
30
|
+
|
31
|
+
|
32
|
+
class Completions(object):
|
33
|
+
|
34
|
+
def __init__(self, api_key: Optional[str] = None):
|
35
|
+
self.api_key = api_key
|
36
|
+
self.client = AsyncOpenAI(api_key=api_key)
|
37
|
+
|
38
|
+
async def create(self, request: CompletionRequest):
|
39
|
+
"""
|
40
|
+
:param request:
|
41
|
+
:return:
|
42
|
+
"""
|
43
|
+
data = to_openai_params(request)
|
44
|
+
data['model'] = 'deepseek-reasoner'
|
45
|
+
data['max_tokens'] = 1 # 火山 支持max_tokens=1输出思维链
|
46
|
+
if request.stream:
|
47
|
+
reasoning_content = ""
|
48
|
+
completions = await chatfire_client.chat.completions.create(**data)
|
49
|
+
async for chunk in completions:
|
50
|
+
yield chunk
|
51
|
+
delta = chunk.choices[0].delta
|
52
|
+
if hasattr(delta, "reasoning_content"):
|
53
|
+
reasoning_content += delta.reasoning_content
|
54
|
+
|
55
|
+
request.messages = [
|
56
|
+
{
|
57
|
+
'role': 'user',
|
58
|
+
'content': f"""<think>\n\n{reasoning_content}\n\n</think>\n\n{request.last_user_content}"""
|
59
|
+
}
|
60
|
+
]
|
61
|
+
data = to_openai_params(request)
|
62
|
+
async for chunk in await self.client.chat.completions.create(**data):
|
63
|
+
yield chunk
|
64
|
+
else:
|
65
|
+
reasoning_content = ""
|
66
|
+
completions = await chatfire_client.chat.completions.create(**data)
|
67
|
+
message = completions.choices[0].message
|
68
|
+
if hasattr(message, "reasoning_content"):
|
69
|
+
reasoning_content += message.reasoning_content
|
70
|
+
|
71
|
+
request.messages = [
|
72
|
+
{
|
73
|
+
'role': 'user',
|
74
|
+
'content': f"""<think>\n\n{reasoning_content}\n\n</think>\n\n\n{request.last_user_content}"""
|
75
|
+
}
|
76
|
+
]
|
77
|
+
data = to_openai_params(request)
|
78
|
+
_completions = await self.client.chat.completions.create(**data)
|
79
|
+
completions.choices[0].message.content = _completions.choices[0].message.content
|
80
|
+
yield completions
|
81
|
+
|
82
|
+
async def screate(self, request: CompletionRequest):
|
83
|
+
pass
|
84
|
+
|
85
|
+
|
86
|
+
if __name__ == '__main__':
|
87
|
+
c = Completions()
|
88
|
+
|
89
|
+
request = CompletionRequest(
|
90
|
+
# model="qwen-turbo-2024-11-01",
|
91
|
+
# model="claude-3-5-sonnet-20241022",
|
92
|
+
model="deepseek-chat",
|
93
|
+
stream=True,
|
94
|
+
|
95
|
+
messages=[{
|
96
|
+
'role': 'user',
|
97
|
+
'content': "1+1"
|
98
|
+
}])
|
99
|
+
|
100
|
+
arun(c.create(request))
|
meutils/oss/__init__.py
CHANGED
@@ -8,13 +8,7 @@
|
|
8
8
|
# @Software : PyCharm
|
9
9
|
# @Description :
|
10
10
|
|
11
|
-
from meutils.pipe import *
|
12
11
|
|
13
12
|
|
14
|
-
def upload(file: bytes, purpos="zhipu"):
|
15
|
-
from meutils.oss.minio_oss import Minio
|
16
|
-
from meutils.apis.chatglm.glm_video import upload_task
|
17
|
-
|
18
|
-
file_task = upload_task(file)
|
19
13
|
|
20
14
|
|
meutils/schemas/oneapi/common.py
CHANGED
@@ -425,7 +425,7 @@ MODEL_RATIO = {
|
|
425
425
|
"qwen2.5-math-72b-instruct": 2,
|
426
426
|
"qwen2.5-coder-32b-instruct": 0.5,
|
427
427
|
|
428
|
-
"qwq-32b":
|
428
|
+
"qwq-32b": 1,
|
429
429
|
"qwq-max": 2,
|
430
430
|
"qwq-max-search": 2,
|
431
431
|
"qwen-max-search": 2,
|
@@ -858,8 +858,8 @@ COMPLETION_RATIO = {
|
|
858
858
|
|
859
859
|
"gemini-2.0-flash-lite-preview-02-05": 4,
|
860
860
|
|
861
|
-
"gemini-2.0-pro":
|
862
|
-
"gemini-2.0-pro-exp-02-05":
|
861
|
+
"gemini-2.0-pro": 5,
|
862
|
+
"gemini-2.0-pro-exp-02-05": 5,
|
863
863
|
|
864
864
|
"gemma2-9b-it": 4,
|
865
865
|
"gemma2-27b-it": 4,
|
@@ -871,6 +871,8 @@ COMPLETION_RATIO = {
|
|
871
871
|
"qwen-turbo-2024-11-01": 3,
|
872
872
|
"qwen/qwq-32b-preview": 3,
|
873
873
|
"Qwen/QwQ-32B-Preview": 3,
|
874
|
+
"qwq-32b": 3,
|
875
|
+
|
874
876
|
"qwq-32b-preview": 3,
|
875
877
|
"qvq-72b-preview": 3,
|
876
878
|
|
meutils/schemas/openai_types.py
CHANGED
@@ -121,9 +121,6 @@ class CompletionRequest(BaseModel):
|
|
121
121
|
def __init__(self, **kwargs):
|
122
122
|
super().__init__(**kwargs)
|
123
123
|
|
124
|
-
class Config:
|
125
|
-
extra = "allow"
|
126
|
-
|
127
124
|
@cached_property
|
128
125
|
def last_message(self):
|
129
126
|
return self.messages and self.messages[-1]
|
@@ -132,12 +129,23 @@ class CompletionRequest(BaseModel):
|
|
132
129
|
def last_user_content(self) -> str:
|
133
130
|
for i, message in enumerate(self.messages[::-1], 1):
|
134
131
|
if message.get("role") == "user":
|
135
|
-
|
136
|
-
if isinstance(
|
137
|
-
for content in
|
132
|
+
contents = message.get("content")
|
133
|
+
if isinstance(contents, list):
|
134
|
+
for content in contents:
|
138
135
|
return content.get('text', "")
|
139
136
|
else:
|
140
|
-
return str(
|
137
|
+
return str(contents)
|
138
|
+
|
139
|
+
@cached_property
|
140
|
+
def last_assistant_content(self) -> str:
|
141
|
+
for i, message in enumerate(self.messages[::-1], 1):
|
142
|
+
if message.get("role") == "assistant":
|
143
|
+
contents = message.get("content")
|
144
|
+
if isinstance(contents, list):
|
145
|
+
for content in contents:
|
146
|
+
return content.get('text', "")
|
147
|
+
else:
|
148
|
+
return str(contents)
|
141
149
|
|
142
150
|
@cached_property
|
143
151
|
def last_urls(self): # file_url 多轮对话需要 sum(request.last_urls.values(), [])
|
@@ -180,6 +188,24 @@ class CompletionRequest(BaseModel):
|
|
180
188
|
#
|
181
189
|
# return message
|
182
190
|
|
191
|
+
class Config:
|
192
|
+
extra = "allow"
|
193
|
+
|
194
|
+
json_schema_extra = {
|
195
|
+
"examples": [
|
196
|
+
{
|
197
|
+
"model": "deepseek-chat",
|
198
|
+
"messages": [
|
199
|
+
{
|
200
|
+
"role": "user",
|
201
|
+
"content": "hi"
|
202
|
+
}
|
203
|
+
],
|
204
|
+
"stream": True
|
205
|
+
},
|
206
|
+
]
|
207
|
+
}
|
208
|
+
|
183
209
|
|
184
210
|
class ChatCompletionRequest(BaseModel):
|
185
211
|
"""
|
@@ -20,6 +20,8 @@ HTML_PARSER = re.compile(r'```html(.*?)```', re.DOTALL)
|
|
20
20
|
|
21
21
|
# re.sub(r'=(.+)', r'=123','s=xxxxx')
|
22
22
|
|
23
|
+
|
24
|
+
|
23
25
|
@lru_cache()
|
24
26
|
def remove_date_suffix(filename):
|
25
27
|
"""
|
@@ -152,6 +154,8 @@ if __name__ == '__main__':
|
|
152
154
|
|
153
155
|
print(parse_url(text))
|
154
156
|
|
157
|
+
print(parse_url("[](https://oss.ffire.cc/cdn/2025-03-20/YbHhMbrXV82XGn4msunAJw)"))
|
158
|
+
|
155
159
|
# print('https://mj101-1317487292.cos.ap-shanghai.myqcloud.com/ai/test.pdf\\n\\n'.strip(r"\n"))
|
156
160
|
|
157
161
|
# print(parse_url("http://154.3.0.117:39666/docs#/default/get_content_preview_spider_playwright_get"))
|
File without changes
|
File without changes
|
{MeUtils-2025.3.19.19.13.35.dist-info → MeUtils-2025.3.21.10.18.9.dist-info}/entry_points.txt
RENAMED
File without changes
|
File without changes
|