XFEstudio/gpt4free
feat: integrate Pollinations AI enhancements and simplify gpt4free references
- Replaced the large GitHub project stats table in `README.md` with summaries and logos for Pollinations AI and MoneyPrinter V2 - Introduced `STATIC_URL` and `DIST_DIR` constants in new `g4f/constants.py` and used them across multiple files - Updated `PollinationsAI.py` to support conversation title and follow-up generation using tool calls - Modified `PollinationsAI.py` and `PollinationsImage.py` to use `STATIC_URL` for the `referrer` header - Enhanced `PollinationsAI.stream_complete` to yield `ToolCalls`, `TitleGeneration`, and `SuggestedFollowups` - Added `ToolCalls` handling in `client/__init__.py` to support non-stream and stream modes - Updated `ChatCompletionDelta` model in `client/stubs.py` to support `ToolCalls` - Modified `HarProvider` to merge `DEFAULT_HEADERS` into request headers - Improved `OpenaiChat.py` by adding optional chaining to page evaluation expressions for robustness - Updated `any_provider.py` to force use of `PollinationsAI` if `tools` key is present in kwargs - Refactored `is_content` into a reusable function in `providers/response.py` and used in `retry_provider.py` - Updated `gui/server/website.py` to use `STATIC_URL` and simplify `GPT4FREE_URL` handling - Removed redundant constants from `version.py` and imported them from `constants.py
57cbd55d
代码差异
@@ -247,465 +247,29 @@ Run the Web UI on your smartphone for easy access on the go. Check out the dedic
---
## 🔗 Powered by gpt4free
### 🚀 Used by gpt4free
<table>
<thead align="center">
<tr border: none;>
<td>
<b>🎁 Projects</b>
</td>
<td>
<b>⭐ Stars</b>
</td>
<td>
<b>📚 Forks</b>
</td>
<td>
<b>🛎 Issues</b>
</td>
<td>
<b>📬 Pull requests</b>
</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<a href="https://github.com/xtekky/gpt4free">
<b>gpt4free</b>
</a>
</td>
<td>
<a href="https://github.com/xtekky/gpt4free/stargazers">
<img alt="Stars" src="https://img.shields.io/github/stars/xtekky/gpt4free?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/xtekky/gpt4free/network/members">
<img alt="Forks" src="https://img.shields.io/github/forks/xtekky/gpt4free?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/xtekky/gpt4free/issues">
<img alt="Issues" src="https://img.shields.io/github/issues/xtekky/gpt4free?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/xtekky/gpt4free/pulls">
<img alt="Pull Requests" src="https://img.shields.io/github/issues-pr/xtekky/gpt4free?style=flat-square&labelColor=343b41" />
</a>
</td>
</tr>
<td>
<a href="https://github.com/xiangsx/gpt4free-ts">
<b>gpt4free-ts</b>
</a>
</td>
<td>
<a href="https://github.com/xiangsx/gpt4free-ts/stargazers">
<img alt="Stars" src="https://img.shields.io/github/stars/xiangsx/gpt4free-ts?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/xiangsx/gpt4free-ts/network/members">
<img alt="Forks" src="https://img.shields.io/github/forks/xiangsx/gpt4free-ts?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/xiangsx/gpt4free-ts/issues">
<img alt="Issues" src="https://img.shields.io/github/issues/xiangsx/gpt4free-ts?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/xiangsx/gpt4free-ts/pulls">
<img alt="Pull Requests" src="https://img.shields.io/github/issues-pr/xiangsx/gpt4free-ts?style=flat-square&labelColor=343b41" />
</a>
</td>
</tr>
<tr>
<td>
<a href="https://github.com/zukixa/cool-ai-stuff/">
<b>Free AI API's & Potential Providers List</b>
</a>
</td>
<td>
<a href="https://github.com/zukixa/cool-ai-stuff/stargazers">
<img alt="Stars" src="https://img.shields.io/github/stars/zukixa/cool-ai-stuff?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/zukixa/cool-ai-stuff/network/members">
<img alt="Forks" src="https://img.shields.io/github/forks/zukixa/cool-ai-stuff?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/zukixa/cool-ai-stuff/issues">
<img alt="Issues" src="https://img.shields.io/github/issues/zukixa/cool-ai-stuff?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/zukixa/cool-ai-stuff/pulls">
<img alt="Pull Requests" src="https://img.shields.io/github/issues-pr/zukixa/cool-ai-stuff?style=flat-square&labelColor=343b41" />
</a>
</td>
</tr>
<tr>
<tr>
<td>
<a href="https://github.com/xtekky/chatgpt-clone">
<b>ChatGPT-Clone</b>
</a>
</td>
<td>
<a href="https://github.com/xtekky/chatgpt-clone/stargazers">
<img alt="Stars" src="https://img.shields.io/github/stars/xtekky/chatgpt-clone?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/xtekky/chatgpt-clone/network/members">
<img alt="Forks" src="https://img.shields.io/github/forks/xtekky/chatgpt-clone?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/xtekky/chatgpt-clone/issues">
<img alt="Issues" src="https://img.shields.io/github/issues/xtekky/chatgpt-clone?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/xtekky/chatgpt-clone/pulls">
<img alt="Pull Requests" src="https://img.shields.io/github/issues-pr/xtekky/chatgpt-clone?style=flat-square&labelColor=343b41" />
</a>
</td>
</tr>
<tr>
<td>
<a href="https://github.com/mishalhossin/Discord-Chatbot-Gpt4Free">
<b>Ai agent</b>
</a>
</td>
<td>
<a href="https://github.com/Josh-XT/AGiXT/stargazers">
<img alt="Stars" src="https://img.shields.io/github/stars/mishalhossin/Discord-Chatbot-Gpt4Free?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/Josh-XT/AGiXT/network/members">
<img alt="Forks" src="https://img.shields.io/github/forks/mishalhossin/Discord-Chatbot-Gpt4Free?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/Josh-XT/AGiXT/issues">
<img alt="Issues" src="https://img.shields.io/github/issues/mishalhossin/Discord-Chatbot-Gpt4Free?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/Josh-XT/AGiXT/pulls">
<img alt="Pull Requests" src="https://img.shields.io/github/issues-pr/mishalhossin/Discord-Chatbot-Gpt4Free?style=flat-square&labelColor=343b41" />
</a>
</td>
</tr>
<tr>
<td>
<a href="https://github.com/mishalhossin/Discord-Chatbot-Gpt4Free">
<b>ChatGpt Discord Bot</b>
</a>
</td>
<td>
<a href="https://github.com/mishalhossin/Discord-Chatbot-Gpt4Free/stargazers">
<img alt="Stars" src="https://img.shields.io/github/stars/mishalhossin/Discord-Chatbot-Gpt4Free?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/mishalhossin/Discord-Chatbot-Gpt4Free/network/members">
<img alt="Forks" src="https://img.shields.io/github/forks/mishalhossin/Discord-Chatbot-Gpt4Free?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/mishalhossin/Discord-Chatbot-Gpt4Free/issues">
<img alt="Issues" src="https://img.shields.io/github/issues/mishalhossin/Discord-Chatbot-Gpt4Free?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/mishalhossin/Coding-Chatbot-Gpt4Free/pulls">
<img alt="Pull Requests" src="https://img.shields.io/github/issues-pr/mishalhossin/Discord-Chatbot-Gpt4Free?style=flat-square&labelColor=343b41" />
</a>
</td>
<tr>
<tr>
<td>
<a href="https://github.com/Zero6992/chatGPT-discord-bot">
<b>chatGPT-discord-bot</b>
</a>
</td>
<td>
<a href="https://github.com/Zero6992/chatGPT-discord-bot/stargazers">
<img alt="Stars" src="https://img.shields.io/github/stars/Zero6992/chatGPT-discord-bot?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/Zero6992/chatGPT-discord-bot/network/members">
<img alt="Forks" src="https://img.shields.io/github/forks/Zero6992/chatGPT-discord-bot?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/Zero6992/chatGPT-discord-bot/issues">
<img alt="Issues" src="https://img.shields.io/github/issues/Zero6992/chatGPT-discord-bot?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/Zero6992/chatGPT-discord-bot/pulls">
<img alt="Pull Requests" src="https://img.shields.io/github/issues-pr/Zero6992/chatGPT-discord-bot?style=flat-square&labelColor=343b41" />
</a>
</td>
<tr>
<td>
<a href="https://github.com/SamirXR/Nyx-Bot">
<b>Nyx-Bot (Discord)</b>
</a>
</td>
<td>
<a href="https://github.com/SamirXR/Nyx-Bot/stargazers">
<img alt="Stars" src="https://img.shields.io/github/stars/SamirXR/Nyx-Bot?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/SamirXR/Nyx-Bot/network/members">
<img alt="Forks" src="https://img.shields.io/github/forks/SamirXR/Nyx-Bot?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/SamirXR/Nyx-Bot/issues">
<img alt="Issues" src="https://img.shields.io/github/issues/SamirXR/Nyx-Bot?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/SamirXR/Nyx-Bot/pulls">
<img alt="Pull Requests" src="https://img.shields.io/github/issues-pr/SamirXR/Nyx-Bot?style=flat-square&labelColor=343b41" />
</a>
</td>
</tr>
</tr>
<tr>
<td>
<a href="https://github.com/MIDORIBIN/langchain-gpt4free">
<b>LangChain gpt4free</b>
</a>
</td>
<td>
<a href="https://github.com/MIDORIBIN/langchain-gpt4free/stargazers">
<img alt="Stars" src="https://img.shields.io/github/stars/MIDORIBIN/langchain-gpt4free?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/MIDORIBIN/langchain-gpt4free/network/members">
<img alt="Forks" src="https://img.shields.io/github/forks/MIDORIBIN/langchain-gpt4free?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/MIDORIBIN/langchain-gpt4free/issues">
<img alt="Issues" src="https://img.shields.io/github/issues/MIDORIBIN/langchain-gpt4free?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/MIDORIBIN/langchain-gpt4free/pulls">
<img alt="Pull Requests" src="https://img.shields.io/github/issues-pr/MIDORIBIN/langchain-gpt4free?style=flat-square&labelColor=343b41" />
</a>
</td>
</tr>
<tr>
<td>
<a href="https://github.com/HexyeDEV/Telegram-Chatbot-Gpt4Free">
<b>ChatGpt Telegram Bot</b>
</a>
</td>
<td>
<a href="https://github.com/HexyeDEV/Telegram-Chatbot-Gpt4Free/stargazers">
<img alt="Stars" src="https://img.shields.io/github/stars/HexyeDEV/Telegram-Chatbot-Gpt4Free?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/HexyeDEV/Telegram-Chatbot-Gpt4Free/network/members">
<img alt="Forks" src="https://img.shields.io/github/forks/HexyeDEV/Telegram-Chatbot-Gpt4Free?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/HexyeDEV/Telegram-Chatbot-Gpt4Free/issues">
<img alt="Issues" src="https://img.shields.io/github/issues/HexyeDEV/Telegram-Chatbot-Gpt4Free?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/HexyeDEV/Telegram-Chatbot-Gpt4Free/pulls">
<img alt="Pull Requests" src="https://img.shields.io/github/issues-pr/HexyeDEV/Telegram-Chatbot-Gpt4Free?style=flat-square&labelColor=343b41" />
</a>
</td>
</tr>
<tr>
<td>
<a href="https://github.com/Lin-jun-xiang/chatgpt-line-bot">
<b>ChatGpt Line Bot</b>
</a>
</td>
<td>
<a href="https://github.com/Lin-jun-xiang/chatgpt-line-bot/stargazers">
<img alt="Stars" src="https://img.shields.io/github/stars/Lin-jun-xiang/chatgpt-line-bot?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/Lin-jun-xiang/chatgpt-line-bot/network/members">
<img alt="Forks" src="https://img.shields.io/github/forks/Lin-jun-xiang/chatgpt-line-bot?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/Lin-jun-xiang/chatgpt-line-bot/issues">
<img alt="Issues" src="https://img.shields.io/github/issues/Lin-jun-xiang/chatgpt-line-bot?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/Lin-jun-xiang/chatgpt-line-bot/pulls">
<img alt="Pull Requests" src="https://img.shields.io/github/issues-pr/Lin-jun-xiang/chatgpt-line-bot?style=flat-square&labelColor=343b41" />
</a>
</td>
</tr>
<tr>
<td>
<a href="https://github.com/Lin-jun-xiang/action-translate-readme">
<b>Action Translate Readme</b>
</a>
</td>
<td>
<a href="https://github.com/Lin-jun-xiang/action-translate-readme/stargazers">
<img alt="Stars" src="https://img.shields.io/github/stars/Lin-jun-xiang/action-translate-readme?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/Lin-jun-xiang/action-translate-readme/network/members">
<img alt="Forks" src="https://img.shields.io/github/forks/Lin-jun-xiang/action-translate-readme?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/Lin-jun-xiang/action-translate-readme/issues">
<img alt="Issues" src="https://img.shields.io/github/issues/Lin-jun-xiang/action-translate-readme?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/Lin-jun-xiang/action-translate-readme/pulls">
<img alt="Pull Requests" src="https://img.shields.io/github/issues-pr/Lin-jun-xiang/action-translate-readme?style=flat-square&labelColor=343b41" />
</a>
</td>
</tr>
<tr>
<td>
<a href="https://github.com/Lin-jun-xiang/docGPT-streamlit">
<b>Langchain Document GPT</b>
</a>
</td>
<td>
<a href="https://github.com/Lin-jun-xiang/docGPT-streamlit/stargazers">
<img alt="Stars" src="https://img.shields.io/github/stars/Lin-jun-xiang/docGPT-streamlit?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/Lin-jun-xiang/docGPT-streamlit/network/members">
<img alt="Forks" src="https://img.shields.io/github/forks/Lin-jun-xiang/docGPT-streamlit?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/Lin-jun-xiang/docGPT-streamlit/issues">
<img alt="Issues" src="https://img.shields.io/github/issues/Lin-jun-xiang/docGPT-streamlit?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/Lin-jun-xiang/docGPT-streamlit/pulls">
<img alt="Pull Requests" src="https://img.shields.io/github/issues-pr/Lin-jun-xiang/docGPT-streamlit?style=flat-square&labelColor=343b41" />
</a>
</td>
</tr>
<tr>
<td>
<a href="https://github.com/Simatwa/python-tgpt">
<b>python-tgpt</b>
</a>
</td>
<td>
<a href="https://github.com/Simatwa/python-tgpt/stargazers">
<img alt="Stars" src="https://img.shields.io/github/stars/Simatwa/python-tgpt?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/Simatwa/python-tgpt/network/members">
<img alt="Forks" src="https://img.shields.io/github/forks/Simatwa/python-tgpt?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/Simatwa/python-tgpt/issues">
<img alt="Issues" src="https://img.shields.io/github/issues/Simatwa/python-tgpt?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/Simatwa/python-tgpt/pulls">
<img alt="Pull Requests" src="https://img.shields.io/github/issues-pr/Simatwa/python-tgpt?style=flat-square&labelColor=343b41" />
</a>
</td>
</tr>
<tr>
<td>
<a href="https://github.com/zachey01/gpt4free.js">
<b>GPT4js</b>
</a>
</td>
<td>
<a href="https://github.com/zachey01/gpt4free.js/stargazers">
<img alt="Stars" src="https://img.shields.io/github/stars/zachey01/gpt4free.js?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/zachey01/gpt4free.js/network/members">
<img alt="Forks" src="https://img.shields.io/github/forks/zachey01/gpt4free.js?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/zachey01/gpt4free.js/issues">
<img alt="Issues" src="https://img.shields.io/github/issues/zachey01/gpt4free.js?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/zachey01/gpt4free.js/pulls">
<img alt="Pull Requests" src="https://img.shields.io/github/issues-pr/zachey01/gpt4free.js?style=flat-square&labelColor=343b41" />
</a>
</td>
</tr>
<tr>
<td>
<a href="https://github.com/yjg30737/pyqt-openai">
<b>VividNode (pyqt-openai)</b>
</a>
</td>
<td>
<a href="https://github.com/yjg30737/pyqt-openai/stargazers">
<img alt="Stars" src="https://img.shields.io/github/stars/yjg30737/pyqt-openai?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/yjg30737/pyqt-openai/network/members">
<img alt="Forks" src="https://img.shields.io/github/forks/yjg30737/pyqt-openai?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/yjg30737/pyqt-openai/issues">
<img alt="Issues" src="https://img.shields.io/github/issues/yjg30737/pyqt-openai?style=flat-square&labelColor=343b41" />
</a>
</td>
<td>
<a href="https://github.com/yjg30737/pyqt-openai/pulls">
<img alt="Pull Requests" src="https://img.shields.io/github/issues-pr/yjg30737/pyqt-openai?style=flat-square&labelColor=343b41" />
</a>
</td>
</tr>
</tbody>
</table>
**🌟 Pollinations AI**
<img src="https://image.pollinations.ai/prompt/Create+a+logo+for+Pollinations+AI+featuring+an+abstract+flower+blooming+digital+petals+glowing+center+futuristic+font+Pollinations+AI?width=512&height=256&nologo=true" height="128">
A creative AI content platform that generates images, audios, and other media using advanced generative models. Pollinations AI empowers users and developers to turn text into visuals and multimedia experiences.
> [github.com/pollinations/pollinations](https://github.com/pollinations/pollinations)
---
### 💸 Powered by GPT4Free
**🖨️ MoneyPrinter**
<img src="https://image.pollinations.ai/prompt/Create+a+logo+for+MoneyPrinter+glowing+center+futuristic+font?width=512&height=256&nologo=true" height="128">
MoneyPrinter V2 cranks up the automation for making money online. It’s a complete overhaul of the original MoneyPrinter, rebuilt from the ground up for more features and a plug-and-play, modular design. MPV2 takes the grind and guesswork out of online income: just set it up, let it run, and watch your earnings stack.
> [FujiwaraChoki/MoneyPrinterV2 on GitHub](https://github.com/FujiwaraChoki/MoneyPrinterV2)
> [Full list of GPT4Free powered sites and tools](https://github.com/gpt4free/gpt4free.github.io/blob/main/docs/powered-by.md)
## 🤝 Contribute
We welcome contributions from the community. Whether you're adding new providers or features, or simply fixing typos and making small improvements, your input is valued. Creating a pull request is all it takes – our co-pilot will handle the code review process. Once all changes have been addressed, we'll merge the pull request into the main branch and release the updates at a later time.
@@ -98,8 +98,6 @@ class Cloudflare(AsyncGeneratorProvider, ProviderModelMixin, AuthFileMixin):
messages: Messages,
proxy: str = None,
max_tokens: int = 2048,
cookies: Cookies = None,
timeout: int = 300,
**kwargs
) -> AsyncResult:
cache_file = cls.get_cache_file()
@@ -109,7 +107,7 @@ class Cloudflare(AsyncGeneratorProvider, ProviderModelMixin, AuthFileMixin):
cls._args = json.load(f)
elif has_nodriver:
try:
cls._args = await get_args_from_nodriver(cls.url)
cls._args = await get_args_from_nodriver(cls.url, proxy=proxy)
except (RuntimeError, FileNotFoundError) as e:
debug.log(f"Nodriver is not available: {type(e).__name__}: {e}")
cls._args = {"headers": DEFAULT_HEADERS, "cookies": {}, "impersonate": "chrome"}
@@ -18,8 +18,9 @@ from ..requests.raise_for_status import raise_for_status
from ..requests.aiohttp import get_connector
from ..image.copy_images import save_response_media
from ..image import use_aspect_ratio
from ..providers.response import FinishReason, Usage, ToolCalls, ImageResponse, Reasoning
from ..providers.response import FinishReason, Usage, ToolCalls, ImageResponse, Reasoning, TitleGeneration, SuggestedFollowups
from ..tools.media import render_messages
from ..constants import STATIC_URL
from .. import debug
DEFAULT_HEADERS = {
@@ -30,6 +31,36 @@ DEFAULT_HEADERS = {
"origin": "https://pollinations.ai",
}
FOLLOWUPS_TOOLS = [{
"type": "function",
"function": {
"name": "options",
"description": "Provides options for the conversation",
"parameters": {
"properties": {
"title": {
"title": "Conversation Title",
"type": "string"
},
"followups": {
"items": {
"type": "string"
},
"title": "Suggested Followups",
"type": "array"
}
},
"title": "Conversation",
"type": "object"
}
}
}]
FOLLOWUPS_DEVELOPER_MESSAGE = [{
"role": "developer",
"content": "Prefix conversation title with one or more emojies. Suggested 4 Followups"
}]
class PollinationsAI(AsyncGeneratorProvider, ProviderModelMixin):
label = "Pollinations AI"
url = "https://pollinations.ai"
@@ -201,7 +232,7 @@ class PollinationsAI(AsyncGeneratorProvider, ProviderModelMixin):
stream: bool = True,
proxy: str = None,
cache: bool = False,
referrer: str = "https://gpt4free.github.io/",
referrer: str = STATIC_URL,
extra_body: dict = {},
# Image generation parameters
prompt: str = None,
@@ -400,6 +431,9 @@ class PollinationsAI(AsyncGeneratorProvider, ProviderModelMixin):
content = choice.get("delta", {}).get("content")
if content:
yield content
tool_calls = choice.get("delta", {}).get("tool_calls")
if tool_calls:
yield ToolCalls(choice["delta"]["tool_calls"])
reasoning_content = choice.get("delta", {}).get("reasoning_content")
if reasoning_content:
reasoning = True
@@ -409,6 +443,26 @@ class PollinationsAI(AsyncGeneratorProvider, ProviderModelMixin):
yield FinishReason(finish_reason)
if reasoning:
yield Reasoning(status="Done")
if "action" in kwargs and "tools" not in data and "response_format" not in data:
data = {
"model": model,
"messages": messages + FOLLOWUPS_DEVELOPER_MESSAGE,
"tool_choice": "required",
"tools": FOLLOWUPS_TOOLS
}
async with session.post(url, json=data, headers={"referer": referrer}) as response:
try:
await raise_for_status(response)
tool_calls = (await response.json()).get("choices", [{}])[0].get("message", {}).get("tool_calls", [])
if tool_calls:
arguments = json.loads(tool_calls.pop().get("function", {}).get("arguments"))
if arguments.get("title"):
yield TitleGeneration(arguments.get("title"))
if arguments.get("followups"):
yield SuggestedFollowups(arguments.get("followups"))
except Exception as e:
debug.error("Error generating title and followups")
debug.error(e)
elif response.headers["content-type"].startswith("application/json"):
result = await response.json()
if "choices" in result:
@@ -4,6 +4,7 @@ from typing import Optional
from .helper import format_image_prompt
from ..typing import AsyncResult, Messages
from ..constants import STATIC_URL
from .PollinationsAI import PollinationsAI
class PollinationsImage(PollinationsAI):
@@ -37,7 +38,7 @@ class PollinationsImage(PollinationsAI):
model: str,
messages: Messages,
proxy: str = None,
referrer: str = "https://gpt4free.github.io/",
referrer: str = STATIC_URL,
prompt: str = None,
aspect_ratio: str = "1:1",
width: int = None,
@@ -6,7 +6,7 @@ import uuid
from urllib.parse import urlparse
from ...typing import AsyncResult, Messages, MediaListType
from ...requests import StreamSession, StreamResponse, FormData, raise_for_status
from ...requests import DEFAULT_HEADERS, StreamSession, StreamResponse, FormData, raise_for_status
from ...providers.response import JsonConversation
from ...tools.media import merge_media
from ...image import to_bytes, is_accepted_format
@@ -192,7 +192,7 @@ class HarProvider(AsyncGeneratorProvider, ProviderModelMixin):
postData = postData.replace("__MODEL__", model)
request_url = request_url.replace("__SESSION__", conversation.session_hash)
method = v['request']['method'].lower()
async with getattr(session, method)(request_url, data=postData, headers=get_headers(v), proxy=proxy) as response:
async with getattr(session, method)(request_url, data=postData, headers={**get_headers(v), **DEFAULT_HEADERS}, proxy=proxy) as response:
await raise_for_status(response)
async for chunk in read_response(response):
yield chunk
@@ -680,9 +680,9 @@ class OpenaiChat(AsyncAuthedProvider, ProviderModelMixin):
page.add_handler(nodriver.cdp.network.RequestWillBeSent, on_request)
page = await browser.get(cls.url)
user_agent = await page.evaluate("window.navigator.userAgent", return_by_value=True)
while not await page.evaluate("document.getElementById('prompt-textarea').id"):
while not await page.evaluate("document.getElementById('prompt-textarea')?.id"):
await asyncio.sleep(1)
while not await page.evaluate("document.querySelector('[data-testid=\"send-button\"]').type"):
while not await page.evaluate("document.querySelector('[data-testid=\"send-button\"]')?.type"):
await asyncio.sleep(1)
await page.evaluate("document.querySelector('[data-testid=\"send-button\"]').click()")
while True:
@@ -41,7 +41,7 @@ except NameError:
def add_chunk(content, chunk):
if content == "" and isinstance(chunk, (MediaResponse, AudioResponse)):
content = chunk
elif not isinstance(chunk, Reasoning):
elif not isinstance(chunk, (Reasoning, ToolCalls)):
content = str(content) + str(chunk)
return content
@@ -85,8 +85,9 @@ def iter_response(
conversation = chunk
continue
elif isinstance(chunk, ToolCalls):
tool_calls = chunk.get_list()
continue
if not stream:
tool_calls = chunk.get_list()
continue
elif isinstance(chunk, Usage):
usage = chunk
continue
@@ -99,10 +100,10 @@ def iter_response(
continue
elif isinstance(chunk, Exception):
continue
elif not chunk:
continue
content = add_chunk(content, chunk)
if not content:
continue
idx += 1
if max_tokens is not None and idx >= max_tokens:
@@ -187,8 +188,9 @@ async def async_iter_response(
conversation = chunk
continue
elif isinstance(chunk, ToolCalls):
tool_calls = chunk.get_list()
continue
if not stream:
tool_calls = chunk.get_list()
continue
elif isinstance(chunk, Usage):
usage = chunk
continue
@@ -201,10 +203,10 @@ async def async_iter_response(
continue
elif isinstance(chunk, Exception):
continue
elif not chunk:
continue
content = add_chunk(content, chunk)
if not content:
continue
idx += 1
if max_tokens is not None and idx >= max_tokens:
@@ -7,7 +7,7 @@ from time import time
from ..image import extract_data_uri
from ..image.copy_images import get_media_dir
from ..client.helper import filter_markdown
from ..providers.response import Reasoning
from ..providers.response import Reasoning, ToolCalls
from .helper import filter_none
try:
@@ -253,18 +253,23 @@ class ChatCompletionDelta(BaseModel):
role: str
content: Optional[str]
reasoning_content: Optional[str] = None
tool_calls: list[ToolCallModel] = None
@classmethod
def model_construct(cls, content: Optional[str]):
if isinstance(content, Reasoning):
return super().model_construct(role="reasoning", content=content, reasoning_content=str(content))
elif isinstance(content, ToolCalls):
return super().model_construct(role="assistant", content=None, tool_calls=[
ToolCallModel.model_construct(**tool_call) for tool_call in content.get_list()
])
return super().model_construct(role="assistant", content=content)
@field_serializer('content')
def serialize_content(self, content: Optional[str]):
if content is None:
return ""
if isinstance(content, Reasoning):
if isinstance(content, (Reasoning, ToolCalls)):
return None
return str(content)
@@ -0,0 +1,5 @@
PACKAGE_NAME = "g4f"
GITHUB_REPOSITORY = "xtekky/gpt4free"
STATIC_DOMAIN = "gpt4free.github.io"
STATIC_URL = f"https://{STATIC_DOMAIN}/"
DIST_DIR = f"./{STATIC_DOMAIN}/dist"
@@ -7,17 +7,16 @@ from flask import send_from_directory, redirect
from ...image.copy_images import secure_filename
from ...cookies import get_cookies_dir
from ...errors import VersionNotFoundError
from ...constants import STATIC_URL, DIST_DIR
from ... import version
GPT4FREE_URL = "https://gpt4free.github.io"
DIST_DIR = "./gpt4free.github.io/dist"
def redirect_home():
return redirect('/chat')
def render(filename = "chat", add_origion = True):
def render(filename = "chat"):
is_live = True
if os.path.exists(DIST_DIR):
add_origion = False
is_live = False
path = os.path.abspath(os.path.join(os.path.dirname(DIST_DIR), (filename + ("" if "." in filename else ".html"))))
return send_from_directory(os.path.dirname(path), os.path.basename(path))
try:
@@ -26,13 +25,13 @@ def render(filename = "chat", add_origion = True):
latest_version = version.utils.current_version
today = datetime.today().strftime('%Y-%m-%d')
cache_dir = os.path.join(get_cookies_dir(), ".gui_cache")
cache_file = os.path.join(cache_dir, f"{today}.{secure_filename(filename)}.{version.utils.current_version}-{latest_version}{'.live' if add_origion else ''}.html")
cache_file = os.path.join(cache_dir, f"{today}.{secure_filename(f'{filename}.{version.utils.current_version}-{latest_version}')}{'.live' if is_live else ''}.html")
if not os.path.exists(cache_file):
os.makedirs(cache_dir, exist_ok=True)
html = requests.get(f"{GPT4FREE_URL}/{filename}.html").text
if add_origion:
html = requests.get(f"{STATIC_URL}{filename}.html").text
if is_live:
html = html.replace("../dist/", f"dist/")
html = html.replace("\"dist/", f"\"{GPT4FREE_URL}/dist/")
html = html.replace("\"dist/", f"\"{STATIC_URL}dist/")
with open(cache_file, 'w', encoding='utf-8') as f:
f.write(html)
return send_from_directory(os.path.abspath(cache_dir), os.path.basename(cache_file))
@@ -221,7 +221,9 @@ class AnyProvider(AsyncGeneratorProvider, ProviderModelMixin):
has_audio = True
break
has_image = True
if "audio" in kwargs or "audio" in kwargs.get("modalities", []):
if "tools" in kwargs:
providers = [PollinationsAI]
elif "audio" in kwargs or "audio" in kwargs.get("modalities", []):
providers = [PollinationsAI, EdgeTTS, gTTS]
elif has_audio:
providers = [PollinationsAI, Microsoft_Phi_4_Multimodal, MarkItDown]
@@ -6,6 +6,9 @@ from typing import Union, Dict, List, Optional
from abc import abstractmethod
from urllib.parse import quote_plus, unquote_plus
def is_content(chunk):
return isinstance(chunk, (str, MediaResponse, AudioResponse, Reasoning, ToolCalls))
def quote_url(url: str) -> str:
"""
Quote parts of a URL while preserving the domain structure.