feat: support fish audio TTS (#7982)

This commit is contained in:
Leng Yue
2024-09-04 23:18:39 -07:00
committed by GitHub
parent 3e7597f2bd
commit bd0992275c
12 changed files with 433 additions and 0 deletions

View File

@@ -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()

View File

@@ -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",
}
)

View File

@@ -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""