返回提交历史
Modified
.github/workflows/unittest.yml
+2
-0
Modified
g4f/Provider/DeepInfra.py
+1
-1
Modified
g4f/Provider/glm/__init__.py
+3
-2
Modified
g4f/Provider/local/Ollama.py
+2
-2
Modified
g4f/Provider/needs_auth/Puter.py
+1
-1
Modified
g4f/Provider/needs_auth/hf/HuggingChat.py
+1
-1
Modified
g4f/Provider/needs_auth/hf/HuggingFaceInference.py
+2
-2
Modified
g4f/Provider/needs_auth/hf/HuggingFaceMedia.py
+1
-1
XFEstudio/gpt4free
fix(CI): add timeout to get_models() network requests and CI step limit
- Add timeout parameter to requests.get() in 7 provider files where timeout=5 from test was silently ignored via **kwargs - Add timeout-minutes: 5 to CI workflow as safety net - Prevents indefinite hang when Cloudflare tarpits connections on CI
e9d4370c
代码差异
8 个文件
+13
-10
@@ -24,6 +24,7 @@ jobs:
24
24
run: pip install -r requirements-min.txt
25
25
- name: Run tests
26
26
run: python -m etc.unittest
27
timeout-minutes: 5
27
28
- name: Set up Python 3.14
28
29
uses: actions/setup-python@v6
29
30
with:
@@ -34,6 +35,7 @@ jobs:
34
35
pip install -r requirements.txt
35
36
- name: Run tests
36
37
run: python -m etc.unittest
38
timeout-minutes: 5
37
39
- name: Save PR number
38
40
env:
39
41
PR_NUMBER: ${{ github.event.number }}
@@ -162,7 +162,7 @@ class DeepInfra(OpenaiTemplate):
162
162
def get_models(cls, **kwargs):
163
163
if not cls.models:
164
164
url = 'https://api.deepinfra.com/models/featured'
165
response = requests.get(url)
165
response = requests.get(url, timeout=kwargs.get("timeout", 15))
166
166
models = response.json()
167
167
168
168
cls.models = {model["model_name"]: {"id": model["model_name"], **model} for model in models if model.get("type") == "text-generation" or model.get("reported_type") == "text-to-image"}
@@ -220,14 +220,15 @@ class GLM(AsyncGeneratorProvider, ProviderModelMixin, AuthFileMixin):
220
220
@classmethod
221
221
def get_models(cls, **kwargs) -> list:
222
222
if not cls.models:
223
response = requests.get(f"{cls.url}/api/v1/auths/")
223
response = requests.get(f"{cls.url}/api/v1/auths/", timeout=kwargs.get("timeout", 15))
224
224
auth_data = response.json()
225
225
cls.api_key = auth_data.get("token")
226
226
cls.auth_user_id = str(auth_data.get("id", ""))
227
227
cls.auth_user_name = auth_data.get("name") or auth_data.get("nickname") or "User"
228
228
response = requests.get(
229
229
f"{cls.url}/api/models",
230
headers={"Authorization": f"Bearer {cls.api_key}"}
230
headers={"Authorization": f"Bearer {cls.api_key}"},
231
timeout=kwargs.get("timeout", 15)
231
232
)
232
233
items = response.json().get("data", [])
233
234
cls.model_aliases = {
@@ -100,7 +100,7 @@ class Ollama(OpenaiTemplate):
100
100
cls.models = []
101
101
if not api_key or AppConfig.disable_custom_api_key:
102
102
api_key = AuthManager.load_api_key(cls)
103
models = requests.get("https://ollama.com/api/tags").json()["models"]
103
models = requests.get("https://ollama.com/api/tags", timeout=kwargs.get("timeout", 15)).json()["models"]
104
104
if models:
105
105
cls.live += 1
106
106
cls.models = [model["name"] for model in models]
@@ -111,7 +111,7 @@ class Ollama(OpenaiTemplate):
111
111
else:
112
112
url = base_url.replace("/v1", "/api/tags")
113
113
try:
114
models = requests.get(url).json()["models"]
114
models = requests.get(url, timeout=kwargs.get("timeout", 15)).json()["models"]
115
115
except requests.exceptions.RequestException as e:
116
116
return cls.models
117
117
if cls.live == 0 and models:
@@ -209,7 +209,7 @@ class Puter(AsyncGeneratorProvider, ProviderModelMixin):
209
209
if not cls.models:
210
210
try:
211
211
url = cls.models_endpoint
212
cls.models = requests.get(url).json().get("models", [])
212
cls.models = requests.get(url, timeout=kwargs.get("timeout", 15)).json().get("models", [])
213
213
cls.models = [model for model in cls.models if model not in ["abuse", "costly", "fake", "model-fallback-test-1"]]
214
214
cls.live += 1
215
215
except Exception as e:
@@ -50,7 +50,7 @@ class HuggingChat(AsyncAuthedProvider, ProviderModelMixin):
50
50
def get_models(cls, **kwargs) -> list[str]:
51
51
if not cls.models:
52
52
try:
53
models = requests.get(f"{cls.url}/api/v2/models").json().get("json")
53
models = requests.get(f"{cls.url}/api/v2/models", timeout=kwargs.get("timeout", 15)).json().get("json")
54
54
cls.text_models = [model["id"] for model in models]
55
55
cls.models = cls.text_models + cls.image_models
56
56
cls.vision_models = [model["id"] for model in models if model["multimodal"]]
@@ -38,12 +38,12 @@ class HuggingFaceInference(AsyncGeneratorProvider, ProviderModelMixin):
38
38
if not cls.models:
39
39
models = text_models.copy()
40
40
url = "https://huggingface.co/api/models?inference=warm&pipeline_tag=text-generation"
41
response = requests.get(url)
41
response = requests.get(url, timeout=kwargs.get("timeout", 15))
42
42
if response.ok:
43
43
extra_models = [model["id"] for model in response.json() if model.get("trendingScore", 0) >= 10]
44
44
models = extra_models + vision_models + [model for model in models if model not in extra_models]
45
45
url = "https://huggingface.co/api/models?pipeline_tag=text-to-image"
46
response = requests.get(url)
46
response = requests.get(url, timeout=kwargs.get("timeout", 15))
47
47
cls.image_models = image_models.copy()
48
48
if response.ok:
49
49
extra_models = [model["id"] for model in response.json() if model.get("trendingScore", 0) >= 20]
@@ -32,7 +32,7 @@ class HuggingFaceMedia(AsyncGeneratorProvider, ProviderModelMixin):
32
32
def get_models(cls, **kwargs) -> list[str]:
33
33
if not cls.models:
34
34
url = "https://huggingface.co/api/models?inference=warm&expand[]=inferenceProviderMapping"
35
response = requests.get(url)
35
response = requests.get(url, timeout=kwargs.get("timeout", 15))
36
36
if response.ok:
37
37
models = response.json()
38
38
providers = {