MeUtils 2025.3.31.19.40.39__py3-none-any.whl → 2025.4.8.18.11.44__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.31.19.40.39.dist-info → MeUtils-2025.4.8.18.11.44.dist-info}/METADATA +264 -264
- {MeUtils-2025.3.31.19.40.39.dist-info → MeUtils-2025.4.8.18.11.44.dist-info}/RECORD +41 -27
- examples/_openaisdk/openai_ark_bots.py +64 -0
- examples/_openaisdk/openai_audio_gpt.py +67 -0
- examples/_openaisdk/openai_google.py +129 -77
- examples/_openaisdk/openai_kindo.py +1 -1
- examples/_openaisdk/zhipu_/346/231/272/350/203/275/344/275/223.py +5 -2
- meutils/ai_audio/tts/minimax.py +34 -0
- meutils/apis/google_apis/__init__.py +11 -0
- meutils/apis/google_apis/audios.py +115 -0
- meutils/apis/google_apis/common.py +251 -0
- meutils/apis/google_apis/files.py +19 -0
- meutils/apis/google_apis/gemini_sdk.py +170 -0
- meutils/apis/google_apis/google2openai.py +89 -0
- meutils/apis/google_apis/images.py +11 -0
- meutils/apis/google_apis/search.py +46 -0
- meutils/apis/hailuoai/videos.py +1 -1
- meutils/apis/images/google/__init__.py +11 -0
- meutils/apis/images/google/images.py +32 -0
- meutils/apis/jimeng/images.py +2 -1
- meutils/apis/search/ark_web_search.py +69 -0
- meutils/apis/search/{web_search.py → zhipu_web_search.py} +21 -30
- meutils/apis/textin_apis/common.py +1 -1
- meutils/apis/tripo3d/images.py +1 -1
- meutils/caches/common.py +4 -2
- meutils/data/VERSION +1 -1
- meutils/io/files_utils.py +27 -22
- meutils/llm/clients.py +6 -5
- meutils/llm/completions/assistants/ppt.py +17 -13
- meutils/llm/completions/chat_gemini.py +1 -1
- meutils/llm/completions/qwenllm.py +8 -2
- meutils/llm/openai_utils/common.py +5 -0
- meutils/oss/minio_oss.py +38 -8
- meutils/oss/minio_utils.py +2 -2
- meutils/schemas/oneapi/common.py +23 -6
- meutils/schemas/openai_types.py +70 -40
- meutils/str_utils/regular_expression.py +6 -3
- {MeUtils-2025.3.31.19.40.39.dist-info → MeUtils-2025.4.8.18.11.44.dist-info}/LICENSE +0 -0
- {MeUtils-2025.3.31.19.40.39.dist-info → MeUtils-2025.4.8.18.11.44.dist-info}/WHEEL +0 -0
- {MeUtils-2025.3.31.19.40.39.dist-info → MeUtils-2025.4.8.18.11.44.dist-info}/entry_points.txt +0 -0
- {MeUtils-2025.3.31.19.40.39.dist-info → MeUtils-2025.4.8.18.11.44.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Project : AI. @by PyCharm
|
4
|
+
# @File : minimax
|
5
|
+
# @Time : 2025/4/1 12:14
|
6
|
+
# @Author : betterme
|
7
|
+
# @WeChat : meutils
|
8
|
+
# @Software : PyCharm
|
9
|
+
# @Description :
|
10
|
+
|
11
|
+
from meutils.pipe import *
|
12
|
+
import requests
|
13
|
+
import json
|
14
|
+
|
15
|
+
url = "https://api.minimax.chat/v1/text2voice"
|
16
|
+
api_key = "请输入您的api key"
|
17
|
+
|
18
|
+
payload = json.dumps({
|
19
|
+
"gender": "female",
|
20
|
+
"age": "old",
|
21
|
+
"voice_desc": [
|
22
|
+
"Kind and friendly",
|
23
|
+
"Kind and amiable",
|
24
|
+
"Kind hearted",
|
25
|
+
"Calm tone"
|
26
|
+
],
|
27
|
+
"text": "真正的危险不是计算机开始像人一样思考,而是人开始像计算机一样思考"
|
28
|
+
})
|
29
|
+
headers = {
|
30
|
+
'Content-Type': 'application/json',
|
31
|
+
'Authorization': f'Bearer {api_key}',
|
32
|
+
}
|
33
|
+
|
34
|
+
response = requests.request("POST", url, headers=headers, data=payload)
|
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Project : AI. @by PyCharm
|
4
|
+
# @File : __init__.py
|
5
|
+
# @Time : 2025/4/2 10:40
|
6
|
+
# @Author : betterme
|
7
|
+
# @WeChat : meutils
|
8
|
+
# @Software : PyCharm
|
9
|
+
# @Description :
|
10
|
+
|
11
|
+
from meutils.apis.google_apis.common import GeminiClient
|
@@ -0,0 +1,115 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Project : AI. @by PyCharm
|
4
|
+
# @File : audios
|
5
|
+
# @Time : 2025/4/2 11:00
|
6
|
+
# @Author : betterme
|
7
|
+
# @WeChat : meutils
|
8
|
+
# @Software : PyCharm
|
9
|
+
# @Description : https://platform.openai.com/docs/guides/audio?example=audio-in
|
10
|
+
|
11
|
+
from meutils.pipe import *
|
12
|
+
#!/usr/bin/env python
|
13
|
+
# -*- coding: utf-8 -*-
|
14
|
+
# @Project : AI. @by PyCharm
|
15
|
+
# @File : openai_siliconflow
|
16
|
+
# @Time : 2024/6/26 10:42
|
17
|
+
# @Author : betterme
|
18
|
+
# @WeChat : meutils
|
19
|
+
# @Software : PyCharm
|
20
|
+
# @Description :
|
21
|
+
import os
|
22
|
+
|
23
|
+
from meutils.pipe import *
|
24
|
+
from openai import OpenAI
|
25
|
+
from openai import OpenAI, APIStatusError
|
26
|
+
from meutils.schemas.openai_types import ChatCompletionRequest
|
27
|
+
from meutils.llm.openai_utils import to_openai_completion_params
|
28
|
+
from meutils.io.files_utils import to_base64
|
29
|
+
|
30
|
+
base64_audio = arun(to_base64("https://oss.ffire.cc/files/lipsync.mp3"))
|
31
|
+
|
32
|
+
|
33
|
+
client = OpenAI(
|
34
|
+
# api_key=os.getenv("GOOGLE_API_KEY"),
|
35
|
+
api_key="AIzaSyAQAt73dfL5-v3zaAHtXajZalZxfiumMOU",
|
36
|
+
base_url=os.getenv("GOOGLE_BASE_URL"),
|
37
|
+
)
|
38
|
+
|
39
|
+
print(client.models.list().model_dump_json(indent=4))
|
40
|
+
|
41
|
+
# {
|
42
|
+
# "gemini-2.0-pro-exp": "models/gemini-2.0-pro-exp",
|
43
|
+
# "gemini-2.0-pro-exp-02-05": "models/gemini-2.0-pro-exp-02-05",
|
44
|
+
# "gemini-2.5-pro-exp-03-25": "models/gemini-2.5-pro-exp-03-25",
|
45
|
+
# "gemini-2.0-flash-thinking-exp": "models/gemini-2.0-flash-thinking-exp",
|
46
|
+
# "gemini-2.0-flash": "models/gemini-2.0-flash"
|
47
|
+
#
|
48
|
+
# }
|
49
|
+
|
50
|
+
|
51
|
+
if __name__ == '__main__':
|
52
|
+
# messages = [
|
53
|
+
#
|
54
|
+
# {
|
55
|
+
# "role": "user", "content": [
|
56
|
+
# {
|
57
|
+
# "type": "text",
|
58
|
+
# "text": "一句话总结"
|
59
|
+
# },
|
60
|
+
# {
|
61
|
+
# "type": "image_url",
|
62
|
+
# "image_url": {
|
63
|
+
# "url": "https://oss.ffire.cc/files/kling_watermark.png"
|
64
|
+
# }
|
65
|
+
# }
|
66
|
+
# ]
|
67
|
+
# }
|
68
|
+
#
|
69
|
+
# ]
|
70
|
+
messages = [
|
71
|
+
{
|
72
|
+
"role": "user",
|
73
|
+
"content": [
|
74
|
+
{
|
75
|
+
"type": "text",
|
76
|
+
"text": "一句话总结",
|
77
|
+
},
|
78
|
+
{
|
79
|
+
"type": "input_audio",
|
80
|
+
"input_audio": {
|
81
|
+
"data": base64_audio,
|
82
|
+
"format": "wav"
|
83
|
+
}
|
84
|
+
}
|
85
|
+
],
|
86
|
+
}
|
87
|
+
]
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
try:
|
92
|
+
completion = client.chat.completions.create(
|
93
|
+
# model="models/gemini-2.5-pro-exp-03-25",
|
94
|
+
model="models/gemini-2.0-flash",
|
95
|
+
# model="models/gemini-2.0-flash-exp-image-generation",
|
96
|
+
messages=messages,
|
97
|
+
# top_p=0.7,
|
98
|
+
top_p=None,
|
99
|
+
temperature=None,
|
100
|
+
# stream=True,
|
101
|
+
stream=False,
|
102
|
+
|
103
|
+
max_tokens=None,
|
104
|
+
)
|
105
|
+
except APIStatusError as e:
|
106
|
+
print(e.status_code)
|
107
|
+
|
108
|
+
print(e.response)
|
109
|
+
print(e.message)
|
110
|
+
print(e.code)
|
111
|
+
print(completion)
|
112
|
+
for chunk in completion: # 剔除extra body
|
113
|
+
print(chunk)
|
114
|
+
if chunk.choices:
|
115
|
+
print(chunk.choices[0].delta.content)
|
@@ -0,0 +1,251 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Project : AI. @by PyCharm
|
4
|
+
# @File : common
|
5
|
+
# @Time : 2025/4/2 13:03
|
6
|
+
# @Author : betterme
|
7
|
+
# @WeChat : meutils
|
8
|
+
# @Software : PyCharm
|
9
|
+
# @Description : https://ai.google.dev/gemini-api/docs/openai?hl=zh-cn
|
10
|
+
import asyncio
|
11
|
+
import os
|
12
|
+
|
13
|
+
import shortuuid
|
14
|
+
|
15
|
+
from meutils.pipe import *
|
16
|
+
from meutils.llm.clients import AsyncOpenAI
|
17
|
+
from meutils.io.files_utils import to_url, to_bytes, guess_mime_type
|
18
|
+
from meutils.str_utils.regular_expression import parse_url
|
19
|
+
|
20
|
+
from meutils.schemas.openai_types import chat_completion, chat_completion_chunk, CompletionRequest, CompletionUsage
|
21
|
+
|
22
|
+
from meutils.config_utils.lark_utils import get_next_token_for_polling
|
23
|
+
from google import genai
|
24
|
+
from google.genai import types
|
25
|
+
from google.genai.types import HttpOptions, GenerateContentConfig, Content, HarmCategory, HarmBlockThreshold, Part
|
26
|
+
from google.genai.types import UserContent, ModelContent
|
27
|
+
|
28
|
+
FEISHU_URL = "https://xchatllm.feishu.cn/sheets/Bmjtst2f6hfMqFttbhLcdfRJnNf?sheet=MJw6hI"
|
29
|
+
|
30
|
+
"""
|
31
|
+
Gemini 1.5 Pro 和 1.5 Flash 最多支持 3,600 个文档页面。文档页面必须采用以下文本数据 MIME 类型之一:
|
32
|
+
|
33
|
+
PDF - application/pdf
|
34
|
+
JavaScript - application/x-javascript、text/javascript
|
35
|
+
Python - application/x-python、text/x-python
|
36
|
+
TXT - text/plain
|
37
|
+
HTML - text/html
|
38
|
+
CSS - text/css
|
39
|
+
Markdown - text/md
|
40
|
+
CSV - text/csv
|
41
|
+
XML - text/xml
|
42
|
+
RTF - text/rtf
|
43
|
+
|
44
|
+
- 小文件
|
45
|
+
- 大文件: 需要等待处理
|
46
|
+
"""
|
47
|
+
|
48
|
+
|
49
|
+
class GeminiClient(object):
|
50
|
+
def __init__(self, api_key: Optional[str] = None):
|
51
|
+
self.api_key = api_key # or await get_next_token_for_polling(feishu_url=FEISHU_URL, from_redis=True)
|
52
|
+
self.base_url = "https://all.chatfire.cc/genai"
|
53
|
+
|
54
|
+
async def create(self, request: CompletionRequest):
|
55
|
+
client = await self.get_client()
|
56
|
+
|
57
|
+
if any(i in request.model for i in ("image",)):
|
58
|
+
messages = await self.to_image_messages(request)
|
59
|
+
|
60
|
+
if len(messages) > 1:
|
61
|
+
history = messages[:-1]
|
62
|
+
message = messages[-1].parts
|
63
|
+
else:
|
64
|
+
history = []
|
65
|
+
message = messages[-1].parts
|
66
|
+
|
67
|
+
chat = client.aio.chats.create( # todo: system_instruction
|
68
|
+
model=request.model,
|
69
|
+
config=GenerateContentConfig(
|
70
|
+
response_modalities=['Text', 'Image'],
|
71
|
+
),
|
72
|
+
history=history
|
73
|
+
)
|
74
|
+
|
75
|
+
logger.debug(message)
|
76
|
+
|
77
|
+
# message = [
|
78
|
+
# Part.from_text(text="画条狗")
|
79
|
+
# ]
|
80
|
+
|
81
|
+
for i in range(5):
|
82
|
+
try:
|
83
|
+
chunks = await chat.send_message_stream(message)
|
84
|
+
async for chunk in chunks:
|
85
|
+
|
86
|
+
if chunk.candidates:
|
87
|
+
parts = chunk.candidates[0].content.parts or []
|
88
|
+
for part in parts:
|
89
|
+
logger.debug(part)
|
90
|
+
if part.text:
|
91
|
+
yield part.text
|
92
|
+
|
93
|
+
if part.inline_data:
|
94
|
+
image_url = await to_url(
|
95
|
+
part.inline_data.data,
|
96
|
+
mime_type=part.inline_data.mime_type
|
97
|
+
)
|
98
|
+
yield f""
|
99
|
+
break
|
100
|
+
|
101
|
+
except Exception as e:
|
102
|
+
logger.debug(f"重试{i}: {e}")
|
103
|
+
if "The model is overloaded." in str(e):
|
104
|
+
await asyncio.sleep(1)
|
105
|
+
continue
|
106
|
+
else:
|
107
|
+
yield e
|
108
|
+
raise e
|
109
|
+
|
110
|
+
async def to_image_messages(self, request: CompletionRequest):
|
111
|
+
# 两轮即可连续编辑图片
|
112
|
+
|
113
|
+
messages = []
|
114
|
+
for m in request.messages:
|
115
|
+
contents = m.get("content")
|
116
|
+
if m.get("role") == "assistant":
|
117
|
+
assistant_content = str(contents)
|
118
|
+
if urls := parse_url(assistant_content): # assistant
|
119
|
+
datas = await asyncio.gather(*map(to_bytes, urls))
|
120
|
+
|
121
|
+
parts = [
|
122
|
+
Part.from_bytes(
|
123
|
+
data=data,
|
124
|
+
mime_type="image/png"
|
125
|
+
)
|
126
|
+
for data in datas
|
127
|
+
]
|
128
|
+
parts += [
|
129
|
+
Part.from_text(
|
130
|
+
text=request.last_assistant_content
|
131
|
+
),
|
132
|
+
]
|
133
|
+
messages.append(ModelContent(parts=parts))
|
134
|
+
|
135
|
+
elif m.get("role") == "user":
|
136
|
+
if isinstance(contents, list):
|
137
|
+
parts = []
|
138
|
+
for content in contents:
|
139
|
+
if content.get("type") == "image_url":
|
140
|
+
image_url = content.get("image_url", {}).get("url")
|
141
|
+
data = await to_bytes(image_url)
|
142
|
+
|
143
|
+
parts += [
|
144
|
+
Part.from_bytes(data=data, mime_type="image/png")
|
145
|
+
]
|
146
|
+
|
147
|
+
elif content.get("type") == "text":
|
148
|
+
text = content.get("text")
|
149
|
+
if text.startswith('http'):
|
150
|
+
image_url, text = text.split(maxsplit=1)
|
151
|
+
data = await to_bytes(image_url)
|
152
|
+
|
153
|
+
parts += [
|
154
|
+
Part.from_bytes(data=data, mime_type="image/png"),
|
155
|
+
Part.from_text(text=text)
|
156
|
+
]
|
157
|
+
else:
|
158
|
+
parts += [
|
159
|
+
Part.from_text(text=text)
|
160
|
+
]
|
161
|
+
|
162
|
+
messages.append(UserContent(parts=parts))
|
163
|
+
|
164
|
+
else: # str
|
165
|
+
if str(contents).startswith('http'): # 修正提问格式, 兼容 url
|
166
|
+
image_url, text = str(contents).split(maxsplit=1)
|
167
|
+
data = await to_bytes(image_url)
|
168
|
+
parts = [
|
169
|
+
Part.from_bytes(
|
170
|
+
data=data,
|
171
|
+
mime_type="image/png"
|
172
|
+
),
|
173
|
+
Part.from_text(
|
174
|
+
text=str(contents)
|
175
|
+
),
|
176
|
+
]
|
177
|
+
else:
|
178
|
+
parts = [
|
179
|
+
Part.from_text(
|
180
|
+
text=str(contents)
|
181
|
+
),
|
182
|
+
]
|
183
|
+
messages.append(UserContent(parts=parts))
|
184
|
+
|
185
|
+
return messages
|
186
|
+
|
187
|
+
async def upload(self, files: Union[str, List[str]]): # => openai files
|
188
|
+
client = await self.get_client()
|
189
|
+
|
190
|
+
if isinstance(files, list):
|
191
|
+
return await asyncio.gather(*map(self.upload, files))
|
192
|
+
|
193
|
+
file_config = {"name": f"{shortuuid.random().lower()}", "mime_type": guess_mime_type(files)}
|
194
|
+
return await client.aio.files.upload(file=io.BytesIO(await to_bytes(files)), config=file_config)
|
195
|
+
|
196
|
+
@alru_cache()
|
197
|
+
async def get_client(self):
|
198
|
+
api_key = self.api_key or await get_next_token_for_polling(feishu_url=FEISHU_URL, from_redis=True)
|
199
|
+
|
200
|
+
logger.info(f"GeminiClient: {api_key}")
|
201
|
+
|
202
|
+
return genai.Client(
|
203
|
+
api_key=api_key,
|
204
|
+
http_options=HttpOptions(
|
205
|
+
base_url=self.base_url
|
206
|
+
)
|
207
|
+
)
|
208
|
+
|
209
|
+
|
210
|
+
if __name__ == '__main__':
|
211
|
+
file = "https://oss.ffire.cc/files/kling_watermark.png"
|
212
|
+
|
213
|
+
api_key = os.getenv("GOOGLE_API_KEY")
|
214
|
+
|
215
|
+
# arun(GeminiClient(api_key=api_key).upload(file))
|
216
|
+
# arun(GeminiClient(api_key=api_key).upload([file] * 2))
|
217
|
+
# arun(GeminiClient(api_key=api_key).create())
|
218
|
+
|
219
|
+
content = [
|
220
|
+
|
221
|
+
{"type": "text", "text": "https://oss.ffire.cc/files/nsfw.jpg 移除右下角的水印"},
|
222
|
+
|
223
|
+
# {"type": "text", "text": "总结下"},
|
224
|
+
# {"type": "image_url", "image_url": {"url": url}},
|
225
|
+
|
226
|
+
# {"type": "video_url", "video_url": {"url": url}}
|
227
|
+
|
228
|
+
]
|
229
|
+
|
230
|
+
# content = "https://oss.ffire.cc/files/nsfw.jpg 移除右下角的水印"
|
231
|
+
|
232
|
+
#
|
233
|
+
request = CompletionRequest(
|
234
|
+
# model="qwen-turbo-2024-11-01",
|
235
|
+
# model="gemini-all",
|
236
|
+
model="gemini-2.0-flash-exp-image-generation",
|
237
|
+
# model="qwen-plus-latest",
|
238
|
+
|
239
|
+
messages=[
|
240
|
+
{
|
241
|
+
'role': 'user',
|
242
|
+
|
243
|
+
'content': content
|
244
|
+
},
|
245
|
+
|
246
|
+
],
|
247
|
+
stream=True,
|
248
|
+
)
|
249
|
+
|
250
|
+
# arun(GeminiClient(api_key=api_key).to_image_messages(request))
|
251
|
+
arun(GeminiClient(api_key=api_key).create(request))
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Project : AI. @by PyCharm
|
4
|
+
# @File : files
|
5
|
+
# @Time : 2025/4/2 10:40
|
6
|
+
# @Author : betterme
|
7
|
+
# @WeChat : meutils
|
8
|
+
# @Software : PyCharm
|
9
|
+
# @Description :
|
10
|
+
|
11
|
+
from meutils.pipe import *
|
12
|
+
|
13
|
+
|
14
|
+
file = "/Users/betterme/PycharmProjects/AI/QR.png"
|
15
|
+
#
|
16
|
+
# file_object = client.files.upload(file=file)
|
17
|
+
# prompt = "一句话总结"
|
18
|
+
|
19
|
+
file_object = client.aio.files.upload(file=file)
|
@@ -0,0 +1,170 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Project : AI. @by PyCharm
|
4
|
+
# @File : st
|
5
|
+
# @Time : 2025/4/3 15:24
|
6
|
+
# @Author : betterme
|
7
|
+
# @WeChat : meutils
|
8
|
+
# @Software : PyCharm
|
9
|
+
# @Description :
|
10
|
+
|
11
|
+
from meutils.pipe import *
|
12
|
+
from meutils.async_utils import async_to_sync
|
13
|
+
|
14
|
+
from meutils.io.files_utils import to_url, to_bytes
|
15
|
+
from meutils.schemas.openai_types import CompletionRequest
|
16
|
+
|
17
|
+
from google import genai
|
18
|
+
from google.genai.types import HttpOptions, GenerateContentConfig, Content, HarmCategory, HarmBlockThreshold, Part, \
|
19
|
+
ThinkingConfig
|
20
|
+
from google.genai.chats import _is_part_type
|
21
|
+
|
22
|
+
config = GenerateContentConfig(
|
23
|
+
|
24
|
+
temperature=0.7,
|
25
|
+
top_p=0.8,
|
26
|
+
response_modalities=['Text', 'Image'],
|
27
|
+
)
|
28
|
+
|
29
|
+
# self._http_options.base_url = 'https://generativelanguage.googleapis.com/'
|
30
|
+
# self._http_options.api_version = 'v1beta'
|
31
|
+
client = genai.Client(
|
32
|
+
api_key="AIzaSyCa8PYURpxFKz7yOtQB_O_wRfrX0gYh9L4",
|
33
|
+
http_options=HttpOptions(
|
34
|
+
base_url="https://all.chatfire.cc/genai"
|
35
|
+
)
|
36
|
+
)
|
37
|
+
|
38
|
+
if __name__ == '__main__':
|
39
|
+
model = "gemini-2.0-flash-exp-image-generation"
|
40
|
+
|
41
|
+
request = CompletionRequest(
|
42
|
+
model=model,
|
43
|
+
messages=[
|
44
|
+
{
|
45
|
+
"role": "user", "content": [
|
46
|
+
{
|
47
|
+
"type": "text",
|
48
|
+
"text": "一句话总结"
|
49
|
+
},
|
50
|
+
{
|
51
|
+
"type": "image_url",
|
52
|
+
"image_url": {
|
53
|
+
|
54
|
+
"url": "https://oss.ffire.cc/files/kling_watermark.png"
|
55
|
+
|
56
|
+
}
|
57
|
+
}
|
58
|
+
]
|
59
|
+
}],
|
60
|
+
|
61
|
+
)
|
62
|
+
|
63
|
+
response = client.aio.chats.create(
|
64
|
+
model=model,
|
65
|
+
config=GenerateContentConfig(
|
66
|
+
system_instruction=None,
|
67
|
+
max_output_tokens=None,
|
68
|
+
response_modalities=['Text', 'Image'],
|
69
|
+
|
70
|
+
# thinking_config=ThinkingConfig(include_thoughts=True),
|
71
|
+
|
72
|
+
),
|
73
|
+
|
74
|
+
# history=[
|
75
|
+
#
|
76
|
+
# Content(
|
77
|
+
# role="user",
|
78
|
+
# parts=[
|
79
|
+
# Part.from_text(
|
80
|
+
# text="画条狗"
|
81
|
+
# )
|
82
|
+
# ]
|
83
|
+
# ),
|
84
|
+
# Content(
|
85
|
+
# role="model",
|
86
|
+
# parts=[
|
87
|
+
# Part.from_text(
|
88
|
+
# text="Ok"
|
89
|
+
# ),
|
90
|
+
#
|
91
|
+
# Part.from_bytes(
|
92
|
+
# data=async_to_sync(to_bytes)("https://oss.ffire.cc/files/kling_watermark.png"),
|
93
|
+
# mime_type="image/png"
|
94
|
+
# ),
|
95
|
+
# ]
|
96
|
+
# )
|
97
|
+
#
|
98
|
+
# ]
|
99
|
+
)
|
100
|
+
|
101
|
+
# "mime_type": "image/png"
|
102
|
+
|
103
|
+
p = Part.from_uri(file_uri="https://oss.ffire.cc/files/kling_watermark.png", mime_type="image/png")
|
104
|
+
pp = Part.from_bytes(
|
105
|
+
data=async_to_sync(to_bytes)("https://oss.ffire.cc/files/kling_watermark.png"),
|
106
|
+
mime_type="image/png"
|
107
|
+
)
|
108
|
+
|
109
|
+
|
110
|
+
# pt = Part.from_text(text="文本")
|
111
|
+
|
112
|
+
# {'video_metadata': None,
|
113
|
+
# 'thought': None,
|
114
|
+
# 'code_execution_result': None,
|
115
|
+
# 'executable_code': None,
|
116
|
+
# 'file_data': {'file_uri': 'https://oss.ffire.cc/files/kling_watermark.png',
|
117
|
+
# 'mime_type': 'image/png'},
|
118
|
+
# 'function_call': None,
|
119
|
+
# 'function_response': None,
|
120
|
+
# 'inline_data': None,
|
121
|
+
# 'text': None}
|
122
|
+
|
123
|
+
#
|
124
|
+
async def main():
|
125
|
+
message = [
|
126
|
+
Part.from_text(text="画条狗 带个眼镜"),
|
127
|
+
# pp
|
128
|
+
]
|
129
|
+
|
130
|
+
print(_is_part_type(message))
|
131
|
+
chunks = await response.send_message_stream(message)
|
132
|
+
|
133
|
+
async for chunk in chunks:
|
134
|
+
if chunk.candidates:
|
135
|
+
parts = chunk.candidates[0].content.parts
|
136
|
+
for part in parts or []:
|
137
|
+
if len(str(part)) < 500:
|
138
|
+
logger.debug(part)
|
139
|
+
if part.inline_data:
|
140
|
+
image_url = await to_url(part.inline_data.data, mime_type=part.inline_data.mime_type)
|
141
|
+
logger.info(image_url)
|
142
|
+
|
143
|
+
if part.text:
|
144
|
+
logger.info(part.text)
|
145
|
+
# print(i.model_dump_json(indent=4, exclude_none=True)) # inline_data
|
146
|
+
|
147
|
+
|
148
|
+
# response = client.models.generate_content(
|
149
|
+
# model="gemini-2.0-flash-exp-image-generation",
|
150
|
+
# contents=['画条狗'],
|
151
|
+
#
|
152
|
+
# # model="gemini-2.5-pro-exp-03-25",
|
153
|
+
# # model="gemini-2.0-flash",
|
154
|
+
#
|
155
|
+
# # contents=[
|
156
|
+
# # Part.from_uri(file_uri='https://generativelanguage.googleapis.com/v1beta/files/test', mime_type='image/png'),
|
157
|
+
# #
|
158
|
+
# # "一句话总结"],
|
159
|
+
# config=config
|
160
|
+
# )
|
161
|
+
#
|
162
|
+
# # client.aio.
|
163
|
+
# # client.aio.chats.create()
|
164
|
+
#
|
165
|
+
# if __name__ == '__main__':
|
166
|
+
# arun(file_object)
|
167
|
+
|
168
|
+
arun(main())
|
169
|
+
|
170
|
+
# ValueError: Message must be a valid part type: typing.Union[google.genai.types.File, google.genai.types.Part, PIL.Image.Image, str] or typing.Union[google.genai.types.File, google.genai.types.Part, PIL.Image.Image, str, google.genai.types.PartDict], got <class 'list'>
|
@@ -0,0 +1,89 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Project : AI. @by PyCharm
|
4
|
+
# @File : google2openai
|
5
|
+
# @Time : 2025/4/1 13:38
|
6
|
+
# @Author : betterme
|
7
|
+
# @WeChat : meutils
|
8
|
+
# @Software : PyCharm
|
9
|
+
# @Description :
|
10
|
+
"""
|
11
|
+
1. 生图 编辑图 多轮
|
12
|
+
2. 文件上传、大文件问答
|
13
|
+
|
14
|
+
注意 :借助 File API,您最多可为每个项目存储 20 GB 的文件,每个文件的大小上限为 2 GB。文件会存储 48 小时。您可以在该时间段内使用 API 密钥访问这些数据,但无法从 API 下载这些数据。在已推出 Gemini API 的所有地区,此功能均可免费使用。
|
15
|
+
|
16
|
+
"""
|
17
|
+
from meutils.pipe import *
|
18
|
+
from meutils.schemas.openai_types import CompletionRequest
|
19
|
+
|
20
|
+
from google import genai
|
21
|
+
from google.genai.types import HttpOptions, GenerateContentConfig, Content, HarmCategory, HarmBlockThreshold, Part
|
22
|
+
|
23
|
+
# Content(role="user", parts=[Part.from_text(text=prompt)]),
|
24
|
+
# Content(role="model", parts=[Part.from_text(text="Ok")]),
|
25
|
+
|
26
|
+
config = GenerateContentConfig(
|
27
|
+
|
28
|
+
temperature=0.7,
|
29
|
+
top_p=0.8,
|
30
|
+
response_modalities=['Text', 'Image'],
|
31
|
+
|
32
|
+
# 公民诚信类别的默认屏蔽阈值为 Block none(对于别名为 gemini-2.0-flash、gemini-2.0-pro-exp-02-05 和 gemini-2.0-flash-lite 的 gemini-2.0-flash-001),适用于 Google AI Studio 和 Gemini API;仅适用于 Google AI Studio 中的所有其他模型的 Block most。
|
33
|
+
# safety_settings=[
|
34
|
+
# SafetySetting(
|
35
|
+
# category=HarmCategory.HARM_CATEGORY_HATE_SPEECH,
|
36
|
+
# threshold=HarmBlockThreshold.BLOCK_LOW_AND_ABOVE,
|
37
|
+
# ),
|
38
|
+
# ]
|
39
|
+
)
|
40
|
+
|
41
|
+
|
42
|
+
# self._http_options.base_url = 'https://generativelanguage.googleapis.com/'
|
43
|
+
# self._http_options.api_version = 'v1beta'
|
44
|
+
client = genai.Client(
|
45
|
+
api_key="AIzaSyAlpq4kR9ZP0NwaqQzqHtDKqiV8PLdUqnA",
|
46
|
+
http_options=HttpOptions(
|
47
|
+
base_url="https://all.chatfire.cc/genai"
|
48
|
+
)
|
49
|
+
)
|
50
|
+
|
51
|
+
file = "/Users/betterme/PycharmProjects/AI/QR.png"
|
52
|
+
#
|
53
|
+
# file_object = client.files.upload(file=file)
|
54
|
+
# prompt = "一句话总结"
|
55
|
+
|
56
|
+
# file_object = client.aio.files.upload(file=file)
|
57
|
+
# https://generativelanguage.googleapis.com/v1beta/files/ickgffcfb9zl
|
58
|
+
#
|
59
|
+
# contents = ('Hi, can you create a 3d rendered image of a pig '
|
60
|
+
# 'with wings and a top hat flying over a happy '
|
61
|
+
# 'futuristic scifi city with lots of greenery?')
|
62
|
+
#
|
63
|
+
# prompt = "9.11 9.8哪个大呢"
|
64
|
+
#
|
65
|
+
|
66
|
+
# client.aio.chats.create(
|
67
|
+
# model="gemini-2.0-flash-exp-image-generation",
|
68
|
+
# )
|
69
|
+
|
70
|
+
response = client.models.generate_content(
|
71
|
+
model="gemini-2.0-flash-exp-image-generation",
|
72
|
+
contents=['画条狗'],
|
73
|
+
|
74
|
+
# model="gemini-2.5-pro-exp-03-25",
|
75
|
+
# model="gemini-2.0-flash",
|
76
|
+
|
77
|
+
# contents=[
|
78
|
+
# Part.from_uri(file_uri='https://generativelanguage.googleapis.com/v1beta/files/test', mime_type='image/png'),
|
79
|
+
#
|
80
|
+
# "一句话总结"],
|
81
|
+
config=config
|
82
|
+
)
|
83
|
+
|
84
|
+
# client.aio.
|
85
|
+
# client.aio.chats.create()
|
86
|
+
|
87
|
+
if __name__ == '__main__':
|
88
|
+
# arun(file_object)
|
89
|
+
pass
|