# OpenRouter (LLM интеграция) GenAudioBookInfo поддерживает опциональную нормализацию метаданных через LLM с помощью [OpenRouter](https://openrouter.ai/) — унифицированного API-шлюза к сотням AI-моделей. --- ## Зачем нужно LLM Теги в аудиофайлах и имена папок часто содержат: - Инициалы вместо полного имени: `Акунин Б.` → `Акунин Борис` - Неправильный порядок: `Борис Акунин` → `Акунин Борис` - Лишние символы, транслитерацию, опечатки - Номера серий и части в названии LLM нормализует автора в формат `Фамилия Имя` и очищает название книги. --- ## Настройка ### 1. Получить API ключ Зарегистрируйтесь на [openrouter.ai](https://openrouter.ai/) и создайте API ключ в личном кабинете. ### 2. Добавить в `config.yaml` ```yaml openrouter: api_key: sk-or-v1-xxxxxxxxxxxxxxxxxxxxxxxxxxxx model: openai/gpt-4o-mini ``` ### Или через переменную окружения ```bash export OPENROUTER_API_KEY=sk-or-v1-xxxx ./genaudiobookinfo ``` Переменная `OPENROUTER_API_KEY` проверяется если `api_key` в конфиге пуст. --- ## Настройки в `config.yaml` ```yaml openrouter: api_key: sk-or-v1-xxxx # API ключ (или env OPENROUTER_API_KEY) base_url: https://openrouter.ai/api/v1 timeout: 30s # Таймаут HTTP запроса model: openai/gpt-4o-mini # Идентификатор модели max_retries: 3 # Ретраи при ошибках API retry_backoff: 2s # Начальная задержка backoff retry_backoff_max: 30s # Максимальная задержка backoff prompt: | # Системный промпт Ты эксперт по русскоязычным аудиокнигам... ``` --- ## Промпт Промпт определяет, как LLM должна обработать метаданные. Требования к промпту: 1. Отвечать **только JSON** без дополнительного текста. 2. Формат ответа: `{"author": "Фамилия Имя", "title": "Название"}`. 3. Автор в формате `Фамилия Имя` (не инициалы). ### Пример промпта ```yaml prompt: | Ты эксперт по русскоязычным аудиокнигам. Тебе дадут сырые данные об аудиокниге (автор и название). Твоя задача — нормализовать их: 1. Автор: формат "Фамилия Имя" (полное имя, без инициалов) 2. Название: убрать номера частей, лишние скобки, год Верни ответ строго в JSON формате: {"author": "Фамилия Имя", "title": "Чистое название"} Только JSON, никакого лишнего текста. ``` --- ## Выбор модели OpenRouter предоставляет доступ к сотням моделей. Формат: `provider/model-name`. Рекомендуемые модели для нормализации текста: | Модель | Стоимость | Качество | |---|---|---| | `openai/gpt-4o-mini` | низкая | хорошее | | `openai/gpt-4o` | средняя | отличное | | `anthropic/claude-3-haiku` | низкая | хорошее | | `google/gemini-flash-1.5` | очень низкая | хорошее | | `meta-llama/llama-3.1-8b-instruct:free` | бесплатно | среднее | Полный список: [openrouter.ai/models](https://openrouter.ai/models) --- ## Поведение при ошибках | Ситуация | Действие | |---|---| | API ключ не задан | LLM выключен, книга обрабатывается с исходными тегами | | Ошибка HTTP | Ретрай до `max_retries` раз с backoff | | Невалидный JSON в ответе | WARN в лог, используются исходные теги | | Пустые поля в ответе | LLM результат игнорируется, используются исходные теги | | Таймаут запроса | WARN в лог, используются исходные теги | LLM-ошибки **не прерывают** обработку книги — конвейер продолжается с оригинальными данными. --- ## Архитектура интеграции ``` usecase/scan_audiobooks.go │ ▼ (если llmClient != nil) domain.LLMClient.NormalizeMetadata(rawAuthor, rawTitle) │ ▼ infrastructure/openrouter_client.go OpenRouterClient.NormalizeMetadata() │ ├── HTTP POST /chat/completions │ Authorization: Bearer │ {"model": "...", "messages": [...]} │ └── разбор JSON {"author": "...", "title": "..."} ``` `LLMClient` — интерфейс в `domain/llm.go`. Легко заменить на любой другой LLM провайдер.