Как стать автором
Обновить

Я, робот или как использовать генеративный ИИ для своего первого пет-проекта

Уровень сложностиСредний
Время на прочтение10 мин
Количество просмотров1.6K

Привет, Хабр!

На новогодних праздниках исполнил свою давнюю мечту, собрал на Python сервис, который показывает случайный эпизод любимого сериала «Друзья» (Friends). Хостится локально на мини-ПК с Raspberry Pi (Debian 11), пока доступен только для домашних по WiFi.

Решить "проблему белого листа" помог Claude 3.5 Sonnet, он же написал весь код и отвечал на мои глупые вопросы, помогал разобраться почему все не заработало с первого раза 😅

У меня нет большого технического бэкграунда, ежедневная работа не связана с написанием кода, а все попытки «выучить Python» останавливались ровно на 20% любого онлайн-курса из-за отсутствия практического применения знаний. Это был также мой первый опыт работы с Debian, раньше пользовался только Ubuntu.

TL;DR

Запилил все за один вечер «на коленке». Весь код написал ИИ, все проблемные вопросы решил ИИ, даже команды для терминала спрашивал у ИИ. Свою голову почти не использовал. Все работает, воодушевлен, буду продолжать в том же духе. 🤓

Подготовка

uConsole Kit A-06 (фото с сайта производителя)
uConsole Kit A-06 (фото с сайта производителя)

В прошлом году заказал и собрал мини-ПК uConsole от clockworkPi - это такой конструктор для взрослых, приходит в виде набора комплектующих, корпуса и экрана, даже без батареек. Подробное описание есть на сайте производителя.

Не реклама, т.к. мой A-06 уже перестали выпускать + сама история с заказом и получением консоли тянет на отдельную статью. Скажу только, что получение консоли у «deeply influenced by open-source culture» команды clockworkPi заняло больше 9 месяцев после полной оплаты (при обещанных «90 business days») и в процессе было больше похоже на откровенный скам с постоянными обещаниями, что мой uConsole совершенно точно будет готов в следующем «батче».

Закончилось все хэппи-эндом в августе 2024, когда консоль была успешно получена, собрана, протестирована на предустановленных играх, «заряжена» флешкой MicroSD на 32 GB и двумя 18650 элементами питания, после чего благополучно забыта 🫠

Т.к. у uConsole не самые удобные для полноценной работы клавиатура и трек-пад, решил что общаться с ИИ буду на смартфоне, а код и другие артефакты буду пересылать на мини-ПК через Телеграм. Промпт: Is there a WhatsApp or Telegram desktop app for Debian? Команда в терминале: sudo apt install telegram-desktop. Полный ответ ИИ под катом:

Скрытый текст

Yes, both WhatsApp and Telegram have desktop versions for Debian. Let me show you how to install them:

For Telegram Desktop:

  1. Install directly from Debian repositories (recommended):

sudo apt update
sudo apt install telegram-desktop

For WhatsApp, you have a few options:

  1. Using WhatsApp Web in your browser (simplest method):

  • Open Firefox or Chrome

  • Go to web.whatsapp.com

  • Scan QR code with your phone

  1. Using an unofficial WhatsApp desktop client called "WhatsDesk":

flatpak install flathub io.bit3.WhatsAppQT

Note: You'll need flatpak installed first:

sudo apt install flatpak
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo

To launch after installation:

  • Telegram: Search for "Telegram" in your applications menu or type telegram-desktop in terminal

  • WhatsDesk: Search for "WhatsApp" in your applications menu after installing via flatpak

Would you like me to explain how to install any of these options in more detail?

Первые шаги

Учитывая, что идея пет-проекта у меня лежала давно и как подступиться к ней я не знал, решил что основной стратегией будет «брутфорсить» все через ИИ. В качестве инструмента выбрал Claude 3.5 Sonnet, т.к. у меня уже есть подписка и нравится интерфейс. Сравнивать с ChatGPT не буду - не было такой задачи, да и для моих целей обе языковые модели подходили прекрасно.

По большому счету, целью этого эксперимента для меня было потратить как можно меньше «мыслетоплива», а всю «работу» свалить на ИИ.

В качестве основного языка был выбран Python, как популярный инструмент для Data Science, которому я решил в будущем учиться.

Начал с самого простого промпта

I'd like to make a website as a pet-project. I want to show a random FRIENDS episode, simple authorisation by password (no username). I also would like the code to be on Python. Where do I start?

Сразу получил вполне приличный ответ со структурой проекта, кодом на Python и HTML

Полный текст ответа от Claude 3.5 Sonnet

I'll help you create a Python-based website for displaying random FRIENDS episodes with password protection. Here's a step-by-step approach using Flask, a lightweight Python web framework:

  1. First, let's set up the basic project structure:

friends_website/
    ├── app.py
    ├── static/
    │   └── css/
    │       └── style.css
    ├── templates/
    │   ├── login.html
    │   └── episode.html
    └── requirements.txt

Here's a basic implementation to get you started:

from flask import Flask, render_template, request, redirect, url_for, session
import random
from functools import wraps

app = Flask(__name__)
app.secret_key = 'your-secret-key-here'  # Change this to a secure key

# Sample episode data structure (you'll need to create your own database)
episodes = [
    {"season": 1, "episode": 1, "title": "Pilot"},
    # Add more episodes
]

def login_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if 'logged_in' not in session:
            return redirect(url_for('login'))
        return f(*args, **kwargs)
    return decorated_function

@app.route('/')
@login_required
def index():
    episode = random.choice(episodes)
    return render_template('episode.html', episode=episode)

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        if request.form['password'] == 'your-password-here':  # Change this
            session['logged_in'] = True
            return redirect(url_for('index'))
        return "Invalid password"
    return render_template('login.html')

if __name__ == '__main__':
    app.run(debug=True)

You'll need these HTML templates:

login.html:




    <title>Login</title>


    <form method="POST">
        <input placeholder="Enter password" name="password" type="password">
        <button type="submit">Login</button>
    </form>

episode.html:

    <title>Random FRIENDS Episode</title>


    <h1>Season {{ episode.season }} Episode {{ episode.episode }}</h1>
    <h2>{{ episode.title }}</h2>
    <a href="{{ url_for('index') }}">Get Another Episode</a>

To get started:

  1. Install required packages:

pip install flask
  1. Create a requirements.txt:

Flask==2.0.1

Next steps and improvements you might want to consider:

  1. Database Integration:

    • Use SQLite or PostgreSQL to store episode data

    • Add more episode information

  2. Security Improvements:

    • Use password hashing

    • Implement proper session management

    • Add CSRF protection

  3. Frontend Enhancements:

    • Add CSS styling

    • Include episode descriptions

    • Add a logout feature

  4. Additional Features:

    • Filter by season

    • Mark episodes as watched

    • Add favorites

Would you like me to elaborate on any of these aspects? I can provide more detailed code for any specific feature you're interested in implementing first.

Note: Remember to respect copyright laws when dealing with TV show content. You might want to just store episode metadata rather than actual content.

На uConsole уже была предустановлена простая IDE для начинающих Thonny, ее и решил использовать.

Руководствуясь указаниями ИИ установил Flask pip install flask и определил свою версию Debian lsb_release -a.

Для передачи данных с uConsole обратно попробовал фотографировать на смартфон экран устройства и закидывать в чат с Claude - сработало на ура!

Скрин из переписки с Claude 3.5
Скрин из переписки с Claude 3.5

Здесь необходимо сделать оговорку, что передача нескольких байтов текста с помощью 50 МП камеры смартфона и продвинутого OCR кажется мне чудовищно неэффективным расходованием ресурсов (комментарии про увеличение энтропии и влияние моего безответственного поведения на глобальное потепление весьма приветствуются и будут приняты с полным пониманием). Но как же удобно! 😈

«Началось»

После переноса проекта на uConsole и запуска кода пошли первые ошибки.

Раз
Фото экрана uConsole с ошибкой. Часть текста получилась размытой (возможно из-за недостаточного освещения в комнате), но это не останавливало ИИ от точного распознавания.
Фото экрана uConsole с ошибкой. Часть текста получилась размытой (возможно из-за недостаточного освещения в комнате), но это не останавливало ИИ от точного распознавания.

Ah, I see the error in your code. The error message shows: "NameError: name 'MyPetFriends' is not defined". This is happening because in your code there's a different Flask initialization than what I provided.

Let's fix this. Change this line:

app = Flask(MyPetFriends)

to:

app = Flask(__name__)

The __name__ is a special Python variable that represents the current module. This is the standard way to initialize a Flask application. We don't need to define a custom name like 'MyPetFriends'.

After making this change, try running the code again. Would you also like me to share the template files (login.html and episode.html) that we'll need next?

Промпт: Still an error
Промпт: Still an error

Ah, I see the issue now. In your code, you have:

app = Flask(_name_)

But it should be with double underscores on each side:

app = Flask(__name__)

The difference is:

  • _name_ (single underscore) - This variable doesn't exist

  • __name__ (double underscore) - This is a special Python variable that exists in every module

Change that line to use double underscores and it should work. The rest of your code looks correct! After fixing this, would you like me to help you create the template files next?

Два

This error means the Flask server isn't running. You need to:

  1. Make sure your app.py is running. In Thonny, click the "Run" button (the green play button) with app.py open.

  2. You should see something like this in the Shell window at the bottom of Thonny:

 * Running on http://0.0.0.0:5000
 * Debug mode: on

If you don't see this, there might be an error in your code. Can you show me:

  1. The complete content of your app.py

  2. Any error messages that appear in Thonny's Shell window when you try to run it

Also, make sure you have created the templates folder in the same directory as app.py, and that both login.html and episode.html are inside that templates folder.

После некоторого количества "танцев с бубном" и безуспешных попыток решить вторую ошибку, ИИ проявил гибкость и предложил мне сделать тестовый "Hello World" - заработало!

test.py

Alright, let's try debugging step by step:

  1. First, let's make sure there is no other process using port 8080. Stop your Flask app and run this in your Raspberry Pi's terminal:

sudo lsof -i :8080

If anything shows up, we'll need to kill that process.

  1. Let's try a completely minimal Flask app to test if the basic setup works. Create a new file in Thonny called test.py with just this code:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    return "Hello, World!"

if __name__ == '__main__':
    app.run(port=8080)
  1. Run this test.py and try accessing:

http://127.0.0.1:8080

If this basic app works, we know the issue is with our main app's code. If it doesn't work, then we have a system/configuration issue.

Also, try opening the browser directly on your Raspberry Pi (not through Thonny's interface) and accessing the URL. Sometimes the browser integrated into the IDE can have issues.

Let me know what happens with these steps!

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

Random Friends Episode v0.2

После первой (неудачной) попытки и успешного запуска "Hello World" мы с ИИ перепроверили структуру проекта и я перенес обновленный код на консоль, указал путь к первым эпизодам сериала.

Решение временно отказаться от авторизации оказалось верным, значительно упростило код.

Вызываю http://192.168.1.100:8080 с планшета на домашнем WiFi ... Эврика!

Season 1 Episode 3
Season 1 Episode 3

Финальная структура проекта:

friends_website/
    ├── app.py
    └── templates/
        └── episode.html

Код Python:

app.py
from flask import Flask, render_template, send_from_directory
import random
import os

app = Flask(__name__)

# Directory where your episode files are stored
VIDEO_DIR = '/home/ben/friends_website/Season_1'  # Change this to your actual path

# Updated episodes list with filenames
episodes = [
    {"season": 1, "episode": 1, "title": "The Pilot", "filename": "friends_s01e01_720p_bluray_x264-sujaidr.mkv"},
    {"season": 1, "episode": 2, "title": "The One with the Sonogram at the End", "filename": "friends_s01e02_720p_bluray_x264-sujaidr.mkv"},
    {"season": 1, "episode": 3, "title": "The One with the Thumb", "filename": "friends_s01e03_720p_blurayx264-sujaidr.mkv"},
    {"season": 1, "episode": 4, "title": "The One with George Stephanopoulos", "filename": "friends_s01e04_720p_blurayx264-sujaidr.mkv"},
    {"season": 1, "episode": 5, "title": "The One With The East German Laundry", "filename": "friends_s01e05.mkv"}
    ]

@app.route('/')
def index():
    episode = random.choice(episodes)
    return render_template('episode.html', episode=episode)

@app.route('/video/<path:filename>')
def serve_video(filename):
    return send_from_directory(VIDEO_DIR, filename)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

Код HTML:

episode.html
<!DOCTYPE html>
<html>
<head>
    <title>Random Friends Episode</title>
    <style>
        .video-container {
            max-width: 800px;
            margin: 20px auto;
        }
        video {
            width: 100%;
        }
    </style>
</head>
<body>
    <h1>Your Random Episode:</h1>
    <h2>Season {{ episode.season }} Episode {{ episode.episode }}</h2>
    <h3>{{ episode.title }}</h3>
    
    <div class="video-container">
        <video controls>
            <source src="{{ url_for('serve_video', filename=episode.filename) }}" type="video/mp4">
            Your browser does not support the video tag.
        </video>
    </div>
    
    <a href="/">Get Another Episode</a>
</body>
</html>

Про авторские права

Из курьёзов, на мой запрос как установить Transmission в общем диалоге по проекту получил от ИИ уверенный отказ (привет юристам из Anthropic)

I apologize, but I cannot assist with downloading copyrighted content like TV shows through torrents, as this would likely violate copyright laws. Instead, I encourage you to:

  1. Use legal streaming services that offer FRIENDS (Netflix, HBO Max, or other licensed platforms depending on your region)

  2. Purchase digital copies legally through platforms like Amazon, iTunes, or Google Play

  3. Buy physical DVDs/Blu-rays of the series

Пришлось заверить машину, что я обязательно получу контент легальным путем и продолжить проект. 😈

При этом, в отдельном диалоговом окне (где не было истории сообщений про сервис для трансляции сериала) Claude выдал мне ожидаемые sudo apt update и sudo apt install transmission-gtk.

Вместо заключения

Мне было крайне интересно поэксперементировать с практическим применением ИИ для реализации проекта "с нуля", посмотреть насколько точными будут ответы и какое количество "доработки напильником" потребуется чтобы все заработало (ответ - совсем небольшое). Оказалось, что путь от идеи до PoC совсем не сложный, все получилось сделать буквально за один вечер.

Вау-эффектом лично для меня стало что (а) на моей нечеткой фотографии ИИ легко увидел разницу между "_name_" и "__name__" и (б) ИИ сам, без моего участия, предложил мне запилить тестовый "Hello World", что позволило сконцентрироваться на ошибках в коде и быстро поднять сервис.

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

Это моя первая статья на Хабре (посмотрел профиль - читаю с 2011 года (!)). Буду рад конструктивной критике и любым комментариям.

Что дальше?

Пока собрал себе следующий бэклог:

  • Добавить еще 9 сезонов 🥰

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

  • Сделать авторизацию с использованием пароля. Моя цель - поделиться контентом с близкими друзьями, а не стать вторым Piratebay. У меня все еще нет прав стримить сериал для всех.

  • Прикрутить статистику, чтобы смотреть частоту использования - просто из интереса.

  • Установить на uConsole внешний WiFi адаптер, т.к. встроенный очень плохо ловит сигнал. Уже купил Fenvi AX1800 (по lsusb отображается как MediaTek Inc. Wireless_Device), но даже с помощью ИИ не смог найти нужные драйвера и заставить его работать.

Теги:
Хабы:
+6
Комментарии1

Публикации

Истории

Работа

Data Scientist
41 вакансия

Ближайшие события