补充 OpenAI 主备验收与可复用双协议测试
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Run inside a separate LiteLLM container exec: fake OAuth failures, real API backup."""
|
||||
import asyncio
|
||||
from copy import deepcopy
|
||||
from functools import wraps
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
import litellm
|
||||
import yaml
|
||||
|
||||
litellm.suppress_debug_info = True
|
||||
|
||||
|
||||
async def main():
|
||||
config = yaml.safe_load(Path('/tmp/litellm.yaml').read_text())
|
||||
primary, backup = 'codex/gpt-luna-latest', 'openai/gpt-luna-latest'
|
||||
routes = [deepcopy(r) for r in config['model_list'] if r['model_name'] in (primary, backup)]
|
||||
assert len(routes) == 2
|
||||
assert {primary: [backup]} in config['router_settings']['fallbacks']
|
||||
for route in routes:
|
||||
if route['model_name'] == backup:
|
||||
route['litellm_params']['api_key'] = os.environ['OPENAI_API_KEY']
|
||||
actual_chat, actual_responses = litellm.acompletion, litellm.aresponses
|
||||
for protocol in ('chat', 'responses'):
|
||||
for error_type, expected in ((litellm.RateLimitError, 429),
|
||||
(litellm.AuthenticationError, 401),
|
||||
(litellm.ServiceUnavailableError, 503)):
|
||||
calls = []
|
||||
|
||||
async def invoke(real, *args, **kwargs):
|
||||
model = kwargs.get('model', '')
|
||||
if model.startswith('chatgpt/'):
|
||||
calls.append('subscription-rejected')
|
||||
raise error_type(message='Synthetic OAuth failure; isolated test only',
|
||||
llm_provider='chatgpt', model=model)
|
||||
assert model.startswith('openai/')
|
||||
calls.append('official-api')
|
||||
return await real(*args, **kwargs)
|
||||
|
||||
@wraps(actual_chat)
|
||||
async def chat(*args, **kwargs):
|
||||
return await invoke(actual_chat, *args, **kwargs)
|
||||
|
||||
@wraps(actual_responses)
|
||||
async def responses(*args, **kwargs):
|
||||
return await invoke(actual_responses, *args, **kwargs)
|
||||
|
||||
with patch.object(litellm, 'acompletion', chat), patch.object(litellm, 'aresponses', responses):
|
||||
router = litellm.Router(model_list=deepcopy(routes), fallbacks=[{primary: [backup]}],
|
||||
num_retries=0, timeout=60)
|
||||
if protocol == 'chat':
|
||||
result = await router.acompletion(model=primary, messages=[
|
||||
{'role': 'user', 'content': 'Reply only OK. Synthetic test.'}], max_tokens=32)
|
||||
assert result.choices and result.choices[0].message.content
|
||||
else:
|
||||
result = await router.aresponses(model=primary, input=[
|
||||
{'role': 'user', 'content': 'Reply only OK. Synthetic test.'}],
|
||||
max_output_tokens=32, store=False)
|
||||
assert result.status == 'completed'
|
||||
assert calls[0] == 'subscription-rejected' and calls[-1] == 'official-api', calls
|
||||
print(json.dumps({'protocol': protocol, 'injected_error': expected,
|
||||
'calls': calls, 'backup': backup, 'passed': True}), flush=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user