Files
hotels/model_providers.py
Фёдор 0cf3297290 Проект аудита отелей: основные скрипты и документация
- Краулеры: smart_crawler.py, regional_crawler.py
- Аудит: audit_orel_to_excel.py, audit_chukotka_to_excel.py
- РКН проверка: check_rkn_registry.py, recheck_unclear_rkn.py
- Отчёты: create_orel_horizontal_report.py
- Обработка: process_all_hotels_embeddings.py
- Документация: README.md, DB_SCHEMA_REFERENCE.md
2025-10-16 10:52:09 +03:00

278 lines
10 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
API для получения списка моделей от разных провайдеров
"""
import requests
import json
from typing import Dict, List, Optional
from llm_config import OPENAI_CONFIG, OPENROUTER_CONFIG, OLLAMA_CONFIG
class ModelProvider:
"""Базовый класс для провайдеров моделей"""
def __init__(self, config: Dict):
self.config = config
self.provider = config['provider']
self.api_base = config['api_base']
self.api_key = config.get('api_key')
self.proxy = config.get('proxy')
def get_models(self) -> List[Dict]:
"""Получить список доступных моделей"""
raise NotImplementedError
def _make_request(self, endpoint: str, method: str = 'GET', data: Optional[Dict] = None) -> Optional[Dict]:
"""Универсальный запрос к API"""
url = f"{self.api_base}/{endpoint}"
headers = {}
if self.api_key:
headers["Authorization"] = f"Bearer {self.api_key}"
if self.provider == 'openrouter':
headers["HTTP-Referer"] = "https://hotel-audit.ru"
headers["X-Title"] = "Hotel Audit System"
headers["Content-Type"] = "application/json"
proxies = None
if self.proxy:
proxies = {'http': self.proxy, 'https': self.proxy}
try:
if method == 'GET':
response = requests.get(url, headers=headers, proxies=proxies, timeout=30)
elif method == 'POST':
response = requests.post(url, headers=headers, json=data, proxies=proxies, timeout=30)
if response.status_code == 200:
return response.json()
else:
print(f"Ошибка {self.provider}: {response.status_code} - {response.text}")
return None
except Exception as e:
print(f"Ошибка соединения {self.provider}: {e}")
return None
class OpenAIProvider(ModelProvider):
"""Провайдер OpenAI"""
def get_models(self) -> List[Dict]:
"""Получить модели OpenAI"""
data = self._make_request("models")
if not data:
return []
models = []
for model in data.get('data', []):
model_id = model['id']
# Фильтруем только чат-модели
if any(x in model_id.lower() for x in ['gpt-3.5', 'gpt-4', 'o1']):
models.append({
'id': model_id,
'name': model_id,
'provider': 'openai',
'description': self._get_model_description(model_id),
'context_length': model.get('context_length', 0),
'pricing': self._get_pricing(model_id)
})
return sorted(models, key=lambda x: x['name'])
def _get_model_description(self, model_id: str) -> str:
"""Описание модели"""
descriptions = {
'gpt-4o-mini': 'Быстрая и дешёвая модель',
'gpt-4o': 'Самая умная модель OpenAI',
'gpt-4-turbo': 'Баланс скорости и качества',
'gpt-4': 'Классическая GPT-4',
'gpt-3.5-turbo': 'Проверенная временем модель',
'o1-preview': 'Новая рассуждающая модель',
'o1-mini': 'Компактная рассуждающая модель'
}
for key, desc in descriptions.items():
if key in model_id.lower():
return desc
return 'Модель OpenAI'
def _get_pricing(self, model_id: str) -> Dict:
"""Примерная стоимость"""
pricing = {
'gpt-4o-mini': {'input': 0.15, 'output': 0.60},
'gpt-4o': {'input': 5.00, 'output': 15.00},
'gpt-4-turbo': {'input': 10.00, 'output': 30.00},
'gpt-3.5-turbo': {'input': 0.50, 'output': 1.50},
'o1-preview': {'input': 15.00, 'output': 60.00},
'o1-mini': {'input': 3.00, 'output': 12.00},
'gpt-4': {'input': 30.00, 'output': 60.00},
'gpt-3.5': {'input': 0.50, 'output': 1.50}
}
# Ищем точное совпадение или частичное
for key, price in pricing.items():
if key in model_id.lower():
return price
# Если не найдено, возвращаем базовую цену
return {'input': 0.50, 'output': 1.50}
class OpenRouterProvider(ModelProvider):
"""Провайдер OpenRouter"""
def get_models(self) -> List[Dict]:
"""Получить модели OpenRouter"""
data = self._make_request("models")
if not data:
return []
models = []
for model in data.get('data', []):
model_id = model['id']
# Фильтруем популярные модели
if any(x in model_id.lower() for x in ['claude', 'gemini', 'llama', 'mistral', 'qwen']):
models.append({
'id': model_id,
'name': model_id,
'provider': 'openrouter',
'description': self._get_model_description(model_id),
'context_length': model.get('context_length', 0),
'pricing': self._get_pricing(model_id)
})
return sorted(models, key=lambda x: x['name'])
def _get_model_description(self, model_id: str) -> str:
"""Описание модели"""
if 'claude' in model_id.lower():
if 'haiku' in model_id.lower():
return 'Claude 3 Haiku - быстрая модель Anthropic'
elif 'sonnet' in model_id.lower():
return 'Claude 3.5 Sonnet - умная модель Anthropic'
elif 'opus' in model_id.lower():
return 'Claude 3 Opus - самая мощная модель Anthropic'
else:
return 'Claude модель от Anthropic'
elif 'gemini' in model_id.lower():
return 'Gemini модель от Google'
elif 'llama' in model_id.lower():
return 'Llama модель от Meta'
elif 'mistral' in model_id.lower():
return 'Mistral модель'
elif 'qwen' in model_id.lower():
return 'Qwen модель от Alibaba'
return 'Модель через OpenRouter'
def _get_pricing(self, model_id: str) -> Dict:
"""Примерная стоимость"""
pricing = {
'claude-3-haiku': {'input': 0.25, 'output': 1.25},
'claude-3.5-sonnet': {'input': 3.00, 'output': 15.00},
'claude-3-opus': {'input': 15.00, 'output': 75.00},
'gemini-flash': {'input': 0.075, 'output': 0.30},
'gemini-pro': {'input': 0.50, 'output': 1.50},
'llama3.1': {'input': 0.20, 'output': 0.20},
'mistral': {'input': 0.25, 'output': 0.25}
}
for key, price in pricing.items():
if key in model_id.lower():
return price
return {'input': 0, 'output': 0}
class OllamaProvider(ModelProvider):
"""Провайдер Ollama (локальный)"""
def get_models(self) -> List[Dict]:
"""Получить модели Ollama"""
data = self._make_request("api/tags")
if not data:
return []
models = []
for model in data.get('models', []):
model_id = model['name']
models.append({
'id': model_id,
'name': model_id,
'provider': 'ollama',
'description': self._get_model_description(model_id),
'context_length': model.get('size', 0),
'pricing': {'input': 0, 'output': 0} # Бесплатно
})
return sorted(models, key=lambda x: x['name'])
def _get_model_description(self, model_id: str) -> str:
"""Описание модели"""
if 'llama' in model_id.lower():
return 'Llama модель (локальная)'
elif 'mistral' in model_id.lower():
return 'Mistral модель (локальная)'
elif 'qwen' in model_id.lower():
return 'Qwen модель (локальная)'
elif 'codellama' in model_id.lower():
return 'Code Llama для программирования'
else:
return 'Локальная модель Ollama'
def get_all_models() -> Dict[str, List[Dict]]:
"""Получить все модели от всех провайдеров"""
providers = {
'openai': OpenAIProvider(OPENAI_CONFIG),
'openrouter': OpenRouterProvider(OPENROUTER_CONFIG),
'ollama': OllamaProvider(OLLAMA_CONFIG)
}
all_models = {}
for provider_name, provider in providers.items():
print(f"Загружаю модели {provider_name}...")
try:
models = provider.get_models()
all_models[provider_name] = models
print(f"{provider_name}: {len(models)} моделей")
except Exception as e:
print(f"{provider_name}: ошибка - {e}")
all_models[provider_name] = []
return all_models
if __name__ == "__main__":
print("=" * 70)
print("🤖 ЗАГРУЗКА МОДЕЛЕЙ ОТ ПРОВАЙДЕРОВ")
print("=" * 70)
all_models = get_all_models()
print(f"\n📊 ИТОГО:")
for provider, models in all_models.items():
print(f" {provider.upper()}: {len(models)} моделей")
print(f"\n🎯 ПРИМЕРЫ МОДЕЛЕЙ:")
for provider, models in all_models.items():
if models:
print(f"\n{provider.upper()}:")
for model in models[:3]: # Показываем первые 3
print(f" - {model['name']}: {model['description']}")
print("=" * 70)