XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 1
返回提交历史

XFEstudio/gpt4free

Optimization and bug fixes for PollinationsAI provider: improved error handling, model validation, and HTTP request processing

21eecea0
kqlio67 <>
提交于

代码差异

1 个文件 +63 -74
Modified g4f/Provider/PollinationsAI.py +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)