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

XFEstudio/gpt4free

Add selenium to dockerfile Load model and provider list in gui Remove needs_auth in HuggingChat Add default model and login url in gui

3576dee7
Heiner Lohaus <hlohaus@users.noreply.github.com>
提交于

代码差异

19 个文件 +189 -242
Deleted Dockerfile +0 -33
@@ -1,33 +0,0 @@
1 # Use the official lightweight Python image.
2 # https://hub.docker.com/_/python
3 FROM python:3.9-slim
4
5 # Ensure Python outputs everything immediately (useful for real-time logging in Docker).
6 ENV PYTHONUNBUFFERED 1
7
8 # Set the working directory in the container.
9 WORKDIR /app
10
11 # Update the system packages and install system-level dependencies required for compilation.
12 # gcc: Compiler required for some Python packages.
13 # build-essential: Contains necessary tools and libraries for building software.
14 RUN apt-get update && apt-get install -y --no-install-recommends \
15 gcc \
16 build-essential \
17 && rm -rf /var/lib/apt/lists/*
18
19 # Copy the project's requirements file into the container.
20 COPY requirements.txt /app/
21
22 # Upgrade pip for the latest features and install the project's Python dependencies.
23 RUN pip install --upgrade pip && pip install -r requirements.txt
24
25 # Copy the entire project into the container.
26 # This may include all code, assets, and configuration files required to run the application.
27 COPY . /app/
28
29 # Expose port 80 and 1337
30 EXPOSE 80 1337
31
32 # Define the default command to run the app using Python's module mode.
33 ENTRYPOINT ["python", "-m", "g4f.cli"]
Modified README.md +1 -1
@@ -1,4 +1,4 @@
1 ![248433934-7886223b-c1d1-4260-82aa-da5741f303bb](https://github.com/xtekky/gpt4free/assets/98614666/ea012c87-76e0-496a-8ac4-e2de090cc6c9)
1 ![g4f](g4f.png)
2 2
3 3 <a href='https://ko-fi.com/xtekky' target='_blank'><img height='35' style='border:0px;height:46px;' src='https://az743702.vo.msecnd.net/cdn/kofi3.png?v=0' border='0' alt='Buy Me a Coffee at ko-fi.com' />
4 4 <div id="top"></div>
Modified docker-compose.yml +7 -8
@@ -1,18 +1,17 @@
1 1 version: '3'
2 2
3 3 services:
4 gpt4free-api: &gpt4free
4 gpt4free:
5 5 image: gpt4free:latest
6 shm_size: 2gb
6 7 build:
7 8 context: .
8 dockerfile: Dockerfile
9 dockerfile: docker/Dockerfile
9 10 cache_from:
10 11 - gpt4free:latest
11 ports:
12 - '1337:1337'
13 command: api
14 gpt4free-gui:
15 <<: *gpt4free
12 volumes:
13 - .:/app
16 14 ports:
17 15 - '8080:80'
18 command: gui
16 - '1337:1337'
17 - '7900:7900'
Added docker/Dockerfile +42 -0
@@ -0,0 +1,42 @@
1 FROM selenium/node-chrome
2
3 ENV SE_SCREEN_WIDTH 1920
4 ENV G4F_LOGIN_URL http://localhost:7900/?autoconnect=1&resize=scale&password=secret
5
6 USER root
7
8 # Python packages
9 RUN apt-get -qqy update \
10 && apt-get -qqy install \
11 python3 \
12 python-is-python3 \
13 pip
14
15 # Cleanup
16 RUN rm -rf /var/lib/apt/lists/* /var/cache/apt/* \
17 && apt-get -qyy autoremove \
18 && apt-get -qyy clean
19
20 # Update entrypoint
21 COPY docker/start-selenium-node.sh /opt/bin/
22
23 # Change background image
24 COPY g4f.png /usr/share/images/fluxbox/ubuntu-light.png
25
26 # Switch user
27 USER 1200
28
29 # Set the working directory in the container.
30 WORKDIR /app
31
32 # Copy the project's requirements file into the container.
33 COPY requirements.txt /app/
34
35 # Upgrade pip for the latest features and install the project's Python dependencies.
36 RUN pip install --upgrade pip && pip install -r requirements.txt
37
38 # Copy the entire package into the container.
39 COPY g4f /app/g4f
40
41 # Expose ports
42 EXPOSE 80 1337
Added docker/start-selenium-node.sh +17 -0
@@ -0,0 +1,17 @@
1 #!/bin/bash
2
3 # Start the pulseaudio server
4 pulseaudio -D --exit-idle-time=-1
5
6 # Load the virtual sink and set it as default
7 pacmd load-module module-virtual-sink sink_name=v1
8 pacmd set-default-sink v1
9
10 # Set the monitor of v1 sink to be the default source
11 pacmd set-default-source v1.monitor
12
13 rm -f /tmp/.X*lock
14
15 # Start app servers
16 python -m g4f.cli api &
17 python -m g4f.cli gui
Added g4f.png +0 -0
二进制文件已变更,无法进行逐行预览。
Modified g4f/Provider/Bing.py +5 -2
@@ -156,8 +156,11 @@ async def delete_conversation(session: ClientSession, conversation: Conversation
156 156 "optionsSets": ["autosave"]
157 157 }
158 158 async with session.post(url, json=json, proxy=proxy) as response:
159 response = await response.json()
160 return response["result"]["value"] == "Success"
159 try:
160 response = await response.json()
161 return response["result"]["value"] == "Success"
162 except:
163 return False
161 164
162 165 class Defaults:
163 166 delimiter = "\x1e"
Modified g4f/Provider/PerplexityAi.py +4 -5
@@ -1,6 +1,10 @@
1 1 from __future__ import annotations
2 2
3 3 import time
4 from selenium.webdriver.common.by import By
5 from selenium.webdriver.support.ui import WebDriverWait
6 from selenium.webdriver.support import expected_conditions as EC
7 from selenium.webdriver.common.keys import Keys
4 8
5 9 from ..typing import CreateResult, Messages
6 10 from .base_provider import BaseProvider
@@ -27,11 +31,6 @@ class PerplexityAi(BaseProvider):
27 31 **kwargs
28 32 ) -> CreateResult:
29 33 with WebDriverSession(webdriver, "", virtual_display=virtual_display, proxy=proxy) as driver:
30 from selenium.webdriver.common.by import By
31 from selenium.webdriver.support.ui import WebDriverWait
32 from selenium.webdriver.support import expected_conditions as EC
33 from selenium.webdriver.common.keys import Keys
34
35 34 prompt = format_prompt(messages)
36 35
37 36 driver.get(f"{cls.url}/")
Modified g4f/Provider/helper.py +7 -2
@@ -6,6 +6,7 @@ import webbrowser
6 6 import random
7 7 import string
8 8 import secrets
9 import os
9 10 from os import path
10 11 from asyncio import AbstractEventLoop
11 12 from platformdirs import user_config_dir
@@ -18,7 +19,7 @@ from browser_cookie3 import (
18 19 edge,
19 20 vivaldi,
20 21 firefox,
21 BrowserCookieError
22 _LinuxPasswordManager
22 23 )
23 24
24 25 from ..typing import Dict, Messages
@@ -81,6 +82,10 @@ def init_cookies():
81 82 except webbrowser.Error:
82 83 continue
83 84
85 # Check for broken dbus address in docker image
86 if os.environ.get('DBUS_SESSION_BUS_ADDRESS') == "/dev/null":
87 _LinuxPasswordManager.get_password = lambda a, b: b"secret"
88
84 89 # Load cookies for a domain from all supported browsers.
85 90 # Cache the results in the "_cookies" variable.
86 91 def get_cookies(domain_name=''):
@@ -100,7 +105,7 @@ def get_cookies(domain_name=''):
100 105 for cookie in cookie_jar:
101 106 if cookie.name not in cookies:
102 107 cookies[cookie.name] = cookie.value
103 except BrowserCookieError as e:
108 except:
104 109 pass
105 110 _cookies[domain_name] = cookies
106 111 return _cookies[domain_name]
Modified g4f/Provider/needs_auth/Bard.py +10 -6
@@ -1,6 +1,11 @@
1 1 from __future__ import annotations
2 2
3 3 import time
4 import os
5 from selenium.webdriver.common.by import By
6 from selenium.webdriver.support.ui import WebDriverWait
7 from selenium.webdriver.support import expected_conditions as EC
8 from selenium.webdriver.common.keys import Keys
4 9
5 10 from ...typing import CreateResult, Messages
6 11 from ..base_provider import BaseProvider
@@ -27,10 +32,6 @@ class Bard(BaseProvider):
27 32 prompt = format_prompt(messages)
28 33 session = WebDriverSession(webdriver, user_data_dir, headless, proxy=proxy)
29 34 with session as driver:
30 from selenium.webdriver.common.by import By
31 from selenium.webdriver.support.ui import WebDriverWait
32 from selenium.webdriver.support import expected_conditions as EC
33
34 35 try:
35 36 driver.get(f"{cls.url}/chat")
36 37 wait = WebDriverWait(driver, 10 if headless else 240)
@@ -40,6 +41,9 @@ class Bard(BaseProvider):
40 41 if not webdriver:
41 42 driver = session.reopen()
42 43 driver.get(f"{cls.url}/chat")
44 login_url = os.environ.get("G4F_LOGIN_URL")
45 if login_url:
46 yield f"Please login: [Google Bard]({login_url})\n\n"
43 47 wait = WebDriverWait(driver, 240)
44 48 wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div.ql-editor.textarea")))
45 49 else:
@@ -61,8 +65,8 @@ XMLHttpRequest.prototype.open = function(method, url) {
61 65 driver.execute_script(script)
62 66
63 67 # Submit prompt
64 driver.find_element(By.CSS_SELECTOR, "div.ql-editor.ql-blank.textarea").send_keys(prompt)
65 driver.find_element(By.CSS_SELECTOR, "button.send-button").click()
68 driver.find_element(By.CSS_SELECTOR, "div.ql-editor.textarea").send_keys(prompt)
69 driver.find_element(By.CSS_SELECTOR, "div.ql-editor.textarea").send_keys(Keys.ENTER)
66 70
67 71 # Yield response
68 72 while True:
Modified g4f/Provider/needs_auth/HuggingChat.py +2 -4
@@ -11,7 +11,6 @@ from ..helper import format_prompt, get_cookies
11 11
12 12 class HuggingChat(AsyncGeneratorProvider):
13 13 url = "https://huggingface.co/chat"
14 needs_auth = True
15 14 working = True
16 15 model = "meta-llama/Llama-2-70b-chat-hf"
17 16
@@ -22,12 +21,11 @@ class HuggingChat(AsyncGeneratorProvider):
22 21 messages: Messages,
23 22 stream: bool = True,
24 23 proxy: str = None,
24 web_search: bool = False,
25 25 cookies: dict = None,
26 26 **kwargs
27 27 ) -> AsyncResult:
28 28 model = model if model else cls.model
29 if proxy and "://" not in proxy:
30 proxy = f"http://{proxy}"
31 29 if not cookies:
32 30 cookies = get_cookies(".huggingface.co")
33 31
@@ -46,7 +44,7 @@ class HuggingChat(AsyncGeneratorProvider):
46 44 "inputs": format_prompt(messages),
47 45 "is_retry": False,
48 46 "response_id": str(uuid.uuid4()),
49 "web_search": False
47 "web_search": web_search
50 48 }
51 49 async with session.post(f"{cls.url}/conversation/{conversation_id}", json=send, proxy=proxy) as response:
52 50 async for line in response.content:
Modified g4f/Provider/needs_auth/OpenaiChat.py +15 -22
@@ -1,12 +1,15 @@
1 1 from __future__ import annotations
2 2
3 import uuid, json, asyncio
3 import uuid, json, asyncio, os
4 4 from py_arkose_generator.arkose import get_values_for_request
5 5 from asyncstdlib.itertools import tee
6 6 from async_property import async_cached_property
7
7 from selenium.webdriver.common.by import By
8 from selenium.webdriver.support.ui import WebDriverWait
9 from selenium.webdriver.support import expected_conditions as EC
10
8 11 from ..base_provider import AsyncGeneratorProvider
9 from ..helper import get_event_loop
12 from ..helper import get_event_loop, format_prompt
10 13 from ...webdriver import get_browser
11 14 from ...typing import AsyncResult, Messages
12 15 from ...requests import StreamSession
@@ -84,7 +87,12 @@ class OpenaiChat(AsyncGeneratorProvider):
84 87 if not parent_id:
85 88 parent_id = str(uuid.uuid4())
86 89 if not access_token:
87 access_token = await cls.get_access_token(proxy)
90 access_token = cls._access_token
91 if not access_token:
92 login_url = os.environ.get("G4F_LOGIN_URL")
93 if login_url:
94 yield f"Please login: [ChatGPT]({login_url})\n\n"
95 access_token = cls._access_token = await cls.browse_access_token(proxy)
88 96 headers = {
89 97 "Accept": "text/event-stream",
90 98 "Authorization": f"Bearer {access_token}",
@@ -106,10 +114,11 @@ class OpenaiChat(AsyncGeneratorProvider):
106 114 "history_and_training_disabled": history_disabled and not auto_continue,
107 115 }
108 116 if action != "continue":
117 prompt = format_prompt(messages) if not conversation_id else messages[-1]["content"]
109 118 data["messages"] = [{
110 119 "id": str(uuid.uuid4()),
111 120 "author": {"role": "user"},
112 "content": {"content_type": "text", "parts": [messages[-1]["content"]]},
121 "content": {"content_type": "text", "parts": [prompt]},
113 122 }]
114 123 async with session.post(f"{cls.url}/backend-api/conversation", json=data) as response:
115 124 try:
@@ -155,14 +164,7 @@ class OpenaiChat(AsyncGeneratorProvider):
155 164 @classmethod
156 165 async def browse_access_token(cls, proxy: str = None) -> str:
157 166 def browse() -> str:
158 try:
159 from selenium.webdriver.common.by import By
160 from selenium.webdriver.support.ui import WebDriverWait
161 from selenium.webdriver.support import expected_conditions as EC
162
163 driver = get_browser(proxy=proxy)
164 except ImportError:
165 return
167 driver = get_browser(proxy=proxy)
166 168 try:
167 169 driver.get(f"{cls.url}/")
168 170 WebDriverWait(driver, 1200).until(
@@ -177,15 +179,6 @@ class OpenaiChat(AsyncGeneratorProvider):
177 179 None,
178 180 browse
179 181 )
180
181 @classmethod
182 async def get_access_token(cls, proxy: str = None) -> str:
183 if not cls._access_token:
184 cls._access_token = await cls.browse_access_token(proxy)
185 if not cls._access_token:
186 raise RuntimeError("Read access token failed")
187 return cls._access_token
188
189 182
190 183 async def get_arkose_token(proxy: str = None, timeout: int = None) -> str:
191 184 config = {
Modified g4f/__init__.py +9 -6
@@ -25,7 +25,8 @@ def get_model_and_provider(model : Union[Model, str],
25 25 provider : Union[type[BaseProvider], None],
26 26 stream : bool,
27 27 ignored : List[str] = None,
28 ignore_working: bool = False) -> tuple[Model, type[BaseProvider]]:
28 ignore_working: bool = False,
29 ignore_stream: bool = False) -> tuple[Model, type[BaseProvider]]:
29 30
30 31 if isinstance(model, str):
31 32 if model in ModelUtils.convert:
@@ -45,7 +46,7 @@ def get_model_and_provider(model : Union[Model, str],
45 46 if not provider.working and not ignore_working:
46 47 raise RuntimeError(f'{provider.__name__} is not working')
47 48
48 if not provider.supports_stream and stream:
49 if not ignore_stream and not provider.supports_stream and stream:
49 50 raise ValueError(f'{provider.__name__} does not support "stream" argument')
50 51
51 52 if debug.logging:
@@ -61,15 +62,17 @@ class ChatCompletion:
61 62 stream : bool = False,
62 63 auth : Union[str, None] = None,
63 64 ignored : List[str] = None,
64 ignore_working: bool = False, **kwargs) -> Union[CreateResult, str]:
65 ignore_working: bool = False,
66 ignore_stream_and_auth: bool = False,
67 **kwargs) -> Union[CreateResult, str]:
65 68
66 model, provider = get_model_and_provider(model, provider, stream, ignored, ignore_working)
69 model, provider = get_model_and_provider(model, provider, stream, ignored, ignore_working, ignore_stream_and_auth)
67 70
68 if provider.needs_auth and not auth:
71 if not ignore_stream_and_auth and provider.needs_auth and not auth:
69 72 raise ValueError(
70 73 f'{provider.__name__} requires authentication (use auth=\'cookie or token or jwt ...\' param)')
71 74
72 if provider.needs_auth:
75 if auth:
73 76 kwargs['auth'] = auth
74 77
75 78 result = provider.create_completion(model.name, messages, stream, **kwargs)
Modified g4f/gui/client/js/chat.v1.js +35 -60
Modified g4f/gui/server/backend.py +25 -19
Deleted g4f/gui/server/provider.py +0 -14
Modified g4f/models.py +2 -1
Modified g4f/webdriver.py +8 -2
Deleted ptest.py +0 -57