Rozbicie problemu na czynniki pierwsze

https://aie24.pl/

W przypadku tak skomplikowanego żądania, jak generowanie oprogramowania z SRS, znacznie bardziej prawdopodobne jest uzyskanie akceptowalnych wyników poprzez rozbicie problemu na kroki. Jednak fragmenty wyników z odpowiedzi na monit zerowego strzału mogą być pomocne w ustaleniu, jak rozbić problem na czynniki pierwsze. Ponieważ ChatGPT jest dostrojony do kreatywności (ma wysoką domyślną temperaturę), był idealnym narzędziem do pomocy w pisaniu SRS. Jednak zwykle nie jest to najlepsza opcja do generowania działającego kodu. Przy mojej drugiej próbie zbudowania gry w kółko i krzyżyk zwróciłem się do GitHub Copilot. Zanim poprosiłem Copilot o pomoc w mojej aplikacji, użyłem wbudowanego debugera w przeglądarce Chrome, aby dowiedzieć się, co było nie tak z kodem dostarczonym przez ChatGPT. Okazuje się, że funkcja, która umieszcza X użytkownika na planszy, ma następujący wiersz kodu, aby zamieniać symbol użytkownika między X i O:

currentPlayer = currentPlayer === ‘X’ ? ‘O’ : ‘X’;

W tym stwierdzeniu zmienna currentPlayer przechowuje symbol (X lub O), który zostanie zagrany na planszy, gdy użytkownik wykona ruch. Operator warunkowy (lub trójkowy) w tym stwierdzeniu sprawdza, czy wartość currentPlayer wynosi X i zmienia ją na O, jeśli tak jest. W przeciwnym razie (jeśli currentPlayer nie jest równy X) zmienia jej wartość na O. Problem polega jednak na tym, że wartość currentPlayer jest używana w programie tylko do reprezentowania gracza ludzkiego. W rezultacie zmiana wartości currentPlayer na O powoduje, że człowiek gra co drugi ruch symbolem AI. Po zakomentowaniu tego wiersza mogłem grać w kółko i krzyżyk i wygrywać za każdym razem (ponieważ komputerowy gracz po prostu losowo wybiera z dostępnych pól w tym momencie). Przy mądrzejszym przeciwniku gra powinna być remisowa za każdym razem, więc zdecydowałem się zaimplementować funkcję poziomów trudności z SRS.

Używanie podejścia zero-shot

https://aie24.pl/

Jeśli czujesz się szczęśliwy, możesz spróbować prostego monitu, prosząc chatbota o wygenerowanie całego programu na podstawie SRS. To podejście nazywa się monit zero-shot i jest opisane bardziej szczegółowo w rozdziale 4. Monit zero-shot to taki, w którym nie podajesz przykładów ani kodu, a zamiast tego polegasz po prostu na danych, na których model został wytrenowany. W tej samej rozmowie, w której poprosiłem ChatGPT o napisanie SRS, wprowadziłem następujący monit:

Jesteś profesjonalnym programistą oprogramowania. Napisz grę w kółko i krzyżyk opisaną w powyższym SRS.

Po kilku sekundach ChatGPT zwrócił kod HTML, CSS i JavaScript, co według jego opisu było uproszczoną wersją aplikacji, jak pokazano na rysunku .

Przed zbadaniem kodu skopiowałem go do plików index.html, styles.css i script.js w moim edytorze kodu i otworzyłem plik HTML w przeglądarce. Interfejs użytkownika przypomina grę w kółko i krzyżyk i używa kolorów i tekstu, które można uznać za przyjazne dzieciom. Jednak po próbie gry odkryłem, że nie spełnia ona najważniejszego wymogu. Spójrz na rysunek i sprawdź, czy możesz zidentyfikować problem. W tej pierwszej próbie gry w kółko i krzyżyk, sztuczna inteligencja napisała grę, która nieprawidłowo przełącza się między X i O, co powoduje, że O ma więcej tur i zawsze wygrywa grę. Oszustwa sztucznej inteligencji.

Generowanie kodu z SRS

https://aie24.pl/

Gdy masz SRS (niezależnie od tego, czy sam go napisałeś, czy skorzystałeś z pomocy asystenta AI), jesteś w dobrej pozycji, aby zacząć kodować. Możesz podjąć kilka różnych podejść. Pierwszym sposobem jest po prostu poproszenie ChatGPT o zakodowanie programu opisanego w SRS. Przynajmniej zaowocuje to kilkoma pomysłami, których możesz użyć, aby zacząć kodować go samodzielnie.

Pisanie SRS

https://aie24.pl/

Postanowiłem, że chcę stworzyć grę w kółko i krzyżyk. Aby pomóc sobie i mojemu asystentowi kodowania AI zrozumieć projekt, sformułowałem następujący monit dla ChatGPT:

Działaj jak doświadczony kierownik projektu oprogramowania. Zadaj mi pytania i wykorzystaj moje odpowiedzi do napisania specyfikacji wymagań oprogramowania dla gry w kółko i krzyżyk.

Szukam bardziej kreatywnej odpowiedzi, więc używam modelu GPT-4, a nie standardowego (w tym momencie) modelu GPT-3.5.

Odpowiedź ChatGPT pokazano na rysunku .

Moim następnym zadaniem jest napisanie odpowiedzi na pytania ChatGPT. Ponieważ ChatGPT ma swoje pytania jako kontekst w mojej bieżącej rozmowie, poprzedziłem każdą z moich odpowiedzi numerem i literą konkretnego pytania, jak pokazano na rysunku 2.

Aby uniknąć używania niepotrzebnych tokenów, wpisałem swoją odpowiedź na pytania w jednej wiadomości, naciskając Shift+Enter po każdym wierszu mojej odpowiedzi. Pozwala to ChatGPT na pobranie całej odpowiedzi na raz i unika konieczności odpowiadania przez model na każdą odpowiedź z osobna. Po przesłaniu moich odpowiedzi ChatGPT odpowiedział za pomocą SRS pokazanego na rysunku

SRS wygląda wystarczająco dobrze, ale jeśli chcę go zachować w pliku poza oknem ChatGPT, będę potrzebował go w bardziej użytecznym formacie. Poprosiłem ChatGPT o konwersję SRS na składnię Markdown. (Markdown to prosty język znaczników służący do dodawania formatowania do dokumentów tekstowych). Wynik pokazano na rysunku 4. Skopiowałem kod Markdown i zapisałem go w pliku z rozszerzeniem .md w nowym repozytorium Git dla projektu.

Wymagania niefunkcjonalne

https://aie24.pl/

Wymagania niefunkcjonalne odnoszą się do jakości systemu oprogramowania, w tym bezpieczeństwa, łatwości utrzymania, niezawodności, skalowalności i możliwości ponownego użycia. Ustalanie priorytetów dla wymagań niefunkcjonalnych często wiąże się z rozważeniem różnych założeń i ograniczeń, które mają zastosowanie do projektu. Założenia to czynniki, które uważa się za prawdziwe, ale nie zostały potwierdzone. Poniżej przedstawiono kategorie założeń:

»»Założenia techniczne odnoszą się do technologii, takiej jak sprzęt, systemy operacyjne i infrastruktura. Na przykład założenie techniczne może być takie, że komputer użytkownika będzie miał określoną ilość pamięci RAM.

»»Założenia operacyjne mają związek z zachowaniem i czynnikami użytkownika lub organizacji. Na przykład założenie operacyjne dla tej książki jest takie, że czytelnik jest programistą komputerowym (lub chce nim zostać).

»»Założenia biznesowe koncentrują się na kontekście biznesowym, w którym projekt będzie używany, takim jak polityka biznesowa i warunki rynkowe, które mogą mieć wpływ na projekt lub funkcjonalność oprogramowania.

»»Założenia środowiskowe to czynniki zewnętrzne, które mogą mieć wpływ na oprogramowanie, takie jak czynniki kulturowe, społeczne lub geograficzne lub dostępność stabilnego połączenia internetowego

Ograniczenia ograniczają opcje dostępne dla programistów systemu. Typy ograniczeń obejmują następujące:

»»Ograniczenia interfejsu definiują ograniczenia, jakie interfejs użytkownika oprogramowania nakłada na projekt. Jeśli opracowujesz aplikację mobilną, rozmiar ekranów urządzeń mobilnych ogranicza funkcjonalność i projekt aplikacji.

»»Ograniczenia wydajności definiują konkretne kryteria wydajności, które oprogramowanie musi spełniać. Na przykład możesz zdefiniować procent czasu sprawności lub maksymalny czas ładowania witryny.

»»Ograniczenia operacyjne odnoszą się do istniejących procesów organizacyjnych, zasad lub praktyk. Przykłady obejmują to, czy firma, w której oprogramowanie zostanie wdrożone, zezwala na korzystanie z określonych bibliotek oprogramowania lub zasady organizacji dotyczące korzystania z asystentów kodowania AI.

»»Ograniczenia cyklu życia dotyczą możliwości konserwacji, przenośności i ciągłego życia oprogramowania po jego zbudowaniu.

»»Ograniczenia ekonomiczne obejmują budżet na budowę i obsługę oprogramowania. Finanse są głównym ograniczeniem każdego projektu.

Określanie wymagań dotyczących oprogramowania jest ważną częścią każdego projektu i, wraz z pojawieniem się asystentów kodowania AI, umiejętnością, którą powinien posiadać każdy programista oprogramowania. Na temat wymagań dotyczących oprogramowania napisano wiele książek, ale najważniejszą z nich jest Software Requirements, 3rd Edition (Microsoft Press) autorstwa Karla Wiegersa i Joy Beatty.

Wymagania funkcjonalne

https://aie24.pl/

Wymagania funkcjonalne definiują sposób zachowania się systemu oprogramowania i są zazwyczaj definiowane przy użyciu określonych odpowiedzi na dane wejściowe lub warunki. Te oświadczenia dotyczące wymagań funkcjonalnych nazywane są przypadkami użycia lub historiami użytkownika. Przypadek użycia to szczegółowy opis wymogu funkcjonalnego. Definiuje, używając języka naturalnego, sposoby, w jakie użytkownik może wchodzić w interakcję z systemem (takim jak oprogramowanie lub strona internetowa) i jak system zareaguje. Szczegóły określone w przypadku użycia obejmują:

»»Cel

»»Czy użytkownik (nazywany aktorem w przypadkach użycia) jest człowiekiem czy innym systemem

»»Warunki wstępne, które muszą być obecne dla przypadku użycia (na przykład użytkownik musi być zalogowany)

»»Seria kroków, które wykona system

»»Alternatywne kroki (na przykład, co się dzieje, gdy użytkownik nie jest zalogowany)

»»Co się dzieje po zakończeniu kroków (znane również jako warunki końcowe)

Przypadki użycia nie są już powszechne we współczesnym rozwoju oprogramowania ze względu na popularność zwinnego rozwoju oprogramowania, w którym wymagania funkcjonalne są określane za pomocą historii użytkownika. Historie użytkownika to zazwyczaj nieformalne oświadczenia jednozdaniowe, napisane z punktu widzenia użytkownika. Zawierają one kto, co i dlaczego w odniesieniu do wyniku, który użytkownicy chcą osiągnąć za pomocą systemu. Historie użytkowników są często pisane w następującym formacie:

Jako [osoba], [chcę], [aby].

Na przykład:

Jako użytkownik, chcę móc zresetować swoje hasło, jeśli je zapomnę, abym mógł odzyskać dostęp do swojego konta.

Ten format nie jest jednak wymagany podczas pisania historii użytkowników. Często zdarza się również, zwłaszcza podczas początkowego procesu dokumentowania wymagań funkcjonalnych, że pojawiają się mniej ustrukturyzowane oświadczenia, które mogą ostatecznie zostać przekształcone w historie użytkowników.

Niezależnie od tego, czy zdecydujesz się pisać przypadki użycia, czy historie użytkowników, poniżej przedstawiono przykłady wymagań funkcjonalnych:

»»System musi umożliwiać użytkownikom tworzenie konta.

»»System musi umożliwiać użytkownikom logowanie się za pomocą nazwy użytkownika i hasła.

»»System musi umożliwiać użytkownikom kliknięcie łącza „zapomniałem hasła”, aby zresetować hasło.

»»Po utworzeniu konta przez użytkownika zostanie wyświetlona strona logowania, na której może on wprowadzić nazwę użytkownika i hasło, aby się zalogować.

»»Po pomyślnym zalogowaniu się użytkownika zostanie wyświetlona strona kanału informacyjnego.

»»Strona kanału informacyjnego przedstawia użytkownikowi listę najnowszych postów zamieszczonych przez innych użytkowników.

»»Na dole strony kanału informacyjnego użytkownicy mogą wprowadzić tekst do pola wprowadzania i kliknąć przycisk Prześlij, aby utworzyć nowy post.

Nie musisz uwzględniać wszystkich szczegółów wymagań funkcjonalnych dla SRS. Jednak określenie, kto będzie korzystał z systemu, co należy zbudować i dlaczego należy to zrobić, zapewni większą przejrzystość podczas pisania kodu i zapewni Twojemu asystentowi AI większy kontekst.

Wymagania domenowe

https://aie24.pl/

Wymagania domenowe są specyficzne dla kategorii, celu lub branży, w której oprogramowanie będzie używane. Możliwe jest, że oprogramowanie będzie funkcjonalne i przyjazne dla użytkownika, ale nie będzie akceptowalne do użytku, ponieważ nie spełnia wymagań domenowych. Na przykład, jeśli opracujesz aplikację bankowości internetowej, która nie spełnia wymagań prawnych i regulacyjnych mających zastosowanie do aplikacji bankowości internetowej, nie spełnia ona swoich wymagań.

Zrozumienie wymagań projektu

https://aie24.pl/

Jeśli kiedykolwiek zostałeś rzucony na pracę nad nowym projektem, którego nie do końca rozumiesz, możesz utożsamić się z tym, co czułby asystent kodowania przez cały czas — gdyby asystent kodowania mógł cokolwiek czuć. Chociaż asystenci kodowania widzieli wiele kodu, jedynym sposobem, w jaki mogą ci pomóc, jest posiadanie kontekstu dotyczącego konkretnych wymagań kodu, który piszesz.

Określanie wymagań dotyczących oprogramowania

Rozpoczynając pracę z asystentem kodowania, zastanów się, co musisz wiedzieć przed rozpoczęciem pracy nad projektem. W szczególności musisz wiedzieć:

»»Co będzie robić oprogramowanie?

»»Dla kogo tworzysz oprogramowanie?

»»Kto będzie korzystać z oprogramowania?

»»Gdzie i jak oprogramowanie będzie robić to, co robi?

»»Jak użytkownik będzie wchodzić w interakcję z oprogramowaniem?

»»Jakich języków i technologii użyjesz do zbudowania oprogramowania?

»»Jakie są cele oprogramowania?

»»Czy istnieją jakieś normy prawne lub regulacyjne, z którymi oprogramowanie musi

spełniać?

W świecie rozwoju oprogramowania odpowiedzi na te pytania nazywamy wymaganiami dotyczącymi oprogramowania. Możesz określić wymagania dotyczące oprogramowania swojego projektu, korzystając ze specyfikacji wymagań dotyczących oprogramowania (SRS), która jest dokumentem szczegółowo opisującym, co planowane oprogramowanie będzie robić i jak będzie się od niego oczekiwać. W przypadku małych projektów pełna SRS zazwyczaj nie jest konieczna. Jednak jakaś forma dokumentacji wymagań jest niezbędna w każdym projekcie, a ustalenie wymagań dla siebie jest niezbędne, aby móc przekazać je innemu programiście lub asystentowi kodowania AI. Wymagania dotyczące oprogramowania można podzielić na trzy szerokie kategorie: wymagania domenowe, wymagania funkcjonalne i wymagania niefunkcjonalne.

Przejście od planu do prototypu

https://aie24.pl/

Chociaż możliwe jest korzystanie z asystenta kodowania AI w celu generowania działającego kodu, a nawet całych programów, akceptowalne wyniki są dalekie od gwarancji. Jakość wyników, które otrzymasz, zależy od kilku czynników, w tym używanego LLM, danych wejściowych, które przekazujesz modelowi, własnych umiejętności kodowania i tego, jak jasno zdefiniowałeś wymagania projektu. Rozdział 4 zawiera przykład wykorzystania AI do zrobienia czegoś, co większość programistów mogłaby zrobić szybciej i lepiej bez AI. W tym rozdziale zaczynasz poznawać procesy i wskazówki dotyczące uzyskiwania spójnych i wyższej jakości wyników.

Plik config.py

https://aie24.pl/

OPENAI_API_KEY = “YOUR_API_KEY_HERE”

Zanim uruchomisz chatbota, musisz zainstalować Gradio i bibliotekę OpenAI. Uruchom następujące dwa polecenia w swoim terminalu:

pip install openai

pip install gradio

Po zainstalowaniu tych elementów możesz uruchomić program, wpisując python chatbot_demo.py w terminalu. Ten kod technicznie działa w ten sposób, że wysyła tekst, który wpisuję do pola tekstowego, do API OpenAI i wyświetla wynik. Ale to nie to, co miałem na myśli, a uzupełnienie, które zwraca, to bełkot, jak pokazano na rysunku .

Największym problemem jest to, że program wysyła każde naciśnięcie klawisza do API, zamiast czekać, aż zakończę wprowadzanie danych i kliknę przycisk. Sprawdzając moje konto na platformie OpenAI, widzę, że mój szybki test tego programu kosztował mnie 3 centy. To niewiele, ale podejrzewam, że zmiana kodu tak, aby czekał na wysłanie wszystkich monitów na raz, zamiast wysyłać jeden list na raz, zaoszczędziłaby mi dużo pieniędzy i skutkowałaby lepszym wynikiem. Prosta zmiana wartości właściwości live z True na False rozwiązuje ten problem. Następnym problemem jest to, że model używa modelu GPT-3. Podejrzewam, że wyniki, które otrzymam, będą znacznie lepsze, jeśli przełączę się na używanie GPT-3.5. Aby to naprawić, zmieniłem model=”davinci” na model=”gpt-3.5-turbo”, a następnie zatrzymałem i ponownie uruchomiłem program Python. Tym razem, gdy próbowałem przesłać swoje dane wejściowe, otrzymałem błąd w konsoli, że punkt końcowy nie obsługuje ukończeń czatu. Skonsultowałem dokumentację Python OpenAI i odkryłem, że muszę zmienić openai.Completion na openai.ChatCompletion i zmienić parametry, które przekazywałem do OpenAI. Przetestowałem to ponownie, a wynik pokazano na rysunku .

Proces, przez który przeszedłem, aby uzyskać działającą wersję demonstracyjną, obejmował przeglądanie dokumentacji w bibliotece Python OpenAI i bibliotece Gradio bardziej niż otrzymywanie pomocnych wskazówek od modeli AI. Ostatecznie, chociaż udało mi się uruchomić mojego chatbota, miałem wrażenie, że o wiele szybciej byłoby zakodować aplikację od podstaw bez pomocy AI. Zaczynając od następnego rozdziału, pokazuję lepsze podejście do pracy z generatywną AI, które z większym prawdopodobieństwem zaowocuje działającym kodem, który robi to, co powinien robić.