Înapoi la blog

Aplicații AI cu Python: ghid de la API la produs (2026)

Ghid practic 2026: cum construiești aplicații AI cu Python și SDK-urile oficiale OpenAI și Anthropic, de la primul apel de API la un produs livrat.

Aplicații AI cu Python: ghid de la API la produs (2026)

Dacă știi deja un pic de Python și te uiți la valul de produse AI cu sentimentul că „ar trebui să pot face și eu asta", ai dreptate: poți. A construi aplicații AI cu Python în 2026 nu mai înseamnă să antrenezi modele sau să înțelegi matematica din spatele rețelelor neuronale. Înseamnă să folosești, prin câteva linii de cod, modele deja antrenate — Claude de la Anthropic, GPT de la OpenAI — exact așa cum folosești orice alt API: trimiți o cerere, primești un răspuns, construiești logică în jur. Diferența dintre un demo impresionant și un produs livrat stă tocmai în acea logică din jur: cum gestionezi erorile, costul, datele tale, conversațiile lungi și momentul în care modelul trebuie să „facă" ceva, nu doar să vorbească.

Acest ghid este un tutorial fundamental, end-to-end, scris pentru dezvoltatori la nivel începător spre intermediar. Scriem cod Python real cu SDK-urile oficiale, nu generăm aplicații prin no-code. Parcurgem traseul complet: de la setarea mediului și primul apel de chat, prin streaming, function calling, ieșiri structurate validate și RAG introductiv, până la elementele de producție și primul agent. Pe scurt: de la API la produs.

Aplicații AI cu Python — de la primul apel de API la un produs livrat, cu SDK-urile oficiale OpenAI și Anthropic

Notă despre nume de modele și versiuni de SDK: peisajul se schimbă des. Numele de model din acest articol (claude-opus-4-8, claude-sonnet-4-6, gpt-5.5) sunt valori-exemplu valabile în iunie 2026; verifică întotdeauna identificatorii exacți disponibili în contul tău pe docs.anthropic.com și platform.openai.com. Folosim peste tot SDK-urile oficiale anthropic și openai și niciodată chei reale în cod — doar placeholdere și variabile de mediu.

De ce Python pentru aplicații AI

Python a devenit limba maternă a aplicațiilor AI dintr-un motiv pragmatic, nu ideologic: providerii majori își lansează și își întrețin cel mai bine SDK-urile oficiale în Python, iar ecosistemul din jur (validare de date, manipulare de fișiere, framework-uri web) este matur și ușor de combinat. Pentru un dezvoltator, aceasta înseamnă cel mai scurt drum de la o idee la cod care rulează.

Important: nu construiești un model, ci consumi unul prin API. Modelul rulează pe infrastructura providerului; tu trimiți text și primești text. Toată „inteligența" aplicației tale stă în cum orchestrezi aceste apeluri — ce instrucțiuni dai, ce date adaugi în context, ce faci cu răspunsul. Aici intervine codul tău Python, și aici se câștigă sau se pierde calitatea produsului.

Acest articol acoperă fundamentele scrisului de cod. Dacă vrei să mergi mai departe în zona de integrare avansată în producție (idempotență, circuit breakers, tool use paralel, MCP), avem un ghid dedicat: integrarea LLM avansată prin function calling și tool use. Iar dacă, dimpotrivă, preferi să construiești fără să scrii cod, citește despre vibe coding și uneltele prompt-to-app. Ghidul de față stă fix la mijloc: cod Python real, dar la nivel de fundamente.

Cei șase pași de la API la produs

O aplicație AI funcțională, indiferent cât de ambițioasă, se construiește pe aceleași șase straturi. Le parcurgem pe rând în restul articolului. Schema de mai jos este harta întregului traseu — revino la ea ori de câte ori te pierzi în detalii.

Cei șase pași de la API la produs: setup mediu, primul apel, streaming, tool use și JSON, RAG și conversații, producție și agent

Frumusețea acestei structuri este că fiecare strat adaugă o capabilitate, dar nu invalidează ce ai învățat înainte. Apelul de chat de la pasul 2 rămâne motorul; tool use-ul de la pasul 4 doar îl învelește într-o buclă; agentul de la pasul 6 automatizează acea buclă. Construiești prin acumulare, nu prin rescriere.

Pasul 1: Setup-ul mediului — venv, pip și chei sigure

Înainte de orice apel ai nevoie de un mediu Python izolat și de chei API stocate corect. Izolarea se face cu un mediu virtual, ca dependențele proiectului tău să nu se amestece cu cele de sistem:

python -m venv .venv
source .venv/bin/activate        # pe Windows: .venv\Scripts\activate
pip install anthropic openai python-dotenv pydantic

Recomandarea, valabilă pentru orice proiect serios, este să fixezi versiunile SDK-urilor (de exemplu pip install "anthropic==0.105.*" "openai==2.41.*"), pentru reproducibilitate. Verifică versiunea curentă în documentația oficială înainte de a o pune în requirements.txt.

Acum partea critică, pe care o repetăm de-a lungul întregului articol: cheile API nu se pun niciodată în cod și nu se comit niciodată în Git. Convenția standard este o variabilă de mediu, încărcată dintr-un fișier .env care este adăugat în .gitignore:

# fișier .env — placeholdere, NU chei reale; .env intră în .gitignore
ANTHROPIC_API_KEY=sk-ant-PLACEHOLDER
OPENAI_API_KEY=sk-PLACEHOLDER
import os
from dotenv import load_dotenv

load_dotenv()  # citește .env în variabilele de mediu
# cheia se ia mereu din mediu, niciodată hardcodată:
anthropic_key = os.environ["ANTHROPIC_API_KEY"]

O cheie scursă într-un repo public poate fi exploatată automat în câteva minute, generând costuri reale pe contul tău. Tratează cheia ca pe o parolă. În producție, în loc de .env, folosești un secret manager (de exemplu cel oferit de platforma ta de hosting), dar principiul rămâne identic: cheia trăiește în mediu, nu în cod.

Pasul 2: Primul apel de chat completions

Aici se întâmplă „hello world"-ul oricărei aplicații AI. Un apel de chat are mereu aceleași trei piese: clientul (autentificat cu cheia din mediu), lista de mesaje cu roluri și parametrul model. Iată-l cu SDK-ul oficial Anthropic:

import os
from anthropic import Anthropic

client = Anthropic()  # citește singur ANTHROPIC_API_KEY din mediu

message = client.messages.create(
    model="claude-sonnet-4-6",        # valoare-exemplu; verifică în cont
    max_tokens=1024,
    system="Ești un asistent care răspunde concis, în limba română.",
    messages=[
        {"role": "user", "content": "Explică-mi în două fraze ce este un token."}
    ],
)

print(message.content[0].text)

Și echivalentul cu SDK-ul oficial OpenAI, prin Chat Completions:

from openai import OpenAI

client = OpenAI()  # citește singur OPENAI_API_KEY din mediu

response = client.chat.completions.create(
    model="gpt-5.5",                  # valoare-exemplu; verifică în cont
    messages=[
        {"role": "system", "content": "Ești un asistent care răspunde concis, în limba română."},
        {"role": "user", "content": "Explică-mi în două fraze ce este un token."},
    ],
)

print(response.choices[0].message.content)

Observă diferența de formă, importantă în practică: la Anthropic, mesajul de sistem se transmite ca parametru separat system; la OpenAI, mesajul system intră în aceeași listă messages. În rest, modelul mental este identic: o conversație este o secvență de mesaje cu roluri (system setează comportamentul, user este intrarea, assistant sunt răspunsurile din tururile anterioare), iar modelul generează următorul mesaj assistant.

Parametrii de control: temperature și max tokens

Doi parametri îți dau pârghii directe asupra răspunsului:

  • temperature controlează cât de „creativ" sau cât de determinist este modelul. Valori mici (apropiate de 0) produc răspunsuri mai consistente și mai predictibile — ideal pentru extragere de date, clasificare, sarcini cu un singur răspuns corect. Valori mai mari aduc varietate — util pentru brainstorming sau text creativ.
  • max_tokens limitează lungimea răspunsului. Este și un mecanism de control al costului: un plafon rezonabil te protejează de răspunsuri neașteptat de lungi.

Interpretarea răspunsului: usage și finish reason

Răspunsul nu este doar text. Conține metadate pe care un dezvoltator serios le citește mereu:

  • usage — numărul de tokeni de intrare și de ieșire. Aceasta este baza pentru a-ți calcula și monitoriza costul real. Notă: prețurile API se schimbă des și diferă per model; nu cităm tarife în acest articol — verifică pagina oficială de prețuri a providerului.
  • finish_reason (OpenAI) / stop_reason (Anthropic) — de ce s-a oprit generarea. Un length / max_tokens înseamnă că răspunsul a fost tăiat pentru că a atins plafonul, nu pentru că modelul a terminat ideea. Dacă ignori acest câmp, vei livra utilizatorilor răspunsuri trunchiate fără să-ți dai seama.

Tratarea greșelilor comune (cheie invalidă, rate limit, timeout) o detaliem la pasul de producție.

Pasul 3: Streaming pentru un UX care pare instant

Când rulezi un apel normal, aștepți ca tot răspunsul să fie generat înainte să-l vezi. Pentru un text lung, asta înseamnă secunde de ecran gol — o experiență proastă. Soluția este streaming: primești răspunsul token cu token, pe măsură ce este generat, exact ca efectul de „tastare" pe care îl vezi în ChatGPT sau Claude.

Conceptul-cheie este TTFT (Time To First Token) — timpul până la prima bucată de text. Chiar dacă răspunsul complet durează la fel de mult, percepția de viteză se schimbă radical: utilizatorul vede ceva imediat și citește în timp ce restul se generează.

from openai import OpenAI

client = OpenAI()

stream = client.chat.completions.create(
    model="gpt-5.5",
    messages=[{"role": "user", "content": "Scrie un paragraf despre orașul Cluj-Napoca."}],
    stream=True,
)

for chunk in stream:
    delta = chunk.choices[0].delta.content
    if delta:
        print(delta, end="", flush=True)

SDK-ul Anthropic oferă un mecanism echivalent (client.messages.stream(...)), cu aceeași idee: iterezi peste fragmentele de text pe măsură ce sosesc. Pentru o aplicație web reală, aceste fragmente le trimiți mai departe către interfață (de regulă prin Server-Sent Events), dar logica de bază — iterezi și afișezi incremental — rămâne aceasta.

Pasul 4: Function calling și ieșiri structurate

Aici aplicația ta trece de la „chatbot care vorbește" la „software care face lucruri". Function calling (la Anthropic: tool use) este mecanismul prin care modelul poate cere codului tău să execute o funcție reală — să caute în baza de date, să apeleze un API extern, să facă un calcul — și apoi să folosească rezultatul în răspuns.

Subtilitatea esențială: modelul nu execută nimic singur. El doar cere un apel, indicând numele funcției și argumentele. Codul tău decide dacă și cum execută, apoi trimite rezultatul înapoi. Acest dans se desfășoară într-o buclă.

Bucla de function calling: modelul cere un tool, codul tău execută funcția, trimite rezultatul înapoi, modelul răspunde final

Bucla de execuție, pas cu pas

  1. Trimiți mesajele plus lista de tool-uri disponibile (fiecare cu nume, descriere și o schemă JSON a argumentelor).
  2. Verifici semnalul: la Anthropic răspunsul are stop_reason == "tool_use"; la OpenAI, finish_reason == "tool_calls". Dacă nu apare, răspunsul este deja final.
  3. Citești numele și argumentele. Atenție la o capcană frecventă: la OpenAI, argumentele vin ca string JSON și trebuie parsate cu json.loads; la Anthropic, vin deja ca obiect.
  4. Mapezi numele la o funcție Python reală (un dicționar de dispecerizare este cel mai curat) și o execuți.
  5. Trimiți rezultatul înapoi modelului, cu identificatorul corect al apelului (tool_call_id la OpenAI, tool_use_id la Anthropic), și reiei bucla până când modelul produce un răspuns final.
import json

def get_vreme(oras: str) -> str:
    # aici ai apela un API real de meteo; întoarcem un exemplu
    return json.dumps({"oras": oras, "temperatura_c": 21, "stare": "însorit"})

# registry: numele cunoscut de model -> funcția reală
TOOLS = {"get_vreme": get_vreme}

def executa_tool(nume: str, argumente: dict) -> str:
    functie = TOOLS[nume]          # validează că numele este permis
    return functie(**argumente)

Validarea numelui în registry, înainte de execuție, nu este opțională: este un strat de securitate. Nu lăsa modelul să dicteze ce cod rulează — tu controlezi exact ce funcții sunt apelabile.

Ieșiri structurate: JSON valid, validat cu Pydantic

Multe aplicații nu au nevoie de o conversație, ci de date într-un format fix: un obiect cu câmpuri precise pe care îl poți salva în baza de date sau trimite mai departe. Aici intervin structured outputs — ceri modelului un răspuns conform unei scheme, iar apoi îl validezi în Python.

Unealta standard este Pydantic (v2 în 2026). Descrii forma datelor ca o clasă, iar Pydantic convertește și validează la momentul construirii obiectului:

from pydantic import BaseModel
from datetime import date

class Factura(BaseModel):
    furnizor: str
    total: float
    data_emiterii: date
    moneda: str = "RON"        # câmp opțional cu valoare implicită

# după ce primești JSON-ul de la model:
date_brute = {"furnizor": "ACME SRL", "total": "1250.50", "data_emiterii": "2026-06-04"}
factura = Factura(**date_brute)   # "1250.50" devine float, string-ul devine date real
print(factura.total, factura.moneda)

Principiul de aur se numește defense in depth: validezi chiar dacă mecanismul ar trebui să garanteze forma. Un model poate, ocazional, să returneze un câmp lipsă sau un tip greșit; Pydantic transformă acel eșec dintr-un bug subtil care explodează mai târziu într-o eroare clară, exact la graniță. Aici se vede diferența dintre fundamentele de cod și integrarea avansată de structured outputs și tool use în producție, unde adaugi retry pe validare, idempotență și apeluri paralele.

Pasul 5: RAG introductiv și conversații multi-tur

Modelul nu „știe" datele tale private — documentele firmei, baza ta de cunoștințe, fișierele tale. RAG (Retrieval-Augmented Generation) rezolvă exact asta: cauți bucățile relevante din datele tale și le injectezi în context înainte de a pune întrebarea. Modelul răspunde apoi pe baza informației pe care i-ai dat-o tu, nu doar pe baza a ce a învățat la antrenament — ceea ce reduce drastic halucinațiile pe domeniul tău.

Mecanismul minimal are trei piese:

  1. Chunking — împarți documentele în bucăți (paragrafe, secțiuni) de dimensiune gestionabilă.
  2. Embeddings — transformi fiecare bucată într-un vector numeric (cu un model de embeddings, oferit tot prin SDK), care surprinde sensul textului. Bucățile cu sens apropiat au vectori apropiați.
  3. Retrieval — pentru fiecare întrebare, calculezi embedding-ul întrebării, găsești cele mai apropiate bucăți și le pui în prompt ca context.

Pentru un prototip, un calcul de similaritate în memorie este suficient; pe măsură ce crește volumul, treci la o bază de date vectorială. RAG este o disciplină în sine, cu multe decizii de design (mărimea chunk-urilor, re-ranking, evaluare) — dacă vrei să o aprofundezi, este subiectul cursului dedicat RAG (Retrieval-Augmented Generation).

Conversații multi-tur

Un detaliu care surprinde mulți începători: modelul nu ține minte nimic între apeluri. Fiecare cerere este independentă (stateless). Iluzia de memorie din ChatGPT vine din faptul că, la fiecare tur, se retrimite întregul istoric al conversației în lista messages.

În cod, înseamnă că ții o listă de mesaje și o tot extinzi:

istoric = [{"role": "system", "content": "Ești un asistent util."}]

def tur(intrebare: str) -> str:
    istoric.append({"role": "user", "content": intrebare})
    r = client.chat.completions.create(model="gpt-5.5", messages=istoric)
    raspuns = r.choices[0].message.content
    istoric.append({"role": "assistant", "content": raspuns})  # păstrezi răspunsul
    return raspuns

Pentru că istoricul crește (și deci costul în tokeni crește), o aplicație matură gestionează contextul: trunchiază tururile vechi sau le rezumă atunci când conversația devine lungă. Aici se naște și nevoia de o arhitectură curată — separi logica de apelare a modelului de starea conversației și de interfață, exact ca în orice aplicație bine structurată.

Pasul 6: Producție și primul agent

Un demo care merge pe mașina ta nu este un produs. Diferența o fac câteva discipline pe care un model mental sănătos le tratează ca obligatorii, nu opționale.

Error handling și retry

API-urile externe cad ocazional: rate limit atins, timeout de rețea, eroare temporară de server. Codul tău trebuie să le anticipeze. Pattern-ul standard este retry cu backoff exponențial pentru erorile tranzitorii (aștepți puțin, apoi din ce în ce mai mult între încercări), dar fără retry pentru erorile permanente (cheie invalidă, cerere malformată) — pe acelea le ridici clar, ca să le repari, nu să le maschezi.

Cost și rate limits

Fiecare apel consumă tokeni, iar fiecare provider impune limite de rată. În producție urmărești usage pe fiecare apel, agregi costul și setezi bugete. O strategie eficientă este să alegi modelul potrivit pentru sarcină: un model rapid și ieftin (de exemplu un Haiku sau un model mini) pentru clasificări simple, și unul puternic (Opus, GPT-5.5) doar acolo unde calitatea contează cu adevărat.

Logging responsabil

Logarea este esențială pentru depanare, dar are o latură de conformitate care nu e negociabilă. Regula: loghezi metadate (durată, model, tokeni, cod de eroare), dar nu loghezi date personale sau secrete — nu pui chei API, parole sau date sensibile ale utilizatorilor în loguri. Sub GDPR, conținutul conversațiilor poate conține date cu caracter personal; tratează-l cu grijă, minimizează ce stochezi și clarifică în politica ta de confidențialitate ce reții și de ce.

Primul agent

Bucla de tool use pe care ai construit-o manual la pasul 4 este, în esență, scheletul unui agent: un sistem care, dat un obiectiv, decide singur ce tool-uri să folosească, le execută în buclă și se oprește când a terminat. Un framework de agenți (de exemplu OpenAI Agents SDK) automatizează exact acea buclă, ca să nu o mai scrii de mână:

from agents import Agent, Runner, function_tool

@function_tool
def cauta_in_documente(intrebare: str) -> str:
    """Caută în documentele locale și întoarce pasajele relevante."""
    return "...pasaj relevant găsit..."

agent = Agent(
    name="Asistent documente",
    instructions="Răspunde folosind tool-ul de căutare în documente.",
    model="gpt-5.5",
    tools=[cauta_in_documente],
)

rezultat = Runner.run_sync(agent, "Ce spune politica de retur?")
print(rezultat.final_output)

Aici se oprește acest ghid de fundamente: un agent simplu, cu un tool și o buclă gestionată de framework. Subiecte mai avansate — agenți cu mai multe tool-uri, handoffs între agenți, guardrails, observabilitate — fac obiectul unui parcurs dedicat de agenți AI și automatizare.

Capstone: leagă totul într-un produs

Cele șase straturi capătă sens când le combini într-un produs livrabil. Proiectul-far al acestui traseu este un asistent peste documentele tale: utilizatorul pune o întrebare, sistemul caută în documentele indexate (RAG), construiește contextul, apelează modelul cu streaming pentru un UX bun, folosește tool-uri unde e nevoie, validează ieșirea și gestionează erorile și costul. Este, la scară mică, exact arhitectura din spatele produselor AI pe care le admiri.

Diferența între un proiect de portofoliu și un produs real stă în ultimii 20%: testarea pe cazuri-limită, documentarea limitărilor (ce NU poate face), un README clar și o privire onestă asupra costului. Acel ultim strat este și ce te face angajabil sau ce-ți face produsul demn de încredere.

Greșeli frecvente de evitat

  • Cheia API în cod sau în Git. Cea mai costisitoare greșeală de începător. Mereu din variabile de mediu.
  • Ignorarea lui finish_reason / stop_reason. Livrezi răspunsuri trunchiate fără să știi.
  • Presupunerea că modelul ține minte. Fiecare apel este stateless; retrimiți istoricul.
  • Încredere oarbă în JSON-ul modelului. Validează mereu cu Pydantic.
  • Lipsa retry-ului. Codul cade la prima eroare de rețea sau rate limit.
  • Logarea datelor sensibile. Risc de conformitate; loghează metadate, nu conținut personal.
  • Confundarea „modelul cere tool" cu „modelul execută tool". Codul tău execută; modelul doar cere.

Concluzie

A construi aplicații AI cu Python în 2026 este, în mare parte, inginerie software solidă aplicată unui API nou și puternic. Modelul face partea grea a generării; tu construiești tot ce-l face util, sigur și fiabil: setarea corectă a mediului, apelul de chat bine structurat, streaming pentru UX, tool use pentru acțiuni, ieșiri validate, RAG pentru datele tale, și disciplina de producție care transformă un demo într-un produs. Niciun pas nu este greu izolat; măiestria stă în a le combina coerent.

Dacă vrei să parcurgi acest traseu structurat, cu cod rulat pas cu pas și un proiect capstone livrabil, cursul Construire de aplicații AI cu Python și SDK-uri (OpenAI, Anthropic) acoperă exact fluxul din acest articol, de la primul apel până la primul agent. Pentru a-ți ascuți instrucțiunile date modelelor, completează-l cu Prompt Engineering Masterclass; iar pentru pasul următor în producție, cu Advanced LLM Integration.

Surse

Continuă să înveți

Aplică ce ai citit pe platformă

Cursuri interactive, exerciții practice și progres salvat. Începe cu un plan potrivit pentru tine.