diff --git a/.gitignore b/.gitignore index 7e9271c..ef4a6e3 100644 --- a/.gitignore +++ b/.gitignore @@ -23,9 +23,10 @@ test_web.py .eggs/ .conda/ + main.py .python-version pyproject.toml uv.lock -.ruff_cache/ \ No newline at end of file +.ruff_cache/ diff --git a/README.md b/README.md index 77bce7f..edf4020 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,8 @@ To learn more about all available JigsawStack AI services, view the [Documentati | ----------------- | -------------------------------------------------- | | **👉 General** | Translation, Summarization, Sentiment Analysis | | **🌐 Web** | AI Web Scraping, AI Web Search | -| **🎵 Audio** | Text to Speech, Speech to Text | +| **🎵 Audio** | Speech to Text | | **👀 Vision** | vOCR, Object Detection | -| **🧠 LLMs** | Prompt Engine | | **🖼️ Generative** | AI Image (Flux, SD, SDXL-Fast & more), HTML to Any | | **✅ Validation** | Email, NSFW images, profanity & more | @@ -58,13 +57,6 @@ params = { result = jigsaw.web.ai_scrape(params) ``` -Text To Speech Example: - -```py -params = {"text": "Hello, how are you doing?"} -result = jigsaw.audio.text_to_speech(params) -``` - Speech To Text Example: ```py diff --git a/jigsawstack/__init__.py b/jigsawstack/__init__.py index 8dafca5..e6a2f5f 100644 --- a/jigsawstack/__init__.py +++ b/jigsawstack/__init__.py @@ -11,7 +11,6 @@ from .sentiment import Sentiment, AsyncSentiment from .validate import Validate, AsyncValidate from .summary import Summary, AsyncSummary -from .prompt_engine import PromptEngine, AsyncPromptEngine from .embedding import Embedding, AsyncEmbedding from .exceptions import JigsawStackError from .image_generation import ImageGeneration, AsyncImageGeneration @@ -25,7 +24,6 @@ class JigsawStack: file: Store web: Web search: Search - prompt_engine: PromptEngine classification: Classification api_key: str api_url: str @@ -104,11 +102,6 @@ def __init__( disable_request_logging=disable_request_logging, ) - self.prompt_engine = PromptEngine( - api_key=api_key, - api_url=api_url, - disable_request_logging=disable_request_logging, - ) self.embedding = Embedding( api_key=api_key, api_url=api_url, @@ -135,7 +128,6 @@ class AsyncJigsawStack: vision: AsyncVision image_generation: AsyncImageGeneration store: AsyncStore - prompt_engine: AsyncPromptEngine api_key: str api_url: str disable_request_logging: bool @@ -220,11 +212,7 @@ def __init__( disable_request_logging=disable_request_logging, ) - self.prompt_engine = AsyncPromptEngine( - api_key=api_key, - api_url=api_url, - disable_request_logging=disable_request_logging, - ) + self.embedding = AsyncEmbedding( api_key=api_key, api_url=api_url, diff --git a/jigsawstack/audio.py b/jigsawstack/audio.py index 8489ce8..e3bcab7 100644 --- a/jigsawstack/audio.py +++ b/jigsawstack/audio.py @@ -9,30 +9,6 @@ from .helpers import build_path -class TextToSpeechParams(TypedDict): - text: str - accent: NotRequired[SupportedAccents] - speaker_clone_url: NotRequired[str] - speaker_clone_file_store_key: NotRequired[str] - return_type: NotRequired[Literal["url", "binary", "base64"]] - - -class TTSCloneParams(TypedDict): - url: NotRequired[str] - file_store_key: NotRequired[str] - name: str - - -class ListTTSVoiceClonesParams(TypedDict): - limit: NotRequired[int] - page: NotRequired[int] - - -class TextToSpeechResponse(TypedDict): - success: bool - text: str - chunks: List[object] - class SpeechToTextParams(TypedDict): url: NotRequired[str] @@ -115,51 +91,6 @@ def speech_to_text( ).perform_with_content() return resp - def text_to_speech(self, params: TextToSpeechParams) -> TextToSpeechResponse: - path = "/ai/tts" - resp = Request( - config=self.config, - path=path, - params=cast(Dict[Any, Any], params), - verb="post", - ).perform_with_content() - return resp - - def speaker_voice_accents(self) -> TextToSpeechResponse: - path = "/ai/tts" - resp = Request( - config=self.config, path=path, params={}, verb="get" - ).perform_with_content() - return resp - - def create_clone(self, params: TTSCloneParams) -> TextToSpeechResponse: - path = "/ai/tts/clone" - resp = Request( - config=self.config, - path=path, - params=cast(Dict[Any, Any], params), - verb="post", - ).perform_with_content() - - return resp - - def list_clones(self, params: ListTTSVoiceClonesParams) -> TextToSpeechResponse: - path = "/ai/tts/clone" - resp = Request( - config=self.config, - path=path, - params=cast(Dict[Any, Any], params), - verb="get", - ).perform_with_content() - return resp - - def delete_clone(self, voice_id: str) -> TextToSpeechResponse: - path = f"/ai/tts/clone/{voice_id}" - resp = Request( - config=self.config, path=path, params={}, verb="delete" - ).perform_with_content() - return resp - class AsyncAudio(ClientConfig): config: AsyncRequestConfig @@ -215,51 +146,3 @@ async def speech_to_text( ).perform_with_content() return resp - async def text_to_speech(self, params: TextToSpeechParams) -> TextToSpeechResponse: - path = "/ai/tts" - resp = await AsyncRequest( - config=self.config, - path=path, - params=cast(Dict[Any, Any], params), - verb="post", - ).perform_with_content() - return resp - - async def speaker_voice_accents(self) -> TextToSpeechResponse: - path = "/ai/tts" - resp = await AsyncRequest( - config=self.config, - path=path, - params={}, - verb="get", - ).perform_with_content() - return resp - - async def create_clone(self, params: TTSCloneParams) -> TextToSpeechResponse: - path = "/ai/tts/clone" - resp = await AsyncRequest( - config=self.config, - path=path, - params=cast(Dict[Any, Any], params), - verb="post", - ).perform_with_content() - return resp - - async def list_clones( - self, params: ListTTSVoiceClonesParams - ) -> TextToSpeechResponse: - path = "/ai/tts/clone" - resp = await AsyncRequest( - config=self.config, - path=path, - params=cast(Dict[Any, Any], params), - verb="get", - ).perform_with_content() - return resp - - async def delete_clone(self, voice_id: str) -> TextToSpeechResponse: - path = f"/ai/tts/clone/{voice_id}" - resp = await AsyncRequest( - config=self.config, path=path, params={}, verb="delete" - ).perform_with_content() - return resp diff --git a/jigsawstack/prompt_engine.py b/jigsawstack/prompt_engine.py deleted file mode 100644 index 05a570a..0000000 --- a/jigsawstack/prompt_engine.py +++ /dev/null @@ -1,319 +0,0 @@ -from typing import Any, Dict, List, Union, cast, Generator, Literal -from typing_extensions import NotRequired, TypedDict -from .request import Request, RequestConfig -from .async_request import AsyncRequest -from typing import List, Union -from ._config import ClientConfig -from .helpers import build_path - - -class PromptEngineResult(TypedDict): - prompt: str - return_prompt: str - id: str - - -class PromptEngineRunParams(TypedDict): - prompt: str - inputs: NotRequired[List[object]] - return_prompt: Union[str, List[object], Dict[str, str]] - input_values: NotRequired[Dict[str, str]] - stream: Union[bool, None] = False - use_internet: Union[bool, None] = False - prompt_guard: NotRequired[ - Literal[ - "defamation", - "specialized_advice", - "privacy", - "intellectual_property", - "indiscriminate_weapons", - "hate", - "sexual_content", - "elections", - "code_interpreter_abuse", - ] - ] - - -class PromptEngineExecuteParams(TypedDict): - id: str - input_values: object - stream: Union[bool, None] = False - - -class PromptEngineRunResponse(TypedDict): - success: bool - result: Any - - -class PromptEngineCreateParams(TypedDict): - prompt: str - inputs: NotRequired[List[object]] - return_prompt: Union[str, List[object], Dict[str, str]] - use_internet: Union[bool, None] = False - optimize_prompt: Union[bool, None] = False - prompt_guard: NotRequired[ - Literal[ - "defamation", - "specialized_advice", - "privacy", - "intellectual_property", - "indiscriminate_weapons", - "hate", - "sexual_content", - "elections", - "code_interpreter_abuse", - ] - ] - - -class PromptEngineCreateResponse(TypedDict): - success: bool - prompt_engine_id: str - - -class PromptEngineGetResponse(PromptEngineResult): - success: bool - - -class PromptEngineListResponse(TypedDict): - success: bool - prompt_engines: List[PromptEngineResult] - - -class PromptEngineListParams(TypedDict): - limit: str - page: str - - -class PromptEngineDeleteResponse(TypedDict): - prompt_engine_id: str - - -class PromptEngine(ClientConfig): - - config: RequestConfig - - def __init__( - self, - api_key: str, - api_url: str, - disable_request_logging: Union[bool, None] = False, - ): - super().__init__(api_key, api_url, disable_request_logging) - self.config = RequestConfig( - api_url=api_url, - api_key=api_key, - disable_request_logging=disable_request_logging, - ) - - def create(self, params: PromptEngineCreateParams) -> PromptEngineCreateResponse: - path = "/prompt_engine" - resp = Request( - config=self.config, - path=path, - params=cast(Dict[Any, Any], params), - verb="post", - ).perform_with_content() - return resp - - def get(self, id: str) -> PromptEngineGetResponse: - path = f"/prompt_engine/{id}" - resp = Request( - config=self.config, path=path, params={}, verb="get" - ).perform_with_content() - return resp - - def list( - self, params: Union[PromptEngineListParams, None] = None - ) -> PromptEngineListResponse: - - if params is None: - params = {} - - # Default limit and page to 20 and 1 respectively - if params.get("limit") is None: - params["limit"] = 20 - - if params.get("page") is None: - params["page"] = 0 - - path = build_path( - base_path="/prompt_engine", - params=params, - ) - resp = Request( - config=self.config, path=path, params={}, verb="get" - ).perform_with_content() - return resp - - def delete(self, id: str) -> PromptEngineDeleteResponse: - path = f"/prompt_engine/{id}" - resp = Request( - config=self.config, - path=path, - params={}, - verb="DELETE", - ).perform_with_content() - return resp - - def run_prompt_direct( - self, params: PromptEngineRunParams - ) -> Union[PromptEngineRunResponse, Generator[Any, None, None]]: - path = "/prompt_engine/run" - stream = params.get("stream") - if stream: - resp = Request( - config=self.config, - path=path, - params=cast(Dict[Any, Any], params), - verb="post", - ).perform_with_content_streaming() - return resp - - resp = Request( - config=self.config, - path=path, - params=cast(Dict[Any, Any], params), - verb="post", - ).perform_with_content() - return resp - - def run( - self, params: PromptEngineExecuteParams - ) -> Union[PromptEngineRunResponse, Generator[Any, None, None]]: - id = params.get("id") - path = f"/prompt_engine/{id}" - stream = params.get("stream") - - if stream: - resp = Request( - config=self.config, - path=path, - params=cast(Dict[Any, Any], params), - verb="post", - ).perform_with_content_streaming() - return resp - - resp = Request( - config=self.config, - path=path, - params=cast(Dict[Any, Any], params), - verb="post", - ).perform_with_content() - return resp - - -class AsyncPromptEngine(ClientConfig): - - config: RequestConfig - - def __init__( - self, - api_key: str, - api_url: str, - disable_request_logging: Union[bool, None] = False, - ): - super().__init__(api_key, api_url, disable_request_logging) - self.config = RequestConfig( - api_url=api_url, - api_key=api_key, - disable_request_logging=disable_request_logging, - ) - - async def create( - self, params: PromptEngineCreateParams - ) -> PromptEngineCreateResponse: - path = "/prompt_engine" - resp = await AsyncRequest( - config=self.config, - path=path, - params=cast(Dict[Any, Any], params), - verb="post", - ).perform_with_content() - return resp - - async def get(self, id: str) -> PromptEngineGetResponse: - path = f"/prompt_engine/{id}" - resp = await AsyncRequest( - config=self.config, path=path, params={}, verb="get" - ).perform_with_content() - return resp - - async def list( - self, params: Union[PromptEngineListParams, None] = None - ) -> PromptEngineListResponse: - - if params is None: - params = {} - - # Default limit and page to 20 and 1 respectively - if params.get("limit") is None: - params["limit"] = 20 - - if params.get("page") is None: - params["page"] = 0 - - path = build_path( - base_path="/prompt_engine", - params=params, - ) - resp = await AsyncRequest( - config=self.config, path=path, params={}, verb="get" - ).perform_with_content() - return resp - - async def delete(self, id: str) -> PromptEngineDeleteResponse: - path = f"/prompt_engine/{id}" - resp = await AsyncRequest( - config=self.config, - path=path, - params={}, - verb="DELETE", - ).perform_with_content() - return resp - - async def run_prompt_direct( - self, params: PromptEngineRunParams - ) -> Union[PromptEngineRunResponse, Generator[Any, None, None]]: - path = "/prompt_engine/run" - stream = params.get("stream") - if stream: - resp = await AsyncRequest( - config=self.config, - path=path, - params=cast(Dict[Any, Any], params), - verb="post", - ).perform_with_content_streaming() - return resp - resp = await AsyncRequest( - config=self.config, - path=path, - params=cast(Dict[Any, Any], params), - verb="post", - ).perform_with_content() - return resp - - async def run( - self, params: PromptEngineExecuteParams - ) -> Union[PromptEngineRunResponse, Generator[Any, None, None]]: - id = params.get("id") - path = f"/prompt_engine/{id}" - stream = params.get("stream") - - if stream: - resp = await AsyncRequest( - config=self.config, - path=path, - params=cast(Dict[Any, Any], params), - verb="post", - ).perform_with_content_streaming() - return resp - - resp = await AsyncRequest( - config=self.config, - path=path, - params=cast(Dict[Any, Any], params), - verb="post", - ).perform_with_content() - return resp diff --git a/tests/test_audio.py b/tests/test_audio.py deleted file mode 100644 index cb492e5..0000000 --- a/tests/test_audio.py +++ /dev/null @@ -1,112 +0,0 @@ -from unittest.mock import MagicMock -import unittest -from jigsawstack.exceptions import JigsawStackError -from jigsawstack import AsyncJigsawStack -import pytest -import asyncio -import logging -from jigsawstack import AsyncJigsawStack - -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) - - -def test_text_to_speech(): - async def _test(): - client = AsyncJigsawStack() - - """Test converting text to speech""" - try: - response = await client.audio.text_to_speech( - { - "text": "Hello world, this is a test of the JigsawStack text to speech API." - } - ) - print("Text to speech response:", response) - assert response["success"] == True - - except Exception as e: - print(f"Error in text_to_speech test: {e}") - - asyncio.run(_test()) - - -def test_speaker_voice_accents(): - async def _test(): - client = AsyncJigsawStack() - - """Test getting available voice accents""" - try: - response = await client.audio.speaker_voice_accents() - print("Speaker voice accents response:", response) - assert response["success"] == True - - except Exception as e: - print(f"Error in speaker voice accents test: {e}") - - -def test_create_clone(): - async def _test(): - client = AsyncJigsawStack() - - """Test creating a voice clone with URL""" - try: - audio_url = ( - "https://jigsawstack.com/audio/test.mp3" # Replace with an actual URL - ) - clone_response_url = await client.audio.create_clone( - {"url": audio_url, "name": "Test Voice Clone URL"} - ) - - assert clone_response_url["success"] == True - - clone_response_file_store_key = client.audio.create_clone( - { - "file_store_key": "hello_audio", - "name": "Test Voice Clone File Store Key", - } - ) - - assert clone_response_file_store_key["success"] == True - - except Exception as e: - print(f"Error in voice_cloning test: {e}") - - asyncio.run(_test()) - - -def test_list_clones(): - async def _test(): - client = AsyncJigsawStack() - """Test listing voice clones""" - try: - # List available voice clones - clones_response = await client.audio.list_clones({"limit": 10, "page": 1}) - - assert clones_response["success"] == True - - except Exception as e: - print(f"Error in voice_cloning test: {e}") - - asyncio.run(_test()) - - -def test_delete_clone(): - async def _test(): - client = AsyncJigsawStack() - """Test getting a voice clone""" - try: - create_clone_response = await client.audio.create_clone( - {"name": "Test Voice Clone URL", "file_store_key": "hello_audio"} - ) - clones = await client.audio.list_clones({"limit": 10, "page": 1}) - print("Clones:", clones) - clone_id = clones["data"][0]["id"] - delete_clone_response = await client.audio.delete_clone(clone_id) - print("Delete clone response:", delete_clone_response) - assert delete_clone_response["success"] == True - - except Exception as e: - print(f"Error in list_clones test: {e}") - - asyncio.run(_test()) diff --git a/tests/test_prompt_engine.py b/tests/test_prompt_engine.py deleted file mode 100644 index cb3b7a6..0000000 --- a/tests/test_prompt_engine.py +++ /dev/null @@ -1,20 +0,0 @@ -from unittest.mock import MagicMock -import unittest -from jigsawstack.exceptions import JigsawStackError -import jigsawstack -import pytest - -# flake8: noq - -jigsaw = jigsawstack.JigsawStack() - - -@pytest.mark.skip(reason="Skipping TestWebAPI class for now") -class TestPromptEngine(unittest.TestCase): - - def test_get_prompt_engine_response_success(self) -> None: - try: - result = jigsaw.prompt_engine.get("b08921b8-0b30-409e-8257-06fa1620c7e6") - assert result["success"] == True - except JigsawStackError as e: - assert e.message == "Failed to parse API response. Please try again."