Зачем нужны новости от Рика Санчеза?
Традиционные новостные сайты унылы. Они подают информацию с серьезными лицами, будто мир вот-вот рухнет. А что, если бы новости читал циничный, пьяный гений из мультсериала? Контент стал бы в разы интереснее. Проблема в том, что нанимать актера дорого и не масштабируемо. Зато есть нейросети.
Идея проста: автоматический конвейер, который берет реальные новости, пересказывает их в стилистике Рика и Морти, генерирует соответствующие изображения и публикует на сайте. Все локально, без вечных подписок на OpenAI.
Архитектура: что крутим, что вертим
Собираем систему из четырех основных модулей. Каждый можно заменить, если найдешь что-то лучше.
| Компонент | Роль | Альтернативы |
|---|---|---|
| Скрапер | Собирает сырые новости с RSS или сайтов | Scrapy, BeautifulSoup, готовые API |
| Ollama + Nemotron-3-nano | Локальная LLM для переработки текста | Qwen 1.5B, Gemma 3n, другие мелкие модели |
| Gemini (или замена) | Улучшение согласованности и стиля | Локальная модель побольше, ансамбль LLM |
| Nano Banana | Генерация изображений в нужной стилистике | Stable Diffusion, другие локальные image модели |
| Веб-сервер | Отдает контент пользователям | Flask, FastAPI, любой фреймворк |
Главный вопрос: зачем Gemini, если есть локальные модели? Для качества. Nemotron-3-nano - модель на 1.4B параметров. Она быстрая и легкая, но иногда тупит. Gemini (например, 2.5 Flash) может подчистить текст, добавить креатива. Но если хочешь полную локальность, ищешь замену. Об этом ниже.
1 Собираем новости: скрапинг без головной боли
Берем Python и библиотеку BeautifulSoup. Или Scrapy для сложных случаев. Цель: получить заголовок и текст новости с нескольких источников. Не бери все подряд - выбери 3-5 сайтов с RSS. Так проще.
import requests
from bs4 import BeautifulSoup
import json
def scrape_news(url):
try:
response = requests.get(url, timeout=10)
soup = BeautifulSoup(response.content, 'html.parser')
# Ищем заголовок и основной текст - селекторы свои для каждого сайта
title = soup.find('h1').text.strip()
article_body = ' '.join([p.text for p in soup.find_all('p', class_='article-content')])
return {'title': title, 'body': article_body[:1000]} # Ограничиваем длину
except Exception as e:
print(f"Ошибка при скрапинге {url}: {e}")
return None
Сохраняй результаты в SQLite или JSON. Не нужно сложной базы на этом этапе. Главное - сырой материал для нейросети.
Не делай скрапинг каждую минуту. Во-первых, тебя забанят. Во-вторых, новости не появляются так часто. Раз в час - более чем достаточно. Используй планировщик задач (cron или Celery).
2 Запускаем локальную LLM: Ollama и Nemotron-3-nano
Устанавливаем Ollama. Это проще, чем кажется. Скачиваешь, запускаешь, тянешь модель.
# Установка Ollama (Linux/macOS)
curl -fsSL https://ollama.com/install.sh | sh
# Загружаем Nemotron-3-nano (1.4B параметров, требуется ~3GB RAM)
ollama pull nemotron-3-nano:latest
# Проверяем, что работает
ollama run nemotron-3-nano "Привет!"
Теперь пишем скрипт, который берет сырую новость и превращает ее в текст от лица Рика.
import subprocess
import json
def generate_rick_style(news_text):
prompt = f"""Ты - Рик Санчез из мультсериала 'Рик и Морти'.
Перескажи следующую новость в своем стиле: саркастично, цинично, с научными терминами.
Добавь немного безумия. Не пиши от себя комментарии, только пересказ.
Новость: {news_text}
"""
# Используем Ollama через subprocess
cmd = ['ollama', 'run', 'nemotron-3-nano', prompt]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
if result.returncode == 0:
return result.stdout.strip()
else:
print(f"Ошибка генерации: {result.stderr}")
return None
Nemotron-3-nano справляется неплохо, но иногда выдает откровенную чушь. Тут два пути: тюнить промпт или добавить второй этап обработки.
3 Улучшаем текст: Gemini или локальная замена
Если готов платить за Gemini API (или использовать бесплатный тариф), отправляй текст туда для полировки. Gemini отлично справляется со стилизацией. Но если проект должен быть полностью локальным, ищем альтернативу.
def improve_with_gemini(text, api_key):
import google.generativeai as genai
genai.configure(api_key=api_key)
model = genai.GenerativeModel('gemini-2.5-flash')
prompt = f"""Исправь текст, сохранив стиль Рика Санчеза. Убери противоречия, добавь остроумия.
Текст: {text}
Исправленный текст:"""
response = model.generate_content(prompt)
return response.text.strip()
Gemini хорош, но не забывай про стоимость. Для тестового проекта, возможно, лучше обойтись без него. Кстати, если интересно, как Gemini создает интерфейсы на лету, почитай про интерактивный калькулятор в поиске.
4 Рисуем безумие: Nano Banana для изображений
Текст есть, нужна картинка. Nano Banana - это тонко настроенная версия Stable Diffusion для генерации изображений в стиле Рика и Морти. Устанавливаешь через его репозиторий или используешь API, если он есть.
# Пример использования Nano Banana через его API (если запущен локально)
import requests
def generate_image(prompt):
url = "http://localhost:7860/api/predict" # Примерный эндпоинт
payload = {
"prompt": f"{prompt}, Rick and Morty style, cartoon, sci-fi",
"negative_prompt": "realistic, photo, ugly",
"steps": 20
}
response = requests.post(url, json=payload)
if response.status_code == 200:
# Возвращаем путь к изображению или base64
return response.json()['image']
else:
print(f"Ошибка генерации изображения: {response.text}")
return None
Промпт для изображения составляй на основе заголовка новости. Например: "Рик Санчез комментирует выборы президента, мультяшный стиль". Nano Banana справится. Если хочешь сравнить его с Gemini, есть отличная статья: Nano Banana против Gemini 2.5 Flash.
5 Собираем веб-приложение: просто и функционально
Бэкенд на Flask, фронт - простые HTML шаблоны. База данных - SQLite. Ничего лишнего.
from flask import Flask, render_template
import sqlite3
app = Flask(__name__)
def get_news_from_db():
conn = sqlite3.connect('news.db')
cursor = conn.cursor()
cursor.execute("SELECT title, content, image_path FROM articles ORDER BY id DESC LIMIT 10")
articles = cursor.fetchall()
conn.close()
return articles
@app.route('/')
def index():
articles = get_news_from_db()
return render_template('index.html', articles=articles)
if __name__ == '__main__':
app.run(debug=True)
Шаблон HTML сделай в духе мультсериала: неоновые цвета, шрифты в стиле Rick and Morty. Можно добавить аватарку Рика, которая озвучивает новости. Кстати, про аватаров есть отдельный гайд: Как встроить говорящего AI-аватара на сайт одной строкой кода.
Где все ломается: нюансы и ошибки
Собрал список типичных проблем, с которыми столкнешься. Знать их заранее - сэкономить часы дебага.
- Nemotron-3-nano генерирует короткий или несвязный текст. Решение: уточняй промпт. Добавь примеры нужного стиля. Или увеличь параметр `num_predict` в Ollama (по умолчанию 128).
- Скрапинг блокируют. Используй User-Agent, добавляй задержки между запросами. Или перейди на RSS, если есть.
- Nano Banana тормозит или не запускается. Проверь, хватает ли VRAM. Для работы нужно минимум 4GB. Уменьши разрешение изображений.
- Веб-приложение не справляется с нагрузкой. Это же тестовый проект. Если планируешь высокие нагрузки, кэшируй статьи, используй Nginx, перенеси базу в PostgreSQL.
Самая частая ошибка: пытаться сделать все идеально с первого раза. Не получится. Сначала собери работающий прототип, даже если он корявый. Потом улучшай по частям.
FAQ: коротко о главном
| Вопрос | Ответ |
|---|---|
| Можно ли обойтись без Gemini? | Да. Используй цепочку локальных моделей: одна генерирует, вторая проверяет. Или тюнь промпты. |
| Хватит ли 8GB RAM? | Для Nemotron-3-nano и Nano Banana - впритык. Лучше 16GB. |
| Как автоматизировать публикацию? | Напиши скрипт, который запускает весь конвейер по расписанию (cron). |
| Можно ли добавить другие стили? | Конечно. Меняй промпты и модель для изображений. Например, в стиле AI-радиостанции VibeCast. |
Итог: сайт AI-новостей - отличный способ разобраться с локальными LLM, скрапингом и генерацией контента. Не бойся экспериментировать. И помни: если что-то не работает, скорее всего, проблема в промпте. Удачи, и не забывай про бутылку сосульки!