Add isolated Gemini dictation route with native personal vocabulary
This commit is contained in:
@@ -48,10 +48,12 @@ services:
|
||||
volumes:
|
||||
- ./models.yaml:/etc/litellm/models.yaml:ro
|
||||
- ./render_config.py:/etc/litellm/render_config.py:ro
|
||||
- ./personal_transcription.py:/etc/litellm/personal_transcription.py:ro
|
||||
- /opt/litellm/personal-vocabulary.json:/etc/litellm/personal-vocabulary.json:ro
|
||||
- oauth:/tokens
|
||||
entrypoint: [/bin/sh, -c]
|
||||
command:
|
||||
- 'python /etc/litellm/render_config.py && exec litellm --config /tmp/litellm.yaml --host 0.0.0.0 --port 4000 --num_workers 1'
|
||||
- 'python /etc/litellm/render_config.py && exec python /etc/litellm/personal_transcription.py --config /tmp/litellm.yaml --host 0.0.0.0 --port 4000 --num_workers 1'
|
||||
healthcheck:
|
||||
test: [CMD, python, -c, 'import urllib.request; urllib.request.urlopen("http://127.0.0.1:4000/health/liveliness", timeout=5)']
|
||||
interval: 30s
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
"""Add native vocabulary only to explicitly opted-in Gemini transcription calls."""
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
VOCABULARY = Path('/etc/litellm/personal-vocabulary.json')
|
||||
|
||||
|
||||
def vocabulary(path=VOCABULARY):
|
||||
words = json.loads(path.read_text())
|
||||
if not isinstance(words, list) or not 1 <= len(words) <= 100:
|
||||
raise ValueError('Personal vocabulary must contain 1–100 terms')
|
||||
if any(not isinstance(word, str) or not word.strip() or len(word) > 100 for word in words):
|
||||
raise ValueError('Invalid personal vocabulary term')
|
||||
return list(dict.fromkeys(words))
|
||||
|
||||
|
||||
def install():
|
||||
from litellm.llms.gemini.audio_transcription.transformation import GeminiAudioTranscriptionConfig
|
||||
original = GeminiAudioTranscriptionConfig.transform_audio_transcription_request
|
||||
if getattr(original, '_personal_vocabulary_patch', False):
|
||||
return
|
||||
|
||||
def transform(self, model, audio_file, optional_params, litellm_params):
|
||||
enabled = optional_params.get('personal_vocabulary') is True
|
||||
if not enabled:
|
||||
return original(self, model, audio_file, optional_params, litellm_params)
|
||||
if model.removeprefix('gemini/') != 'gemini-3.5-transcribe':
|
||||
raise ValueError('Personal vocabulary is restricted to Gemini 3.5 Transcribe')
|
||||
if optional_params.get('timestamp_granularities') or optional_params.get('response_format') not in (None, 'json', 'text'):
|
||||
raise ValueError('Personal dictation does not support timestamps or diarization')
|
||||
clean = {key: value for key, value in optional_params.items() if key != 'personal_vocabulary'}
|
||||
result = original(self, model, audio_file, clean, litellm_params)
|
||||
config = result.data.setdefault('generation_config', {}).setdefault('transcription_config', {})
|
||||
# Fail closed if a future LiteLLM version enables conflicting features by default.
|
||||
if config.get('mode'):
|
||||
raise ValueError('Unexpected Gemini transcription mode')
|
||||
config['custom_vocabulary'] = vocabulary()
|
||||
return result
|
||||
|
||||
transform._personal_vocabulary_patch = True
|
||||
GeminiAudioTranscriptionConfig.transform_audio_transcription_request = transform
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
from litellm import run_server
|
||||
install()
|
||||
sys.argv[0] = 'litellm'
|
||||
sys.exit(run_server())
|
||||
@@ -56,6 +56,8 @@ def build_config(catalog, env, exists):
|
||||
add(alias, 'openai/' + model, 'ZENMUX_SUBSCRIPTION_API_KEY',
|
||||
api_base='https://zenmux.ai/api/v1', max_retries=0)
|
||||
if env.get('GOOGLE_AI_STUDIO_API_KEY'):
|
||||
add('gemini-transcribe-personal', 'gemini/gemini-3.5-transcribe',
|
||||
'GOOGLE_AI_STUDIO_API_KEY', personal_vocabulary=True)
|
||||
for alias, model in catalog['google_ai_studio'].items():
|
||||
add(alias, 'gemini/' + model, 'GOOGLE_AI_STUDIO_API_KEY')
|
||||
if env.get('VERTEXAI_ENABLED', '').lower() == 'true' and env.get('VERTEXAI_PROJECT'):
|
||||
|
||||
Reference in New Issue
Block a user