返回提交历史
Modified
g4f/Provider/needs_auth/Azure.py
+18
-4
Modified
g4f/Provider/template/OpenaiTemplate.py
+15
-6
Modified
g4f/client/service.py
+1
-1
Modified
g4f/gui/server/api.py
+0
-3
Modified
g4f/image/copy_images.py
+1
-1
Modified
g4f/providers/base_provider.py
+2
-3
Modified
projects/windows/docker-compose.yml
+2
-1
XFEstudio/gpt4free
Support audio model in Azure provider
c4b18df7
代码差异
7 个文件
+39
-19
@@ -4,7 +4,7 @@ import os
4
4
import json
5
5
6
6
from ...typing import Messages, AsyncResult
7
from ...errors import MissingAuthError
7
from ...errors import MissingAuthError, ModelNotFoundError
8
8
from ..template import OpenaiTemplate
9
9
10
10
class Azure(OpenaiTemplate):
@@ -15,9 +15,20 @@ class Azure(OpenaiTemplate):
15
15
active_by_default = True
16
16
login_url = "https://discord.gg/qXA4Wf4Fsm"
17
17
routes: dict[str, str] = {}
18
audio_models = ["gpt-4o-mini-audio-preview"]
19
model_extra_body = {
20
"gpt-4o-mini-audio-preview": {
21
"audio": {
22
"voice": "alloy",
23
"format": "mp3"
24
},
25
"modalities": ["text", "audio"],
26
"stream": False
27
}
28
}
18
29
19
30
@classmethod
20
def get_models(cls, **kwargs) -> list[str]:
31
def get_models(cls, api_key: str = None, **kwargs) -> list[str]:
21
32
routes = os.environ.get("AZURE_ROUTES")
22
33
if routes:
23
34
try:
@@ -27,7 +38,7 @@ class Azure(OpenaiTemplate):
27
38
cls.routes = routes
28
39
if cls.routes:
29
40
return list(cls.routes.keys())
30
return super().get_models(**kwargs)
41
return super().get_models(api_key=api_key, **kwargs)
31
42
32
43
@classmethod
33
44
async def create_async_generator(
@@ -40,6 +51,9 @@ class Azure(OpenaiTemplate):
40
51
) -> AsyncResult:
41
52
if not model:
42
53
model = os.environ.get("AZURE_DEFAULT_MODEL", cls.default_model)
54
if model in cls.model_extra_body:
55
for key, value in cls.model_extra_body[model].items():
56
kwargs.setdefault(key, value)
43
57
if not api_key:
44
58
raise ValueError(f"API key is required for Azure provider. Ask for API key in the {cls.login_url} Discord server.")
45
59
if not api_endpoint:
@@ -47,7 +61,7 @@ class Azure(OpenaiTemplate):
47
61
cls.get_models()
48
62
api_endpoint = cls.routes.get(model)
49
63
if cls.routes and not api_endpoint:
50
raise ValueError(f"No API endpoint found for model: {model}")
64
raise ModelNotFoundError(f"No API endpoint found for model: {model}")
51
65
if not api_endpoint:
52
66
api_endpoint = os.environ.get("AZURE_API_ENDPOINT")
53
67
try:
@@ -7,6 +7,7 @@ from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin, RaiseErr
7
7
from ...typing import Union, AsyncResult, Messages, MediaListType
8
8
from ...requests import StreamSession, raise_for_status
9
9
from ...image import use_aspect_ratio
10
from ...image.copy_images import save_response_media
10
11
from ...providers.response import FinishReason, ToolCalls, Usage, ImageResponse, ProviderInfo
11
12
from ...tools.media import render_messages
12
13
from ...errors import MissingAuthError, ResponseError
@@ -62,7 +63,7 @@ class OpenaiTemplate(AsyncGeneratorProvider, ProviderModelMixin, RaiseErrorMixin
62
63
max_tokens: int = None,
63
64
top_p: float = None,
64
65
stop: Union[str, list[str]] = None,
65
stream: bool = False,
66
stream: bool = None,
66
67
prompt: str = None,
67
68
headers: dict = None,
68
69
impersonate: str = None,
@@ -115,7 +116,7 @@ class OpenaiTemplate(AsyncGeneratorProvider, ProviderModelMixin, RaiseErrorMixin
115
116
max_tokens=max_tokens,
116
117
top_p=top_p,
117
118
stop=stop,
118
stream=stream,
119
stream="audio" not in extra_parameters if stream is None else stream,
119
120
**extra_parameters,
120
121
**extra_body
121
122
)
@@ -136,10 +137,18 @@ class OpenaiTemplate(AsyncGeneratorProvider, ProviderModelMixin, RaiseErrorMixin
136
137
yield Usage(**data["usage"])
137
138
if "choices" in data:
138
139
choice = next(iter(data["choices"]), None)
139
if choice and "content" in choice["message"] and choice["message"]["content"]:
140
yield choice["message"]["content"].strip()
141
if "tool_calls" in choice["message"]:
142
yield ToolCalls(choice["message"]["tool_calls"])
140
message = choice.get("message", {})
141
if choice and "content" in message and message["content"]:
142
yield message["content"].strip()
143
if "tool_calls" in message:
144
yield ToolCalls(message["tool_calls"])
145
audio = message.get("audio", {})
146
if "data" in audio:
147
async for chunk in save_response_media(audio["data"], prompt, [model, extra_body.get("audio", {}).get("voice")]):
148
yield chunk
149
if "transcript" in audio:
150
yield "\n\n"
151
yield audio["transcript"]
143
152
if choice and "finish_reason" in choice and choice["finish_reason"] is not None:
144
153
yield FinishReason(choice["finish_reason"])
145
154
return
@@ -23,7 +23,7 @@ def convert_to_provider(provider: str) -> ProviderType:
23
23
24
24
def get_model_and_provider(model : Union[Model, str],
25
25
provider : Union[ProviderType, str, None],
26
stream : bool,
26
stream : bool = False,
27
27
ignore_working: bool = False,
28
28
ignore_stream: bool = False,
29
29
logging: bool = True,
@@ -149,7 +149,6 @@ class Api:
149
149
"model": model,
150
150
"provider": provider,
151
151
"messages": messages,
152
"stream": True,
153
152
"ignore_stream": True,
154
153
**kwargs
155
154
}
@@ -166,8 +165,6 @@ class Api:
166
165
try:
167
166
model, provider_handler = get_model_and_provider(
168
167
kwargs.get("model"), provider,
169
stream=True,
170
ignore_stream=True,
171
168
has_images="media" in kwargs,
172
169
)
173
170
if "user" in kwargs:
@@ -112,7 +112,7 @@ def get_filename(tags: list[str], alt: str, extension: str, image: str) -> str:
112
112
return "".join((
113
113
f"{int(time.time())}_",
114
114
f"{secure_filename(tags + alt)}_" if alt else secure_filename(tags),
115
hashlib.sha256(image.encode()).hexdigest()[:16],
115
hashlib.sha256(str(time.time()).encode() if image is None else image.encode()).hexdigest()[:16],
116
116
extension
117
117
))
118
118
@@ -292,7 +292,7 @@ class AsyncGeneratorProvider(AbstractProvider):
292
292
cls,
293
293
model: str,
294
294
messages: Messages,
295
stream: bool = True,
295
stream: bool = None,
296
296
timeout: int = None,
297
297
**kwargs
298
298
) -> CreateResult:
@@ -312,7 +312,7 @@ class AsyncGeneratorProvider(AbstractProvider):
312
312
"""
313
313
return to_sync_generator(
314
314
cls.create_async_generator(model, messages, stream=stream, **kwargs),
315
stream=stream,
315
stream=stream is not False,
316
316
timeout=timeout
317
317
)
318
318
@@ -321,7 +321,6 @@ class AsyncGeneratorProvider(AbstractProvider):
321
321
async def create_async_generator(
322
322
model: str,
323
323
messages: Messages,
324
stream: bool = True,
325
324
**kwargs
326
325
) -> AsyncResult:
327
326
"""
@@ -16,4 +16,5 @@ services:
16
16
stop_grace_period: 2m
17
17
restart: on-failure
18
18
volumes:
19
- /var/win:/storage
19
- /var/win:/storage
20
- ./:/data