Strona główna / Artykuły

Stwórz agenta do weryfikacji kandydatów na stanowisko lidera w dziedzinie AI w Pythonie przy użyciu FastAPI i Pydantic

Przekształć surowe leady w wyselekcjonowane: strukturyzowane wydobywanie danych za pomocą LLM, walidacja za pomocą Pydantic, ocenianie na podstawie reguł, przechowywanie w PostgreSQL, kolejki oraz proces przeglądu przez człowieka.

Wydawca: REACTAPP.TOP12 min czytania2818 słów

Źródła: I Built an AI Lead Filtering Agent in Python — From Raw Leads to Qualified Customers

Większość firm nie cierpi na brak potencjalnych klientów. Ich problemem jest ich weryfikacja. Setki zapytań mogą przychodzić przez formularze internetowe, kampanie e-mailowe i narzędzia marketingowe, a ktoś musi je wszystkie otworzyć, przeczytać wiadomość, zrozumieć, czego chce klient, sprawdzić jego budżet i zdecydować, czy zasługuje na uwagę. W miarę wzrostu ilości takich zapytań ta ręczna selekcja staje się kosztowna.

Prawdziwe pytanie brzmi, czy agent AI może przyjmować przychodzące zapytania, zrozumieć intencję klienta, sprawdzić je pod kątem zasad biznesowych i skierować te odpowiednie do działu sprzedaży. Może to zrobić, ale nie poprzez wklejanie każdego zapytania do modelu językowego i poleganie na jego odpowiedzi. Niezawodny system wymaga ustrukturyzowanych wyników, jasnych zasad, weryfikacji, przechowywania danych oraz sprawnej procedury pracy. Poniższe sekcje pokazują, jak stworzyć taki system w Pythonie.

Co robi system

Proces jest prosty: pojawia się potencjalny klient, system go interpretuje, ocenia, zapisuje wynik i uruchamia następny krok.

Weźmy tę wiadomość od potencjalnego klienta:

"Nasz zespół sprzedaży potrzebuje specjalnie dostosowanego CRM na około 30 użytkowników, który ma zostać dostarczony w ciągu dwóch miesięcy. Ile to mniej więcej będzie kosztować?"

Człowiek od razu wyróżniłby kilka faktów:

  • istnieje wyraźna potrzeba biznesowa
  • projekt dotyczy oprogramowania dostosowanego pod potrzeby klienta
  • zespół ma około 30 użytkowników
  • istnieje określony termin dostawy
  • kluczowym pytaniem jest koszt

Agent powinien wyróżnić te same fakty i pomóc zespołowi sprzedaży w decydowaniu, co robić dalej. Nie powinien zakładać, że każda szczegółowa wiadomość to dobry potencjalny klient. Musi ocenić informacje pod kątem rzeczywistych kryteriów wyboru firmy.

Architektura

Planowany przepływ pracy przedstawiono poniżej:

┌──────────────────┐
                  │   Incoming Lead  │
                  │ Website / Email  │
                  └────────┬─────────┘
                           │
                           ▼
                  ┌──────────────────┐
                  │  Lead Ingestion   │
                  │ Validate & Store  │
                  └────────┬─────────┘
                           │
                           ▼
                  ┌──────────────────┐
                  │   AI Extraction   │
                  │ Intent, Need,     │
                  │ Budget, Timeline  │
                  └────────┬─────────┘
                           │
                           ▼
                  ┌──────────────────┐
                  │ Business Rules    │
                  │ Qualification     │
                  └────────┬─────────┘
                           │
                           ▼
                  ┌──────────────────┐
                  │  Lead Scoring     │
                  │ Qualified /       │
                  │ Review / Reject   │
                  └────────┬─────────┘
                           │
                           ▼
                  ┌──────────────────┐
                  │ PostgreSQL        │
                  │ Store Result      │
                  └────────┬─────────┘
                           │
                           ▼
                  ┌──────────────────┐
                  │ Automation        │
                  │ CRM / Email /     │
                  │ Sales Notification│
                  └──────────────────┘

Jedna decyzja projektowa ma największe znaczenie: trzeba oddzielić zrozumienie AI od decyzji biznesowych. LLM wydobywa informacje z leadu, natomiast twój własny kod decyduje, w jaki sposób te informacje wpływają na ocenę kwalifikacji. Dzięki takiemu podziałowi system jest łatwiejszy do testowania, naprawiania i modyfikowania.

Krok 1: Zdecyduj, co kwalifikuje leada

Zasady biznesowe przychodzą przed kodem. Weźmy za przykład agencję rozwoju oprogramowania – może ona uznać leada za kwalifikującego się wtedy, gdy:

  1. klient ma rzeczywisty wymóg dotyczący oprogramowania
  2. wymóg odpowiada usługom oferowanym przez agencję
  3. wiadomość zawiera wystarczająco dużo szczegółów, aby zrozumieć projekt
  4. budżet lub intencja zakupu spełniają wymagania agencji
  5. wiadomość nie jest spamem ani wyraźnie nieistotnym zapytaniem

Te zasady mają charakter ilustracyjny, a rzeczywisty biznes powinien ustalić własne progi. Wypełniony rekord może wyglądać tak: usługa to dostosowanie CRM, budżet wynosi 500 000 ₹, termin realizacji to dwa miesiące, liczba użytkowników w firmie to 30, intensywność potrzeb jest wysoka, a decyzja jest uzasadniona.

Sztuczna inteligencja powinna wydobyć dane. Ostateczną decyzję powinny podjąć zasady biznesowe.

Krok 2: Stworzenie projektu w Pythonie

Python nadaje się do tego zadania dzięki swojemu ekosystemowi obejmującemu API, integracje z LLM, przetwarzanie danych oraz automatyzację. Struktura projektu wygląda w ten sposób:

ai-lead-agent/
│
├── app/
│   ├── main.py
│   ├── config.py
│   │
│   ├── agents/
│   │   └── lead_agent.py
│   │
│   ├── schemas/
│   │   └── lead.py
│   │
│   ├── services/
│   │   ├── lead_service.py
│   │   └── scoring_service.py
│   │
│   └── db/
│       └── database.py
│
├── tests/
│   └── test_scoring.py
│
├── requirements.txt
└── .env

Zainstaluj wymagane pakiety:

pip install openai pydantic fastapi uvicorn python-dotenv

Komponenty to:

  • FastAPI do API backendu
  • Pydantic do strukturalnej walidacji
  • API OpenAI do przykładu z LLM
  • PostgreSQL jako baza danych produkcyjna
  • zwykły Python do oceny potencjalnych klientów

Dostawcę LLM można później zastąpić innym.

Krok 3: Zdefiniuj strukturalny schemat potencjalnych klientów

Powszechnym błędem w aplikacjach AI jest przyjmowanie tekstu wolnego jako wyniku końcowego. Taką odpowiedź trudno jest przetwarzać w sposób niezawodny:

This looks like a good lead.
The customer wants a CRM and seems interested.

Celem jest przewidywalny JSON. Stwórz plik app/schemas/lead.py i zacznij od importów:

from typing import Optional, Literal
from pydantic import BaseModel, Field

Następnie zdefiniuj modele, począwszy od przychodzącego potencjalnego klienta, a następnie przechodząc do analizy, którą model musi zwrócić:

class LeadInput(BaseModel):
    name: str
    email: str
    company: Optional[str] = None
    message: str
class LeadAnalysis(BaseModel):
    summary: str    service_type: Optional[str] = None    intent: Literal[
        "high",
        "medium",
        "low",
        "unknown"
    ]    budget: Optional[float] = None    currency: Optional[str] = None    timeline: Optional[str] = None    is_spam: bool = False    missing_information: list[str] = Field(
        default_factory=list
    )    qualification_notes: str    recommended_action: Literal[
        "contact_sales",
        "request_more_information",
        "reject",
        "manual_review"
    ]

Teraz odpowiedź AI ma określony kształt. Jeśli model zwróci nieważną wartość, aplikacja może ją odrzucić lub ją przetworzyć, zamiast po cichu przechowywać błędne dane.

Krok 4: Stworzenie funkcji analizy leadów

Następnie przychodzi plik app/agents/lead_agent.py. Model powinien interpretować to, co mówi lead, i nie może wymyślać niczego, czego nie ma. Zacznijmy od importów:

import json
import os

Następnie przychodzi sama funkcja analizy. Wysyła dane do modelu, prosi o wynik zgodny ze schematem i weryfikuje to, co wraca:

from openai import OpenAIfrom app.schemas.lead import (
    LeadInput,
    LeadAnalysis
)
client = OpenAI(
    api_key=os.getenv("OPENAI_API_KEY")
)
SYSTEM_PROMPT = """
You are a lead analysis assistant for a software
development agency.Your task is to analyze incoming customer leads.Extract:
- Customer requirement
- Service type
- Buying intent
- Budget if explicitly mentioned
- Timeline if explicitly mentioned
- Spam indicators
- Missing informationRules:
1. Never invent a budget.
2. Never invent a timeline.
3. If information is missing, return null.
4. Return valid structured JSON.
5. Do not make a final business decision based
   only on assumptions.
"""
def analyze_lead(lead: LeadInput) -> LeadAnalysis:    user_prompt = f"""
    Analyze this incoming lead:    Name: {lead.name}
    Email: {lead.email}
    Company: {lead.company}
    Message: {lead.message}
    """    response = client.chat.completions.create(
        model="gpt-4o-mini",
        temperature=0,
        response_format={
            "type": "json_object"
        },
        messages=[
            {
                "role": "system",
                "content": SYSTEM_PROMPT
            },
            {
                "role": "user",
                "content": user_prompt
            }
        ]
    )    result = json.loads(
        response.choices[0].message.content
    )    return LeadAnalysis.model_validate(result)

Dlaczego temperatura wynosi zero

Przy ekstrakcji potrzebna jest spójność, a nie kreatywny styl pisania. Niska temperatura zmniejsza zmienność odpowiedzi, ale nie gwarantuje ich poprawności. Dlatego nadal konieczna jest weryfikacja schematu oraz reguły biznesowe.

Nazwy modeli i funkcje API również zmieniają się z czasem. Przy wdrażaniu rozwiązania w środowisku produkcyjnym wybierz model oraz metodę strukturyzowanego wyjścia, które są obecnie obsługiwane przez twojego dostawcę.

Krok 5: Dodanie reguł kwalifikacji

Tę część nie należy w całości powierzać modelowi językowemu. Załóżmy, że przykładowe kryteria agencji są następujące:

  • projekt stanowi istotną pracę nad oprogramowaniem
  • jeśli podano budżet, to wynosi on co najmniej ₹2,00,000
  • wiadomość nie jest spamem
  • istnieje wystarczająco dużo informacji, aby zrozumieć wymagania

Stwórz plik app/services/scoring_service.py, zaczynając od importu:

from app.schemas.lead import LeadAnalysis

Następnie funkcja oceny, która zaczyna się od zera, zbiera powody każdej korekty i zwraca natychmiast zero dla spamu:

def score_lead(analysis: LeadAnalysis) -> dict:    score = 0
    reasons = []    if analysis.is_spam:
        return {
            "score": 0,
            "status": "rejected",
            "reasons": ["Spam detected"]
        }    if analysis.service_type:
        score += 25
        reasons.append(
            "Service requirement identified"
        )    if analysis.intent == "high":
        score += 30
        reasons.append(
            "High buying intent"
        )    elif analysis.intent == "medium":
        score += 15
        reasons.append(
            "Medium buying intent"
        )    if analysis.budget is not None:
        if analysis.budget >= 200000:
            score += 25
            reasons.append(
                "Budget meets example threshold"
            )
        else:
            reasons.append(
                "Budget below example threshold"
            )    if analysis.timeline:
        score += 10
        reasons.append(
            "Timeline provided"
        )    if analysis.missing_information:
        score -= 10
        reasons.append(
            "Some information is missing"
        )    score = max(0, min(score, 100))    if score >= 70:
        status = "qualified"    elif score >= 40:
        status = "review"    else:
        status = "unqualified"    return {
        "score": score,
        "status": status,
        "reasons": reasons
    }

To jest prosty, ilustracyjny schemat oceniania. Rzeczywista agencja może brać pod uwagę inne czynniki:

  • rozmiar projektu
  • sektor przemysłowy
  • lokalizacja
  • dostępność usługi
  • pilność żądania klienta
  • poprzednia współpraca
  • pewność co do podanego budżetu
  • powtórne zapytania

Przed tym, jak pozwolić systemowi automatycznie odrzucać zapytania, przetestuj funkcję oceniania na rzeczywistych przykładach.

Krok 6: Połączenie agenta z FastAPI

Stwórz plik app/main.py i zaimportuj FastAPI:

from fastapi import FastAPI

Pozostała część pliku łączy schemat, funkcję analizy oraz usługę oceniania za pośrednictwem jednego punktu końcowego:

from app.schemas.lead import LeadInput
from app.agents.lead_agent import analyze_lead
from app.services.scoring_service import score_lead
app = FastAPI(
    title="AI Lead Filtering Agent"
)
@app.get("/health")
def health_check():
    return {
        "status": "ok"
    }
@app.post("/analyze-lead")
def analyze_incoming_lead(
    lead: LeadInput
):    analysis = analyze_lead(lead)    score = score_lead(analysis)    return {
        "lead": lead,
        "analysis": analysis,
        "qualification": score
    }

Rozpocznij serwer:

uvicorn app.main:app --reload

Następnie otwórz interaktywne dokumentacje API:

http://127.0.0.1:8000/docs

Stamtąd możesz wysłać lead i przejrzeć strukturalną odpowiedź.

Krok 7: Spróbuj zrealistowanego leadu

Wyślij próbny wniosek taki jak ten:

{
  "name": "Rahul Sharma",
  "email": "rahul@example.com",
  "company": "Example Technologies",
  "message": "We need a custom CRM for around 30 users. Our budget is approximately 500000 INR and we want to launch within 2 months."
}

Prawdopodobny wynik wydobywania wygląda następująco:

{
  "summary": "Customer needs a custom CRM.",
  "service_type": "CRM development",
  "intent": "high",
  "budget": 500000,
  "currency": "INR",
  "timeline": "2 months",
  "is_spam": false,
  "missing_information": [],
  "qualification_notes": "Clear requirement, budget, and timeline.",
  "recommended_action": "contact_sales"
}

Usługa oceny następnie analizuje wydobyte dane, przy czym wynik wygląda następująco:

{
  "score": 90,
  "status": "qualified",
  "reasons": [
    "Service requirement identified",
    "High buying intent",
    "Budget meets example threshold",
    "Timeline provided"
  ]
}

Należy pamiętać, że ten wynik jest jedynie ilustracją tego, czego można się spodziewać, a nie pomiarem uzyskanym podczas rzeczywistego uruchomienia API.

Krok 8: Przechowywanie leadów w PostgreSQL

Dla rzeczywistego zastosowania biznesowego przechowywanie wyników wyłącznie w pamięci nie wystarcza, dlatego konieczna jest trwałość danych. Prosta tabela wygląda w ten sposób:

CREATE TABLE leads (
    id BIGSERIAL PRIMARY KEY,

Pozostałe kolumny zawierają szczegóły lidera oraz analizę:

    name VARCHAR(150) NOT NULL,    email VARCHAR(255) NOT NULL,    company VARCHAR(255),    message TEXT NOT NULL,    service_type VARCHAR(255),    intent VARCHAR(20),    budget NUMERIC(14, 2),    currency VARCHAR(10),    timeline VARCHAR(100),    is_spam BOOLEAN DEFAULT FALSE,    ai_score INTEGER,    qualification_status VARCHAR(30),    analysis JSONB,    created_at TIMESTAMPTZ DEFAULT NOW()
);

Kolumna analysis przechowuje oryginalny, ustrukturyzowany wynik generowany przez sztuczną inteligencję, co jest przydatne, gdy musisz zdiagnozować, dlaczego dany lead otrzymał określoną klasifikację.

Dla środowiska produkcyjnego należy również zaplanować:

  • unikalny identyfikator dla każdego leadu
  • sposób wykrywania duplikatów
  • indeksy obejmujące status i czas utworzenia
  • szifrowanie oraz ścisłą kontrolę dostępu, ponieważ dane leadów są wrażliwe
  • migracje schematu
  • ślad audytowy

Krok 9: Dodanie automatyzacji

W tym momencie agent staje się czymś więcej niż zwykłą API. Wyobraź sobie ten przepływ:

New Lead
   │
   ▼
Save in PostgreSQL
   │
   ▼
Analyze with AI
   │
   ▼
Calculate Qualification
   │
   ├── Qualified ────────► Notify Sales
   │
   ├── Review ───────────► Human Review Queue
   │
   └── Unqualified ─────► Store for Reporting

Gdy pojawi się kwalifikowany lead, system może:

  1. przechować go w bazie danych
  2. poinformować zespół sprzedaży
  3. stworzyć rekord w CRM
  4. przydzielić przedstawiciela sprzedaży
  5. umówić się na kolejne spotkanie
  6. aktualizować status leada

Słoj automatyzacji może stanowić n8n, proces w tle lub system oparty na kolejce. W środowisku produkcyjnym nie jest rozsądne polegać w całości na jednym synchronicznym żądaniu HTTP. Lepszy projekt umieszcza kolejkę pomiędzy poszczególnymi etapami:

Lead API
   │
   ▼
Message Queue
   │
   ▼
Background Worker
   │
   ▼
AI Analysis
   │
   ▼
Database
   │
   ▼
Automation

Leady są następnie przetwarzane asynchronicznie, a nieudane zlecenia można spróbować ponownie.

Krok 10: Dodanie przeglądu przez człowieka

To może być najważniejszy element. Sztuczna inteligencja może błędnie zinterpretować leada. Rozważmy następującą wiadomość:

"W tej chwili porównujemy opcje CRM i nie ustaliliśmy budżetu, choć chcielibyśmy mieć pojęcie o cenach."

Model może oznaczyć intencję jako średnią lub wysoką, podczas gdy firma woli skierować leada do osoby zamiast automatycznie uznać go za odpowiedniego. Dlatego istnieją trzy statusy:

  • Odpowiedni: lead spełnia wymagania i trafia do zespołu sprzedaży.
  • W przeglądzie: lead zawiera przydatne informacje, ale decyzję powinien podjąć człowiek.
  • Nieodpowiedni: lead nie spełnia ustawionych kryteriów.

Przegląd przez człowieka jest najbardziej pomocny wtedy, gdy:

  • nie podano budżetu
  • potrzeba jest niejasna
  • model wydaje się niepewny swojego wyniku
  • detale w wiadomości są ze sobą sprzeczne
  • nadawca działa w branży, której firma nie obsługuje

Dobry system AI nie ukrywa niepewności. Uczynia ją widoczną.

Co czyni to agentem

Zwykłe wezwanie LLM to po prostu dane wejściowe, model, wynik:

Input → LLM → Output

Przepływ pracy agenta robi o wiele więcej. Rozumie przychodzące zadanie, wydobywa istotne informacje, stosuje narzędzia lub zasady biznesowe, wybiera następny krok, przechowuje stan, uruchamia działanie oraz próbuje ponownie lub eskaluje sytuację, gdy coś się psuje. Dla filtru leadów pełna ścieżka wygląda w ten sposób:

Incoming Lead
      │
      ▼
AI Analysis
      │
      ▼
Business Rules
      │
      ▼
Qualification Decision
      │
      ▼
Action / Human Review

Sztuczna inteligencja to tylko jeden z elementów. Aplikacja backendowa sprawia, że cały proces jest niezawodny, a ta różnica ma znaczenie.

Ulepszenia przed wdrożeniem

Pierwsza wersja wystarcza, aby zobaczyć przepływ pracy, ale nie powinna trafiać do użytkowników w takim stanie.

Przetwarzanie w tle. Wykonuj analizę leadów za pomocą kolejki zadań, takiej jak Celery z Redis, RQ, zarządzanej chmurą kolejki lub systemu zadań opartego na bazie danych. To ułatwia ponawianie prób i obsługę dużych ilości danych.

Wykrywanie duplikatów. Jeden lead może pojawić się dwa razy – raz z strony internetowej, a raz z kampanii e-mailowej. Porównuj adres e-mail, nazwę firmy oraz inne identyfikatory.

Wersjonowanie promptów. Przechowuj wersję promptu obok każdego wyniku generowanego przez sztuczną inteligencję. Gdy zmienią się kryteria, można wtedy określić, który prompt i reguły doprowadziły do wcześniejszego wyniku.

Obserwowalność. Śledź opóźnienia w działaniu AI, błędy API, użycie tokenów, koszt za potencjalnego klienta, rozkład wyników weryfikacji oraz to, jak często ludzie przejmują kontrolę nad agentem.

Zbiór danych do oceny. Zbieraj rzeczywiste potencjalne klientów z etykietami sprawdzonymi przez ludzi i testuj system na ich podstawie. To mówi o wiele więcej niż ocena agenta na podstawie jednego dobrego przykładu.

Bезpieczeństwo. Unikaj umieszczania kluczy API w kodzie frontendu, sprawdzaj każdą przychodzącą prośbę, chronij dane osobowe i ogranicz dostęp do informacji o potencjalnych klientach.

Lekcja z architektury

Budowa agenta AI to nie tylko wywoływanie modelu LLM. Prawdziwa inżynieria dotyczy samego modelu: jasnego problemu biznesowego, ustrukturyzowanych danych, niezawodnej weryfikacji, reguł deterministycznych, zachowania danych, automatyzacji, ludzkiej oceny oraz monitoringu. Bez tych elementów powstaje chatbot, który wydaje się inteligentny, ale nie rozwiązuje problemu biznesowego.

Filtr leadów nie powinien jedynie generować odpowiedzi – powinien tworzyć przydatny, śledzalny proces pracy. Model rozumie nieuporządkowane wiadomości klientów, Python uruchamia ten proces, reguły biznesowe określają kryteria kwalifikacji, PostgreSQL przechowuje dane, a automatyzacja łączy wynik z zespołem sprzedaży. Razem przekształcają one demonstrację AI w działającą aplikację.

Naturalnym krokiem jest połączenie API z rzeczywistym źródłem leadów, dodanie zadań w tle oraz stworzenie panelu kontrolnego, który umożliwi sprzedaży sprawdzanie, które leady są odpowiednie. Celem nie jest zastąpienie każdej decyzji sprzedażowej sztuczną inteligencją, lecz zmniejszenie ilości powtarzalnej pracy, aby pracownicy mogli skupić się na leadach, które na to zasługują.