mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-07 08:26:10 +00:00
Use audio content for caching
This commit is contained in:
parent
b83bc10562
commit
f486fb2283
3 changed files with 114 additions and 1 deletions
|
|
@ -2,6 +2,7 @@
|
|||
Utils used for litellm.transcription() and litellm.atranscription()
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
|
@ -127,6 +128,67 @@ def get_audio_file_name(file_obj: FileTypes) -> str:
|
|||
return repr(file_obj)
|
||||
|
||||
|
||||
def get_audio_file_content_hash(file_obj: FileTypes) -> str:
|
||||
"""
|
||||
Compute SHA-256 hash of audio file content for cache keys.
|
||||
Falls back to filename hash if content extraction fails.
|
||||
"""
|
||||
file_content: Optional[bytes] = None
|
||||
fallback_filename: Optional[str] = None
|
||||
|
||||
if isinstance(file_obj, tuple):
|
||||
if len(file_obj) < 2:
|
||||
fallback_filename = str(file_obj[0]) if len(file_obj) > 0 else None
|
||||
else:
|
||||
fallback_filename = str(file_obj[0]) if file_obj[0] is not None else None
|
||||
file_content_obj = file_obj[1]
|
||||
else:
|
||||
file_content_obj = file_obj
|
||||
fallback_filename = get_audio_file_name(file_obj)
|
||||
|
||||
try:
|
||||
if isinstance(file_content_obj, (bytes, bytearray)):
|
||||
file_content = bytes(file_content_obj)
|
||||
elif isinstance(file_content_obj, (str, os.PathLike)):
|
||||
try:
|
||||
with open(str(file_content_obj), "rb") as f:
|
||||
file_content = f.read()
|
||||
if fallback_filename is None:
|
||||
fallback_filename = str(file_content_obj)
|
||||
except (OSError, IOError):
|
||||
fallback_filename = str(file_content_obj)
|
||||
file_content = None
|
||||
elif hasattr(file_content_obj, "read"):
|
||||
try:
|
||||
current_position = file_content_obj.tell() if hasattr(file_content_obj, "tell") else None
|
||||
if hasattr(file_content_obj, "seek"):
|
||||
file_content_obj.seek(0)
|
||||
file_content = file_content_obj.read() # type: ignore
|
||||
if current_position is not None and hasattr(file_content_obj, "seek"):
|
||||
file_content_obj.seek(current_position) # type: ignore
|
||||
except (OSError, IOError, AttributeError):
|
||||
file_content = None
|
||||
else:
|
||||
file_content = None
|
||||
except Exception:
|
||||
file_content = None
|
||||
|
||||
if file_content is not None and isinstance(file_content, bytes):
|
||||
try:
|
||||
hash_object = hashlib.sha256(file_content)
|
||||
return hash_object.hexdigest()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if fallback_filename:
|
||||
hash_object = hashlib.sha256(fallback_filename.encode('utf-8'))
|
||||
return hash_object.hexdigest()
|
||||
|
||||
file_obj_str = str(file_obj)
|
||||
hash_object = hashlib.sha256(file_obj_str.encode('utf-8'))
|
||||
return hash_object.hexdigest()
|
||||
|
||||
|
||||
def get_audio_file_for_health_check() -> FileTypes:
|
||||
"""
|
||||
Get an audio file for health check
|
||||
|
|
|
|||
|
|
@ -790,7 +790,7 @@ def function_setup( # noqa: PLR0915
|
|||
):
|
||||
_file_obj: FileTypes = args[1] if len(args) > 1 else kwargs["file"]
|
||||
file_checksum = (
|
||||
litellm.litellm_core_utils.audio_utils.utils.get_audio_file_name(
|
||||
litellm.litellm_core_utils.audio_utils.utils.get_audio_file_content_hash(
|
||||
file_obj=_file_obj
|
||||
)
|
||||
)
|
||||
|
|
@ -7346,6 +7346,8 @@ class ProviderConfigManager:
|
|||
return litellm.NvidiaNimRerankConfig()
|
||||
elif litellm.LlmProviders.VERTEX_AI == provider:
|
||||
return litellm.VertexAIRerankConfig()
|
||||
elif litellm.LlmProviders.FIREWORKS_AI == provider:
|
||||
return litellm.FireworksAIRerankConfig()
|
||||
return litellm.CohereRerankConfig()
|
||||
|
||||
@staticmethod
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import pytest
|
|||
from litellm.litellm_core_utils.audio_utils.utils import (
|
||||
ProcessedAudioFile,
|
||||
calculate_request_duration,
|
||||
get_audio_file_content_hash,
|
||||
get_audio_file_for_health_check,
|
||||
get_audio_file_name,
|
||||
process_audio_file,
|
||||
|
|
@ -263,3 +264,51 @@ class TestCalculateRequestDuration:
|
|||
assert file_obj.tell() == len(
|
||||
wav_header
|
||||
), "File position should be restored to original position"
|
||||
|
||||
|
||||
class TestGetAudioFileContentHash:
|
||||
"""Test the get_audio_file_content_hash function for cache key generation"""
|
||||
|
||||
def test_different_content_same_filename_different_hash(self):
|
||||
"""Test that different content with same filename produces different hashes"""
|
||||
content1 = b"audio content 1"
|
||||
content2 = b"audio content 2"
|
||||
filename = "test.mp3"
|
||||
|
||||
hash1 = get_audio_file_content_hash((filename, content1))
|
||||
hash2 = get_audio_file_content_hash((filename, content2))
|
||||
|
||||
assert hash1 != hash2, "Different content should produce different hashes"
|
||||
|
||||
def test_same_content_same_hash(self):
|
||||
"""Test that same content produces same hash"""
|
||||
content = b"same audio content"
|
||||
filename1 = "test1.mp3"
|
||||
filename2 = "test2.mp3"
|
||||
|
||||
hash1 = get_audio_file_content_hash((filename1, content))
|
||||
hash2 = get_audio_file_content_hash((filename2, content))
|
||||
|
||||
assert hash1 == hash2, "Same content should produce same hash regardless of filename"
|
||||
|
||||
def test_bytes_input(self):
|
||||
"""Test that raw bytes input works"""
|
||||
content = b"raw bytes content"
|
||||
hash1 = get_audio_file_content_hash(content)
|
||||
hash2 = get_audio_file_content_hash(content)
|
||||
|
||||
assert hash1 == hash2, "Same bytes should produce same hash"
|
||||
assert len(hash1) == 64, "SHA-256 hash should be 64 characters"
|
||||
|
||||
def test_fallback_to_filename(self):
|
||||
"""Test that function falls back to filename when content extraction fails"""
|
||||
# Use a non-readable object that will trigger fallback
|
||||
class UnreadableFile:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
file_obj = UnreadableFile("test.mp3")
|
||||
hash_result = get_audio_file_content_hash(file_obj)
|
||||
|
||||
assert isinstance(hash_result, str)
|
||||
assert len(hash_result) == 64, "Should return valid hash even on fallback"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue