diff --git a/CHANGELOG.md b/CHANGELOG.md index b9fb7ce..6db1147 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,12 @@ All notable changes to `slashml-python-client` aka `slashml` will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/). -## 0.0.4 - 2023-05-08 +## 0.0.6 - 2023-05-11 + +### Changed +- Combined submit_job and status check into a single function call. + +## 0.0.5 - 2023-05-08 ### Added - SpeechToText service diff --git a/README.md b/README.md index 49b2146..bef32fa 100644 --- a/README.md +++ b/README.md @@ -16,28 +16,17 @@ pip install slashml ```python from slashml import TextToSpeech -import time -# Initialize model -model = TextToSpeech() - -service_provider = TextToSpeech.ServiceProvider.GOOGLE - -# Submit speechification request -job = model.speechify(text="To be or not to be, that is the question!", service_provider=service_provider) - -assert job.status != "ERROR", f"{job}" -print(f"Job ID: {job.id}") +# Replace `API_KEY` with your SlasML API token. This example still runs without +# the API token but usage will be limited +model = TextToSpeech(api_key=None) -# check job status -response = model.status(job.id, service_provider=service_provider) +input_text = "to be or not to be, that is the question!" -while response.status == "IN_PROGRESS": - time.sleep(5) - response = model.status(job.id, service_provider=service_provider) - print(f"Response = {response}. Retrying in 5 seconds") +# Submit request +job = model.execute(text=input_text, service_provider=TextToSpeech.ServiceProvider.AWS) -print(response) +print (f"\n\n\n You can access the audio file here: {job.audio_url}") ``` #### Transcribe an audio file @@ -45,27 +34,18 @@ print(response) ```python from slashml import SpeechToText -import time - -# Initialize model -model = SpeechToText() - -service_provider = SpeechToText.ServiceProvider.WHISPER -# Submit transcription request -job = model.transcribe(upload_url="https://slashml.s3.ca-central-1.amazonaws.com/c7d38026-3ab4-4a04-ad9e-b6679ab79a87", service_provider=service_provider) -assert job.status != "ERROR", f"{job}" -print(f"Job ID: {job.id}") +# Replace `API_KEY` with your SlasML API token. This example still runs without +# the API token but usage will be limited +model = SpeechToText(api_key=None) -# check job status -response = model.status(job.id, service_provider=service_provider) +response = model.execute( + upload_url='https://slashml.s3.ca-central-1.amazonaws.com/695c711f-9f5d-4ff1-ae4f-4439842eef5f', + service_provider=SpeechToText.ServiceProvider.WHISPER +) -while response.status == "IN_PROGRESS": - time.sleep(5) - response = model.status(job.id, service_provider=service_provider) - print(f"Response = {response}. Retrying in 5 seconds") +print(f"\n\n\n\nTranscription = {response.transcription_data.transcription}") -print(response) ``` #### Summarize a text input @@ -73,35 +53,19 @@ print(response) ```python from slashml import TextSummarization -import time -# Initialize model -model = TextSummarization() - -service_provider = TextSummarization.ServiceProvider.OPENAI - -# Submit summariztion request -job = model.summarize(text="There are of course kinds of thinking that can be done without writing. If you don't need to go too deeply into a problem, you can solve it without writing. If you're thinking about how two pieces of machinery should fit together, writing about it probably won't help much. And when a problem can be described formally, you can sometimes solve it in your head. But if you need to solve a complicated, ill-defined problem, it will almost always help to write about it. Which in turn means that someone who's not good at writing will almost always be at a disadvantage in solving such problems.", service_provider=service_provider) +model = TextSummarization(api_key=None) -assert job.status != "ERROR", f"{job}" -print(f"Job ID: {job.id}") +input_text = """A good writer doesn't just think, and then write down what he thought, as a sort of transcript. A good writer will almost always discover new things in the process of writing. And there is, as far as I know, no substitute for this kind of discovery. Talking about your ideas with other people is a good way to develop them. But even after doing this, you'll find you still discover new things when you sit down to write. There is a kind of thinking that can only be done by writing.""" -# check job status -response = model.status(job.id, service_provider=service_provider) +response = model.execute(text=input_text, service_provider=TextSummarization.ServiceProvider.OPENAI) -while response.status == "IN_PROGRESS": - time.sleep(5) - response = model.status(job.id, service_provider=service_provider) - print(f"Response = {response}. Retrying in 5 seconds") +print(f"Summary = {response.summarization_data}") -print(response) ``` - - ### View the list of service providers available - ```python from slashml import TextToSpeech diff --git a/examples/pipeline_podcast_summary.py b/examples/pipeline_podcast_summary.py new file mode 100644 index 0000000..bc8eb59 --- /dev/null +++ b/examples/pipeline_podcast_summary.py @@ -0,0 +1,37 @@ +from slashml import SpeechToText, TextSummarization, TextToSpeech + +# Replace `API_KEY` with your SlasML API token. This example still runs without +# the API token but usage will be limited +API_KEY = "a7011983a0f3d64ee113317b1e36f8e5bf56c14a" + +service_provider_speech_to_text = SpeechToText.ServiceProvider.WHISPER +service_provider_summarize = TextSummarization.ServiceProvider.OPENAI +service_provider_text_to_speech = TextToSpeech.ServiceProvider.GOOGLE + +# 10 minute audio file already uploaded +uploaded_url = ( + "https://slashml.s3.ca-central-1.amazonaws.com/fda70f6a-6057-4541-adf1-2cf4f4182929" +) + +transcribe = SpeechToText(api_key=API_KEY) +summarize = TextSummarization(api_key=API_KEY) +speechify = TextToSpeech(api_key=API_KEY) + + +response = transcribe.execute( + upload_url=uploaded_url, service_provider=service_provider_speech_to_text +) + +print('starting pipeline, the first response might take 10 secs') +transcribed_text = response.transcription_data.transcription +print (f"Transcribed Text = {transcribed_text}") + +response_summarize = summarize.execute(transcribed_text, service_provider_summarize) + +summary = response_summarize.summarization_data + +print (f"Summarized Text = {summary}") + +response = speechify.execute(summary, service_provider_text_to_speech) + +print (f"\n\n\n You can access the audio file here: {response.audio_url}") \ No newline at end of file diff --git a/examples/speech_to_text.py b/examples/speech_to_text_async.py similarity index 95% rename from examples/speech_to_text.py rename to examples/speech_to_text_async.py index a3d5d95..7a3a90f 100644 --- a/examples/speech_to_text.py +++ b/examples/speech_to_text_async.py @@ -1,6 +1,7 @@ from slashml import SpeechToText import time +# update the examples using execute from the SpeechToText class def speech_to_text(audio_filepath, service_provider, api_key): # Initialize model diff --git a/examples/speech_to_text_sync.py b/examples/speech_to_text_sync.py new file mode 100644 index 0000000..39e5955 --- /dev/null +++ b/examples/speech_to_text_sync.py @@ -0,0 +1,24 @@ +from slashml import SpeechToText + +# Replace `API_KEY` with your SlasML API token. This example still runs without +# the API token but usage will be limited +API_KEY = None +service_provider = SpeechToText.ServiceProvider.AWS +audio_filepath = "test.mp3" + +# Find all the service providers that we support by running the choices() method +print(f"Available providers: {SpeechToText.ServiceProvider.choices()}") +print(f"Selected provider: {service_provider}") + + +model = SpeechToText(api_key=API_KEY) + +# Upload audio +uploaded_file = model.upload_audio(audio_filepath) +print(f"file uploaded: {uploaded_file}") + +response = model.execute( + upload_url=uploaded_file["upload_url"], service_provider=service_provider +) + +print(f"\n\n\n\nTranscription = {response.transcription_data.transcription}") diff --git a/examples/summarize.py b/examples/summarize_async.py similarity index 100% rename from examples/summarize.py rename to examples/summarize_async.py diff --git a/examples/summarize_sync.py b/examples/summarize_sync.py new file mode 100644 index 0000000..17f95c8 --- /dev/null +++ b/examples/summarize_sync.py @@ -0,0 +1,19 @@ +from slashml import TextSummarization + + +# Replace `API_KEY` with your SlasML API token. This example still runs without +# the API token but usage will be limited +API_KEY = "a7011983a0f3d64ee113317b1e36f8e5bf56c14a" +service_provider = TextSummarization.ServiceProvider.OPENAI + +input_text = """A good writer doesn't just think, and then write down what he thought, as a sort of transcript. A good writer will almost always discover new things in the process of writing. And there is, as far as I know, no substitute for this kind of discovery. Talking about your ideas with other people is a good way to develop them. But even after doing this, you'll find you still discover new things when you sit down to write. There is a kind of thinking that can only be done by writing.""" + +model = TextSummarization(api_key=API_KEY) + +# Find all the service providers that we support by running the choices() method +print(f"Available providers: {TextSummarization.ServiceProvider.choices()}") +print(f"Selected provider: {service_provider}") + +response = model.execute(text=input_text, service_provider=service_provider) + +print(f"Summary = {response.summarization_data}") diff --git a/examples/text_to_speech.py b/examples/text_to_speech_async copy.py similarity index 100% rename from examples/text_to_speech.py rename to examples/text_to_speech_async copy.py diff --git a/examples/text_to_speech_sync.py b/examples/text_to_speech_sync.py new file mode 100644 index 0000000..b96e7d7 --- /dev/null +++ b/examples/text_to_speech_sync.py @@ -0,0 +1,18 @@ +from slashml import TextToSpeech + +# Replace `API_KEY` with your SlasML API token. This example still runs without +# the API token but usage will be limited +API_KEY = None +service_provider = TextToSpeech.ServiceProvider.AWS +input_text = "To be or not to be, that is the question!" + +# Find all the service providers that we support by running the choices() method +print(f"Available providers: {TextToSpeech.ServiceProvider.choices()}") +print(f"Selected provider: {service_provider}") + +model = TextToSpeech(api_key=API_KEY) + +# Submit request +job = model.execute(text=input_text, service_provider=service_provider) + +print (f"\n\n\n You can access the audio file here: {job.audio_url}") diff --git a/setup.py b/setup.py index 135a32a..b6a2182 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ def read_req_file(req_type): setup( name="slashml", - version="0.0.5", + version="0.0.6", url="https://slashml.com/", author="eff-kay", author_email="faiizan14@gmail.com", diff --git a/slashml/speech_to_text.py b/slashml/speech_to_text.py index 7359797..cf7ae9b 100644 --- a/slashml/speech_to_text.py +++ b/slashml/speech_to_text.py @@ -1,4 +1,5 @@ import requests +import time from enum import Enum from .utils import generateURL, baseUrl, generateHeaders, formatResponse, getTaskStatus @@ -25,7 +26,7 @@ def upload_audio(self, file_location: str): response = requests.post(url, headers=self._headers, files=files) return formatResponse(response) - def transcribe(self, upload_url: str, service_provider: ServiceProvider): + def submit_job(self, upload_url: str, service_provider: ServiceProvider): url = generateURL(self._base_url, "jobs") payload = { "uploaded_audio_url": upload_url, @@ -36,3 +37,28 @@ def transcribe(self, upload_url: str, service_provider: ServiceProvider): def status(self, job_id: str, service_provider: ServiceProvider): return getTaskStatus(self._base_url, self._headers, job_id, service_provider) + + def execute(self, upload_url: str, service_provider: ServiceProvider): + url = generateURL(self._base_url, "jobs") + + payload = { + "uploaded_audio_url": upload_url, + "service_provider": service_provider.value, + } + + response = requests.post(url, headers=self._headers, data=payload) + job = formatResponse(response) + + assert job.status != "ERROR", f"{job}" + print(f"Got Job ID: {job.id}") + + # check job status + response = getTaskStatus(self._base_url, self._headers, job.id, service_provider) + + while response.status == "IN_PROGRESS": + time.sleep(5) + response = getTaskStatus(self._base_url, self._headers, job.id, service_provider) + print(f"Response = {response}. Retrying in 5 seconds") + + return response + diff --git a/slashml/text_summarization.py b/slashml/text_summarization.py index 80914c5..929b493 100644 --- a/slashml/text_summarization.py +++ b/slashml/text_summarization.py @@ -1,4 +1,5 @@ import requests +import time from enum import Enum from .utils import generateURL, baseUrl, generateHeaders, formatResponse, getTaskStatus @@ -17,7 +18,7 @@ def choices(cls): def __init__(self, api_key: str = None): self._headers = generateHeaders(api_key) - def summarize(self, text: str, service_provider: ServiceProvider): + def submit_job(self, text: str, service_provider: ServiceProvider): url = generateURL(self._base_url, "jobs") payload = {"text": [text], "service_provider": service_provider.value} response = requests.post(url, headers=self._headers, data=payload) @@ -25,3 +26,23 @@ def summarize(self, text: str, service_provider: ServiceProvider): def status(self, job_id: str, service_provider: ServiceProvider): return getTaskStatus(self._base_url, self._headers, job_id, service_provider) + + def execute(self, text: str, service_provider: ServiceProvider): + url = generateURL(self._base_url, "jobs") + payload = {"text": [text], "service_provider": service_provider.value} + response = requests.post(url, headers=self._headers, data=payload) + job = formatResponse(response) + + assert job.status != "ERROR", f"{job}" + print(f"Got Job ID: {job.id}") + + # check job status + response = getTaskStatus(self._base_url, self._headers, job.id, service_provider) + + while response.status == "IN_PROGRESS": + time.sleep(5) + response = getTaskStatus(self._base_url, self._headers, job.id, service_provider) + print(f"Response = {response}. Retrying in 5 seconds") + + return response + diff --git a/slashml/text_to_speech.py b/slashml/text_to_speech.py index d2b884e..cb8f38f 100644 --- a/slashml/text_to_speech.py +++ b/slashml/text_to_speech.py @@ -1,4 +1,6 @@ import requests +import time + from enum import Enum from .utils import generateURL, baseUrl, generateHeaders, formatResponse, getTaskStatus @@ -18,7 +20,7 @@ def choices(cls): def __init__(self, api_key: str = None): self._headers = generateHeaders(api_key) - def speechify(self, text: str, service_provider: ServiceProvider): + def submit_job(self, text: str, service_provider: ServiceProvider): url = generateURL(self._base_url, "jobs") payload = {"text": text, "service_provider": service_provider.value} response = requests.post(url, headers=self._headers, data=payload) @@ -26,3 +28,22 @@ def speechify(self, text: str, service_provider: ServiceProvider): def status(self, job_id: str, service_provider: ServiceProvider): return getTaskStatus(self._base_url, self._headers, job_id, service_provider) + + def execute(self, text: str, service_provider: ServiceProvider): + url = generateURL(self._base_url, "jobs") + payload = {"text": text, "service_provider": service_provider.value} + response = requests.post(url, headers=self._headers, data=payload) + job = formatResponse(response) + + assert job.status != "ERROR", f"{job}" + print(f"Got Job ID: {job.id}") + + # check job status + response = getTaskStatus(self._base_url, self._headers, job.id, service_provider) + + while response.status == "IN_PROGRESS": + time.sleep(5) + response = getTaskStatus(self._base_url, self._headers, job.id, service_provider) + print(f"Response = {response}. Retrying in 5 seconds") + + return response