MeUtils 2024.12.13.15.39.7__py3-none-any.whl → 2024.12.19.9.30.53__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-2024.12.13.15.39.7.dist-info → MeUtils-2024.12.19.9.30.53.dist-info}/METADATA +28 -28
- {MeUtils-2024.12.13.15.39.7.dist-info → MeUtils-2024.12.19.9.30.53.dist-info}/RECORD +28 -19
- examples/_openaisdk/4v.py +2 -1
- examples/_openaisdk/gpt4all.py +0 -5
- examples/_openaisdk/open_router.py +5 -2
- examples/_openaisdk/openai_chatfire.py +8 -2
- examples/caches/llmcache.py +18 -0
- meutils/apis/hailuoai/videos.py +1 -1
- meutils/apis/images/fal/files.py +4 -1
- meutils/apis/jimeng/__init__.py +11 -0
- meutils/apis/jimeng/common.py +253 -0
- meutils/apis/jimeng/files.py +180 -0
- meutils/apis/jimeng/images.py +105 -0
- meutils/apis/jimeng/sig.py +92 -0
- meutils/apis/jimeng/utils.py +177 -0
- meutils/apis/siliconflow/videos.py +38 -9
- meutils/data/VERSION +1 -1
- meutils/data/oneapi/NOTICE.md +12 -29
- meutils/io/files_utils.py +34 -3
- meutils/llm/completions/rag/fire.py +2 -1
- meutils/llm/mappers.py +15 -0
- meutils/office_automation/pdf.py +5 -1
- meutils/schemas/jimeng_types.py +28 -0
- meutils/schemas/oneapi/common.py +9 -0
- {MeUtils-2024.12.13.15.39.7.dist-info → MeUtils-2024.12.19.9.30.53.dist-info}/LICENSE +0 -0
- {MeUtils-2024.12.13.15.39.7.dist-info → MeUtils-2024.12.19.9.30.53.dist-info}/WHEEL +0 -0
- {MeUtils-2024.12.13.15.39.7.dist-info → MeUtils-2024.12.19.9.30.53.dist-info}/entry_points.txt +0 -0
- {MeUtils-2024.12.13.15.39.7.dist-info → MeUtils-2024.12.19.9.30.53.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,180 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Project : AI. @by PyCharm
|
4
|
+
# @File : kaiyuan
|
5
|
+
# @Time : 2024/12/18 16:03
|
6
|
+
# @Author : betterme
|
7
|
+
# @WeChat : meutils
|
8
|
+
# @Software : PyCharm
|
9
|
+
# @Description :
|
10
|
+
|
11
|
+
import hmac
|
12
|
+
import zlib
|
13
|
+
import hashlib
|
14
|
+
|
15
|
+
from meutils.pipe import *
|
16
|
+
from meutils.caches.redis_cache import cache
|
17
|
+
|
18
|
+
|
19
|
+
def random_str(n):
|
20
|
+
return ''.join(random.sample('zyxwvutsrqponmlkjihgfedcba0123456789', n))
|
21
|
+
|
22
|
+
|
23
|
+
def hash256(msg):
|
24
|
+
return hashlib.sha256(msg.encode('utf-8')).hexdigest()
|
25
|
+
|
26
|
+
|
27
|
+
def hmac_hash256(key, msg):
|
28
|
+
if type(key) == str:
|
29
|
+
return hmac.new(key.encode('utf-8'), msg.encode('utf-8'), hashlib.sha256)
|
30
|
+
elif type(key) == hmac.HMAC:
|
31
|
+
return hmac.new(key.digest(), msg.encode('utf-8'), hashlib.sha256)
|
32
|
+
|
33
|
+
|
34
|
+
def fileCRC32(file_buffer):
|
35
|
+
return hex(zlib.crc32(file_buffer) & 0xFFFFFFFF)[2:]
|
36
|
+
|
37
|
+
|
38
|
+
def u(params):
|
39
|
+
new_params = sorted(params.items(), key=lambda x: x[0])
|
40
|
+
new_params = [f"{k}={v}" for k, v in new_params]
|
41
|
+
return "&".join(new_params)
|
42
|
+
|
43
|
+
|
44
|
+
class JJRequest:
|
45
|
+
def __init__(self, e, t, api, method="GET", params=None, data=None):
|
46
|
+
self.t = t
|
47
|
+
self.e = e
|
48
|
+
self.api = api
|
49
|
+
self.method = method
|
50
|
+
self.params = params
|
51
|
+
self.data = data
|
52
|
+
|
53
|
+
def getAuthorization(self):
|
54
|
+
return f"AWS4-HMAC-SHA256 Credential={self.e['access_key_id']}/{self.t[0:8]}/cn-north-1/imagex/aws4_request, SignedHeaders=x-amz-date;x-amz-security-token, Signature={self.signature()}"
|
55
|
+
|
56
|
+
def signature(self):
|
57
|
+
r = self.getSigningKey()
|
58
|
+
return hmac_hash256(r, self.stringToSign()).hexdigest()
|
59
|
+
|
60
|
+
def getSigningKey(self, r="cn-north-1", n="imagex"):
|
61
|
+
o = hmac_hash256("AWS4" + self.e['secret_access_key'], str(self.t[0:8]))
|
62
|
+
i = hmac_hash256(o, str(r))
|
63
|
+
s = hmac_hash256(i, str(n))
|
64
|
+
return hmac_hash256(s, "aws4_request")
|
65
|
+
|
66
|
+
def stringToSign(self):
|
67
|
+
t = []
|
68
|
+
t.append("AWS4-HMAC-SHA256")
|
69
|
+
t.append(self.t)
|
70
|
+
t.append(self.credentialString())
|
71
|
+
t.append(hash256(self.canonicalString()))
|
72
|
+
return "\n".join(t)
|
73
|
+
|
74
|
+
def credentialString(self, region="cn-north-1", serviceName="imagex"):
|
75
|
+
return "/".join([self.t[0:8], region, serviceName, "aws4_request"])
|
76
|
+
|
77
|
+
def canonicalString(self):
|
78
|
+
e = []
|
79
|
+
e.append(self.method)
|
80
|
+
e.append("/")
|
81
|
+
e.append(u(self.params))
|
82
|
+
e.append(self.canonicalHeaders())
|
83
|
+
e.append(self.signedHeaders())
|
84
|
+
e.append(self.hexEncodedBodyHash())
|
85
|
+
return "\n".join(e)
|
86
|
+
|
87
|
+
def canonicalHeaders(self):
|
88
|
+
return f"x-amz-date:{self.t}\nx-amz-security-token:{self.e['session_token']}\n"
|
89
|
+
|
90
|
+
def signedHeaders(self):
|
91
|
+
return "x-amz-date;x-amz-security-token"
|
92
|
+
|
93
|
+
def hexEncodedBodyHash(self):
|
94
|
+
return hash256("")
|
95
|
+
|
96
|
+
|
97
|
+
@cache(ttl=15 * 60)
|
98
|
+
def upload(image: bytes, upload_token: dict): # oss 跨账号不知道是否可以使用
|
99
|
+
# e = auth = upload_token['data']['auth'] # 豆包
|
100
|
+
data = upload_token['data']
|
101
|
+
|
102
|
+
service_id = data.get('service_id', '3jr8j4ixpe') # 即梦 3jr8j4ixpe
|
103
|
+
|
104
|
+
session_token = data['session_token']
|
105
|
+
|
106
|
+
t = time.strftime("%Y%m%dT%H%M%SZ", time.gmtime())
|
107
|
+
|
108
|
+
params = {
|
109
|
+
"Action": "ApplyImageUpload",
|
110
|
+
"Version": "2018-08-01",
|
111
|
+
"ServiceId": service_id,
|
112
|
+
"s": random_str(10),
|
113
|
+
|
114
|
+
"FileExtension": ".png", #####
|
115
|
+
"FileSize": len(image),
|
116
|
+
}
|
117
|
+
|
118
|
+
r = JJRequest(data, t, "https://imagex.bytedanceapi.com/", method="GET", params=params)
|
119
|
+
headers = {
|
120
|
+
'authorization': r.getAuthorization(),
|
121
|
+
'x-amz-date': t,
|
122
|
+
'x-amz-security-token': session_token,
|
123
|
+
}
|
124
|
+
# logger.debug(headers)
|
125
|
+
response = requests.get(r.api, params=params, headers=headers)
|
126
|
+
response.raise_for_status()
|
127
|
+
logger.debug(response.status_code)
|
128
|
+
response = response.json()
|
129
|
+
|
130
|
+
logger.debug(bjson(response))
|
131
|
+
if "Result" not in response:
|
132
|
+
return
|
133
|
+
|
134
|
+
store_info = response['Result']['UploadAddress']['StoreInfos'][0]
|
135
|
+
logger.debug(bjson(store_info))
|
136
|
+
|
137
|
+
oss_uri = store_info['StoreUri']
|
138
|
+
oss_token = store_info['Auth']
|
139
|
+
|
140
|
+
headers = {
|
141
|
+
"authorization": oss_token,
|
142
|
+
"content-length": str(len(image)),
|
143
|
+
"content-Type": "image/jpeg",
|
144
|
+
"content-crc32": fileCRC32(image),
|
145
|
+
}
|
146
|
+
|
147
|
+
# oss_url = f"https://{resp['Result']['UploadAddress']['UploadHosts'][0]}/{oss_uri}"
|
148
|
+
|
149
|
+
# image_resp = requests.put( # post
|
150
|
+
# oss_url,
|
151
|
+
# headers=headers,
|
152
|
+
# data=image,
|
153
|
+
# )
|
154
|
+
# logger.debug(image_resp.json())
|
155
|
+
|
156
|
+
# return get_url(StoreUri)
|
157
|
+
|
158
|
+
# upload_url = f"https://tos-hl-x.snssdk.com/upload/v1/{oss_uri}"
|
159
|
+
upload_url = f"https://{response['Result']['UploadAddress']['UploadHosts'][0]}/upload/v1/{oss_uri}"
|
160
|
+
|
161
|
+
response = requests.post(upload_url, headers=headers, data=image)
|
162
|
+
response.raise_for_status()
|
163
|
+
response = response.json()
|
164
|
+
|
165
|
+
logger.debug(response)
|
166
|
+
|
167
|
+
return oss_uri
|
168
|
+
|
169
|
+
|
170
|
+
if __name__ == "__main__":
|
171
|
+
from meutils.apis.jimeng.common import get_upload_token
|
172
|
+
|
173
|
+
token = "693701c43e477b7c405cc7e2fef0ddbd"
|
174
|
+
|
175
|
+
upload_token = arun(get_upload_token(token))
|
176
|
+
|
177
|
+
with open("11.jpg", "rb") as f:
|
178
|
+
file = image = f.read()
|
179
|
+
|
180
|
+
upload(image, upload_token)
|
@@ -0,0 +1,105 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Project : AI. @by PyCharm
|
4
|
+
# @File : images
|
5
|
+
# @Time : 2024/12/16 17:46
|
6
|
+
# @Author : betterme
|
7
|
+
# @WeChat : meutils
|
8
|
+
# @Software : PyCharm
|
9
|
+
# @Description :
|
10
|
+
|
11
|
+
from meutils.pipe import *
|
12
|
+
|
13
|
+
from meutils.schemas.jimeng_types import BASE_URL, MODELS_MAP, FEISHU_URL
|
14
|
+
from meutils.schemas.image_types import ImageRequest
|
15
|
+
from meutils.schemas.task_types import TaskResponse
|
16
|
+
from meutils.apis.jimeng.common import create_draft_content, get_headers, check_token
|
17
|
+
from meutils.config_utils.lark_utils import get_next_token_for_polling
|
18
|
+
|
19
|
+
from fake_useragent import UserAgent
|
20
|
+
|
21
|
+
ua = UserAgent()
|
22
|
+
|
23
|
+
|
24
|
+
async def create_task(request: ImageRequest, token: Optional[str] = None):
|
25
|
+
token = token or await get_next_token_for_polling(FEISHU_URL, check_token)
|
26
|
+
|
27
|
+
url = "/mweb/v1/aigc_draft/generate"
|
28
|
+
|
29
|
+
headers = get_headers(url, token)
|
30
|
+
|
31
|
+
if "http" in request.prompt: # 图生
|
32
|
+
request.model = "high_aes_general_v20_L:general_v2.0_L"
|
33
|
+
|
34
|
+
draft_content = await create_draft_content(request, token)
|
35
|
+
payload = {
|
36
|
+
"extend": {
|
37
|
+
"root_model": request.model,
|
38
|
+
"template_id": ""
|
39
|
+
},
|
40
|
+
"submit_id": str(uuid.uuid4()),
|
41
|
+
"metrics_extra": "{\"templateId\":\"\",\"generateCount\":1,\"promptSource\":\"custom\",\"templateSource\":\"\",\"lastRequestId\":\"\",\"originRequestId\":\"\"}",
|
42
|
+
"draft_content": json.dumps(draft_content),
|
43
|
+
"http_common_info": {
|
44
|
+
"aid": 513695
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
logger.debug(bjson(payload))
|
49
|
+
|
50
|
+
async with httpx.AsyncClient(base_url=BASE_URL, headers=headers, timeout=60) as client:
|
51
|
+
response = await client.post(url, json=payload)
|
52
|
+
response.raise_for_status()
|
53
|
+
data = response.json()
|
54
|
+
logger.debug(bjson(data))
|
55
|
+
|
56
|
+
task_id = data.get("data", {}).get("aigc_data", {}).get("history_record_id")
|
57
|
+
return TaskResponse(task_id=task_id, system_fingerprint=token)
|
58
|
+
|
59
|
+
|
60
|
+
async def get_task(task_id, token):
|
61
|
+
url = "/mweb/v1/get_history_by_ids"
|
62
|
+
headers = get_headers(url, token)
|
63
|
+
payload = {
|
64
|
+
"history_ids": [
|
65
|
+
task_id
|
66
|
+
]
|
67
|
+
}
|
68
|
+
|
69
|
+
async with httpx.AsyncClient(base_url=BASE_URL, headers=headers, timeout=60) as client:
|
70
|
+
response = await client.post(url, json=payload)
|
71
|
+
response.raise_for_status()
|
72
|
+
data = response.json()
|
73
|
+
# {'ret': '1015', 'errmsg': 'login error', 'systime': '1734524280', 'logid': '20241218201800AC3267447B287E9E6C46', 'data': None}
|
74
|
+
item_list = (data.get("data") or {}).get(task_id, {}).get("item_list")
|
75
|
+
image_data = map(lambda x: x.get("image", {}).get("large_images"), item_list)
|
76
|
+
|
77
|
+
task_data = sum(image_data, []) | xmap_(lambda x: {"url": x.get("image_url")})
|
78
|
+
|
79
|
+
return TaskResponse(
|
80
|
+
task_id=task_id,
|
81
|
+
data=task_data,
|
82
|
+
message=data.get("errmsg"),
|
83
|
+
status=task_data and "success",
|
84
|
+
)
|
85
|
+
|
86
|
+
|
87
|
+
if __name__ == '__main__':
|
88
|
+
token = "693701c43e477b7c405cc7e2fef0ddbd"
|
89
|
+
|
90
|
+
request = ImageRequest(prompt="一个漂亮的姑娘", size="1024x1024")
|
91
|
+
# request = ImageRequest(prompt="https://oss.ffire.cc/files/kling_watermark.png 让她带上墨镜", size="1024x1024")
|
92
|
+
|
93
|
+
arun(create_task(request))
|
94
|
+
|
95
|
+
# task_id = "10040025470722"
|
96
|
+
|
97
|
+
# task_id = "10053536381698"
|
98
|
+
|
99
|
+
# task_id = "10079694738434"
|
100
|
+
|
101
|
+
# task_id = "10080831230210" # 图片编辑
|
102
|
+
|
103
|
+
# task_id = "10082971040514"
|
104
|
+
#
|
105
|
+
# arun(get_task(task_id, token))
|
@@ -0,0 +1,92 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Project : AI. @by PyCharm
|
4
|
+
# @File : sig
|
5
|
+
# @Time : 2024/12/18 15:36
|
6
|
+
# @Author : betterme
|
7
|
+
# @WeChat : meutils
|
8
|
+
# @Software : PyCharm
|
9
|
+
# @Description :
|
10
|
+
import hashlib
|
11
|
+
import hmac
|
12
|
+
import datetime
|
13
|
+
|
14
|
+
|
15
|
+
def sign(key, msg):
|
16
|
+
return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()
|
17
|
+
|
18
|
+
|
19
|
+
def getSignatureKey(key, dateStamp, regionName, serviceName):
|
20
|
+
kDate = sign(('AWS4' + key).encode('utf-8'), dateStamp)
|
21
|
+
kRegion = sign(kDate, regionName)
|
22
|
+
kService = sign(kRegion, serviceName)
|
23
|
+
kSigning = sign(kService, 'aws4_request')
|
24
|
+
return kSigning
|
25
|
+
|
26
|
+
|
27
|
+
if __name__ == '__main__':
|
28
|
+
pass
|
29
|
+
from meutils.pipe import *
|
30
|
+
from meutils.apis.jimeng.utils import get_upload_token
|
31
|
+
|
32
|
+
# data = arun(get_upload_token())
|
33
|
+
|
34
|
+
# access_key_id = data['data']['auth']['access_key_id']
|
35
|
+
# secret_access_key = data['data']['auth']['secret_access_key']
|
36
|
+
# session_token = data['data']['auth']['session_token']
|
37
|
+
|
38
|
+
import hashlib
|
39
|
+
import hmac
|
40
|
+
import datetime
|
41
|
+
|
42
|
+
|
43
|
+
def sign(key, msg):
|
44
|
+
"""计算 HMAC-SHA256"""
|
45
|
+
return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()
|
46
|
+
|
47
|
+
|
48
|
+
def getSignatureKey(key, dateStamp, regionName, serviceName):
|
49
|
+
"""生成签名密钥"""
|
50
|
+
kDate = sign(('AWS4' + key).encode('utf-8'), dateStamp)
|
51
|
+
kRegion = sign(kDate, regionName)
|
52
|
+
kService = sign(kRegion, serviceName)
|
53
|
+
kSigning = sign(kService, 'aws4_request')
|
54
|
+
return kSigning
|
55
|
+
|
56
|
+
|
57
|
+
def calculate_signature(string_to_sign, secret_key, region, service, date):
|
58
|
+
"""计算 AWS4-HMAC-SHA256 签名"""
|
59
|
+
# 生成签名密钥
|
60
|
+
signing_key = getSignatureKey(
|
61
|
+
secret_key,
|
62
|
+
date.strftime('%Y%m%d'),
|
63
|
+
region,
|
64
|
+
service
|
65
|
+
)
|
66
|
+
|
67
|
+
# 计算最终签名
|
68
|
+
signature = hmac.new(
|
69
|
+
signing_key,
|
70
|
+
string_to_sign.encode('utf-8'),
|
71
|
+
hashlib.sha256
|
72
|
+
).hexdigest()
|
73
|
+
|
74
|
+
return signature
|
75
|
+
|
76
|
+
# 示例参数
|
77
|
+
|
78
|
+
|
79
|
+
secret_key = 'AKTPN2VkZWY2MWNhNjVlNGZhZThiZmVmNzEwODA3YjM1YTY'
|
80
|
+
region = 'cn-north-1'
|
81
|
+
service = 'imagex'
|
82
|
+
date = datetime.datetime.utcnow()
|
83
|
+
print(date)
|
84
|
+
hash_of_canonical_request = {
|
85
|
+
"SessionKey": "eyJhY2NvdW50VHlwZSI6IkltYWdlWCIsImFwcElkIjoiIiwiYml6VHlwZSI6IiIsImZpbGVUeXBlIjoiaW1hZ2UiLCJsZWdhbCI6IiIsInN0b3JlSW5mb3MiOiJbe1wiU3RvcmVVcmlcIjpcInRvcy1jbi1pLWE5cm5zMnJsOTgvYmQzZGNlZWIzN2Y3NDA5NjlkMTBiZjBiZjhhMzk0NmUuanBlZ1wiLFwiQXV0aFwiOlwiU3BhY2VLZXkvYTlybnMycmw5OC8xLzp2ZXJzaW9uOnYyOmV5SmhiR2NpT2lKSVV6STFOaUlzSW5SNWNDSTZJa3BYVkNKOS5leUpsZUhBaU9qRTNNelExTXpBd016Z3NJbk5wWjI1aGRIVnlaVWx1Wm04aU9uc2lZV05qWlhOelMyVjVJam9pWm1GclpWOWhZMk5sYzNOZmEyVjVJaXdpWW5WamEyVjBJam9pZEc5ekxXTnVMV2t0WVRseWJuTXljbXc1T0NJc0ltVjRjR2x5WlNJNk1UY3pORFV6TURBek9Dd2labWxzWlVsdVptOXpJanBiZXlKdmFXUkxaWGtpT2lKaVpETmtZMlZsWWpNM1pqYzBNRGsyT1dReE1HSm1NR0ptT0dFek9UUTJaUzVxY0dWbklpd2labWxzWlZSNWNHVWlPaUl4SW4xZExDSmxlSFJ5WVNJNmV5SmliRzlqYTE5dGIyUmxJam9pSWl3aVkyOXVkR1Z1ZEY5MGVYQmxYMkpzYjJOcklqb2llMXdpYldsdFpWOXdZM1JjSWpvd0xGd2liVzlrWlZ3aU9qQXNYQ0p0YVcxbFgyeHBjM1JjSWpwdWRXeHNMRndpWTI5dVpteHBZM1JmWW14dlkydGNJanBtWVd4elpYMGlMQ0psYm1OeWVYQjBYMkZzWjI4aU9pSWlMQ0psYm1OeWVYQjBYMnRsZVNJNklpSXNJbVY0ZEY5amIyNTBaVzUwWDNSNWNHVWlPaUpwYldGblpTOXFjR1ZuSWl3aWFYTmZhVzFoWjJWNElqcDBjblZsTENKemNHRmpaU0k2SW1FNWNtNXpNbkpzT1RnaWZYMTkueVFadDJoYWFVMDBuMTFZREJXZDBCbTNIYWdtVlNUN0UzNXMwSkNnOGpzMFwiLFwiVXBsb2FkSURcIjpcIjE3ZThiODUxNzczNDRlYjFiYmM1MDAzMWU3NzQ3NGUyXCIsXCJVcGxvYWRIZWFkZXJcIjpudWxsLFwiU3RvcmFnZUhlYWRlclwiOm51bGx9XSIsInVwbG9hZEhvc3QiOiJ0b3MtZC14LWxmLnNuc3Nkay5jb20iLCJ1cmkiOiJ0b3MtY24taS1hOXJuczJybDk4L2JkM2RjZWViMzdmNzQwOTY5ZDEwYmYwYmY4YTM5NDZlLmpwZWciLCJ1c2VySWQiOiIifQ=="
|
86
|
+
}
|
87
|
+
hash_of_canonical_request = json.dumps(hash_of_canonical_request)
|
88
|
+
string_to_sign = f'AWS4-HMAC-SHA256\n20241218T075358Z\n20241218/cn-north-1/imagex/aws4_request\n{hash_of_canonical_request}'
|
89
|
+
|
90
|
+
# 计算签名
|
91
|
+
signature = calculate_signature(string_to_sign, secret_key, region, service, date)
|
92
|
+
print(f'签名结果: {signature}')
|
@@ -0,0 +1,177 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Project : AI. @by PyCharm
|
4
|
+
# @File : utils
|
5
|
+
# @Time : 2024/12/18 11:03
|
6
|
+
# @Author : betterme
|
7
|
+
# @WeChat : meutils
|
8
|
+
# @Software : PyCharm
|
9
|
+
# @Description :
|
10
|
+
import httpx
|
11
|
+
|
12
|
+
from meutils.pipe import *
|
13
|
+
import random
|
14
|
+
import base64
|
15
|
+
import time
|
16
|
+
import uuid
|
17
|
+
import secrets
|
18
|
+
import string
|
19
|
+
import hmac
|
20
|
+
import hashlib
|
21
|
+
|
22
|
+
# 常量定义
|
23
|
+
MODEL_NAME = "doubao"
|
24
|
+
DEFAULT_ASSISTANT_ID = "497858"
|
25
|
+
VERSION_CODE = "20800"
|
26
|
+
DEVICE_ID = random.random() * 999999999999999999 + 7000000000000000000
|
27
|
+
WEB_ID = random.random() * 999999999999999999 + 7000000000000000000
|
28
|
+
USER_ID = str(uuid.uuid4()).replace('-', '')
|
29
|
+
MAX_RETRY_COUNT = 3
|
30
|
+
RETRY_DELAY = 5000
|
31
|
+
FILE_MAX_SIZE = 100 * 1024 * 1024
|
32
|
+
|
33
|
+
# 伪装headers
|
34
|
+
FAKE_HEADERS = {
|
35
|
+
"Accept": "*/*",
|
36
|
+
"Accept-Encoding": "gzip, deflate, br, zstd",
|
37
|
+
"Accept-language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
|
38
|
+
"Cache-control": "no-cache",
|
39
|
+
"Last-event-id": "undefined",
|
40
|
+
"Origin": "https://www.doubao.com",
|
41
|
+
"Pragma": "no-cache",
|
42
|
+
"Priority": "u=1, i",
|
43
|
+
"Referer": "https://www.doubao.com",
|
44
|
+
"Sec-Ch-Ua": '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
|
45
|
+
"Sec-Ch-Ua-Mobile": "?0",
|
46
|
+
"Sec-Ch-Ua-Platform": '"Windows"',
|
47
|
+
"Sec-Fetch-Dest": "empty",
|
48
|
+
"Sec-Fetch-Mode": "cors",
|
49
|
+
"Sec-Fetch-Site": "same-origin",
|
50
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
|
51
|
+
}
|
52
|
+
|
53
|
+
|
54
|
+
async def acquire_token(refresh_token: str) -> str:
|
55
|
+
"""
|
56
|
+
获取缓存中的access_token
|
57
|
+
目前doubao的access_token是固定的,暂无刷新功能
|
58
|
+
|
59
|
+
Args:
|
60
|
+
refresh_token: 用于刷新access_token的refresh_token
|
61
|
+
|
62
|
+
Returns:
|
63
|
+
str: access_token
|
64
|
+
"""
|
65
|
+
return refresh_token
|
66
|
+
|
67
|
+
|
68
|
+
def generate_fake_ms_token() -> str:
|
69
|
+
"""
|
70
|
+
生成伪msToken
|
71
|
+
"""
|
72
|
+
# 生成96字节的随机数据
|
73
|
+
random_bytes = secrets.token_bytes(96)
|
74
|
+
# 转换为base64,并替换特殊字符
|
75
|
+
token = base64.b64encode(random_bytes).decode('utf-8')
|
76
|
+
return token.replace('+', '-').replace('/', '_').rstrip('=')
|
77
|
+
|
78
|
+
|
79
|
+
def generate_random_string(length: int) -> str:
|
80
|
+
"""
|
81
|
+
生成指定长度的随机字符串
|
82
|
+
"""
|
83
|
+
chars = string.ascii_letters + string.digits
|
84
|
+
return ''.join(random.choice(chars) for _ in range(length))
|
85
|
+
|
86
|
+
|
87
|
+
def generate_fake_a_bogus() -> str:
|
88
|
+
"""
|
89
|
+
生成伪a_bogus
|
90
|
+
"""
|
91
|
+
return f"mf-{generate_random_string(34)}-{generate_random_string(6)}"
|
92
|
+
|
93
|
+
|
94
|
+
def generate_cookie(refresh_token: str, ms_token: Optional[str] = None) -> str:
|
95
|
+
"""
|
96
|
+
生成cookie
|
97
|
+
"""
|
98
|
+
ms_token = ms_token or generate_fake_ms_token()
|
99
|
+
|
100
|
+
current_timestamp = int(time.time())
|
101
|
+
cookie_parts = [
|
102
|
+
f"is_staff_user=false",
|
103
|
+
f"store-region=cn-gd",
|
104
|
+
f"store-region-src=uid",
|
105
|
+
f"sid_guard={refresh_token}%7C{current_timestamp}%7C5184000%7CSun%2C+02-Feb-2025+04%3A17%3A20+GMT",
|
106
|
+
f"uid_tt={USER_ID}",
|
107
|
+
f"uid_tt_ss={USER_ID}",
|
108
|
+
f"sid_tt={refresh_token}",
|
109
|
+
f"sessionid={refresh_token}",
|
110
|
+
f"sessionid_ss={refresh_token}",
|
111
|
+
f"msToken={ms_token}",
|
112
|
+
]
|
113
|
+
return "; ".join(cookie_parts)
|
114
|
+
|
115
|
+
|
116
|
+
async def get_upload_token(): # 3600过期
|
117
|
+
"""
|
118
|
+
|
119
|
+
{'code': 0,
|
120
|
+
'data': {'auth': {'access_key_id': 'AKTPYzNkMjJlNTNjMWE1NDJiN2E5MWFkOTYxMWViYzQxYTM',
|
121
|
+
'current_time': '2024-12-18T11:17:22+08:00',
|
122
|
+
'expired_time': '2024-12-18T12:17:22+08:00',
|
123
|
+
'secret_access_key': 'HFFTkEFKf+0DVpUrYy2yMzvgnkxLMU6+qydnGUSaDmd0vSRedpIi0qmeWSVElyOU',
|
124
|
+
'session_token': 'STS2eyJMVEFjY2Vzc0tleUlkIjoiQUtMVFlUZGhPR0ptWVRNNFl6ZG1OR1JoWVRoaE0yWTJPVFl5TW1SbU0yRmhNREEiLCJBY2Nlc3NLZXlJZCI6IkFLVFBZek5rTWpKbE5UTmpNV0UxTkRKaU4yRTVNV0ZrT1RZeE1XVmlZelF4WVRNIiwiU2lnbmVkU2VjcmV0QWNjZXNzS2V5IjoiTC9WZTVSMmt4N3dsY1kvS0E5alp1WVlpSlVFM0ZjdHMzQ2Q5QjJZMVE3NlRnUDVONWViMmpKQkRQMUdyUEtqeXNYNXRKVkJPdExvVjVNOGFyY24wQ2ZtdUZRRWMxMG8xMSs3UHdKdGY0LzQ9IiwiRXhwaXJlZFRpbWUiOjE3MzQ0OTU0NDIsIlBvbGljeVN0cmluZyI6IntcIlN0YXRlbWVudFwiOlt7XCJFZmZlY3RcIjpcIkFsbG93XCIsXCJBY3Rpb25cIjpbXCJJbWFnZVg6QXBwbHlJbWFnZVVwbG9hZFwiLFwiSW1hZ2VYOkNvbW1pdEltYWdlVXBsb2FkXCJdLFwiUmVzb3VyY2VcIjpbXCJ0cm46SW1hZ2VYOio6KjpTZXJ2aWNlSWQvYTlybnMycmw5OFwiXX0se1wiRWZmZWN0XCI6XCJBbGxvd1wiLFwiQWN0aW9uXCI6W1wiUFNNXCJdLFwiUmVzb3VyY2VcIjpbXCJmbG93LmFsaWNlLnJlc291cmNlX2FwaVwiXX1dfSIsIlNpZ25hdHVyZSI6ImI2MGUxNDZkZTU0Njg2NTdlYzVlZmFjZjJlOWNlOWE5YTdhY2UwNTFlZTdkYTJjZTRmNjdiYmRiM2U4MDQ3N2IifQ=='},
|
125
|
+
'service_id': 'a9rns2rl98',
|
126
|
+
'upload_host': 'imagex.bytedanceapi.com',
|
127
|
+
'upload_path_prefix': 'bot-chat-image'},
|
128
|
+
'msg': ''}
|
129
|
+
|
130
|
+
:return:
|
131
|
+
"""
|
132
|
+
cookie = generate_cookie('de2215a7bb8e442774cf388f03fac84c')
|
133
|
+
url = "https://www.doubao.com/alice/upload/auth_token"
|
134
|
+
|
135
|
+
headers = {
|
136
|
+
'priority': 'u=1, i',
|
137
|
+
'Cookie': cookie,
|
138
|
+
'User-Agent': 'Apifox/1.0.0 (https://apifox.com)',
|
139
|
+
}
|
140
|
+
payload = {
|
141
|
+
"scene": "bot_chat",
|
142
|
+
"data_type": "image"
|
143
|
+
}
|
144
|
+
|
145
|
+
async with httpx.AsyncClient() as client:
|
146
|
+
response = await client.post(url, headers=headers, json=payload)
|
147
|
+
response.raise_for_status()
|
148
|
+
|
149
|
+
return response.json()
|
150
|
+
|
151
|
+
|
152
|
+
def hmac_hash256(key, msg):
|
153
|
+
if type(key) == str:
|
154
|
+
return hmac.new(key.encode('utf-8'), msg.encode('utf-8'), hashlib.sha256)
|
155
|
+
elif type(key) == hmac.HMAC:
|
156
|
+
return hmac.new(key.digest(), msg.encode('utf-8'), hashlib.sha256)
|
157
|
+
|
158
|
+
|
159
|
+
def get_signing_key(secret_access_key, r="cn-north-1", n="imagex"):
|
160
|
+
dt = str(datetime.datetime.now())[:10].replace('-', '')
|
161
|
+
o = hmac_hash256("AWS4" + secret_access_key, dt)
|
162
|
+
i = hmac_hash256(o, str(r))
|
163
|
+
s = hmac_hash256(i, str(n))
|
164
|
+
return hmac_hash256(s, "aws4_request")
|
165
|
+
|
166
|
+
def signature(secret_access_key):
|
167
|
+
r = get_signing_key(secret_access_key)
|
168
|
+
return hmac_hash256(r, self.stringToSign()).hexdigest()
|
169
|
+
|
170
|
+
# ccd4fef2cca1a114e776badad7f4b6e73f305a4dbb09e68f336759ddb6ac0025
|
171
|
+
|
172
|
+
if __name__ == '__main__':
|
173
|
+
# generate_cookie("")
|
174
|
+
|
175
|
+
# arun(get_upload_token())
|
176
|
+
|
177
|
+
print(get_signing_key('xW9YbDhTlWsXdaN7O2g1lfcyePxf5kJyg/r2mwSZG/iuSmbvVgToO6LVCLmUjVJ3'))
|
@@ -7,13 +7,16 @@
|
|
7
7
|
# @WeChat : meutils
|
8
8
|
# @Software : PyCharm
|
9
9
|
# @Description :
|
10
|
+
import asyncio
|
10
11
|
|
11
12
|
from meutils.pipe import *
|
12
13
|
from meutils.caches.redis_cache import cache
|
14
|
+
from meutils.io.files_utils import to_url, to_url_fal
|
13
15
|
from meutils.llm.check_utils import check_token_for_siliconflow
|
14
16
|
from meutils.schemas.task_types import TaskResponse
|
15
17
|
from meutils.schemas.siliconflow_types import BASE_URL, VideoRequest
|
16
18
|
from meutils.config_utils.lark_utils import get_next_token_for_polling
|
19
|
+
from meutils.apis.translator import deeplx
|
17
20
|
|
18
21
|
from openai import OpenAI, AsyncOpenAI
|
19
22
|
|
@@ -21,38 +24,54 @@ FEISHU_URL_FREE = "https://xchatllm.feishu.cn/sheets/Bmjtst2f6hfMqFttbhLcdfRJnNf
|
|
21
24
|
|
22
25
|
check_token = partial(check_token_for_siliconflow, threshold=0.01)
|
23
26
|
|
27
|
+
MODELS_MAP = {
|
28
|
+
"hunyuan-video": "tencent/HunyuanVideo",
|
29
|
+
"hunyuanvideo": "tencent/HunyuanVideo",
|
30
|
+
"mochi-1-preview": "genmo/mochi-1-preview",
|
31
|
+
"ltx-video": "Lightricks/LTX-Video",
|
32
|
+
}
|
33
|
+
|
24
34
|
|
25
35
|
@cache(ttl=7 * 24 * 3600)
|
26
36
|
async def create_task(request: VideoRequest, token: Optional[str] = None):
|
27
37
|
token = token or await get_next_token_for_polling(FEISHU_URL_FREE, check_token=check_token, from_redis=True)
|
28
38
|
|
29
39
|
payload = request.model_dump(exclude_none=True)
|
30
|
-
payload["model"] = "
|
40
|
+
payload["model"] = MODELS_MAP.get(request.model, "Lightricks/LTX-Video")
|
41
|
+
|
42
|
+
if payload["model"] in {"genmo/mochi-1-preview", "Lightricks/LTX-Video"}: # 中文不友好
|
43
|
+
payload['prompt'] = (
|
44
|
+
await deeplx.translate(deeplx.DeeplxRequest(text=request.prompt, target_lang="EN"))).get("data")
|
31
45
|
|
32
|
-
client =
|
46
|
+
client = AsyncOpenAI(
|
33
47
|
base_url=BASE_URL,
|
34
48
|
api_key=token
|
35
49
|
)
|
36
50
|
|
37
|
-
response = client.post("/video/submit",
|
51
|
+
response = await client.post("/video/submit", body=payload, cast_to=object)
|
38
52
|
logger.debug(response)
|
39
|
-
task_id = response.get('requestId')
|
40
53
|
|
54
|
+
task_id = response.get('requestId')
|
41
55
|
return TaskResponse(task_id=task_id, system_fingerprint=token)
|
42
56
|
|
43
57
|
|
44
58
|
async def get_task(task_id, token: str):
|
45
|
-
client =
|
59
|
+
client = AsyncOpenAI(
|
46
60
|
base_url=BASE_URL,
|
47
61
|
api_key=token
|
48
62
|
)
|
49
63
|
payload = {"requestId": task_id}
|
50
|
-
response = client.post(f"/video/status", cast_to=object, body=payload)
|
64
|
+
response = await client.post(f"/video/status", cast_to=object, body=payload)
|
51
65
|
logger.debug(response)
|
52
66
|
|
67
|
+
data = response.get("results") or {}
|
68
|
+
|
69
|
+
for video in data.get("videos", []):
|
70
|
+
video["url"] = await to_url_fal(video.get("url")) # 异步执行
|
71
|
+
|
53
72
|
return TaskResponse(
|
54
73
|
task_id=task_id,
|
55
|
-
data=
|
74
|
+
data=data,
|
56
75
|
status=response.get("status"),
|
57
76
|
message=response.get("reason"),
|
58
77
|
)
|
@@ -60,12 +79,22 @@ async def get_task(task_id, token: str):
|
|
60
79
|
|
61
80
|
if __name__ == '__main__':
|
62
81
|
token = None
|
82
|
+
token = "sk-raapiguffsnsxgkfiwfusjmbpcyqoxhcohhxaybflrnvpqjw"
|
83
|
+
|
84
|
+
request = VideoRequest(
|
85
|
+
model="Lightricks/LTX-Video",
|
86
|
+
prompt="这个女人笑起来",
|
87
|
+
image='https://oss.ffire.cc/files/kling_watermark.png' # 1148f2e4-0a62-4208-84de-0bf2c88f740d
|
88
|
+
)
|
63
89
|
# tokens = config_manager.text.split()
|
64
90
|
|
65
91
|
# tokens_ = arun(check_token_for_siliconflow(tokens, threshold=0.01))
|
66
92
|
|
67
|
-
token
|
68
|
-
|
93
|
+
# arun(create_task(request, token=token))
|
94
|
+
|
95
|
+
# arun(get_task("fa248aac-00ec-4b00-a2f8-3d6bf1cea6d3", token))
|
96
|
+
# arun(get_task("c716a328-438e-4612-aff2-a669034499cb", token))
|
97
|
+
arun(get_task("1148f2e4-0a62-4208-84de-0bf2c88f740d", token))
|
69
98
|
|
70
99
|
# token = "sk-oeptckzkhfzeidbtsqvbrvyrfdtyaaehubfwsxjytszbgohd"
|
71
100
|
# arun(get_task("5ea22f57-45f0-425c-9d1e-bf3dae7e1e81", token))
|
meutils/data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2024.12.
|
1
|
+
2024.12.19.09.30.53
|