Architektura rejestru promptów
Przechowywanie promptów jako wersjonowanych artefaktów z metadanymi i tagami.
Architektura rejestru promptów to bezpłatna lekcja AI Prompt Engineering 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 Prompt Engineering, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs AI Prompt Engineering zawiera 4 lekcji w sumie.
Dlaczego rejestr promptów?
Bez rejestru prompty są rozproszone w kodzie, plikach konfiguracyjnych i pamięci programistów. Rejestr promptów to scentralizowany magazyn, który traktuje każdy prompt jako wersjonowany i możliwy do śledzenia artefakt — podobnie jak kod oprogramowania.
Do korzyści należą powtarzalność, możliwość przeprowadzania audytów, możliwość wycofywania zmian oraz współpraca zespołowa.
Podstawowe pola artefaktu promptu
Każdy artefakt promptu powinien zawierać następujące pola:
prompt_id— unikalny, stabilny identyfikator (np.summarize-article)version— ciąg znaków oznaczający wersję semantyczną (np.2.1.0)template— właściwy tekst promptu z symbolami zastępczymi{variable}metadata— autor, tagi, docelowy model, created_at, opis
Projektowanie schematu bazy danych
Relacyjny schemat rejestru promptów przechowuje prompty i historię ich wersji w oddzielnych tabelach, umożliwiając wydajne wyszukiwanie i przeprowadzanie audytów.
-- prompts table: one row per unique prompt identity
CREATE TABLE prompts (
prompt_id VARCHAR(100) PRIMARY KEY,
description TEXT,
created_at TIMESTAMP DEFAULT NOW()
);
-- prompt_versions table: one row per versioned artifact
CREATE TABLE prompt_versions (
id SERIAL PRIMARY KEY,
prompt_id VARCHAR(100) REFERENCES prompts(prompt_id),
version VARCHAR(20) NOT NULL,
template TEXT NOT NULL,
author VARCHAR(100),
tags TEXT[],
model VARCHAR(50),
is_active BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP DEFAULT NOW(),
UNIQUE(prompt_id, version)
);Projekt rejestru opartego na plikach
W przypadku mniejszych zespołów rejestr oparty na plikach wykorzystuje uporządkowany układ katalogów. Każdy prompt otrzymuje własny folder, a każda wersja jest przechowywana w osobnym pliku YAML lub JSON.
# Directory structure
prompts/
summarize-article/
1.0.0.yaml
1.1.0.yaml
latest -> 1.1.0.yaml # symlink
classify-sentiment/
1.0.0.yaml
# Example: summarize-article/1.1.0.yaml
prompt_id: summarize-article
version: '1.1.0'
model: gpt-4o-mini
author: alice@company.com
tags: [summarization, articles, english]
created_at: '2024-06-01T10:00:00Z'
template: |
Summarize the following article in {num_sentences} sentences.
Focus on: {focus_area}.
Article:
{article_text}Klasa Python PromptRegistry
Prosta klasa języka Python opakowuje dostęp do bazy danych i udostępnia przejrzyste metody: register(), get_active() oraz list_versions().
import psycopg2
import json
from datetime import datetime
class PromptRegistry:
def __init__(self, dsn):
self.conn = psycopg2.connect(dsn)
def register(self, prompt_id, version, template, author, tags, model):
with self.conn.cursor() as cur:
# Ensure prompt identity exists
cur.execute(
'INSERT INTO prompts (prompt_id) VALUES (%s) ON CONFLICT DO NOTHING',
(prompt_id,)
)
cur.execute(
'''INSERT INTO prompt_versions
(prompt_id, version, template, author, tags, model)
VALUES (%s, %s, %s, %s, %s, %s)''',
(prompt_id, version, template, author, tags, model)
)
self.conn.commit()
print(f'Registered {prompt_id}@{version}')
def get_active(self, prompt_id):
with self.conn.cursor() as cur:
cur.execute(
'SELECT template, version FROM prompt_versions '
'WHERE prompt_id=%s AND is_active=TRUE LIMIT 1',
(prompt_id,)
)
row = cur.fetchone()
if not row:
raise ValueError(f'No active version for {prompt_id}')
return {'template': row[0], 'version': row[1]}Szczegółowe omówienie schematu metadanych
Bogate metadane sprawiają, że rejestr jest przydatny nie tylko do prostego przechowywania danych. Najważniejsze pola metadanych:
- author — odpowiedzialność i osoba kontaktowa
- tags — umożliwiające wyszukiwanie etykiety, takie jak
['production', 'summarization', 'v2'] - model — docelowy model (prompt może nie być niezależny od modelu)
- changelog — zrozumiały dla człowieka opis wprowadzonych zmian
- test_suite — odsyłacz do zbioru danych ewaluacyjnych dla tego promptu
# Extended metadata example
prompt_metadata = {
'prompt_id': 'extract-key-dates',
'version': '2.0.0',
'author': 'bob@company.com',
'tags': ['extraction', 'dates', 'contracts', 'production'],
'model': 'gpt-4o',
'changelog': 'Added support for relative dates (next quarter, end of year)',
'test_suite': 's3://company-evals/extract-key-dates/v2-testset.jsonl',
'created_at': '2024-07-15T09:30:00Z',
'is_active': True
}Renderowanie szablonów ze zmiennymi
Szablony promptów używają składni symboli zastępczych. Rejestr tworzy końcowy prompt, podstawiając zmienne z czasu wykonywania do szablonu. Użycie języka Python i metody str.format_map() jest bezpieczne i proste.
class PromptRegistry:
# ... (previous methods)
def render(self, prompt_id, variables: dict) -> str:
artifact = self.get_active(prompt_id)
template = artifact['template']
try:
rendered = template.format_map(variables)
except KeyError as e:
raise ValueError(f'Missing variable {e} for prompt {prompt_id}')
return rendered
# Usage
registry = PromptRegistry(dsn='postgresql://...')
prompt = registry.render(
'summarize-article',
{
'num_sentences': 3,
'focus_area': 'financial impact',
'article_text': 'Apple reported record revenue of $119B...'
}
)
print(prompt)
# Output: Summarize the following article in 3 sentences.
# Focus on: financial impact. ...Aktywowanie wersji
W środowisku produkcyjnym tylko jedna wersja promptu powinna być jednocześnie aktywna. Aktywowanie powinno być atomowe: dezaktywacja bieżącej wersji i aktywacja nowej powinny odbywać się w ramach jednej transakcji, aby uniknąć przerw.
def activate_version(self, prompt_id, version):
with self.conn.cursor() as cur:
# Deactivate all current versions
cur.execute(
'UPDATE prompt_versions SET is_active=FALSE '
'WHERE prompt_id=%s AND is_active=TRUE',
(prompt_id,)
)
# Activate target version
cur.execute(
'UPDATE prompt_versions SET is_active=TRUE '
'WHERE prompt_id=%s AND version=%s',
(prompt_id, version)
)
if cur.rowcount == 0:
self.conn.rollback()
raise ValueError(f'Version {version} not found for {prompt_id}')
self.conn.commit()
print(f'Activated {prompt_id}@{version}')Wyświetlanie i wyszukiwanie promptów
Rejestr jest przydatny tylko wtedy, gdy można odnaleźć jego zawartość. Należy obsługiwać wyszukiwanie według tagów oraz wyświetlanie wszystkich wersji danego promptu.
def list_versions(self, prompt_id):
with self.conn.cursor() as cur:
cur.execute(
'SELECT version, author, is_active, created_at '
'FROM prompt_versions WHERE prompt_id=%s '
'ORDER BY created_at DESC',
(prompt_id,)
)
return cur.fetchall()
def search_by_tag(self, tag):
with self.conn.cursor() as cur:
cur.execute(
'SELECT prompt_id, version, tags FROM prompt_versions '
'WHERE %s = ANY(tags)',
(tag,)
)
return cur.fetchall()
# Usage
for v in registry.list_versions('summarize-article'):
print(v) # ('1.1.0', 'alice', True, datetime(...))
for p in registry.search_by_tag('production'):
print(p) # ('summarize-article', '1.1.0', ['production', 'summarization'])Punkty końcowe API rejestru
Rejestr należy udostępnić jako API REST, aby wszystkie usługi (backend, potoki ML i narzędzia ewaluacyjne) korzystały z tego samego źródła prawdy. Najważniejsze punkty końcowe:
POST /prompts/{id}/versions— rejestruje nową wersjęGET /prompts/{id}/active— pobiera aktywny szablonPUT /prompts/{id}/activate/{version}— aktywuje wersjęGET /prompts— wyświetla wszystkie prompty wraz z metadanymi
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
app = FastAPI()
registry = PromptRegistry(dsn='postgresql://user:pass@localhost/prompts')
class VersionPayload(BaseModel):
version: str
template: str
author: str
tags: list
model: str
@app.post('/prompts/{prompt_id}/versions')
def register_version(prompt_id: str, payload: VersionPayload):
registry.register(
prompt_id, payload.version, payload.template,
payload.author, payload.tags, payload.model
)
return {'status': 'registered'}
@app.get('/prompts/{prompt_id}/active')
def get_active(prompt_id: str):
try:
return registry.get_active(prompt_id)
except ValueError as e:
raise HTTPException(404, str(e))
@app.put('/prompts/{prompt_id}/activate/{version}')
def activate(prompt_id: str, version: str):
registry.activate_version(prompt_id, version)
return {'status': 'activated'}Dziennik audytu i historia zmian
Każde zdarzenie aktywacji, dezaktywacji i rejestracji powinno być rejestrowane wraz ze znacznikiem czasu i wykonawcą. Ta ścieżka audytu jest niezbędna do debugowania incydentów produkcyjnych i spełniania wymagań zgodności.
CREATE TABLE prompt_audit_log (
id SERIAL PRIMARY KEY,
prompt_id VARCHAR(100),
version VARCHAR(20),
action VARCHAR(50), -- 'registered', 'activated', 'deactivated'
actor VARCHAR(100), -- user or service that performed the action
reason TEXT,
created_at TIMESTAMP DEFAULT NOW()
);
-- Trigger to auto-log activations
CREATE OR REPLACE FUNCTION log_activation()
RETURNS TRIGGER AS $func$
BEGIN
IF NEW.is_active != OLD.is_active THEN
INSERT INTO prompt_audit_log (prompt_id, version, action)
VALUES (NEW.prompt_id, NEW.version,
CASE WHEN NEW.is_active THEN 'activated' ELSE 'deactivated' END);
END IF;
RETURN NEW;
END;
$func$ LANGUAGE plpgsql;
CREATE TRIGGER trg_activation
AFTER UPDATE ON prompt_versions
FOR EACH ROW EXECUTE FUNCTION log_activation();Szybkie sprawdzenie
W schemacie bazy danych rejestru promptów które pole gwarantuje, że w danym momencie w środowisku produkcyjnym udostępniana jest tylko jedna wersja promptu?
Podsumowanie architektury rejestru
Rejestr promptów centralizuje zarządzanie promptami, traktując je jako wersjonowane artefakty. Najważniejsze decyzje projektowe:
- Oddzielna tabela tożsamości (
prompt_id) i tabela wersji (version,template,metadata) - Pojedyncza flaga
is_activei atomowe przełączanie zapobiegają błędom związanym z jednoczesną aktywnością wielu wersji - Bogate metadane (autor, tagi, model, changelog) ułatwiają wyszukiwanie i przeprowadzanie audytów
- Warstwa API REST udostępnia rejestr wszystkim usługom
- Dziennik audytu wspiera zapewnienie zgodności i debugowanie incydentów
Rejestry oparte na plikach sprawdzają się w małych zespołach, natomiast rejestry oparte na bazach danych są preferowane w produkcyjnych systemach obsługujących wiele zespołów i wymagających wysokiej dostępności.
Często zadawane pytania
Czy lekcja „Architektura rejestru promptów” jest bezpłatna?
Tak — pełny tekst „Architektura rejestru promptów” 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 Prompt Engineering, przejdź na CoddyKit PRO. Kurs AI Prompt Engineering zawiera 4 lekcji w sumie.
Co nauczysz się w „Architektura rejestru promptów”?
Przechowywanie promptów jako wersjonowanych artefaktów z metadanymi i tagami. Ćwiczysz AI Prompt Engineering 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 Prompt Engineering?
Nie wymagamy żadnego doświadczenia. AI Prompt Engineering 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 „Architektura rejestru promptów”?
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 Prompt Engineering?
Tak. Każda lekcja AI Prompt Engineering 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
- Architektura rejestru promptów
- Kontrola wersji promptów
- Strategie wdrażania i wycofywania zmian
- Monitorowanie wydajności promptów na produkcji