Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.9.x to main #109

Merged
merged 26 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
d4bc394
add remaining calls function
dishantsethi Jul 23, 2024
5a7d45e
add tests
dishantsethi Jul 23, 2024
70662ee
Merge pull request #99 from dishantsethi/remaining-calls
dishantsethi Jul 23, 2024
9b3d298
Add support for more wft:
dishantsethi Jul 23, 2024
197fa86
Merge pull request #100 from dishantsethi/add-more-wft
dishantsethi Jul 23, 2024
feee710
rename vocal acoustics
dishantsethi Aug 2, 2024
cf08c20
fix test
dishantsethi Aug 2, 2024
fbc3534
Merge pull request #101 from dishantsethi/main
dishantsethi Aug 2, 2024
2e407df
bug fix
dishantsethi Aug 8, 2024
6ecf698
Merge pull request #102 from dishantsethi/main
dishantsethi Aug 8, 2024
8156e87
update workflow tag
dishantsethi Aug 9, 2024
3a48887
Merge pull request #103 from dishantsethi/main
dishantsethi Aug 9, 2024
f205abe
remaining for calls remaining function
dishantsethi Aug 12, 2024
2cc6733
fix
dishantsethi Aug 12, 2024
41d2679
Add support for willisdiarize
dishantsethi Aug 12, 2024
bf5f1ef
add tests
dishantsethi Aug 12, 2024
db3704e
Merge pull request #104 from dishantsethi/main
dishantsethi Aug 12, 2024
6d12892
add json decompression logic
dishantsethi Aug 16, 2024
59c9d1e
add json decompression logic
dishantsethi Aug 16, 2024
6bd44a7
fix testcase
dishantsethi Aug 16, 2024
6ecde79
Merge pull request #105 from dishantsethi/main
dishantsethi Aug 19, 2024
c54bea7
add invalid JSON log
dishantsethi Aug 20, 2024
20d9d79
Merge pull request #106 from dishantsethi/main
dishantsethi Aug 20, 2024
cbaba96
add loggers
dishantsethi Aug 20, 2024
ba68c8b
Merge pull request #107 from dishantsethi/main
vjbytes102 Aug 20, 2024
93929b1
filename added
ritikasharma-brooklyn Aug 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tests/test.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"speech_length_words": []
}
],
"vocal_acoustic_summary": [
"vocal_acoustics_simple_summary": [
{
"f0_mean": [],
"f0_stdev": []
Expand Down
64 changes: 64 additions & 0 deletions tests/test_diarize.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from unittest.mock import patch

from willisapi_client.services.diarize.willisdiarize import (
willis_diarize,
)
from willisapi_client.logging_setup import logger as logger
import logging


class TestDiarizeFunction:
def setup(self):
self.key = "dummy"
self.file_path = "file.json"

@patch(
"willisapi_client.services.diarize.diarize_utils.DiarizeUtils.decode_response"
)
@patch(
"willisapi_client.services.diarize.diarize_utils.DiarizeUtils.request_diarize"
)
@patch(
"willisapi_client.services.diarize.diarize_utils.DiarizeUtils.read_json_file"
)
@patch(
"willisapi_client.services.diarize.diarize_utils.DiarizeUtils.is_valid_file_path"
)
def test_willis_diarize_function_success(
self, mock_file_path, mock_json, mock_api_res, mock_decoded_res, caplog
):
mock_file_path.return_value = True
mock_json.return_value = {"Correct Transcription"}
mock_api_res.return_value = {
"status_code": 200,
"data": "Encoded Response",
}
mock_decoded_res.return_value = {"Correct Transcription"}
with caplog.at_level(logging.INFO):
res = willis_diarize(self.key, self.file_path)

assert res == {"Correct Transcription"}

@patch(
"willisapi_client.services.diarize.diarize_utils.DiarizeUtils.request_diarize"
)
@patch(
"willisapi_client.services.diarize.diarize_utils.DiarizeUtils.read_json_file"
)
@patch(
"willisapi_client.services.diarize.diarize_utils.DiarizeUtils.is_valid_file_path"
)
def test_willis_diarize_function_invalid_json(
self, mock_file_path, mock_json, mock_api_res, caplog
):
mock_file_path.return_value = False
mock_json.return_value = {}
mock_api_res.return_value = {
"status_code": 200,
"data": "Encoded Response",
}

with caplog.at_level(logging.INFO):
res = willis_diarize(self.key, self.file_path)

assert "Input file type is incorrect. We only accept JSON files" in caplog.text
42 changes: 42 additions & 0 deletions tests/test_diarize_call_remaining.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from unittest.mock import patch

from willisapi_client.services.diarize.willisdiarize_call_remaining import (
willis_diarize_call_remaining,
)
from willisapi_client.logging_setup import logger as logger
import logging


class TestDiarizeCallsFunction:
def setup(self):
self.key = "dummy"

@patch(
"willisapi_client.services.diarize.diarize_utils.DiarizeUtils.request_call_remaining"
)
def test_willisdiarize_remaining_calls_failed(self, mocked_data, caplog):
mocked_data.return_value = {}
with caplog.at_level(logging.INFO):
willis_diarize_call_remaining(self.key)
assert "" in caplog.text

@patch(
"willisapi_client.services.diarize.diarize_utils.DiarizeUtils.request_call_remaining"
)
def test_willisdiarize_remaining_calls_missing_auth(self, mocked_data, caplog):
mocked_data.return_value = {"status_code": 401, "message": "message"}
with caplog.at_level(logging.INFO):
willis_diarize_call_remaining(self.key)
assert "message" in caplog.text

@patch(
"willisapi_client.services.diarize.diarize_utils.DiarizeUtils.request_call_remaining"
)
def test_willisdiarize_remaining_calls_success(self, mocked_data, caplog):
mocked_data.return_value = {
"status_code": 401,
"message": "Your account has 10 WillisDiarize API calls remaining.",
}
with caplog.at_level(logging.INFO):
willis_diarize_call_remaining(self.key)
assert "Your account has 10 WillisDiarize API calls remaining." in caplog.text
10 changes: 9 additions & 1 deletion willisapi_client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
login,
upload,
download,
willis_diarize_call_remaining,
willis_diarize,
)

__all__ = ["login", "upload", "download"]
__all__ = [
"login",
"upload",
"download",
"willis_diarize_call_remaining",
"willis_diarize",
]
3 changes: 2 additions & 1 deletion willisapi_client/__version__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""Version details for willisapi_client
"""

__client__ = "willisapi_client"
__latestVersion__ = "1.8"
__latestVersion__ = "1.9"
__url__ = "https://github.com/bklynhlth/willsiapi_client"
__short_description__ = "A Python client for willisapi"
__content_type__ = "text/markdown"
4 changes: 4 additions & 0 deletions willisapi_client/services/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@
from willisapi_client.services.auth import login
from willisapi_client.services.upload import upload
from willisapi_client.services.download import download
from willisapi_client.services.diarize import (
willis_diarize_call_remaining,
willis_diarize,
)
7 changes: 7 additions & 0 deletions willisapi_client/services/diarize/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# website: https://www.brooklyn.health
from willisapi_client.services.diarize.willisdiarize_call_remaining import (
willis_diarize_call_remaining,
)
from willisapi_client.services.diarize.willisdiarize import willis_diarize

__all__ = ["willis_diarize_call_remaining", "willis_diarize"]
99 changes: 99 additions & 0 deletions willisapi_client/services/diarize/diarize_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import requests
import json
import time
import random
import os
import gzip
import base64
from willisapi_client.logging_setup import logger as logger


class DiarizeUtils:
def is_valid_file_path(file_path: str):
return file_path.endswith(".json") and os.path.exists(file_path)

def read_json_file(file_path: str):
data = None
try:
with open(file_path) as f:
json_data = json.load(f)
data = dict(json_data=json_data)
except json.decoder.JSONDecodeError:
logger.info("No data found in the file or JSON is invalid.")
logger.info("Failed!")
return data

def decode_response(encoded_response):
return json.loads(gzip.decompress(base64.b64decode(encoded_response)))

def request_diarize(url, data, headers, try_number):
"""
------------------------------------------------------------------------------------------------------
Class: DiarizeUtils

Function: request_diarize

Description: This is an internal diarize function which makes a GET API call to brooklyn.health API server

Parameters:
----------
url: The URL of the API endpoint.
headers: The headers to be sent in the request.
try_number: The number of times the function has been tried.

Returns:
----------
json: The JSON response from the API server.
------------------------------------------------------------------------------------------------------
"""
try:
response = requests.post(url, json=data, headers=headers)
res_json = response.json()
except (
requests.exceptions.ConnectionError,
json.decoder.JSONDecodeError,
) as ex:
if try_number == 3:
raise
time.sleep(random.random() * 2)
return DiarizeUtils.request_diarize(
url, data, headers, try_number=try_number + 1
)
else:
return res_json

def request_call_remaining(url, headers, try_number):
"""
------------------------------------------------------------------------------------------------------
Class: DiarizeUtils

Function: request_call_remaining

Description: This is an internal diarize function which makes a GET API call to brooklyn.health API server

Parameters:
----------
url: The URL of the API endpoint.
headers: The headers to be sent in the request.
try_number: The number of times the function has been tried.

Returns:
----------
json: The JSON response from the API server.
------------------------------------------------------------------------------------------------------
"""
try:
response = requests.get(url, headers=headers)
res_json = response.json()
except (
requests.exceptions.ConnectionError,
json.decoder.JSONDecodeError,
) as ex:
if try_number == 3:
raise
time.sleep(random.random() * 2)
return DiarizeUtils.request_call_remaining(
url, headers, try_number=try_number + 1
)
else:
return res_json
52 changes: 52 additions & 0 deletions willisapi_client/services/diarize/willisdiarize.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from http import HTTPStatus

from willisapi_client.willisapi_client import WillisapiClient
from willisapi_client.logging_setup import logger as logger
from willisapi_client.services.diarize.diarize_utils import DiarizeUtils


def willis_diarize(key: str, file_path: str, **kwargs):
"""
---------------------------------------------------------------------------------------------------
Function: willis_diarize

Description: This function makes call to WillisDiarize Model

Parameters:
----------
key: AWS access id token (str)
file_path: String

Returns:
----------
json: JSON
---------------------------------------------------------------------------------------------------
"""

logger.info("Passing through WillisDiarize...")
wc = WillisapiClient(env=kwargs.get("env"))
url = wc.get_diarize()
headers = wc.get_headers()
headers["Authorization"] = key
corrected_transcript = None

if not DiarizeUtils.is_valid_file_path(file_path):
logger.info("Input file type is incorrect. We only accept JSON files.")
logger.info("Failed!")
return corrected_transcript

data = DiarizeUtils.read_json_file(file_path)

if not data:
return corrected_transcript

response = DiarizeUtils.request_diarize(url, data, headers, try_number=1)
if response["status_code"] != HTTPStatus.OK:
logger.info(response["message"])
logger.info("Failed!")
else:
logger.info("Returning processed JSON...")
encoded_response = response["data"]
corrected_transcript = DiarizeUtils.decode_response(encoded_response)
logger.info("Done!")
return corrected_transcript
28 changes: 28 additions & 0 deletions willisapi_client/services/diarize/willisdiarize_call_remaining.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from http import HTTPStatus

from willisapi_client.willisapi_client import WillisapiClient
from willisapi_client.logging_setup import logger as logger
from willisapi_client.services.diarize.diarize_utils import DiarizeUtils


def willis_diarize_call_remaining(key: str, **kwargs):
"""
---------------------------------------------------------------------------------------------------
Function: willis_diarize_call_remaining

Description: This function returns the number of remaining calls for willisdiarize

Parameters:
----------
key: AWS access id token (str)
---------------------------------------------------------------------------------------------------
"""

wc = WillisapiClient(env=kwargs.get("env"))
url = wc.get_diarize_remaining_calls_url()
headers = wc.get_headers()
headers["Authorization"] = key

response = DiarizeUtils.request_call_remaining(url, headers, try_number=1)
if response:
logger.info(response["message"])
10 changes: 5 additions & 5 deletions willisapi_client/services/download/download_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from http import HTTPStatus


vocal_acoustic_summary = "vocal_acoustics_summary"
vocal_acoustics_simple_summary = "vocal_acoustics_simple_summary"
speech_characteristics_summary = "speech_characteristics_summary"
rater_qa_summary = "rater_qa_summary"

Expand Down Expand Up @@ -164,7 +164,7 @@ def _get_summary_df_from_json(response, pt, rec, workflow_tag):
and measures_dict[workflow_tag]
and workflow_tag
in [
vocal_acoustic_summary,
vocal_acoustics_simple_summary,
speech_characteristics_summary,
rater_qa_summary,
]
Expand Down Expand Up @@ -239,9 +239,9 @@ def generate_response_df(data) -> Tuple[pd.DataFrame, str]:
columns=DownloadUtils._get_defined_columns(),
)

vocal_acoustics_summary_df = (
vocal_acoustics_simple_summary_df = (
DownloadUtils._get_summary_df_from_json(
data, pt, rec, vocal_acoustic_summary
data, pt, rec, vocal_acoustics_simple_summary
)
)
speech_characteristics_summary_df = (
Expand All @@ -255,7 +255,7 @@ def generate_response_df(data) -> Tuple[pd.DataFrame, str]:
df = pd.concat(
[
main_df,
vocal_acoustics_summary_df,
vocal_acoustics_simple_summary_df,
speech_characteristics_summary_df,
rater_qa_summary_df,
],
Expand Down
4 changes: 3 additions & 1 deletion willisapi_client/services/upload/csv_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def __init__(self, file_path: str):
}
self.gender_field = ["M", "F"]
self.workflow_tags = [
"vocal_acoustics",
"vocal_acoustics_simple",
"speech_characteristics",
"speech_transcription_aws",
"voice_and_speech",
Expand All @@ -71,6 +71,8 @@ def __init__(self, file_path: str):
"scale_",
"speech_characteristics_",
"rater_qa_",
"scale_wd_",
"rater_qa_wd_",
]
self.collect_time_format = r"^\d{4}-\d{2}-\d{2}$"
self.df = None
Expand Down
Loading
Loading