mirror of
http://112.124.100.131/huang.ze/ebiz-dify-ai.git
synced 2025-12-10 03:16:51 +08:00
feat: support fish audio TTS (#7982)
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import os
|
||||
from collections.abc import Callable
|
||||
from typing import Literal
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
from _pytest.monkeypatch import MonkeyPatch
|
||||
|
||||
|
||||
def mock_get(*args, **kwargs):
|
||||
if kwargs.get("headers", {}).get("Authorization") != "Bearer test":
|
||||
raise httpx.HTTPStatusError(
|
||||
"Invalid API key",
|
||||
request=httpx.Request("GET", ""),
|
||||
response=httpx.Response(401),
|
||||
)
|
||||
|
||||
return httpx.Response(
|
||||
200,
|
||||
json={
|
||||
"items": [
|
||||
{"title": "Model 1", "_id": "model1"},
|
||||
{"title": "Model 2", "_id": "model2"},
|
||||
]
|
||||
},
|
||||
request=httpx.Request("GET", ""),
|
||||
)
|
||||
|
||||
|
||||
def mock_stream(*args, **kwargs):
|
||||
class MockStreamResponse:
|
||||
def __init__(self):
|
||||
self.status_code = 200
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
pass
|
||||
|
||||
def iter_bytes(self):
|
||||
yield b"Mocked audio data"
|
||||
|
||||
return MockStreamResponse()
|
||||
|
||||
|
||||
def mock_fishaudio(
|
||||
monkeypatch: MonkeyPatch,
|
||||
methods: list[Literal["list-models", "tts"]],
|
||||
) -> Callable[[], None]:
|
||||
"""
|
||||
mock fishaudio module
|
||||
|
||||
:param monkeypatch: pytest monkeypatch fixture
|
||||
:return: unpatch function
|
||||
"""
|
||||
|
||||
def unpatch() -> None:
|
||||
monkeypatch.undo()
|
||||
|
||||
if "list-models" in methods:
|
||||
monkeypatch.setattr(httpx, "get", mock_get)
|
||||
|
||||
if "tts" in methods:
|
||||
monkeypatch.setattr(httpx, "stream", mock_stream)
|
||||
|
||||
return unpatch
|
||||
|
||||
|
||||
MOCK = os.getenv("MOCK_SWITCH", "false").lower() == "true"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def setup_fishaudio_mock(request, monkeypatch):
|
||||
methods = request.param if hasattr(request, "param") else []
|
||||
if MOCK:
|
||||
unpatch = mock_fishaudio(monkeypatch, methods=methods)
|
||||
|
||||
yield
|
||||
|
||||
if MOCK:
|
||||
unpatch()
|
||||
@@ -0,0 +1,33 @@
|
||||
import os
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
|
||||
from core.model_runtime.errors.validate import CredentialsValidateFailedError
|
||||
from core.model_runtime.model_providers.fishaudio.fishaudio import FishAudioProvider
|
||||
from tests.integration_tests.model_runtime.__mock.fishaudio import setup_fishaudio_mock
|
||||
|
||||
|
||||
@pytest.mark.parametrize("setup_fishaudio_mock", [["list-models"]], indirect=True)
|
||||
def test_validate_provider_credentials(setup_fishaudio_mock):
|
||||
print("-----", httpx.get)
|
||||
provider = FishAudioProvider()
|
||||
|
||||
with pytest.raises(CredentialsValidateFailedError):
|
||||
provider.validate_provider_credentials(
|
||||
credentials={
|
||||
"api_key": "bad_api_key",
|
||||
"api_base": os.environ.get("FISH_AUDIO_API_BASE", "https://api.fish.audio"),
|
||||
"use_public_models": "false",
|
||||
"latency": "normal",
|
||||
}
|
||||
)
|
||||
|
||||
provider.validate_provider_credentials(
|
||||
credentials={
|
||||
"api_key": os.environ.get("FISH_AUDIO_API_KEY", "test"),
|
||||
"api_base": os.environ.get("FISH_AUDIO_API_BASE", "https://api.fish.audio"),
|
||||
"use_public_models": "false",
|
||||
"latency": "normal",
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,32 @@
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
from core.model_runtime.model_providers.fishaudio.tts.tts import (
|
||||
FishAudioText2SpeechModel,
|
||||
)
|
||||
from tests.integration_tests.model_runtime.__mock.fishaudio import setup_fishaudio_mock
|
||||
|
||||
|
||||
@pytest.mark.parametrize("setup_fishaudio_mock", [["tts"]], indirect=True)
|
||||
def test_invoke_model(setup_fishaudio_mock):
|
||||
model = FishAudioText2SpeechModel()
|
||||
|
||||
result = model.invoke(
|
||||
model="tts-default",
|
||||
tenant_id="test",
|
||||
credentials={
|
||||
"api_key": os.environ.get("FISH_AUDIO_API_KEY", "test"),
|
||||
"api_base": os.environ.get("FISH_AUDIO_API_BASE", "https://api.fish.audio"),
|
||||
"use_public_models": "false",
|
||||
"latency": "normal",
|
||||
},
|
||||
content_text="Hello, world!",
|
||||
voice="03397b4c4be74759b72533b663fbd001",
|
||||
)
|
||||
|
||||
content = b""
|
||||
for chunk in result:
|
||||
content += chunk
|
||||
|
||||
assert content != b""
|
||||
Reference in New Issue
Block a user