返回提交历史
Modified
g4f/Provider/PollinationsAI.py
+63
-74
XFEstudio/gpt4free
Optimization and bug fixes for PollinationsAI provider: improved error handling, model validation, and HTTP request processing
21eecea0
代码差异
1 个文件
+63
-74
@@ -73,24 +73,23 @@ class PollinationsAI(AsyncGeneratorProvider, ProviderModelMixin):
73
73
@classmethod
74
74
def get_models(cls, **kwargs):
75
75
if not cls.text_models or not cls.image_models:
76
image_url = "https://image.pollinations.ai/models"
77
image_response = requests.get(image_url)
78
raise_for_status(image_response)
79
new_image_models = image_response.json()
80
81
cls.image_models = list(dict.fromkeys([*cls.extra_image_models, *new_image_models]))
82
cls.extra_image_models = cls.image_models.copy()
83
84
text_url = "https://text.pollinations.ai/models"
85
text_response = requests.get(text_url)
86
raise_for_status(text_response)
87
original_text_models = [model.get("name") for model in text_response.json()]
88
89
combined_text = cls.extra_text_models + [
90
model for model in original_text_models
91
if model not in cls.extra_text_models
92
]
93
cls.text_models = list(dict.fromkeys(combined_text))
76
try:
77
image_response = requests.get("https://image.pollinations.ai/models")
78
image_response.raise_for_status()
79
new_image_models = image_response.json()
80
cls.image_models = list(dict.fromkeys([*cls.extra_image_models, *new_image_models]))
81
82
text_response = requests.get("https://text.pollinations.ai/models")
83
text_response.raise_for_status()
84
original_text_models = [model.get("name") for model in text_response.json()]
85
86
combined_text = cls.extra_text_models + [
87
model for model in original_text_models
88
if model not in cls.extra_text_models
89
]
90
cls.text_models = list(dict.fromkeys(combined_text))
91
except Exception as e:
92
raise RuntimeError(f"Failed to fetch models: {e}") from e
94
93
95
94
return cls.text_models + cls.image_models
96
95
@@ -122,13 +121,14 @@ class PollinationsAI(AsyncGeneratorProvider, ProviderModelMixin):
122
121
try:
123
122
model = cls.get_model(model)
124
123
except ModelNotFoundError:
125
if model not in cls.extra_image_models:
124
if model not in cls.image_models:
126
125
raise
126
127
127
if not cache and seed is None:
128
128
seed = random.randint(0, 10000)
129
129
130
if model in cls.image_models or model in cls.extra_image_models:
131
async for chunk in cls._generate_image(
130
if model in cls.image_models:
131
async for chunk in cls._generate_image(
132
132
model=model,
133
133
prompt=format_image_prompt(messages, prompt),
134
134
proxy=proxy,
@@ -172,25 +172,25 @@ class PollinationsAI(AsyncGeneratorProvider, ProviderModelMixin):
172
172
safe: bool
173
173
) -> AsyncResult:
174
174
params = {
175
"seed": seed,
176
"width": width,
177
"height": height,
175
"seed": str(seed) if seed is not None else None,
176
"width": str(width),
177
"height": str(height),
178
178
"model": model,
179
"nologo": nologo,
180
"private": private,
181
"enhance": enhance,
182
"safe": safe
179
"nologo": str(nologo).lower(),
180
"private": str(private).lower(),
181
"enhance": str(enhance).lower(),
182
"safe": str(safe).lower()
183
183
}
184
params = {k: json.dumps(v) if isinstance(v, bool) else str(v) for k, v in params.items() if v is not None}
185
params = "&".join( "%s=%s" % (key, quote_plus(params[key]))
186
for key in params.keys())
187
url = f"{cls.image_api_endpoint}prompt/{quote_plus(prompt)}?{params}"
184
params = {k: v for k, v in params.items() if v is not None}
185
query = "&".join(f"{k}={quote_plus(v)}" for k, v in params.items())
186
url = f"{cls.image_api_endpoint}prompt/{quote_plus(prompt)}?{query}"
188
187
yield ImagePreview(url, prompt)
188
189
189
async with ClientSession(headers=DEFAULT_HEADERS, connector=get_connector(proxy=proxy)) as session:
190
async with session.head(url) as response:
191
if response.status != 500:
192
await raise_for_status(response)
193
yield ImageResponse(str(response.url), prompt)
190
async with session.get(url, allow_redirects=True) as response:
191
await raise_for_status(response)
192
image_url = str(response.url)
193
yield ImageResponse(image_url, prompt)
194
194
195
195
@classmethod
196
196
async def _generate_text(
@@ -207,60 +207,49 @@ class PollinationsAI(AsyncGeneratorProvider, ProviderModelMixin):
207
207
seed: Optional[int],
208
208
cache: bool
209
209
) -> AsyncResult:
210
jsonMode = False
211
if response_format is not None and "type" in response_format:
212
if response_format["type"] == "json_object":
213
jsonMode = True
210
json_mode = False
211
if response_format and response_format.get("type") == "json_object":
212
json_mode = True
214
213
215
if images is not None and messages:
214
if images and messages:
216
215
last_message = messages[-1].copy()
217
last_message["content"] = [
218
*[{
216
image_content = [
217
{
219
218
"type": "image_url",
220
219
"image_url": {"url": to_data_uri(image)}
221
} for image, _ in images],
222
{
223
"type": "text",
224
"text": messages[-1]["content"]
225
220
}
221
for image, _ in images
226
222
]
223
last_message["content"] = image_content + [{"type": "text", "text": last_message["content"]}]
227
224
messages[-1] = last_message
228
225
229
226
async with ClientSession(headers=DEFAULT_HEADERS, connector=get_connector(proxy=proxy)) as session:
230
data = {
227
data = filter_none(**{
231
228
"messages": messages,
232
229
"model": model,
233
230
"temperature": temperature,
234
231
"presence_penalty": presence_penalty,
235
232
"top_p": top_p,
236
233
"frequency_penalty": frequency_penalty,
237
"jsonMode": jsonMode,
234
"jsonMode": json_mode,
238
235
"stream": False,
239
236
"seed": seed,
240
237
"cache": cache
241
}
242
async with session.post(cls.text_api_endpoint, json=filter_none(**data)) as response:
238
})
239
240
async with session.post(cls.text_api_endpoint, json=data) as response:
243
241
await raise_for_status(response)
244
async for line in response.content:
245
decoded_chunk = line.decode(errors="replace")
246
if "data: [DONE]" in decoded_chunk:
247
break
248
try:
249
json_str = decoded_chunk.replace("data:", "").strip()
250
data = json.loads(json_str)
251
choice = data["choices"][0]
252
message = choice.get("message") or choice.get("delta", {})
253
254
if "usage" in data:
255
yield Usage(**data["usage"])
256
content = message.get("content", "")
257
if content:
258
yield content.replace("\\(", "(").replace("\\)", ")")
259
if "finish_reason" in choice and choice["finish_reason"]:
260
yield FinishReason(choice["finish_reason"])
261
break
262
except json.JSONDecodeError:
263
yield decoded_chunk.strip()
264
except Exception as e:
265
yield FinishReason("error")
266
break
242
result = await response.json()
243
choice = result["choices"][0]
244
message = choice.get("message", {})
245
content = message.get("content", "")
246
247
if content:
248
yield content.replace("\\(", "(").replace("\\)", ")")
249
250
if "usage" in result:
251
yield Usage(**result["usage"])
252
253
finish_reason = choice.get("finish_reason")
254
if finish_reason:
255
yield FinishReason(finish_reason)