Files
GenAudioBookInfo/docs/OPENROUTER.md
Dmitriy Fofanov 402ce7f4f1 Функция: реализованы консольный логгер и презентер для обработки аудиокниг
- Добавлен ConsoleLogger для подробного логирования этапов обработки аудиокниг в консоли.

- Введен ConsolePresenter для форматированного вывода результатов сканирования в консоль.

- Создан ProcessAudioBooksUseCase для обработки полного конвейера обработки аудиокниг, включая сканирование папок, извлечение метаданных, поиск торрентов и запись результатов.

- Реализована проверка LLM для улучшения метаданных.

- Добавлена ​​обработка ошибок и логирование на всех этапах обработки.
2026-02-20 00:35:43 +03:00

11 KiB
Raw Blame History

OpenRouter Integration

Модуль интеграции с OpenRouter API для использования различных LLM моделей в проекте GenAudioBookInfo.

Описание

OpenRouter предоставляет унифицированный API для доступа к различным языковым моделям (GPT-4, Claude, LLaMA и др.) через единый интерфейс, совместимый с OpenAI API.

Архитектура

Модуль реализован в соответствии с Clean Architecture:

  • Domain Layer (internal/domain/):

    • ports.go - интерфейс LLMClient
    • llm.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 ключа

  1. Зарегистрируйтесь на openrouter.ai
  2. Перейдите в раздел Keys
  3. Создайте новый API ключ
  4. Добавьте ключ в 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 не указан"

Проверьте:

  1. Ключ указан в config.yaml
  2. Формат: api_key: "sk-or-v1-..."
  3. Нет лишних пробелов или кавычек

Ошибка: HTTP 401 Unauthorized

  • Проверьте валидность API ключа на openrouter.ai/keys
  • Убедитесь, что ключ активен и не истёк

Ошибка: HTTP 429 Too Many Requests

  • Слишком много запросов, снизьте частоту
  • Проверьте лимиты аккаунта

Таймауты

  • Увеличьте timeout в конфигурации
  • Используйте более быстрые модели (например, claude-3-haiku)
  • Уменьшите max_tokens

Дополнительные ресурсы