0Pricing
AI Engineering Academy · Lekcja

Projektowanie architektury produkcyjnej

Wybierz projekt końcowy, naszkicuj pełną architekturę obejmującą potok RAG, warstwę agenta, buforowanie, obserwowalność i API, a następnie udokumentuj decyzje projektowe oraz kompromisy.

Projektowanie architektury produkcyjnej to bezpłatna lekcja AI Engineering Academy na CoddyKit. To lekcja 1 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 Engineering Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs AI Engineering Academy zawiera 4 lekcji w sumie.

Wybór projektu końcowego

Projekt końcowy łączy wszystkie elementy ścieżki: RAG, agentów, przesyłanie strumieniowe, buforowanie, obserwowalność i bezpieczeństwo. Dobry projekt końcowy jest znacząco złożony — wymaga co najmniej trzech odrębnych komponentów AI — ale jednocześnie ma zakres na tyle ograniczony, aby można go było wdrożyć w ciągu dni, a nie miesięcy. Klasyczne przykłady to: gotowy do użycia produkcyjnie asystent do pytań i odpowiedzi dotyczących dokumentów, autonomiczny agent badawczy z nadzorem człowieka w procesie lub potok ekstrakcji danych dla przedsiębiorstwa.

Identyfikowanie komponentów systemu

Należy rozpocząć od wyszczególnienia odrębnych komponentów potrzebnych w systemie. Projekt AI przeznaczony do użycia produkcyjnego zazwyczaj obejmuje: warstwę pozyskiwania danych (wczytywanie dokumentów, dzielenie na fragmenty, tworzenie embeddingów, indeksowanie w bazie wektorowej), warstwę wyszukiwania (wyszukiwanie hybrydowe, ponowne rankingowanie), warstwę agenta (wywoływanie funkcji, wykonywanie narzędzi), warstwę API (backend FastAPI, endpointy strumieniowe) oraz warstwę obserwowalności (śledzenie, metryki, alerty). Przed napisaniem kodu należy naszkicować przepływ danych między tymi komponentami.

# Component inventory for a Document QA Assistant:
COMPONENTS = [
    'document_ingestion',   # PDF/Word -> chunks -> embeddings -> pgvector
    'hybrid_retriever',     # BM25 + dense + RRF
    'reranker',             # Cohere rerank
    'qa_agent',             # GPT-4o with RAG + function calling
    'semantic_cache',       # Redis + embedding similarity
    'streaming_api',        # FastAPI StreamingResponse
    'tracing',              # LangSmith or Langfuse
    'prompt_injection_filter', # Input sanitization
    'eval_pipeline',        # Automated quality scoring
]

Wybór odpowiedniego stosu technologicznego

Technologię należy wybierać na podstawie znajomości jej przez zespół oraz rzeczywistych wymagań systemu, a nie jej nowości. Rozsądny domyślny stos obejmuje: FastAPI dla warstwy API, pgvector do przechowywania wektorów (wykorzystuje istniejącą infrastrukturę PostgreSQL), LangChain LCEL do komponowania potoków, Redis do buforowania semantycznego i przechowywania stanu limitów zapytań, LangSmith do śledzenia oraz PostgreSQL do przechowywania danych użytkowników i wyników ewaluacji. Komponenty należy dodawać tylko wtedy, gdy prostsze rozwiązania nie spełniają wymagań.

# Technology decisions and their rationale
STACK = {
    'api':           ('FastAPI',    'Async support, OpenAPI docs, streaming easy'),
    'vector_store':  ('pgvector',   'Already on PostgreSQL, no extra infra'),
    'llm_primary':   ('gpt-4o',     'Best quality for the use case'),
    'llm_fallback':  ('claude-3.5', 'Different provider for resilience'),
    'cache':         ('Redis',      'Sub-ms lookup, TTL support built-in'),
    'tracing':       ('LangSmith',  'Native LangChain integration'),
    'embedding':     ('text-embedding-3-small', 'Good quality, low cost'),
    'reranker':      ('Cohere',     'Best-in-class rerank API'),
}

Tworzenie diagramu architektury

Architekturę systemu należy udokumentować za pomocą diagramu przepływu danych pokazującego każdy komponent, przepływające między nimi dane oraz kierunek przepływu. Należy uwzględnić zarówno ścieżkę pozyskiwania danych (offline: dokumenty → fragmenty → embeddingi → baza wektorowa), jak i ścieżkę zapytań (online: zapytanie użytkownika → sprawdzenie cache → wyszukiwanie → ponowne rankingowanie → LLM → odpowiedź strumieniowa). Diagram ten jest punktem odniesienia podczas implementacji i pomaga nowym członkom zespołu natychmiast zrozumieć system.

# Data flow (ASCII art):
#
# INGESTION PATH (offline):
# Documents --> Loader --> Chunker --> Embedder --> pgvector
#                                             |
#                                         BM25 index
#
# QUERY PATH (online):
# User Query
#    |-> Semantic Cache (hit: return) -> miss:
#    |-> Hybrid Retriever (BM25 + dense)
#    |-> Cohere Reranker
#    |-> LangChain LCEL Chain
#    |-> GPT-4o (streaming) --> FastAPI StreamingResponse
#    |-> LangSmith (trace every step)

Wczesne definiowanie kontraktów API

Endpointy API oraz ich schematy żądań i odpowiedzi należy zdefiniować w FastAPI przed zaimplementowaniem logiki backendu. Tworzy to kontrakt między API a wszystkimi korzystającymi z niego frontendami i umożliwia równoległy rozwój. Każdy endpoint należy opisać za pomocą opisów OpenAPI. Co najmniej należy zdefiniować endpointy do: pozyskiwania dokumentów, czatu i zapytań, historii konwersacji, wyników ewaluacji oraz sprawdzania stanu systemu.

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI(title='Document QA Assistant', version='1.0')

class QueryRequest(BaseModel):
    question: str
    conversation_id: str | None = None
    max_chunks: int = 5
    stream: bool = True

class QueryResponse(BaseModel):
    answer: str
    sources: list
    cached: bool
    latency_ms: int
    trace_id: str

@app.post('/query', response_model=QueryResponse)
async def query_endpoint(request: QueryRequest):
    pass  # implementation next lesson

Szacowanie i budżetowanie kosztów

Przed napisaniem choćby jednej linii kodu backendu należy oszacować miesięczny koszt API systemu. Należy uwzględnić: oczekiwaną dzienną liczbę aktywnych użytkowników × liczbę zapytań na użytkownika × średnią liczbę tokenów na zapytanie. W systemie ze 100 DAU, 10 zapytaniami dziennie i 3000 tokenów na zapytanie, przy cenach GPT-4o, daje to 3 miliony tokenów dziennie — około 45 USD dziennie lub 1350 USD miesięcznie. Szacunek ten pokazuje, czy system jest opłacalny oraz które optymalizacje (buforowanie, routing modeli) warto wdrożyć.

# Cost estimation model
DAU = 100           # daily active users
QPD = 10            # queries per user per day
TOKENS_PER_QUERY = {
    'prompt_tokens': 2000,  # system + context + question
    'completion_tokens': 500
}

PRICE_GPT4O_INPUT = 2.50 / 1_000_000   # per token
PRICE_GPT4O_OUTPUT = 10.00 / 1_000_000  # per token

daily_cost = DAU * QPD * (
    TOKENS_PER_QUERY['prompt_tokens'] * PRICE_GPT4O_INPUT +
    TOKENS_PER_QUERY['completion_tokens'] * PRICE_GPT4O_OUTPUT
)
print(f'Daily: ${daily_cost:.2f}, Monthly: ${daily_cost * 30:.2f}')

Planowanie potoku pozyskiwania danych

Potok pozyskiwania danych należy zaprojektować jako proces wsadowy offline uruchamiany na żądanie lub według harmonogramu. Należy określić obsługiwane typy dokumentów (PDF, DOCX, HTML, zwykły tekst), strategię dzielenia na fragmenty, model embeddingów oraz pola metadanych przechowywane wraz z każdym wektorem. Metadane mają kluczowe znaczenie dla filtrowanego wyszukiwania — bez nich nie można ograniczyć wyszukiwania do dokumentów z określonego zakresu dat, autorstwa konkretnej osoby lub należących do danej kategorii.

from dataclasses import dataclass
from typing import Optional

@dataclass
class ChunkMetadata:
    doc_id: str
    source_file: str
    page_number: Optional[int]
    section_title: Optional[str]
    created_at: str
    author: Optional[str]
    doc_type: str  # 'pdf', 'docx', 'html'

# Ingestion config
INGESTION_CONFIG = {
    'chunk_size': 800,
    'chunk_overlap': 100,
    'embedding_model': 'text-embedding-3-small',
    'embedding_dimensions': 1536,
    'batch_size': 100,  # chunks per embedding API call
}

Decyzje dotyczące architektury bezpieczeństwa

Decyzje dotyczące bezpieczeństwa należy podejmować od początku, zamiast dodawać zabezpieczenia później. Należy określić: sposób uwierzytelniania użytkowników (JWT, klucze API), dane możliwe do pobrania przez poszczególnych użytkowników (bezpieczeństwo na poziomie wierszy w zapytaniach pgvector), sposób wykrywania prompt injection, stosowane skanowanie wyników oraz działania wymagające potwierdzenia wieloskładnikowego. Każda z tych decyzji ma wpływ na wydajność i oddziałuje na wybory architektoniczne w całym systemie.

SECURITY_DECISIONS = {
    'auth': 'JWT with 24h expiry',
    'data_isolation': 'tenant_id column in all vector metadata, filter on every query',
    'injection_detection': 'rule-based pre-filter + LLM secondary check for complex inputs',
    'output_scanning': 'check for PII, system prompt leakage patterns',
    'destructive_actions': 'require confirmation token for delete operations',
    'rate_limiting': '20 queries/minute per user, 429 with Retry-After header',
    'key_storage': 'AWS Secrets Manager, rotated every 90 days'
}

Definiowanie metryk sukcesu

Przed rozpoczęciem budowy należy określić, jak będzie wyglądał sukces systemu. Zestaw konkretnych, mierzalnych kryteriów sukcesu pozwala zachować koncentrację podczas prac i zapewnia jasne kryteria decyzji o wdrożeniu. Należy uwzględnić metryki dotyczące: jakości (wynik ewaluacji na zbiorze testowym), opóźnienia (p95 TTFT i całkowite), kosztu (docelowy koszt zapytania) oraz niezawodności (SLA dostępności). Kryteria te należy umieścić w pliku README projektu, aby wszyscy współtwórcy mieli ten sam cel.

SUCCESS_METRICS = {
    # Quality
    'min_correctness_score': 4.0,       # out of 5, LLM-as-judge
    'min_retrieval_hit_rate': 0.85,     # top-5 chunk contains answer
    # Latency
    'p95_ttft_ms': 800,                 # time to first token
    'p95_total_latency_ms': 8000,       # full response
    # Cost
    'max_cost_per_query_usd': 0.05,     # $0.05 per Q&A
    # Reliability
    'target_uptime': 0.999,             # 99.9%
    'cache_hit_rate_target': 0.25,      # 25% queries served from cache
}

Dokumentowanie kompromisów architektonicznych

Każda decyzja architektoniczna wiąże się z kompromisami. Należy je wyraźnie udokumentować w dokumencie Architecture Decision Record (ADR): jaka decyzja została podjęta, jakie alternatywy rozważono i dlaczego wybrano tę opcję. Na przykład: „Wybrano pgvector zamiast Pinecone, ponieważ korzystamy już z PostgreSQL, co zmniejsza nakład pracy operacyjnej. Kompromis: maksymalna skala bez shardingu jest ograniczona do około 10 mln wektorów”. Przyszli członkowie zespołu docenią tę przejrzystość.

# Architecture Decision Records (ADRs):
#
# ADR-001: Use pgvector for vector storage
# Decision: pgvector in existing PostgreSQL
# Alternatives: Pinecone, Weaviate, Qdrant
# Reason: No new infra, row-level security native, familiar operations
# Trade-offs: Limited to ~5M vectors before performance degrades
#
# ADR-002: GPT-4o as primary model
# Decision: gpt-4o for all user-facing queries
# Alternatives: gpt-4o-mini (cheaper), Claude (alternative)
# Reason: Highest quality for use case, Claude as fallback
# Trade-offs: $0.04/query vs $0.002 for gpt-4o-mini

Szkicowanie topologii wdrożenia

Sposób wdrożenia systemu należy określić przed napisaniem kodu infrastruktury. Każdy komponent należy przypisać do jednostki wdrożeniowej: backend FastAPI jako kontener Docker, potok pozyskiwania danych jako osobna usługa worker, pgvector jako zarządzana instancja PostgreSQL, a Redis jako zarządzany cache. Należy określić, które komponenty są bezstanowe (można je skalować horyzontalnie), a które stanowe (wymagają ostrożnych strategii skalowania). Diagram wdrożenia pozwala później zaoszczędzić wiele godzin przeróbek.

# Deployment topology:
#
# Internet -> Load Balancer (AWS ALB)
#                |
#            FastAPI API  (stateless, 2-4 containers, auto-scale)
#                |
#         +------+------+
#         |             |
#    pgvector        Redis Cache
#  (AWS RDS Postgres) (Elasticache)
#         |
#    Ingestion Worker  (separate container, manual trigger)
#         |
#    LangSmith (external SaaS, traces only)
#
# All containers in same VPC, no public access to DB/cache

Szybkie sprawdzenie

Sprawdź swoją wiedzę na temat projektowania architektury produkcyjnych systemów AI.

Podsumowanie lekcji

W tej lekcji dowiedziałeś się, że: inwentaryzacja komponentów i diagramy przepływu danych tworzą wspólną wizję architektury przed rozpoczęciem kodowania, kontrakty API zdefiniowane z wyprzedzeniem umożliwiają równoległy rozwój i precyzują wymagania, a metryki sukcesu zdefiniowane wcześniej pomagają zespołowi zachować zgodność co do celów dotyczących jakości, opóźnień, kosztów i niezawodności. W następnej części zaimplementujemy podstawowe funkcje RAG i agenta.

Często zadawane pytania

Czy lekcja „Projektowanie architektury produkcyjnej” jest bezpłatna?

Tak — pełny tekst „Projektowanie architektury produkcyjnej” 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 Engineering Academy, przejdź na CoddyKit PRO. Kurs AI Engineering Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Projektowanie architektury produkcyjnej”?

Wybierz projekt końcowy, naszkicuj pełną architekturę obejmującą potok RAG, warstwę agenta, buforowanie, obserwowalność i API, a następnie udokumentuj decyzje projektowe oraz kompromisy. Ćwiczysz AI Engineering Academy 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 Engineering Academy?

Nie wymagamy żadnego doświadczenia. AI Engineering Academy 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 1 z 4.

Ile czasu zajmuje lekcja „Projektowanie architektury produkcyjnej”?

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 Engineering Academy?

Tak. Każda lekcja AI Engineering Academy 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. Projektowanie architektury produkcyjnej
  2. Implementowanie podstawowych funkcji RAG i agenta
  3. Wzmacnianie: bezpieczeństwo, buforowanie i niezawodność
  4. Ewaluacja, wdrożenie i retrospektywa
← Powrót do AI Engineering Academy