AI Agents · Lekcja

Agenci interaktywni w stylu REPL

Pętle danych wejściowych, historia i wieloturowa konwersacja w agentach terminalowych.

Lekcja 2 z 413 kroki

Agenci interaktywni w stylu REPL to bezpłatna lekcja AI Agents na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej AI Agents, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs AI Agents zawiera 4 lekcji w sumie.

Czym jest agent w stylu REPL?

REPL (Read-Eval-Print Loop) to interaktywna sesja terminala, w której wpisuje się dane, otrzymuje wynik i kontynuuje pracę. Agenty konwersacyjne działające w terminalu funkcjonują dokładnie w ten sposób: użytkownik wpisuje wiadomość, agent odpowiada, a rozmowa trwa do momentu zakończenia przez użytkownika.

Podstawowa pętla REPL

Najprostszy REPL to pętla while True, która odczytuje dane użytkownika za pomocą input(), przetwarza je i wyświetla wynik. Pętla działa bez końca, dopóki użytkownik nie zasygnalizuje zakończenia.

def run_agent_repl(inputs):
    print('Agent started. Type /exit to quit.')
    conversation_history = []
    for user_input in inputs:
        user_input = user_input.strip()
        if not user_input:
            continue
        if user_input == '/exit':
            print('Goodbye!')
            break
        conversation_history.append({'role': 'user', 'content': user_input})
        agent_reply = f'[Agent reply to: {user_input}]'
        conversation_history.append({'role': 'assistant', 'content': agent_reply})
        print(f'Agent: {agent_reply}')

run_agent_repl(['Hello agent', 'What can you do?', '/exit'])

Elegancka obsługa KeyboardInterrupt

Po naciśnięciu przez użytkownika klawiszy Ctrl+C Python zgłasza wyjątek KeyboardInterrupt. Należy przechwycić go na najwyższym poziomie, aby zamiast śladu stosu wyświetlić przyjazny komunikat pożegnalny.

def run_agent_repl():
    print('Agent ready. Press Ctrl+C to exit.')
    conversation_history = []

    try:
        while True:
            user_input = input('You: ').strip()
            if not user_input:
                continue

            conversation_history.append({'role': 'user', 'content': user_input})
            reply = '[mocked agent response]'
            conversation_history.append({'role': 'assistant', 'content': reply})
            print(f'Agent: {reply}')

    except KeyboardInterrupt:
        print('\nSession ended. Goodbye!')
    except EOFError:
        # Triggered when stdin is closed (piped input ends)
        print('\nEnd of input. Exiting.')

if __name__ == '__main__':
    import builtins
    _demo_inputs = iter(['What agents can you build?', EOFError])
    def _fake_input(prompt=''):
        val = next(_demo_inputs)
        if val is EOFError:
            raise EOFError
        print(prompt + val)
        return val
    builtins.input = _fake_input
    run_agent_repl()

Zachowywanie historii wieloturowej rozmowy

Aby agent miał pamięć rozmowy, należy przechowywać listę wiadomości i przy każdej turze przekazywać do LLM pełną historię. Rozmowę należy rozpocząć od wiadomości systemowej określającej osobowość agenta.

import openai

client = openai.OpenAI(api_key='YOUR_API_KEY')

def run_chat_repl():
    history = [
        {'role': 'system', 'content': 'You are a helpful AI assistant.'}
    ]

    print('Chat started. Type /exit to quit.')

    try:
        while True:
            user_input = input('You: ').strip()
            if not user_input or user_input == '/exit':
                break

            history.append({'role': 'user', 'content': user_input})

            response = client.chat.completions.create(
                model='gpt-4o-mini',
                messages=history
            )

            reply = response.choices[0].message.content
            history.append({'role': 'assistant', 'content': reply})
            print(f'Agent: {reply}')

    except KeyboardInterrupt:
        print('\nGoodbye!')

readline: historia i edycja danych wejściowych

Moduł readline (Unix/Mac) umożliwia poruszanie się za pomocą klawiszy strzałek po wcześniej wprowadzonych danych, podobnie jak w prawdziwej powłoce. Użytkownicy mogą nacisnąć strzałkę w górę, aby przywołać poprzednie wiadomości.

try:
    import readline  # available on Unix/Mac, not Windows
    # Enable persistent history between sessions
    import os
    HISTORY_FILE = os.path.expanduser('~/.agent_history')
    try:
        readline.read_history_file(HISTORY_FILE)
    except FileNotFoundError:
        pass

    import atexit
    atexit.register(readline.write_history_file, HISTORY_FILE)
    readline.set_history_length(500)
    print('History enabled (use up/down arrows)')
except ImportError:
    pass  # readline not available on Windows

# After this, input() automatically has history support

Wbudowane polecenia z ukośnikiem

Należy wyposażyć agenta REPL we wbudowane polecenia z ukośnikiem do typowych operacji: /help, /exit oraz /clear do resetowania rozmowy i /history do wyświetlania poprzednich wiadomości.

def handle_command(cmd: str, history: list) -> bool:
    'Returns True if the command was handled, False if it is a regular message'
    if cmd == '/exit' or cmd == '/quit':
        print('Goodbye!')
        raise SystemExit(0)

    elif cmd == '/help':
        print('Commands: /exit, /clear, /history, /help')
        return True

    elif cmd == '/clear':
        # Keep only the system message
        system = history[0] if history and history[0]['role'] == 'system' else None
        history.clear()
        if system:
            history.append(system)
        print('[Conversation cleared]')
        return True

    elif cmd == '/history':
        for i, msg in enumerate(history):
            if msg['role'] != 'system':
                print(f'  [{msg["role"]}] {msg["content"][:80]}')
        return True

    return False  # not a command, treat as regular message

if __name__ == '__main__':
    demo_history = [
        {'role': 'system', 'content': 'You are a helpful agent.'},
        {'role': 'user', 'content': 'Hi there'},
        {'role': 'assistant', 'content': 'Hello! How can I help?'},
    ]
    handle_command('/help', demo_history)
    handle_command('/history', demo_history)

Ograniczanie długości historii rozmowy

Przekazywanie całej historii rozmowy do LLM przy każdej turze powoduje liniowy wzrost liczby tokenów. Aby kontrolować koszty, należy ograniczyć historię do ostatnich N wiadomości, zachowując wiadomość systemową.

def trim_history(history: list, max_turns: int = 10) -> list:
    system_messages = [m for m in history if m['role'] == 'system']
    non_system = [m for m in history if m['role'] != 'system']

    # Keep the last max_turns messages (each turn = 1 user + 1 assistant)
    max_messages = max_turns * 2
    trimmed = non_system[-max_messages:]

    return system_messages + trimmed

# Usage in the REPL loop:
# history.append({'role': 'user', 'content': user_input})
# trimmed = trim_history(history, max_turns=10)
# response = client.chat.completions.create(model='gpt-4o-mini', messages=trimmed)
print('Trimming history prevents token count from growing unboundedly')

Wyświetlanie powitalnego banera

Powitalny baner sprawia, że REPL wygląda bardziej profesjonalnie. Należy wyświetlić go raz podczas uruchamiania, podając nazwę agenta, jego wersję i dostępne polecenia. Można użyć prostej grafiki ASCII lub biblioteki rich do dodania kolorów.

def print_banner():
    banner = '''
====================================
  AI Research Agent v1.0
====================================
  Type your question to begin.
  Commands: /help  /clear  /exit
====================================
    '''
    print(banner)

# Or with rich colors:
# from rich.console import Console
# from rich.panel import Panel
# console = Console()
# console.print(Panel('[bold cyan]AI Research Agent[/] v1.0', subtitle='Type /help for commands'))

print_banner()

Wyświetlanie wskaźników pisania

Wywołania LLM mogą trwać kilka sekund. Podczas oczekiwania należy wyświetlić komunikat „thinking...”, aby użytkownicy wiedzieli, że agent przetwarza żądanie. Po nadejściu odpowiedzi należy go usunąć.

import sys
import threading
import time

def thinking_spinner(stop_event: threading.Event):
    frames = ['|', '/', '-', '\\']
    i = 0
    while not stop_event.is_set():
        sys.stdout.write(f'\rAgent is thinking... {frames[i % 4]}')
        sys.stdout.flush()
        time.sleep(0.1)
        i += 1
    sys.stdout.write('\r' + ' ' * 30 + '\r')  # clear the line
    sys.stdout.flush()

def call_agent_with_spinner(query: str) -> str:
    stop = threading.Event()
    spinner = threading.Thread(target=thinking_spinner, args=(stop,))
    spinner.start()

    # result = agent.run(query)  # the actual slow call
    time.sleep(1)  # simulating work
    result = 'The answer is 42.'

    stop.set()
    spinner.join()
    return result

if __name__ == '__main__':
    answer = call_agent_with_spinner('What is 6 * 7?')
    print(f'\nFinal answer: {answer}')

Zapisywanie sesji do pliku

Należy umożliwić użytkownikom zapisanie rozmowy do pliku po zakończeniu sesji. Jest to przydatne podczas sesji badawczych, gdy potrzebny jest zapis informacji znalezionych przez agenta.

import json
import datetime
import os

def save_session(history: list, directory: str = 'sessions'):
    os.makedirs(directory, exist_ok=True)
    timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
    filename = os.path.join(directory, f'session_{timestamp}.json')

    with open(filename, 'w') as f:
        json.dump({
            'saved_at': timestamp,
            'messages': history
        }, f, indent=2)

    print(f'Session saved to {filename}')

# Usage in REPL on /save command:
# save_session(conversation_history)

if __name__ == '__main__':
    import tempfile
    demo_dir = tempfile.mkdtemp()
    demo_history = [
        {'role': 'user', 'content': 'Hello'},
        {'role': 'assistant', 'content': 'Hi! How can I help?'},
    ]
    save_session(demo_history, directory=demo_dir)

Kompletny szablon agenta REPL

Połączmy wszystkie elementy: gotowy do użycia szablon REPL z zarządzaniem historią, poleceniami z ukośnikiem, obsługą przerwania klawiaturą i zapisywaniem sesji.

def run_repl(agent):
    history = [{'role': 'system', 'content': 'You are a helpful AI assistant.'}]
    print('Agent ready. Type /help for commands.')
    try:
        while True:
            user_input = input('You: ').strip()
            if not user_input:
                continue
            if user_input.startswith('/'):
                handle_command(user_input, history)
                continue
            history.append({'role': 'user', 'content': user_input})
            trimmed = trim_history(history, max_turns=10)
            reply = agent.run(trimmed)
            history.append({'role': 'assistant', 'content': reply})
            print(f'Agent: {reply}')
    except KeyboardInterrupt:
        print('\nSession ended.')
        save_session(history)

Sprawdzenie wiedzy: agenty w stylu REPL

Sprawdź swoją wiedzę na temat interaktywnych agentów REPL.

Podsumowanie: interaktywne agenty w stylu REPL

Możesz teraz tworzyć w pełni funkcjonalne interaktywne agenty działające w terminalu:

  • Używaj while True: input() jako głównej pętli odczytu
  • Przechwytuj KeyboardInterrupt, aby prawidłowo kończyć działanie po naciśnięciu Ctrl+C
  • Przechowuj listę conversation_history, aby zapewnić pamięć wieloturowej rozmowy
  • Używaj readline do obsługi historii danych wejściowych za pomocą klawiszy strzałek
  • Implementuj polecenia z ukośnikiem: /help, /clear i /exit
  • Ograniczaj historię, aby zapobiec nieograniczonemu wzrostowi liczby tokenów
  • Wyświetlaj animację ładowania lub wskaźnik postępu podczas wywołań LLM
Bezpłatny start

Ucz się AI Agents dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
60
Lekcje
239

Często zadawane pytania

Czy lekcja „Agenci interaktywni w stylu REPL” jest bezpłatna?

Tak — pełny tekst „Agenci interaktywni w stylu REPL” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu AI Agents, przejdź na CoddyKit PRO. Kurs AI Agents zawiera 4 lekcji w sumie.

Co nauczysz się w „Agenci interaktywni w stylu REPL”?

Pętle danych wejściowych, historia i wieloturowa konwersacja w agentach terminalowych. Ćwiczysz AI Agents z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć AI Agents?

Nie wymagamy żadnego doświadczenia. AI Agents w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „Agenci interaktywni w stylu REPL”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji AI Agents?

Tak. Każda lekcja AI Agents zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Tworzenie interfejsów agentów wiersza poleceń
  2. Agenci interaktywni w stylu REPL
  3. Parsowanie argumentów i tekst pomocy
  4. Strumieniowanie wyników w agentach CLI
← Powrót do AI Agents