- Добавлен ConsoleLogger для подробного логирования этапов обработки аудиокниг в консоли. - Введен ConsolePresenter для форматированного вывода результатов сканирования в консоль. - Создан ProcessAudioBooksUseCase для обработки полного конвейера обработки аудиокниг, включая сканирование папок, извлечение метаданных, поиск торрентов и запись результатов. - Реализована проверка LLM для улучшения метаданных. - Добавлена обработка ошибок и логирование на всех этапах обработки.
11 KiB
OpenRouter Integration
Модуль интеграции с OpenRouter API для использования различных LLM моделей в проекте GenAudioBookInfo.
Описание
OpenRouter предоставляет унифицированный API для доступа к различным языковым моделям (GPT-4, Claude, LLaMA и др.) через единый интерфейс, совместимый с OpenAI API.
Архитектура
Модуль реализован в соответствии с Clean Architecture:
-
Domain Layer (
internal/domain/):ports.go- интерфейсLLMClientllm.go- доменные структурыLLMRequest,LLMResponse,LLMMessage
-
Infrastructure Layer (
internal/infrastructure/):openrouter_client.go- реализация HTTP клиента для OpenRouter API
Конфигурация
Добавьте настройки в config.yaml:
openrouter:
api_key: "sk-or-v1-..." # Ваш API ключ с https://openrouter.ai/keys
base_url: "https://openrouter.ai/api/v1" # Базовый URL (по умолчанию)
timeout: 60s # Таймаут запросов
model: "openai/gpt-3.5-turbo" # Модель по умолчанию
prompt: | # System prompt для валидации метаданных (опционально)
Ты — эксперт по метаданным аудиокниг.
Проверяй формат автора (Фамилия Имя) и чистоту названий.
Получение API ключа
- Зарегистрируйтесь на openrouter.ai
- Перейдите в раздел Keys
- Создайте новый API ключ
- Добавьте ключ в
config.yamlили переменную окруженияOPENROUTER_API_KEY
Использование
Базовый пример
package main
import (
"context"
"fmt"
"time"
"github.com/fofanov/genaudiobookinfo/internal/domain"
"github.com/fofanov/genaudiobookinfo/internal/infrastructure"
)
func main() {
// Создание клиента
client := infrastructure.NewOpenRouterClient(infrastructure.OpenRouterConfig{
APIKey: "sk-or-v1-...",
BaseURL: "https://openrouter.ai/api/v1",
Timeout: 60 * time.Second,
Model: "openai/gpt-3.5-turbo",
})
// Создание запроса
req := &domain.LLMRequest{
Model: "openai/gpt-3.5-turbo",
Messages: []domain.LLMMessage{
{
Role: "system",
Content: "Ты — полезный ассистент.",
},
{
Role: "user",
Content: "Привет! Как дела?",
},
},
Temperature: 0.7,
MaxTokens: 100,
}
// Выполнение запроса
ctx := context.Background()
resp, err := client.GenerateCompletion(ctx, req)
if err != nil {
panic(err)
}
// Получение ответа
if len(resp.Choices) > 0 {
fmt.Println(resp.Choices[0].Message.Content)
fmt.Printf("Использовано токенов: %d\n", resp.Usage.TotalTokens)
}
}
Параметры запроса
LLMRequest
| Поле | Тип | Описание |
|---|---|---|
Model |
string | Идентификатор модели (например, openai/gpt-4) |
Messages |
[]LLMMessage | История диалога |
Temperature |
float64 | Случайность генерации (0.0 - 2.0) |
MaxTokens |
int | Максимум токенов в ответе |
TopP |
float64 | Nucleus sampling параметр |
FrequencyPenalty |
float64 | Штраф за повторяющиеся токены |
PresencePenalty |
float64 | Штраф за уже встречавшиеся токены |
LLMMessage
| Поле | Тип | Описание |
|---|---|---|
Role |
string | Роль: system, user, или assistant |
Content |
string | Текст сообщения |
Доступные модели
OpenRouter поддерживает множество моделей. Популярные варианты:
- OpenAI:
openai/gpt-4,openai/gpt-3.5-turbo - Anthropic:
anthropic/claude-3-opus,anthropic/claude-3-haiku - Google:
google/gemini-pro - Meta:
meta-llama/llama-3-70b-instruct - Mistral:
mistralai/mistral-7b-instruct
Полный список: openrouter.ai/docs#models
Примеры использования
Анализ метаданных аудиокниги
req := &domain.LLMRequest{
Model: "openai/gpt-4",
Messages: []domain.LLMMessage{
{
Role: "system",
Content: "Ты — эксперт по метаданным аудиокниг.",
},
{
Role: "user",
Content: "Нормализуй автора: Иванов Петр Сергеевич → формат 'Фамилия Имя'",
},
},
Temperature: 0.3,
MaxTokens: 50,
}
Генерация описания
req := &domain.LLMRequest{
Model: "anthropic/claude-3-haiku",
Messages: []domain.LLMMessage{
{
Role: "system",
Content: "Создавай краткие описания книг на русском языке.",
},
{
Role: "user",
Content: fmt.Sprintf("Создай описание для: %s - %s", author, title),
},
},
Temperature: 0.7,
MaxTokens: 200,
}
Валидация метаданных
Модуль поддерживает автоматическую валидацию метаданных через метод ValidateMetadata:
// Создание клиента с промптом валидации
client := infrastructure.NewOpenRouterClient(infrastructure.OpenRouterConfig{
APIKey: "sk-or-v1-...",
Model: "openai/gpt-3.5-turbo",
Prompt: validationPrompt, // см. config.yaml
})
// Валидация метаданных
result, err := client.ValidateMetadata(ctx, "Иванов Петр Сергеевич", "Путешествие. Книга 1")
if err != nil {
log.Fatal(err)
}
if result != nil {
if result.AuthorFixed {
fmt.Printf("Исправлен автор: %s\n", result.Author) // "Иванов Петр"
}
if result.TitleFixed {
fmt.Printf("Исправлено название: %s\n", result.Title) // "Путешествие"
}
fmt.Printf("Изменения: %s\n", result.Changes)
}
Важно: Валидация работает только если:
- Указан
api_keyв конфигурации - Настроен
promptв конфигурации
Если api_key пустой, метод вернет nil и валидация не выполнится.
Продвинутые возможности
Контроль таймаутов
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
resp, err := client.GenerateCompletion(ctx, req)
Обработка ошибок
resp, err := client.GenerateCompletion(ctx, req)
if err != nil {
if ctx.Err() == context.DeadlineExceeded {
fmt.Println("Таймаут запроса")
} else {
fmt.Printf("Ошибка API: %v\n", err)
}
return
}
if len(resp.Choices) == 0 {
fmt.Println("Пустой ответ от API")
return
}
Настройка параметров генерации
req := &domain.LLMRequest{
Model: "openai/gpt-3.5-turbo",
Messages: messages,
Temperature: 0.8, // Выше = более креативно
MaxTokens: 500, // Ограничение длины ответа
TopP: 0.9, // Nucleus sampling
FrequencyPenalty: 0.5, // Избегать повторов
PresencePenalty: 0.3, // Разнообразие тем
}
Запуск примеров
В папке examples/ находятся примеры использования:
Базовое использование API
# Установите API ключ
export OPENROUTER_API_KEY="sk-or-v1-..."
# Запустите пример общего использования
go run examples/openrouter_example.go
Валидация метаданных аудиокниг
# Запустите пример валидации метаданных
go run examples/validate_metadata_example.go
Этот пример демонстрирует:
- Исправление порядка "Имя Фамилия" → "Фамилия Имя"
- Удаление отчества из имени автора
- Очистку названий от номеров серий, томов, технических терминов
- Обработку различных вариантов некорректных метаданных
Стоимость использования
OpenRouter работает по модели pay-as-you-go. Стоимость зависит от выбранной модели:
- GPT-3.5 Turbo: ~$0.002 / 1K токенов
- GPT-4: ~$0.03-0.06 / 1K токенов
- Claude 3 Haiku: ~$0.25 / 1M токенов
Следите за расходами на openrouter.ai/activity
Безопасность
⚠️ Важно: Никогда не коммитьте API ключи в репозиторий!
Используйте:
- Переменные окружения:
OPENROUTER_API_KEY - Файл
.env(добавьте в.gitignore) - Секреты CI/CD систем
Лимиты и ограничения
- Rate limiting: OpenRouter имеет лимиты на количество запросов
- Timeout: Рекомендуется устанавливать таймаут 30-60 секунд
- Max tokens: Учитывайте лимиты контекста моделей (обычно 4K-128K токенов)
Устранение неполадок
Ошибка: "API key не указан"
Проверьте:
- Ключ указан в
config.yaml - Формат:
api_key: "sk-or-v1-..." - Нет лишних пробелов или кавычек
Ошибка: HTTP 401 Unauthorized
- Проверьте валидность API ключа на openrouter.ai/keys
- Убедитесь, что ключ активен и не истёк
Ошибка: HTTP 429 Too Many Requests
- Слишком много запросов, снизьте частоту
- Проверьте лимиты аккаунта
Таймауты
- Увеличьте
timeoutв конфигурации - Используйте более быстрые модели (например,
claude-3-haiku) - Уменьшите
max_tokens