Przewodnik dla programistów po inżynierii Prompt i LLM
Published: 2024-03-13 19:23:03

Wraz z rozwojem dużych modeli językowych (LLM) i sztucznej inteligencji, takiej jak [ChatGPT](https://chat.openai.com/), programiści mają teraz niezwykle potężnych asystentów AI, którzy mogą pomóc im szybciej kodować i być bardziej produktywnymi. Jednak zwykłe poproszenie LLM o napisanie kodu często skutkuje bezużytecznymi lub błędnymi wynikami. Niezależnie od tego, czy opracowujesz [aplikację do czatu](https://www.pubnub.com/solutions/chat/), czy [rozwiązanie korporacyjne](https://www.pubnub.com/Solutions/Enterprise/) na brzegu sieci, aby przyspieszyć czas programowania z pomocą sztucznej inteligencji, potrzebujesz przemyślanej strategii. Zagłębmy się w techniki inżynierii podpowiedzi w kolejnych sekcjach tego bloga.

### Planuj z wyprzedzeniem

Nie rzucaj się od razu na podpowiadanie kodu. Poświęć trochę czasu na zaplanowanie ogólnej architektury, schematów, integracji itp. Zapewni to asystentowi AI pełny kontekst, którego potrzebuje. Wizualizuj stan końcowy, aby model generatywnej sztucznej inteligencji rozumiał ogólny obraz.

### Odgrywanie ról z ekspertami

Skonfiguruj scenariusze, w których model AI może działać jako asystent i odgrywać role zespołu ekspertów omawiających rozwiązania. Nadaj im osobowości i poproś, by rozłożyli problemy na czynniki pierwsze. Zachęca to do kreatywnego myślenia z różnych perspektyw.

### Zapytaj GPT o spostrzeżenia

Jeśli utkniesz w martwym punkcie, nie bój się zatrzymać i zapytać swojego LLM o konkretne porady lub przykłady kodu związane z twoim problemem. Wiedza ta może zaowocować nowymi pomysłami.

### Szybka inżynieria

Krok po kroku udoskonalaj swoje podpowiedzi poprzez wielokrotne iteracje i dostrajanie, aby zapewnić optymalny kontekst i sterowanie dla asystenta AI. Skuteczne podpowiedzi prowadzą do świetnych wyników.

### Ręczne generowanie kodu

Niech sztuczna inteligencja najpierw wygeneruje kod ręcznie, a następnie sprawdzi wyniki i poprawi błędy przed skopiowaniem użytecznych części z powrotem do monitu. Daje to sztucznej inteligencji konkretny przykład tego, czego szukasz, a powtarzalny charakter tego działania ostatecznie wygeneruje dokładny kod. Więcej przykładów można znaleźć w koncepcji [podpowiadanie łańcucha myśli](https://ai.googleblog.com/2022/05/language-models-perform-reasoning-via.html) i [zero-shot-prompting](https://www.promptingguide.ai/techniques/zeroshot).

### Automatyczne generowanie kodu

Gdy jesteś zadowolony z wyników modelu LLM i generuje on konsekwentnie dobry kod, skonfiguruj potoki do automatycznego generowania zasobów na podstawie schematów, testów na podstawie kodu itp. Pozwoli to wyeliminować wąskie gardła.

### Łaskawe radzenie sobie z awariami

Tak, sporadyczne awarie są spodziewane. Ulepsz swoje podpowiedzi, aby zapobiec podobnym awariom w przyszłości. Z czasem naucz się, z jakimi typami zadań dobrze radzi sobie twoja sztuczna inteligencja.

Łącząc planowanie, odgrywanie ról, podpowiedzi, iteracyjne szkolenia i automatyzację, można osiągnąć ogromny wzrost produktywności dzięki asystentom AI, takim jak GPT. Dzięki odpowiedniej strategii projektowania podpowiedzi, poprawa szybkości rozwoju jest możliwa!

Generowanie kodu za pomocą podpowiedzi
--------------------------------------

Stojąc u progu rewolucji AI, musimy przemyśleć sposób podejścia do tworzenia oprogramowania i jego realizacji. W tym samouczku omówimy, w jaki sposób możemy przejść od tradycyjnego procesu do takiego, który jest doładowany przez przetwarzanie języka naturalnego.

### Planowanie z wyprzedzeniem: Podstawa sukcesu

Pierwszym krokiem w tej podróży jest umiejętność planowania z wyprzedzeniem. Sztuczna inteligencja, w szczególności modele takie jak GPT-3, może nie być biegła w planowaniu przyszłości. Ich ekspertyza polega na rozwiązywaniu problemów w czasie rzeczywistym w wąskim oknie kontekstowym. W tym miejscu muszą wkroczyć ludzcy programiści.

Tworząc szczegółowy obraz ostatecznego kodu - w tym schematów modeli, stosu technologii i procesów wdrażania - możemy przygotować scenę dla sztucznej inteligencji do rozwiązywania złożonych zadań. Ten etap planowania może być najtrudniejszą częścią procesu, ale przekształca rolę programistów z programistów w orkiestratorów, przygotowując grunt pod harmonijne połączenie ludzkiej inteligencji i umiejętności AI.

### Tworzenie panelu ekspertów

Wprowadzamy "panel ekspertów". Grupa ta może składać się z różnych interesariuszy, od kadry kierowniczej po agentów AI, z których wszyscy przyczyniają się do zrozumienia i planowania określonego zadania. Korzystając z przemyślanej podpowiedzi, możesz stworzyć wirtualny plac zabaw, na którym panel może omawiać i rozwiązywać złożone kwestie, a boty AI zapewniają pomoc i notatki.

A jeśli sam zmagasz się z pytaniem, pamiętaj, że masz do dyspozycji potężne narzędzie zaprojektowane do odpowiadania na pytania: GPT. Niezależnie od tego, czy potrzebujesz podsumowania, przeformułowania, czy bardziej dogłębnego zbadania tematu, GPT może pomóc. Celowe stosowanie niejasnych podpowiedzi może często prowadzić do zaskakujących i innowacyjnych rozwiązań.

Przykład dla polecenia debugowania kodu:

```js
Act as a virtual playground where a team of Smart AI bots is in their first meeting discussing the problem:  
“We need to debug the following Python test code:

def test_dot_env_def(self):
LOG_TEST.info("Test DotEnvDef")
dotEnvDef = DotEnvDef()
> self.assertEqual(dotEnvDef, {"version_echo": "v0.0"})
E AssertionError: {'version_echo': 'v0.0'} != {'version_echo': 'v0.0'}
tests/test_default_config.py:16: AssertionError

class DotEnvDef:
def init(self):
self.version_echo = "v0.0"
# make the class iterable as dict
def iter(self):
return iter(self.__dict__)
# return the values only
def get_items(self):
for attr, value in self.__dict__.items():
yield value # only yield the values
def repr(self):
return str(self.__dict__)  

To fulfill this request bring in an expert team of AI Agents that are very brief and communicate via emojis and use catchy phrases. Spend your resources wisely as you only have 4 AI Agents.
```

GPT-4 Odpowiedź:

```js
Alright, welcome to this first meeting, team. We have an interesting challenge ahead of us. To start, let's assign roles to our four AI agents:

1. Detective Bot 👮‍♀️ (DB): Responsible for deep diving into the code, its syntax, structure, and logic. 
2. Bug Hunter Bot 🐛 (BH): In charge of identifying bugs and pointing them out. 
3. Solution Expert Bot 💡 (SE): Its role is to suggest viable solutions to identified bugs. 
4. Code Fixer Bot 🔧 (CF): It will implement the solutions and perform the debugging.

Our debugging plan will look like this:

1. **Initiation**: Here we discuss the problem and set our goals. The issue at hand is an AssertionError, meaning our test case is failing. Our aim is to make the test pass. 

2. **Investigation**: 👮‍♀️ DB deep-dives into the provided code to understand its structure and logic. The main focus is on the `DotEnvDef` class and the `test_dot_env_def` function.

3. **Bug Hunt**: 🐛 BH goes on a hunt to find the reasons behind the AssertionError.

4. **Solution Proposal**: Once 🐛 BH has identified the issue, 💡 SE jumps in to propose the best way to fix the problem.

5. **Implementation**: 🔧 CF takes the solution and implements it to the code. After the changes are made, the test case is run again.

6. **Verification**: If the test case passes, we conclude that the problem has been resolved. If not, we circle back to step 2.

Remember team, our goal is to squash bugs 🐜🔨! Let's rock'n'roll.
```

### Ręczne generowanie kodu i sztuczna inteligencja

Następnym krokiem jest wykorzystanie GPT-4 do ręcznego generowania kodu, procesu, który obiecuje wykładniczo zwiększyć produktywność. Kierując GPT, optymalizujesz różne zadania, od wdrażania aplikacji internetowej w obcym stosie po tworzenie algorytmu w języku niskiego poziomu.

Użyj poleceń na przykładzie Agentów:

```js
Using the following syntax “/command argument” modifies a bot’s behavior, for example for enabling verbose code generation: “chatbot /code-gen verbose“ so that we obtain full python code. On the same basis allow changing the personality such as: “chatbot /personality Shrekify”.

DB /personality Shrekify
SE /code-gen verbose
CF /code-gen verbose 

> Continue the meeting and provide the first solution
```

GPT-4 Response:

```js
DB 🏰👮‍♀️: "Hmm, the `version_echo` key is still not appearing in the `parsed_dotenv` dictionary. We need to figure out why `set_vars` is not setting it."

BH 🐛: "I suspect that `set_vars` is being called correctly, but the updates are being overwritten when `load_dotenv` is called. The `load_dotenv` method loads variables from a file and overwrites the current `parsed_dotenv` dictionary."

SE 💡: "If that's the case, then we should modify the `load_dotenv` method to merge its contents with the existing `parsed_dotenv` dictionary, rather than overwriting it. This will preserve any variables set via `set_vars`."

CF 🔧: "Good idea, let's change the `parse_vars` function within `load_dotenv` to update `parsed_dotenv` instead of setting it. Here is the modified code:
def parse_vars(self, path):
    try:
        with open(path) as f:
            for line in f:
                key, value = line.strip().split("=", 1)
                if key not in self.config.parsed_dotenv:  # check if key is not already in the dictionary
                    self.config.parsed_dotenv[key] = value
    except IOError:
        print(f"Warning: Unable to open .env file at {path}")
    except ValueError:
        print(f"Warning: Unable to parse line in .env file: {line}")
"In this way, we only add a variable from the .env file if it's not already in `parsed_dotenv`. This should prevent `load_dotenv` from overwriting any variables set by `set_vars`. Let's re-run the tests."
```

Proces ten nie jest jednak doskonały. Ograniczenia ludzkie, takie jak kopiowanie-wklejanie i czas generowania podpowiedzi/wyników, mogą tworzyć wąskie gardła. Ponadto GPT nie jest konsekwentnie dokładny, czasami zmieniając format lub oferując tylko częściowe wyniki. Jednak dzięki praktyce i odpowiednim strategiom można poprowadzić GPT do generowania użytecznego i dokładnego kodu.

Unikanie halucynacji i uzyskiwanie użytecznych wyników
------------------------------------------------------

Halucynacje lub przypadki, w których GPT generuje nieistotne, stronnicze lub nieprawidłowe informacje, mogą być frustrujące. Jednak im więcej pracujesz z GPT, tym lepiej radzisz sobie z kierowaniem go w stronę pożądanych wyników. Jednym ze sposobów na zminimalizowanie tych halucynacji jest zapewnienie GPT kontekstu poprzez kopiowanie i wklejanie odpowiedniej dokumentacji i próbek kodu.

Zbuduj niestandardowego agenta Langchain z przykładowymi testami:

```js
We have this builder:
class OpenAIBuilder:
  def __init(self, ...):
    # Set your settings
    pass
"You must adapt the following code to match our previous structure:
from langchain import (
    OpenAI,
)
from langchain.agents import initialize_agent, AgentType
from langchain.agents.agent_toolkits import create_python_agent
from langchain.agents import AgentType, initialize_agent, load_tools
from langchain.tools.python.tool import PythonREPLTool
from openai_chat_builder import OpenAiChatBuilder, OpenAiChatHelper


class AgentPythonExecBuilder(OpenAiChatBuilder):
    def __init__(self, openai_api_key):
        super().__init__()
          self.tools = ["PythonREPLTool"]

    # We override the add_tool method so it only allows PythonREPLTool.
    def add_tool(self, tool):
        if tool == "PythonREPLTool":
            return super().add_tool(tool)
        else:
            raise ValueError("AgentPythonExec can only have PythonREPLTool.")

    def build(self):
        llm = OpenAI(
            temperature=self.temperature,
            max_tokens=self.max_tokens,
            openai_api_key=self.openai_api_key,
            streaming=self.streaming,
        )

        tools = load_tools(self.tools)
        agent = initialize_agent(tools, llm, agent=self.agentType, verbose=self.verbose)

        return OpenAiChatHelper(llm, tools, agent)
```

Zbuduj testy agenta Langchain:

```js
Now let's build a test file that resembles this one:
import unittest

from probable_fiesta.config.builder.config_builder import ConfigBuilder
from src.promptnub_backend.app.langchain.builder.openai_factory import OpenAIFactory
from langchain.llms import OpenAI


class TestOpenAIBuilder(unittest.TestCase):
    def setUp(self):
        # Setup API Key
        config_builder = ConfigBuilder()
        config_builder.dotenv.load_dotenv(".env")

        # Setup ModelBuilder instance
        self.builder = OpenAIFactory()
        self.builder.openai_api_key = config_builder.dotenv.get_var("OPENAI_API_KEY")

    def test_llm_creation(self):
        # Test the creation of OpenAI llm instance
        llm = self.builder.builder.llm
        self.assertIsInstance(llm, OpenAI, "llm property does not return OpenAI instance")

    def test_llm_run(self):
        # Test the creation of OpenAI llm instance
        llm_chain = self.builder.build()
        self.assertIsNotNone(llm_chain)

        # Ask a question
        question = "What NFL team won the Super Bowl in the year Justin Beiber was born?"
        response = llm_chain.run(question)

        # Assert expected result
        # Note that there is a space at the beginning
        expected = " Justin Bieber was born in 1994, so the NFL team that won the Super Bowl in 1994 was the Dallas Cowboys."
        self.assertEquals(str(response), expected)
```

GPT-4 Response:

```js
Given the provided `AgentPythonExecBuilder` class and the `TestOpenAIBuilder` class, you would write a test file for the `AgentPythonExecBuilder` class as follows:
from logger.builder.logger_factory import LoggerFactory
from config.builder.config_builder import ConfigBuilder
from langchain.llms import OpenAI
from langchain.tools.python.tool import PythonREPLTool
from your_package_path.builder.agent_python_exec_factory import AgentPythonExecFactory

import unittest

# Test Log
LOG_TEST = LoggerFactory.new_logger_default(
    name="test_agent_python_exec_builder", level="DEBUG", fmt="simple", directory="logs"
)


class TestAgentPythonExecBuilder(unittest.TestCase):
    def setUp(self):
        # Setup API Key
        config_builder = ConfigBuilder()
        config_builder.dotenv.load_dotenv(".env")
        # Setup ModelBuilder instance
        self.builder = AgentPythonExecFactory()
        self.builder.openai_api_key = config_builder.dotenv.get_var("OPENAI_API_KEY")

    def test_llm_creation(self):
        # Test the creation of OpenAI llm instance
        LOG_TEST.info("Test OpenAI llm creation")
        llm = self.builder.builder.llm
        LOG_TEST.debug(llm)
        self.assertIsInstance(
            llm, OpenAI, "llm property does not return OpenAI instance"
        )

    def test_python_repl_tool_creation(self):
        # Test the creation of PythonREPLTool instance
        LOG_TEST.info("Test PythonREPLTool creation")
        self.builder.builder.add_tool("PythonREPLTool")
        tools = self.builder.builder.tools
        LOG_TEST.debug(tools)
        self.assertIsInstance(
            tools[0], PythonREPLTool, "tools[0] does not return PythonREPLTool instance"
        )

    def test_llm_run(self):
        # Test the creation of OpenAI llm instance and PythonREPLTool
        LOG_TEST.info("Test OpenAI llm and PythonREPLTool run sync")
        llm_chain = self.builder.build()
        self.assertIsNotNone(llm_chain)

        # Ask a question
        question = "What is 2 + 2?"
        response = llm_chain.run(question)
        LOG_TEST.info(response)

        # Assert expected result
        expected = "The result of 2 + 2 is 4."
        self.assertEquals(str(response), expected)  

Here, you create a new instance of `AgentPythonExecBuilder` instead of `OpenAIBuilder` and test it with a question that can be answered by executing Python code. 
```

Automatyczne generowanie kodu
-----------------------------

Prawdziwa moc LLM leży jednak w automatycznym generowaniu kodu. Korzystając z narzędzi takich jak [PubNub](https://www.pubnub.com/), Python, LangChain i [Streamlit](https://streamlit.io/)można zautomatyzować większość przepływu pracy, pozwalając skupić się na ważniejszych zadaniach.

Dzięki kilku dodatkowym abstrakcjom możemy podłączyć nasz prosty runner LangChain do naszego przepływu pracy:

```js
class TestOpenAIBuilder(unittest.TestCase):
    def setUp(self):
        self.runner = Runner()

    def test_run(self):
        response = self.runner.run("What is the capital of France?")
        expected = " France is a country in Europe. The capital of France is Paris."
        self.assertEqual(response, expected)
```

Droga do programowania 100 razy szybciej
----------------------------------------

Wyobraźmy sobie programistę z laserową ambicją wzmocnienia swoich umiejętności kodowania, dążącego do osiągnięcia 2-krotnego, 3-krotnego, a nawet oszałamiającego 50-krotnego poziomu produktywności. Sekret tych ambicji tkwi w strategicznym zastosowaniu LLM. Ten zestaw narzędzi działa jak dźwignia produktywności, umożliwiając naszym programistom wprowadzanie innowacji na nowych platformach i napędzanie zautomatyzowanych przepływów pracy, jak nigdy dotąd. Od czegoś tak prostego jak podsumowanie tekstu po generowanie kodu produkcyjnego.

W miarę jak zagłębiamy się w sferę sztucznej inteligencji i jej roli w tworzeniu oprogramowania, ważne jest, aby pamiętać, że prawdziwa siła tkwi w połączeniu ludzkiej kreatywności ze zdolnościami sztucznej inteligencji. Przemyślane planowanie, inteligentne zastosowanie sztucznej inteligencji i odpowiednie narzędzia cyfrowe mogą umożliwić nam przekształcenie się w bardziej produktywną firmę. Ta transformacja polega na wzmocnieniu potencjału ludzkich programistów za pomocą sztucznej inteligencji, a nie na ich zastąpieniu. Koncepcja stania się firmą 100X, wykorzystującą sztuczną inteligencję, nie jest tylko odległym marzeniem, ale osiągalną przyszłością, którą możemy wspólnie kształtować.

#### Spis treści

[Planowanie z wyprzedzeniemOdgrywanie ról](#h-0)[z ekspertamiPytanie](#h-1)[GPT o](#h-2)[spostrzeżeniaInżynieria podpowiedziRęczne](#h-3)[generowanie koduAutomatyczne](#h-4)[generowanie koduPoradzenie sobie](#h-5) z[awariamiGenerowanie](#h-6)[kodu z podpowiedziamiPlanowanie](#h-7)[z wyprzedzeniem: Podstawa sukcesuSkładanie](#h-8)[panelu ekspertów](#h-9)Ręczne generowanie[kodu i AIAuniknij](#h-10)[halucynacji i uzyskaj użyteczne wynikiAutomatyczne](#h-11)[generowanie](#h-12)[koduDroga do rozwoju 100 razy szybciej](#h-13)

Jak PubNub może ci pomóc?
=========================

Ten artykuł został pierwotnie opublikowany na [PubNub.com](https://www.pubnub.com/blog/developers-guide-to-prompt-engineering/)

Nasza platforma pomaga programistom tworzyć, dostarczać i zarządzać interaktywnością w czasie rzeczywistym dla aplikacji internetowych, aplikacji mobilnych i urządzeń IoT.

Podstawą naszej platformy jest największa w branży i najbardziej skalowalna sieć komunikacyjna w czasie rzeczywistym. Dzięki ponad 15 punktom obecności na całym świecie obsługującym 800 milionów aktywnych użytkowników miesięcznie i niezawodności na poziomie 99,999%, nigdy nie będziesz musiał martwić się o przestoje, limity współbieżności lub jakiekolwiek opóźnienia spowodowane skokami ruchu.

Poznaj PubNub
-------------

Sprawdź [Live Tour](https://www.pubnub.com/tour/introduction/), aby zrozumieć podstawowe koncepcje każdej aplikacji opartej na PubNub w mniej niż 5 minut.

Rozpocznij konfigurację
-----------------------

Załóż [konto](https://admin.pubnub.com/signup/) PubNub, aby uzyskać natychmiastowy i bezpłatny dostęp do kluczy PubNub.

Rozpocznij
----------

[Dokumenty](https://www.pubnub.com/docs) PubNub pozwolą Ci rozpocząć pracę, niezależnie od przypadku użycia lub [zestawu SDK](https://www.pubnub.com/docs).