Ekstrakcja danych z nieustrukturyzowanego tekstu
Uczestnicy zbudują potok ekstrakcji informacji, który odczytuje surowy tekst, taki jak e-maile, paragony i artykuły, a następnie zwraca ustrukturyzowane pola z określonymi typami, wartościami domyślnymi i walidacją.
Ekstrakcja danych z nieustrukturyzowanego tekstu to bezpłatna lekcja AI Engineering Academy na CoddyKit. To lekcja 3 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.
Problem ekstrakcji informacji
Organizacje toną w nieustrukturyzowanym tekście: wiadomościach e-mail, zgłoszeniach do pomocy technicznej, umowach, fakturach, artykułach prasowych, notatkach medycznych i postach w mediach społecznościowych. Wartościowe dane strukturalne są ukryte w tych tekstach, ale ich ręczne wydobywanie jest powolne, kosztowne i podatne na błędy. LLM-y ze strukturalnymi wynikami zmieniają tę sytuację: mogą odczytywać dowolny tekst i na dużą skalę wypełniać wstępnie zdefiniowany schemat odpowiednimi polami, zachowując przy tym rozsądną dokładność.
Ekstrakcja informacji (IE) to proces automatycznego identyfikowania i wydobywania ustrukturyzowanych faktów z nieustrukturyzowanego tekstu. Ekstrakcja informacji oparta na LLM-ach zdecydowanie przewyższa wcześniejsze podejścia oparte na regułach lub klasycznym NLP, ponieważ LLM-y rozumieją kontekst, synonimię i informacje dorozumiane, bez konieczności ręcznego tworzenia wzorców regex dla każdej możliwej odmiany.
Typowe zastosowania ekstrakcji
Ekstrakcja informacji zasila wiele wartościowych zastosowań biznesowych:
- Przetwarzanie faktur: wydobywanie danych dostawcy, pozycji, kwot i terminów płatności z faktur PDF na potrzeby automatyzacji zobowiązań
- Analiza umów: wydobywanie stron umowy, dat wejścia w życie, warunków płatności i klauzul rozwiązania z dokumentów prawnych
- Parsowanie CV: wydobywanie umiejętności, doświadczenia, wykształcenia i danych kontaktowych z CV na potrzeby systemów ATS
- Kategoryzowanie zgłoszeń do pomocy technicznej: wydobywanie kategorii, ważności, produktu, którego dotyczy problem, i poziomu klienta w celu automatycznego kierowania zgłoszeń
- Monitorowanie wiadomości: wydobywanie encji, wydarzeń i nastrojów z artykułów prasowych na potrzeby analizy konkurencji
Budowanie potoku ekstrakcji wiadomości e-mail
Zbudujmy praktyczny potok ekstrakcji, który odczytuje wiadomości e-mail od klientów i wydobywa z nich ustrukturyzowane dane przydatne w działaniu. Potok używa schematu Pydantic do dokładnego zdefiniowania tego, czego oczekujemy z każdej wiadomości e-mail, a następnie przetwarza wiadomości zbiorczo.
import openai
from pydantic import BaseModel
from typing import List, Optional
from enum import Enum
client = openai.OpenAI()
class Priority(str, Enum):
urgent = 'urgent'
high = 'high'
normal = 'normal'
low = 'low'
class EmailExtraction(BaseModel):
subject_summary: str
sender_intent: str
product_mentioned: Optional[str]
issue_category: str # billing / technical / general / feedback
priority: Priority
action_required: bool
action_description: Optional[str]
customer_sentiment: str # positive / negative / neutral / frustrated
def extract_from_email(email_body: str) -> EmailExtraction:
result = client.beta.chat.completions.parse(
model='gpt-4o-mini',
messages=[
{'role': 'system', 'content': 'You are an expert at analyzing customer emails and extracting structured information for a support team.'},
{'role': 'user', 'content': f'Analyze this customer email:\n\n{email_body}'}
],
response_format=EmailExtraction
)
return result.choices[0].message.parsedRozpoznawanie nazwanych encji za pomocą LLM-ów
Rozpoznawanie nazwanych encji (NER) to klasyczne zadanie ekstrakcji informacji: identyfikowanie i klasyfikowanie nazwanych encji (osób, organizacji, lokalizacji, dat i kwot pieniężnych) w tekście. LLM-y znacznie upraszczają NER, ponieważ wystarczy opisać encje, których Państwo potrzebują, a model je wydobędzie bez konieczności używania specjalnie wytrenowanego modelu NER.
import openai
from pydantic import BaseModel
from typing import List, Optional
client = openai.OpenAI()
class NamedEntity(BaseModel):
text: str # The exact text as it appears
entity_type: str # PERSON / ORG / LOCATION / DATE / MONEY / PRODUCT
normalized: Optional[str] # Standardized form where applicable
class NERResult(BaseModel):
entities: List[NamedEntity]
text = '''
Apple Inc. CEO Tim Cook announced yesterday that the company will invest $1.2 billion
in a new manufacturing facility in Austin, Texas, expected to open in Q3 2026.
'''
result = client.beta.chat.completions.parse(
model='gpt-4o-mini',
messages=[
{'role': 'system', 'content': 'Extract all named entities from the text. Classify each as PERSON, ORG, LOCATION, DATE, MONEY, or PRODUCT.'},
{'role': 'user', 'content': text}
],
response_format=NERResult
)
for entity in result.choices[0].message.parsed.entities:
print(f'[{entity.entity_type}] {entity.text}')Ekstrakcja z dokumentów na dużą skalę
W przypadku produkcyjnych potoków ekstrakcji przetwarzających tysiące dokumentów potrzebne są przetwarzanie asynchroniczne i obsługa limitów szybkości. Typowy wzorzec używa asyncio z semaforem, aby przetwarzać dokumenty równolegle z zachowaniem limitów szybkości interfejsu API.
import asyncio
import openai
from pydantic import BaseModel
from typing import List, Optional
async_client = openai.AsyncOpenAI()
class InvoiceExtraction(BaseModel):
vendor: str
total_amount: Optional[float]
currency: str
invoice_date: Optional[str]
async def extract_invoice(doc_text: str, semaphore: asyncio.Semaphore) -> InvoiceExtraction:
async with semaphore: # Limit concurrent requests
result = await async_client.beta.chat.completions.parse(
model='gpt-4o-mini',
messages=[
{'role': 'system', 'content': 'Extract invoice data.'},
{'role': 'user', 'content': doc_text}
],
response_format=InvoiceExtraction
)
return result.choices[0].message.parsed
async def process_invoices(documents: List[str]):
sem = asyncio.Semaphore(5) # Max 5 concurrent requests
tasks = [extract_invoice(doc, sem) for doc in documents]
return await asyncio.gather(*tasks, return_exceptions=True)
# results = asyncio.run(process_invoices(invoice_texts))
print('Async pipeline defined - handles rate limits via semaphore')Obsługa informacji dorozumianych i wywnioskowanych
LLM-y mogą wydobywać nie tylko informacje wyraźnie podane, lecz także informacje wywnioskowane lub dorozumiane. Jeśli recenzja mówi: „Używam tego codziennie od miesiąca i nadal działa idealnie”, model może wywnioskować, że trwałość jest pozytywną cechą, mimo że słowo „trwałość” nigdy się w niej nie pojawia. To istotna przewaga nad ekstrakcją opartą na regex, która może znaleźć wyłącznie to, co występuje w tekście wprost.
Ta możliwość wiąże się jednak z ryzykiem: model może wyciągać zbyt daleko idące wnioski i wypełniać pola przypuszczeniami zamiast faktami. W przypadku ekstrakcji o wysokiej stawce (prawnej, finansowej lub medycznej) należy dodać pole confidence do schematu i polecić modelowi ocenę pewności, a ekstrakcje o niskiej pewności oznaczać do weryfikacji przez człowieka.
Projektowanie promptów do ekstrakcji
Jakość ekstrakcji w dużej mierze zależy od projektu promptu. Najważniejsze zasady dotyczące promptów do ekstrakcji:
- Definiowanie niejednoznacznych pól: jeśli „data” może oznaczać datę wystawienia faktury, termin płatności lub datę otrzymania, należy dokładnie określić, o którą z nich chodzi
- Podawanie przykładów nietypowych formatów: „W przypadku ceny zwróć wyłącznie wartość liczbową, np. 29.99, a nie $29.99”
- Obsługa normalizacji: „Normalizuj nazwy państw do kodów ISO 3166-1 alpha-2”
- Określanie źródła ekstrakcji: „Wydobądź informacje wyłącznie z tematu wiadomości, a nie z jej treści”
Prompt do ekstrakcji należy traktować jak precyzyjną specyfikację dla osoby wprowadzającej dane — każda niejednoznaczność pozostawiona w prompcie będzie prowadzić do niespójnych decyzji modelu.
Wieloprzebiegowa ekstrakcja złożonych dokumentów
Niektóre dokumenty są zbyt złożone, aby przetworzyć je w jednym przebiegu, ponieważ pełny schemat jest obszerny, różne sekcje wymagają odmiennej wiedzy specjalistycznej lub struktura dokumentu jest bardzo zmienna. Wieloprzebiegowa ekstrakcja dzieli zadanie na kolejne etapy: najpierw klasyfikuje typ dokumentu, a następnie wydobywa dane zgodnie ze schematem odpowiednim dla tego typu.
import openai
from pydantic import BaseModel
from typing import Optional
client = openai.OpenAI()
class DocumentType(BaseModel):
doc_type: str # invoice / contract / resume / report
confidence: float
def classify_document(text: str) -> str:
result = client.beta.chat.completions.parse(
model='gpt-4o-mini',
messages=[
{'role': 'system', 'content': 'Classify the document type.'},
{'role': 'user', 'content': text[:500]} # Use only the beginning for classification
],
response_format=DocumentType
)
return result.choices[0].message.parsed.doc_type
# Then route to the appropriate extraction schema
EXTRACTION_SCHEMAS = {
'invoice': 'InvoiceSchema', # Replace with actual Pydantic classes
'contract': 'ContractSchema',
'resume': 'ResumeSchema',
}
print('Multi-pass: classify first, then extract with the right schema')Wzbogacanie danych po ekstrakcji
Wydobyte dane często wymagają wzbogacenia po wstępnej ekstrakcji: przekształcenia wydobytych nazw firm do postaci kanonicznej przez wyszukanie ich w bazie firm, wyszukania miasta i stanu na podstawie wydobytego kodu pocztowego lub przekształcenia wydobytych dat do standardowego formatu. Ten etap wzbogacania powinien odbywać się w kodzie aplikacji po ekstrakcji, a nie w trakcie samego wywołania LLM.
Rozdzielenie ekstrakcji i wzbogacania ułatwia testowanie i utrzymanie potoku. Logikę wzbogacania można testować jednostkowo niezależnie, a model ekstrakcji wymienić bez modyfikowania kodu wzbogacania.
Pomiar dokładności ekstrakcji
W przypadku produkcyjnych potoków ekstrakcji należy systematycznie mierzyć dokładność względem oznaczonego zbioru testowego. Najważniejsze metryki to:
- Dokładność pól: odsetek pól poprawnie wydobytych dla każdego dokumentu
- Dokładne dopasowanie: wartość pola dokładnie odpowiada wartości referencyjnej
- Dopasowanie po normalizacji: wartość pola odpowiada wartości referencyjnej po normalizacji (np. '$1,234.00' == '1234.0')
- Odsetek fałszywie pozytywnych wyników: jak często model wydobywa pole, które powinno mieć wartość null
- Odsetek fałszywie negatywnych wyników: jak często model zwraca wartość null dla pola, które występuje w dokumencie
Tę ocenę należy przeprowadzać za każdym razem, gdy zmieniają Państwo modele, aktualizują prompty lub dodają nowe źródła dokumentów do potoku. Nawet niewielki spadek dokładności może prowadzić do znaczących skutków biznesowych podczas przetwarzania tysięcy dokumentów.
Logowanie ekstrakcji na potrzeby ciągłego doskonalenia
Każdy wynik ekstrakcji w środowisku produkcyjnym jest punktem danych, który może pomóc ulepszyć potok. Należy rejestrować w bazie danych każdy dokument wejściowy, wydobyty wynik i ewentualne błędy walidacji. Okresowo warto pobierać próbki z dzienników produkcyjnych, aby identyfikować typowe wzorce błędów: formaty dokumentów, z którymi model ma trudności, pola, które często mają wartość null, choć nie powinny, lub nietypowe wartości wskazujące na dryf promptu.
Te zarejestrowane dane mogą również stać się przyszłym zbiorem treningowym, jeśli zechcą Państwo dostroić model specjalnie do zadania ekstrakcji, uzyskując dokładniejszą i tańszą alternatywę dla ogólnych LLM-ów w zakresie ekstrakcji strukturalnej.
Szybki test
Sprawdź swoją wiedzę na temat koncepcji inżynierii AI przedstawionych w tej lekcji.
Podsumowanie lekcji
W tej lekcji nauczyli się Państwo, że: LLM-y ze schematami Pydantic niezawodnie wydobywają ustrukturyzowane dane z dowolnego źródła nieustrukturyzowanego tekstu, przetwarzanie asynchroniczne z semaforami umożliwia zbiorczą ekstrakcję z tysięcy dokumentów z zachowaniem limitów szybkości, a wieloprzebiegowa ekstrakcja najpierw klasyfikuje dokumenty, a następnie stosuje odpowiedni schemat dla każdego typu. W dalszej części zbudujemy logikę walidacji i automatycznych ponownych prób, aby obsługiwać sytuacje, w których wydobyte dane nie spełniają reguł biznesowych.
Często zadawane pytania
Czy lekcja „Ekstrakcja danych z nieustrukturyzowanego tekstu” jest bezpłatna?
Tak — pełny tekst „Ekstrakcja danych z nieustrukturyzowanego tekstu” 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 „Ekstrakcja danych z nieustrukturyzowanego tekstu”?
Uczestnicy zbudują potok ekstrakcji informacji, który odczytuje surowy tekst, taki jak e-maile, paragony i artykuły, a następnie zwraca ustrukturyzowane pola z określonymi typami, wartościami domyśln… Ć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 3 z 4.
Ile czasu zajmuje lekcja „Ekstrakcja danych z nieustrukturyzowanego tekstu”?
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
- Tryb JSON i response_format
- Ustrukturyzowane dane wyjściowe z Pydantic
- Ekstrakcja danych z nieustrukturyzowanego tekstu
- Walidowanie i ponawianie dla niepoprawnych danych wyjściowych