Fetch models from Anthropic API. Returns a list of model options with label and value.
(api_key, api_url='')
| 777 | |
| 778 | |
| 779 | def _fetch_anthropic_models(api_key, api_url=''): |
| 780 | """ |
| 781 | Fetch models from Anthropic API. |
| 782 | Returns a list of model options with label and value. |
| 783 | """ |
| 784 | import urllib.request |
| 785 | import urllib.error |
| 786 | from pgadmin.llm.utils import validate_api_url |
| 787 | |
| 788 | base_url = (api_url or 'https://api.anthropic.com/v1').rstrip('/') |
| 789 | |
| 790 | if not validate_api_url(base_url): |
| 791 | raise LLMApiError( |
| 792 | 'API URL is not in the allowed list. ' |
| 793 | 'Check the ALLOWED_LLM_API_URLS configuration.' |
| 794 | ) |
| 795 | |
| 796 | url = f'{base_url}/models' |
| 797 | |
| 798 | headers = { |
| 799 | 'anthropic-version': '2023-06-01' |
| 800 | } |
| 801 | if api_key: |
| 802 | headers['x-api-key'] = api_key |
| 803 | |
| 804 | req = urllib.request.Request(url, headers=headers) |
| 805 | |
| 806 | try: |
| 807 | with urllib.request.urlopen( |
| 808 | req, timeout=30, context=SSL_CONTEXT |
| 809 | ) as response: |
| 810 | data = json.loads(response.read().decode('utf-8')) |
| 811 | except urllib.error.HTTPError as e: |
| 812 | if e.code == 401: |
| 813 | raise LLMApiError('Invalid API key') |
| 814 | raise LLMApiError(f'API error: {e.code}') |
| 815 | except urllib.error.URLError as e: |
| 816 | raise LLMApiError( |
| 817 | f'Cannot connect to Anthropic API: {e.reason}' |
| 818 | ) |
| 819 | |
| 820 | models = [] |
| 821 | seen = set() |
| 822 | |
| 823 | for model in data.get('data', []): |
| 824 | model_id = model.get('id', '') |
| 825 | display_name = model.get('display_name', model_id) |
| 826 | |
| 827 | # Skip if already seen or empty |
| 828 | if not model_id or model_id in seen: |
| 829 | continue |
| 830 | seen.add(model_id) |
| 831 | |
| 832 | # Create a user-friendly label |
| 833 | if display_name and display_name != model_id: |
| 834 | label = f"{display_name} ({model_id})" |
| 835 | else: |
| 836 | label = model_id |
no test coverage detected