-
Notifications
You must be signed in to change notification settings - Fork 19
updates #295
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
updates #295
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -10,6 +10,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from dembrane.s3 import get_signed_url | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from dembrane.utils import get_utc_timestamp | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from dembrane.config import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ENABLE_RUNPOD_DIARIZATION, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| RUNPOD_DIARIZATION_API_KEY, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| RUNPOD_DIARIZATION_TIMEOUT, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| RUNPOD_DIARIZATION_BASE_URL, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -23,7 +24,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def _fetch_chunk_data(chunk_id: str) -> tuple[str, str] | None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Retrieves the audio file URI and project language for a given chunk ID from Directus. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Returns: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| A tuple containing (audio_file_uri, project_language) if successful, or None if retrieval fails. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -33,13 +34,15 @@ def _fetch_chunk_data(chunk_id: str) -> tuple[str, str] | None: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "query": { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "filter": {"id": {"_eq": chunk_id}}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "fields": ["path", "conversation_id.project_id.language"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "fields": ["path", "conversation_id.project_id.language"], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )[0] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| audio_file_uri = directus_item["path"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| project_language = directus_item["conversation_id"]["project_id"]["language"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.debug(f"Starting diarization for chunk_id: {chunk_id}, path: {audio_file_uri}, project_language: {project_language}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.debug( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f"Starting diarization for chunk_id: {chunk_id}, path: {audio_file_uri}, project_language: {project_language}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return audio_file_uri, project_language | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| except Exception as e: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.error(f"Failed to fetch audio_file_uri for chunk_id {chunk_id}: {e}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -49,10 +52,10 @@ def _fetch_chunk_data(chunk_id: str) -> tuple[str, str] | None: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def _generate_audio_url(audio_file_uri: str) -> str | None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Generates a signed URL for the specified audio file. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Args: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| audio_file_uri: The URI of the audio file to sign. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Returns: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| The signed URL as a string if successful, or None if signing fails. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -68,7 +71,7 @@ def _generate_audio_url(audio_file_uri: str) -> str | None: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def _should_skip_diarization(project_language: str) -> bool: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Determines whether diarization should be skipped for a given project language. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Returns True if diarization is disabled for non-English languages based on configuration; otherwise, returns False. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if DISABLE_MULTILINGUAL_DIARIZATION and project_language != "en": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -80,11 +83,11 @@ def _should_skip_diarization(project_language: str) -> bool: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def _submit_diarization_job(audio_url: str, project_language: str) -> tuple[str, str] | None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Submits an audio diarization job to RunPod using the provided audio URL and project language. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Args: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| audio_url: The signed URL of the audio file to be processed. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| project_language: The language code associated with the project. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Returns: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| A tuple containing the job ID and the job status link if submission is successful, or None if the request fails. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -98,7 +101,7 @@ def _submit_diarization_job(audio_url: str, project_language: str) -> tuple[str, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Authorization": f"Bearer {api_key}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| data = {"input": {"audio": audio_url, "language": project_language}} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.debug(f"Sending POST to {base_url}/run with data: {data}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| response = requests.post(f"{base_url}/run", headers=headers, json=data, timeout=timeout) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -115,11 +118,11 @@ def _submit_diarization_job(audio_url: str, project_language: str) -> tuple[str, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def _poll_job_status(job_status_link: str, headers: dict) -> dict | None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Retrieves the current status of a diarization job from the provided status link. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Args: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| job_status_link: The URL to poll for job status. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| headers: HTTP headers to include in the request. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Returns: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| The JSON response containing job status information, or None if the request fails. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -136,7 +139,7 @@ def _poll_job_status(job_status_link: str, headers: dict) -> dict | None: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def _update_chunk_with_results(chunk_id: str, dirz_response_data: dict) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Updates a conversation chunk in Directus with diarization analysis results. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Args: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chunk_id: The ID of the conversation chunk to update. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dirz_response_data: Dictionary containing diarization metrics and results to store. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -145,7 +148,7 @@ def _update_chunk_with_results(chunk_id: str, dirz_response_data: dict) -> None: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cross_talk_instances = dirz_response_data.get("cross_talk_instances") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| silence_ratio = dirz_response_data.get("silence_ratio") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| joined_diarization = dirz_response_data.get("joined_diarization") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| directus.update_item( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "conversation_chunk", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chunk_id, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -162,7 +165,7 @@ def _update_chunk_with_results(chunk_id: str, dirz_response_data: dict) -> None: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def _cancel_job_on_timeout(job_id: str) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Cancels a diarization job on RunPod if it has exceeded the allowed processing time. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Logs a warning before attempting cancellation and logs an error if the cancellation fails. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| base_url = RUNPOD_DIARIZATION_BASE_URL | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -171,7 +174,7 @@ def _cancel_job_on_timeout(job_id: str) -> None: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Content-Type": "application/json", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Authorization": f"Bearer {api_key}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cancel_endpoint = f"{base_url}/cancel/{job_id}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.warning(f"Timeout reached. Cancelling diarization job {job_id} at {cancel_endpoint}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -187,10 +190,14 @@ def get_runpod_diarization( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Orchestrates the diarization process for a given chunk by submitting an audio diarization job to RunPod, polling for completion within a timeout, and updating Directus with the results or canceling the job if it times out. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Args: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chunk_id: The identifier of the audio chunk to process. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not ENABLE_RUNPOD_DIARIZATION: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.debug("Skipping diarization because ENABLE_RUNPOD_DIARIZATION is disabled") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Fetch chunk data | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chunk_data = _fetch_chunk_data(chunk_id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not chunk_data: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -219,24 +226,28 @@ def get_runpod_diarization( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Content-Type": "application/json", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Authorization": f"Bearer {api_key}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| start_time = time.time() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| while time.time() - start_time < timeout: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| response_data = _poll_job_status(job_status_link, headers) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if response_data: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| status = response_data.get("status") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.debug(f"Job {job_id} status: {status}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if status == "COMPLETED": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dirz_response_data = response_data.get("output") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if dirz_response_data: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.info(f"Diarization job {job_id} completed. Updating chunk {chunk_id} with results.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.info( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f"Diarization job {job_id} completed. Updating chunk {chunk_id} with results." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _update_chunk_with_results(chunk_id, dirz_response_data) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.warning(f"Diarization job {job_id} completed but no output data received.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.warning( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f"Diarization job {job_id} completed but no output data received." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
237
to
249
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick Handle failure states; don’t spin until timeout. If RunPod returns FAILED/CANCELED, bail early and optionally annotate the chunk. if response_data:
status = response_data.get("status")
logger.debug(f"Job {job_id} status: {status}")
if status == "COMPLETED":
dirz_response_data = response_data.get("output")
if dirz_response_data:
logger.info(
f"Diarization job {job_id} completed. Updating chunk {chunk_id} with results."
)
_update_chunk_with_results(chunk_id, dirz_response_data)
return
else:
logger.warning(
f"Diarization job {job_id} completed but no output data received."
)
return
+ elif status in {"FAILED", "CANCELED", "CANCELLED", "ERROR"}:
+ logger.warning(f"Diarization job {job_id} ended with status={status}")
+ return📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| time.sleep(3) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Timeout: cancel the job | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -254,6 +265,10 @@ def get_health_status( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Get the health status of conversations. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not ENABLE_RUNPOD_DIARIZATION: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.debug("Skipping diarization because ENABLE_RUNPOD_DIARIZATION is disabled") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return {} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not project_ids and not conversation_ids: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise ValueError("Either project_ids or conversation_ids must be provided") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -325,7 +340,7 @@ def _get_timebound_conversation_chunks( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| response = response[:max_chunks_for_conversation] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| aggregated_response.extend(_flatten_response(response)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| except Exception as e: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -141,6 +141,9 @@ def save_to_s3_from_file_like( | |||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| def get_signed_url(file_name: str, expires_in_seconds: int = 3600) -> str: | ||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||
| WARNING: this will also "get fake signed urls" for files that don't exist | ||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+144
to
+146
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick Don’t just warn—give callers a way to fail fast for missing objects. Presigned URLs are generated without existence checks. Offer an opt‑in existence check to prevent queuing downstream work with dead links. Apply within this function: -def get_signed_url(file_name: str, expires_in_seconds: int = 3600) -> str:
+def get_signed_url(file_name: str, expires_in_seconds: int = 3600, verify_exists: bool = False) -> str:
"""
WARNING: this will also "get fake signed urls" for files that don't exist
"""
- return s3_client.generate_presigned_url(
+ key = get_sanitized_s3_key(file_name)
+ if verify_exists:
+ # HEAD check so callers can opt-in to strict behavior
+ s3_client.head_object(Bucket=STORAGE_S3_BUCKET, Key=key)
+ return s3_client.generate_presigned_url(
"get_object",
- Params={"Bucket": STORAGE_S3_BUCKET, "Key": get_sanitized_s3_key(file_name)},
+ Params={"Bucket": STORAGE_S3_BUCKET, "Key": key},
ExpiresIn=expires_in_seconds,
)And add the import up top: -from botocore.response import StreamingBody
+from botocore.response import StreamingBody
+from botocore.exceptions import ClientError # optional: catch/translate on HEAD failuresWould you like me to wire this stricter mode where we generate signed URLs for diarization/transcription? 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
| return s3_client.generate_presigned_url( | ||||||||||||||||||||||||||||||||||||||||
| "get_object", | ||||||||||||||||||||||||||||||||||||||||
| Params={"Bucket": STORAGE_S3_BUCKET, "Key": get_sanitized_s3_key(file_name)}, | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -15,18 +15,35 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| project = project_service.get_by_id_or_raise(project_id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Import service classes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from .file import get_file_service | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from .event import EventService | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from .project import ProjectService | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from .conversation import ConversationService | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from .file import FileServiceException, get_file_service | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from .project import ProjectService, ProjectServiceException, ProjectNotFoundException | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from .conversation import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ConversationService, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ConversationServiceException, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ConversationNotFoundException, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ConversationChunkNotFoundException, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ConversationNotOpenForParticipationException, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Create service instances without circular dependencies | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| file_service = get_file_service() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| event_service = EventService() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| project_service = ProjectService() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| conversation_service = ConversationService( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| file_service=file_service, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| event_service=event_service, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| project_service=project_service, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exceptions = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "file": { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "FileServiceException": FileServiceException, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "conversation": { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "ConversationChunkNotFoundException": ConversationChunkNotFoundException, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "ConversationNotFoundException": ConversationNotFoundException, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "ConversationNotOpenForParticipationException": ConversationNotOpenForParticipationException, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "ConversationServiceException": ConversationServiceException, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "project": { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "ProjectNotFoundException": ProjectNotFoundException, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "ProjectServiceException": ProjectServiceException, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+35
to
+49
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick Public API polish: export surface explicitly. Optional: define all so downstreams get a stable import surface for services and exceptions. Example: exceptions = {
...
}
+
+__all__ = [
+ "file_service", "project_service", "conversation_service",
+ "FileServiceException",
+ "ProjectService", "ProjectServiceException", "ProjectNotFoundException",
+ "ConversationService", "ConversationServiceException",
+ "ConversationNotFoundException", "ConversationChunkNotFoundException",
+ "ConversationNotOpenForParticipationException",
+ "exceptions",
+]📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick
Drop stale commented code.
This dead snippet adds noise and confuses the enablement story.
🤖 Prompt for AI Agents