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

XFEstudio/gpt4free

feat: Update environment variables and modify model mappings

- Added `OPENROUTER_API_KEY` and `AZURE_API_KEYS` to `example.env`. - Updated `AZURE_DEFAULT_MODEL` to "model-router" in `example.env`. - Added `AZURE_ROUTES` with multiple model URLs in `example.env`. - Changed the mapping for `"phi-4-multimodal"` in `DeepInfraChat.py` to `"microsoft/Phi-4-multimodal-instruct"`. - Added `media` parameter to `GptOss.create_completion` method and raised a `ValueError` if `media` is provided. - Updated `model_aliases` in `any_model_map.py` to include new mappings for various models. - Removed several model aliases from `PollinationsAI` in `any_model_map.py`. - Added new models and updated existing models in `model_map` across various files, including `any_model_map.py` and `__init__.py`. - Refactored `AnyModelProviderMixin` to include `model_aliases` and updated the logic for handling model aliases.

9563f8df
hlohaus <983577+hlohaus@users.noreply.github.com>
提交于

代码差异

14 个文件 +1252 -716
Modified example.env +17 -3
@@ -8,6 +8,20 @@ TOGETHER_API_KEY=
8 8 DEEPINFRA_API_KEY=
9 9 OPENAI_API_KEY=
10 10 GROQ_API_KEY=
11 AZURE_API_KEY=
12 AZURE_API_ENDPOINT=
13 AZURE_DEFAULT_MODEL=
11 OPENROUTER_API_KEY=
12 AZURE_API_KEYS='{
13 "default": "",
14 "flux-1.1-pro": "",
15 "flux.1-kontext-pro": ""
16 }'
17 AZURE_DEFAULT_MODEL="model-router"
18 AZURE_ROUTES='{
19 "model-router": "https://HOST.cognitiveservices.azure.com/openai/deployments/model-router/chat/completions?api-version=2025-01-01-preview",
20 "deepseek-r1": "https://HOST.services.ai.azure.com/models/chat/completions?api-version=2024-05-01-preview",
21 "gpt-4.1": "https://HOST.cognitiveservices.azure.com/openai/deployments/gpt-4.1/chat/completions?api-version=2025-01-01-preview",
22 "gpt-4o-mini-audio-preview": "https://HOST.cognitiveservices.azure.com/openai/deployments/gpt-4o-mini-audio-preview/chat/completions?api-version=2025-01-01-preview",
23 "o4-mini": "https://HOST.cognitiveservices.azure.com/openai/deployments/o4-mini/chat/completions?api-version=2025-01-01-preview",
24 "grok-3": "https://HOST.services.ai.azure.com/models/chat/completions?api-version=2024-05-01-preview",
25 "flux-1.1-pro": "https://HOST.cognitiveservices.azure.com/openai/deployments/FLUX-1.1-pro/images/generations?api-version=2025-04-01-preview",
26 "flux.1-kontext-pro": "https://HOST.services.ai.azure.com/openai/deployments/FLUX.1-Kontext-pro/images/edits?api-version=2025-04-01-preview"
27 }'
Modified g4f/Provider/DeepInfraChat.py +2 -30
@@ -2,10 +2,7 @@ from __future__ import annotations
2 2
3 3 import requests
4 4 from .template import OpenaiTemplate
5 from ..errors import ModelNotFoundError
6 5 from ..config import DEFAULT_MODEL
7 from .. import debug
8
9 6
10 7 class DeepInfraChat(OpenaiTemplate):
11 8 parent = "DeepInfra"
@@ -86,7 +83,7 @@ class DeepInfraChat(OpenaiTemplate):
86 83
87 84 # microsoft
88 85 "phi-4": "microsoft/phi-4",
89 "phi-4-multimodal": default_vision_model,
86 "phi-4-multimodal": "microsoft/Phi-4-multimodal-instruct",
90 87 "phi-4-reasoning-plus": "microsoft/phi-4-reasoning-plus",
91 88 "wizardlm-2-7b": "microsoft/WizardLM-2-7B",
92 89 "wizardlm-2-8x22b": "microsoft/WizardLM-2-8x22B",
@@ -100,29 +97,4 @@ class DeepInfraChat(OpenaiTemplate):
100 97 "qwen-3-32b": "Qwen/Qwen3-32B",
101 98 "qwen-3-235b": "Qwen/Qwen3-235B-A22B",
102 99 "qwq-32b": "Qwen/QwQ-32B",
103 }
104
105 @classmethod
106 def get_model(cls, model: str, **kwargs) -> str:
107 """Get the internal model name from the user-provided model name."""
108 # kwargs can contain api_key, api_base, etc. but we don't need them for model selection
109 if not model:
110 return cls.default_model
111
112 # Check if the model exists directly in our models list
113 if model in cls.models:
114 return model
115
116 # Check if there's an alias for this model
117 if model in cls.model_aliases:
118 alias = cls.model_aliases[model]
119 # If the alias is a list, randomly select one of the options
120 if isinstance(alias, list):
121 import random
122 selected_model = random.choice(alias)
123 debug.log(f"DeepInfraChat: Selected model '{selected_model}' from alias '{model}'")
124 return selected_model
125 debug.log(f"DeepInfraChat: Using model '{alias}' for alias '{model}'")
126 return alias
127
128 raise ModelNotFoundError(f"Model {model} not found")
100 }
Modified g4f/Provider/GptOss.py +4 -1
@@ -1,7 +1,7 @@
1 1 from __future__ import annotations
2 2
3 3
4 from ..typing import AsyncResult, Messages
4 from ..typing import AsyncResult, Messages, MediaListType
5 5 from ..providers.response import JsonConversation, Reasoning, TitleGeneration
6 6 from ..requests import StreamSession, raise_for_status
7 7 from ..config import DEFAULT_MODEL
@@ -26,11 +26,14 @@ class GptOss(AsyncGeneratorProvider, ProviderModelMixin):
26 26 cls,
27 27 model: str,
28 28 messages: Messages,
29 media: MediaListType = None,
29 30 conversation: JsonConversation = None,
30 31 reasoning_effort: str = "high",
31 32 proxy: str = None,
32 33 **kwargs
33 34 ) -> AsyncResult:
35 if media:
36 raise ValueError("Media is not supported by gpt-oss")
34 37 model = cls.get_model(model)
35 38 user_message = get_last_user_message(messages)
36 39 cookies = {}
Modified g4f/Provider/PollinationsAI.py +1 -6
@@ -88,11 +88,7 @@ class PollinationsAI(AsyncGeneratorProvider, ProviderModelMixin):
88 88 vision_models = [default_vision_model]
89 89 _models_loaded = False
90 90 model_aliases = {
91 "gpt-4": "openai",
92 "gpt-4o": "openai",
93 "gpt-4.1-mini": "openai",
94 "gpt-4o-mini": "openai",
95 "gpt-4.1-nano": "openai-fast",
91 "gpt-4.1-nano": "openai",
96 92 "gpt-4.1": "openai-large",
97 93 "o4-mini": "openai-reasoning",
98 94 "qwen-2.5-coder-32b": "qwen-coder",
@@ -106,7 +102,6 @@ class PollinationsAI(AsyncGeneratorProvider, ProviderModelMixin):
106 102 "grok-3-mini": "grok",
107 103 "grok-3-mini-high": "grok",
108 104 "gpt-4o-mini-audio": "openai-audio",
109 "gpt-4o-audio": "openai-audio",
110 105 "sdxl-turbo": "turbo",
111 106 "gpt-image": "gptimage",
112 107 "flux-dev": "flux",
Modified g4f/Provider/__init__.py +1 -1
@@ -1,7 +1,7 @@
1 1 from __future__ import annotations
2 2
3 3 from ..providers.types import BaseProvider, ProviderType
4 from ..providers.retry_provider import RetryProvider, IterListProvider
4 from ..providers.retry_provider import RetryProvider, IterListProvider, RotatedProvider
5 5 from ..providers.base_provider import AsyncProvider, AsyncGeneratorProvider
6 6 from ..providers.create_images import CreateImagesProvider
7 7 from .. import debug
Modified g4f/Provider/needs_auth/Azure.py +1 -1
@@ -79,7 +79,7 @@ class Azure(OpenaiTemplate):
79 79 raise ModelNotFoundError(f"No API endpoint found for model: {model}")
80 80 if not api_endpoint:
81 81 api_endpoint = os.environ.get("AZURE_API_ENDPOINT")
82 if not api_key:
82 if cls.api_keys:
83 83 api_key = cls.api_keys.get(model, cls.api_keys.get("default"))
84 84 if not api_key:
85 85 raise ValueError(f"API key is required for Azure provider. Ask for API key in the {cls.login_url} Discord server.")
Modified g4f/Provider/needs_auth/Together.py +1 -27
@@ -3,8 +3,6 @@ from __future__ import annotations
3 3
4 4 from ..template import OpenaiTemplate
5 5 from ...config import DEFAULT_MODEL
6 from ...errors import ModelNotFoundError
7 from ... import debug
8 6
9 7 class Together(OpenaiTemplate):
10 8 label = "Together"
@@ -141,28 +139,4 @@ class Together(OpenaiTemplate):
141 139 "flux-dev": ["black-forest-labs/FLUX.1-dev", "black-forest-labs/FLUX.1-dev-lora"],
142 140 "flux-kontext-pro": "black-forest-labs/FLUX.1-kontext-pro",
143 141 "flux-kontext-dev": "black-forest-labs/FLUX.1-kontext-dev",
144 }
145
146 @classmethod
147 def get_model(cls, model: str, api_key: str = None, api_base: str = None) -> str:
148 """Get the internal model name from the user-provided model name."""
149 if not model:
150 return cls.default_model
151
152 # Check if the model exists directly in our models list
153 if model in cls.models:
154 return model
155
156 # Check if there's an alias for this model
157 if model in cls.model_aliases:
158 alias = cls.model_aliases[model]
159 # If the alias is a list, randomly select one of the options
160 if isinstance(alias, list):
161 import random # Add this import at the top of the file
162 selected_model = random.choice(alias)
163 debug.log(f"Together: Selected model '{selected_model}' from alias '{model}'")
164 return selected_model
165 debug.log(f"Together: Using model '{alias}' for alias '{model}'")
166 return alias
167
168 raise ModelNotFoundError(f"Together: Model {model} not found")
142 }
Modified g4f/Provider/template/OpenaiTemplate.py +1 -1
@@ -42,7 +42,7 @@ class OpenaiTemplate(AsyncGeneratorProvider, ProviderModelMixin, RaiseErrorMixin
42 42 raise_for_status(response)
43 43 data = response.json()
44 44 data = data.get("data") if isinstance(data, dict) else data
45 cls.image_models = [model.get("id", model.get("name")) for model in data if model.get("image")]
45 cls.image_models = [model.get("id", model.get("name")) for model in data if model.get("image") or model.get("type") == "image"]
46 46 cls.vision_models = cls.vision_models.copy()
47 47 cls.vision_models += [model.get("id", model.get("name")) for model in data if model.get("vision")]
48 48 cls.models = [model.get("id", model.get("name")) for model in data]
Modified g4f/api/__init__.py +1 -0
@@ -363,6 +363,7 @@ class Api:
363 363 "owned_by": getattr(provider, "label", provider.__name__),
364 364 "image": model in getattr(provider, "image_models", []),
365 365 "vision": model in getattr(provider, "vision_models", []),
366 "type": "image" if model in getattr(provider, "image_models", []) else "text",
366 367 } for model in models]
367 368 }
368 369
Modified g4f/gui/server/backend_api.py +1 -0
@@ -127,6 +127,7 @@ class Backend_Api(Api):
127 127 except MissingAuthError as e:
128 128 return jsonify({"error": {"message": f"{type(e).__name__}: {e}"}}), 401
129 129 except Exception as e:
130 logger.exception(e)
130 131 return jsonify({"error": {"message": f"{type(e).__name__}: {e}"}}), 500
131 132 return jsonify(response)
132 133
Modified g4f/providers/any_provider.py +21 -8
@@ -6,7 +6,7 @@ import json
6 6 from ..typing import AsyncResult, Messages, MediaListType, Union
7 7 from ..errors import ModelNotFoundError
8 8 from ..image import is_data_an_audio
9 from ..providers.retry_provider import IterListProvider
9 from ..providers.retry_provider import RotatedProvider
10 10 from ..Provider.needs_auth import OpenaiChat, CopilotAccount
11 11 from ..Provider.hf_space import HuggingSpace
12 12 from ..Provider import Copilot, Cloudflare, Gemini, GeminiPro, Grok, DeepSeekAPI, PerplexityLabs, LambdaChat, PollinationsAI, PuterJS
@@ -18,7 +18,7 @@ from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
18 18 from .. import Provider
19 19 from .. import models
20 20 from .. import debug
21 from .any_model_map import audio_models, image_models, vision_models, video_models, model_map, models_count, parents
21 from .any_model_map import audio_models, image_models, vision_models, video_models, model_map, models_count, parents, model_aliases
22 22
23 23 PROVIERS_LIST_1 = [
24 24 CopilotAccount, OpenaiChat, Cloudflare, PerplexityLabs, Gemini, Grok, DeepSeekAPI, Blackbox, OpenAIFM,
@@ -73,6 +73,7 @@ class AnyModelProviderMixin(ProviderModelMixin):
73 73 models_count = models_count
74 74 models = list(model_map.keys())
75 75 model_map: dict[str, dict[str, str]] = model_map
76 model_aliases: dict[str, str] = model_aliases
76 77
77 78 @classmethod
78 79 def extend_ignored(cls, ignored: list[str]) -> list[str]:
@@ -102,7 +103,7 @@ class AnyModelProviderMixin(ProviderModelMixin):
102 103 cls.create_model_map()
103 104 file = os.path.join(os.path.dirname(__file__), "any_model_map.py")
104 105 with open(file, "w", encoding="utf-8") as f:
105 for key in ["audio_models", "image_models", "vision_models", "video_models", "model_map", "models_count", "parents"]:
106 for key in ["audio_models", "image_models", "vision_models", "video_models", "model_map", "models_count", "parents", "model_aliases"]:
106 107 value = getattr(cls, key)
107 108 f.write(f"{key} = {json.dumps(value, indent=2) if isinstance(value, dict) else repr(value)}\n")
108 109
@@ -118,11 +119,14 @@ class AnyModelProviderMixin(ProviderModelMixin):
118 119 "default": {provider.__name__: "" for provider in models.default.best_provider.providers},
119 120 }
120 121 cls.model_map.update({
121 model.name: {
122 name: {
122 123 provider.__name__: model.get_long_name() for provider in providers
123 124 if provider.working
124 } for _, (model, providers) in models.__models__.items()
125 } for name, (model, providers) in models.__models__.items()
125 126 })
127 for name, (model, providers) in models.__models__.items():
128 if isinstance(model, models.ImageModel):
129 cls.image_models.append(name)
126 130
127 131 # Process special providers
128 132 for provider in PROVIERS_LIST_2:
@@ -234,6 +238,11 @@ class AnyModelProviderMixin(ProviderModelMixin):
234 238 elif provider.__name__ not in cls.parents[provider.get_parent()]:
235 239 cls.parents[provider.get_parent()].append(provider.__name__)
236 240
241 for model, providers in cls.model_map.items():
242 for provider, alias in providers.items():
243 if alias != model and isinstance(alias, str) and alias not in cls.model_map:
244 cls.model_aliases[alias] = model
245
237 246 @classmethod
238 247 def get_grouped_models(cls, ignored: list[str] = []) -> dict[str, list[str]]:
239 248 unsorted_models = cls.get_models(ignored=ignored)
@@ -299,7 +308,7 @@ class AnyModelProviderMixin(ProviderModelMixin):
299 308 groups["image"].append(model)
300 309 added = True
301 310 # Check for OpenAI models
302 elif model.startswith(("gpt-", "chatgpt-", "o1", "o1-", "o3-", "o4-")) or model in ("auto", "searchgpt"):
311 elif model.startswith(("gpt-", "chatgpt-", "o1", "o1", "o3", "o4")) or model in ("auto", "searchgpt"):
303 312 groups["openai"].append(model)
304 313 added = True
305 314 # Check for video models
@@ -371,10 +380,14 @@ class AnyProvider(AsyncGeneratorProvider, AnyModelProviderMixin):
371 380 providers.append(provider)
372 381 model = submodel
373 382 else:
383 if model not in cls.model_map:
384 if model in cls.model_aliases:
385 model = cls.model_aliases[model]
374 386 if model in cls.model_map:
375 387 for provider, alias in cls.model_map[model].items():
376 388 provider = Provider.__map__[provider]
377 provider.model_aliases[model] = alias
389 if model not in provider.model_aliases:
390 provider.model_aliases[model] = alias
378 391 providers.append(provider)
379 392 if not providers:
380 393 for provider in PROVIERS_LIST_1:
@@ -390,7 +403,7 @@ class AnyProvider(AsyncGeneratorProvider, AnyModelProviderMixin):
390 403
391 404 debug.log(f"AnyProvider: Using providers: {[provider.__name__ for provider in providers]} for model '{model}'")
392 405
393 async for chunk in IterListProvider(providers).create_async_generator(
406 async for chunk in RotatedProvider(providers).create_async_generator(
394 407 model,
395 408 messages,
396 409 stream=stream,
Modified g4f/providers/base_provider.py +9 -2
@@ -1,7 +1,7 @@
1 1 from __future__ import annotations
2 2
3 3 import asyncio
4
4 import random
5 5 from asyncio import AbstractEventLoop
6 6 from concurrent.futures import ThreadPoolExecutor
7 7 from abc import abstractmethod
@@ -21,6 +21,7 @@ from .response import BaseConversation, AuthResult
21 21 from .helper import concat_chunks
22 22 from ..cookies import get_cookies_dir
23 23 from ..errors import ModelNotFoundError, ResponseError, MissingAuthError, NoValidHarFileError, PaymentRequiredError, CloudflareError
24 from .. import debug
24 25
25 26 SAFE_PARAMETERS = [
26 27 "model", "messages", "stream", "timeout",
@@ -368,7 +369,13 @@ class ProviderModelMixin:
368 369 if not model and cls.default_model is not None:
369 370 model = cls.default_model
370 371 if model in cls.model_aliases:
371 model = cls.model_aliases[model]
372 alias = cls.model_aliases[model]
373 if isinstance(alias, list):
374 selected_model = random.choice(alias)
375 debug.log(f"{cls.__name__}: Selected model '{selected_model}' from alias '{model}'")
376 return selected_model
377 debug.log(f"{cls.__name__}: Using model '{alias}' for alias '{model}'")
378 return alias
372 379 if model not in cls.model_aliases.values():
373 380 if model not in cls.get_models(**kwargs) and cls.models:
374 381 raise ModelNotFoundError(f"Model not found: {model} in: {cls.__name__} Valid models: {cls.models}")
Modified g4f/providers/retry_provider.py +164 -1