Kurs Python · Moduł 12: Projekt końcowy

Dokumentacja Techniczna

5 min czytania
W tej lekcji3

Najlepszy przewodnik po sawannie jest bezużyteczny, jeśli jego wiedza znika razem z nim. Nowy członek ekspedycji dostaje wtedy tylko kopię tropów bez legendy. Z kodem jest tak samo: projekt bez dokumentacji umie uruchomić jedna osoba, a po trzech miesiącach nawet ona zapomina, jak to robiła. Dokumentacja to most między kodem a ludźmi. Dobra dokumentacja sprawia, że projekt żyje nawet wtedy, gdy Ty śpisz, a rekruter albo nowy współpracownik rozumie go w pięć minut.

Dokumentację budujemy na trzech poziomach: README dla człowieka, który widzi repozytorium pierwszy raz, docstringi dla osoby czytającej kod oraz automatyczna dokumentacja API dla tych, którzy z niego korzystają. Dobra kolejność pracy to najpierw README, potem docstringi, potem konfiguracja generowanej dokumentacji API, a na koniec CHANGELOG.md, czyli dziennik zmian w kolejnych wersjach.

README.md - wizytówka projektu

README to pierwsza rzecz, którą GitHub pokazuje pod listą plików. Typowa kolejność sekcji: tytuł, opis lub funkcje, szybki start, a na końcu licencja. Oto kompletny przykład dla naszego asystenta:

1# AI Document Assistant
2
3Inteligentny asystent do przeszukiwania dokumentów wykorzystujący RAG.
4
5## Funkcje
6
7- Semantic search w dokumentach
8- Odpowiedzi w języku naturalnym
9- Obsługa PDF, DOCX, TXT
10- Szybkie odpowiedzi (<2s)
11
12## Quick Start
13
14### Wymagania
15- Python 3.12+
16- Docker (dla Qdrant)
17
18### Instalacja
19
20```bash
21# Klonuj repo
22git clone https://github.com/user/ai-doc-assistant.git
23cd ai-doc-assistant
24
25# Utwórz środowisko
26python -m venv venv
27source venv/bin/activate
28
29# Zainstaluj zależności
30pip install -r requirements.txt
31
32# Uruchom Qdrant
33docker compose up -d qdrant
34
35# Ustaw zmienne środowiskowe
36cp .env.example .env
37# Edytuj .env i dodaj OPENAI_API_KEY
38
39# Uruchom aplikację
40uvicorn app.main:app --reload
41```
42
43## API Documentation
44
45Po uruchomieniu: http://localhost:8000/docs
46
47## Architecture
48
49[Link do diagramu architektury]
50
51## Testing
52
53```bash
54pytest tests/ -v
55```
56
57## License
58
59MIT

Instrukcja instalacji to kolejne polecenia, które da się skopiować i uruchomić: klon, wirtualne środowisko, zależności, baza, zmienne środowiskowe, start. Zwróć uwagę na cp .env.example .env: prawdziwe klucze nigdy nie trafiają do repozytorium, tylko wzór pliku. docker compose (ze spacją) to obecna wersja narzędzia, wbudowana w Dockera jako plugin.

Docstrings - dokumentacja w kodzie

Docstring to napis w potrójnych cudzysłowach zaraz pod definicją klasy lub funkcji. PEP 257 opisuje ogólne konwencje, a sam format sekcji wybierasz. Najpopularniejsze są Google style i NumPy style, oba czytane przez Sphinx (rozszerzenie napoleon). My używamy Google style: sekcje Attributes, Args, Returns, Raises i Example.

1from typing import Optional
2
3class RAGService:
4    """
5    Serwis RAG do odpowiadania na pytania na podstawie dokumentów.
6
7    Ten serwis implementuje pełny pipeline RAG:
8    1. Embedding pytania
9    2. Wyszukiwanie podobnych dokumentów
10    3. Generowanie odpowiedzi z kontekstem
11
12    Attributes:
13        vector_store: Klient do vector database
14        llm: Klient do modelu językowego
15        embedder: Serwis do tworzenia embeddingów
16
17    Example:
18        >>> service = RAGService(vector_store, llm, embedder)
19        >>> response = await service.query("Co to jest Python?")
20        >>> print(response.answer)
21        Python to język programowania...
22    """

Docstring klasy mówi, co serwis robi i z czego się składa. Przykład w formacie >>> pokazuje użycie, a linia pod nim to wypisany wynik. Konstruktor jest prosty i nie wymaga osobnego opisu:

1    def __init__(
2        self,
3        vector_store: VectorStore,
4        llm: LLMClient,
5        embedder: EmbeddingService
6    ):
7        self.vector_store = vector_store
8        self.llm = llm
9        self.embedder = embedder

Typy argumentów (VectorStore, LLMClient, EmbeddingService) to interfejsy z warstwy infrastruktury, zgodnie z architekturą z poprzedniej lekcji. Najwięcej opisu wymaga metoda publiczna:

1    async def query(
2        self,
3        question: str,
4        top_k: int = 5,
5        filters: Optional[dict] = None
6    ) -> Response:
7        """
8        Wykonuje zapytanie RAG.
9
10        Args:
11            question: Pytanie użytkownika w języku naturalnym
12            top_k: Liczba dokumentów do pobrania (default: 5)
13            filters: Opcjonalne filtry metadanych
14
15        Returns:
16            Response: Obiekt zawierający odpowiedź i źródła
17
18        Raises:
19            ValueError: Gdy pytanie jest puste
20            LLMError: Gdy wystąpi błąd generowania
21
22        Example:
23            >>> response = await service.query(
24            ...     "Jak działa RAG?",
25            ...     top_k=3,
26            ...     filters={"category": "ai"}
27            ... )
28        """
29        if not question.strip():
30            raise ValueError("Question cannot be empty")
31
32        # Implementation...

Sekcja Raises jest często pomijana, a to ona mówi, co może pójść źle. Docstring możesz odczytać w konsoli przez help(RAGService.query), więc to dokumentacja, która zawsze jest pod ręką. Uwaga: przykład z await służy do czytania, zwykły doctest go nie uruchomi.

API Documentation z FastAPI

FastAPI generuje dokumentację API w standardzie OpenAPI (dawniej Swagger) automatycznie, na podstawie typów i modeli Pydantic. Najpierw metadane aplikacji:

1from fastapi import FastAPI, HTTPException
2from pydantic import BaseModel, Field
3
4app = FastAPI(
5    title="AI Document Assistant API",
6    description="REST API dla inteligentnego asystenta dokumentów",
7    version="1.0.0",
8    docs_url="/docs",
9    redoc_url="/redoc"
10)

Pod /docs dostajesz interaktywne Swagger UI, pod /redoc alternatywny widok ReDoc. Teraz modele żądania i odpowiedzi. Pydantic waliduje dane, a Field dodaje ograniczenia i opisy:

1class QueryRequest(BaseModel):
2    """Request do zapytania RAG."""
3    question: str = Field(
4        ...,
5        description="Pytanie w języku naturalnym",
6        examples=["Co to jest machine learning?"]
7    )
8    top_k: int = Field(
9        default=5,
10        ge=1,
11        le=20,
12        description="Liczba dokumentów źródłowych"
13    )
14
15class QueryResponse(BaseModel):
16    """Odpowiedź z systemu RAG."""
17    answer: str = Field(description="Wygenerowana odpowiedź")
18    sources: list[dict] = Field(description="Dokumenty źródłowe")
19    latency_ms: float = Field(description="Czas odpowiedzi w ms")

ge=1, le=20 oznacza "od 1 do 20", więc top_k=50 zostanie odrzucone z błędem 422, zanim trafi do Twojego kodu. Przykładowe wartości podajemy przez examples=[...]. Stary parametr example= jest w Pydantic v2 przestarzały i generuje ostrzeżenie. Na koniec endpoint:

1@app.post(
2    "/query",
3    response_model=QueryResponse,
4    summary="Zadaj pytanie",
5    description="Wykonuje zapytanie RAG i zwraca odpowiedź z źródłami"
6)
7async def query(request: QueryRequest) -> QueryResponse:
8    """
9    Endpoint do zadawania pytań systemowi RAG.
10
11    - **question**: Pytanie w języku naturalnym
12    - **top_k**: Liczba dokumentów do przeszukania
13    """
14    pass

summary i description pojawią się w Swagger UI, a docstring z markdownem również. Nie piszesz żadnego osobnego pliku dokumentacji, schemat powstaje z kodu, więc nie rozjedzie się z rzeczywistością.

Moja rada: pisz README w tym samym dniu, w którym zakładasz repozytorium, a nie na końcu projektu. Dokumentacja pisana na bieżąco jest krótsza i prawdziwsza. W następnej lekcji przejdziemy do deploymentu.

Pamiętaj: dokumentacja to dziennik ekspedycji, dzięki któremu następna wyprawa pójdzie Twoimi tropami bez zgadywania.

Widzisz błąd w tej lekcji?

Sprawdź się

Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.

  1. 1. Który styl docstringów jest zalecany dla Pythona?

  2. 2. Który standard jest używany do dokumentacji REST API w Pythonie?

Zadania praktyczne w grze

  • Edytor kodu

    Stwórz profesjonalny docstring

  • Układanie w pionie

    Uporządkuj kroki:

  • Układanie w poziomie

    Ułóż typowe sekcje README.md:

Przydatne artykuły