Processamento de Linguagem Natural (NLP) com Python
Guia completo de NLP com Python — tokenização, NER, classificação de texto, análise de sentimento usando spaCy e Hugging Face Transformers com exemplos práticos
Processamento de Linguagem Natural (NLP) com Python
Processamento de Linguagem Natural (NLP, do inglês Natural Language Processing) é o campo da inteligência artificial dedicado a ensinar computadores a entender, interpretar e gerar linguagem humana. De assistentes virtuais a tradutores automáticos, de análise de sentimento em redes sociais a chatbots inteligentes — NLP está por toda parte.
Neste tutorial, vamos explorar as principais técnicas de NLP usando Python, com foco em duas bibliotecas poderosas: spaCy para processamento linguístico tradicional e Hugging Face Transformers para técnicas modernas baseadas em deep learning.
Pré-requisitos
Instalação
# spaCy e modelo para português
pip install spacy
python -m spacy download pt_core_news_lg
# Modelo em inglês (opcional)
python -m spacy download en_core_web_sm
# Hugging Face Transformers
pip install transformers torch sentencepiece
# Bibliotecas auxiliares
pip install nltk scikit-learn pandas matplotlib wordcloud
Estrutura do Projeto
nlp-python/
├── src/
│ ├── tokenization.py # Tokenização e processamento básico
│ ├── ner.py # Reconhecimento de Entidades Nomeadas
│ ├── classification.py # Classificação de texto
│ ├── sentiment.py # Análise de sentimento
│ ├── similarity.py # Similaridade semântica
│ └── transformers_nlp.py # NLP com Transformers
├── data/ # Dados de exemplo
├── output/ # Resultados
└── requirements.txt
Parte 1: Fundamentos com spaCy
Introdução ao spaCy
O spaCy é uma biblioteca industrial de NLP — rápida, eficiente e projetada para produção. Vamos começar pelo básico:
"""Fundamentos de NLP com spaCy."""
import spacy
# Carregar modelo para português
nlp = spacy.load("pt_core_news_lg")
# Processar um texto
texto = """A inteligência artificial está transformando o Brasil.
Empresas como a Petrobras e o Banco do Brasil investem milhões em
soluções de machine learning. São Paulo lidera a adoção, com mais de
500 startups de IA registradas na Faria Lima."""
doc = nlp(texto)
# O objeto doc contém toda a análise linguística
print(f"Número de tokens: {len(doc)}")
print(f"Número de sentenças: {len(list(doc.sents))}")
print(f"Número de entidades: {len(doc.ents)}")
Parte 2: Tokenização e Análise Morfológica
Tokenização
Tokenização é o processo de dividir texto em unidades menores (tokens). É o primeiro passo em qualquer pipeline de NLP:
"""Tokenização e análise morfológica detalhada."""
import spacy
from collections import Counter
nlp = spacy.load("pt_core_news_lg")
def tokenize_and_analyze(text: str) -> dict:
"""Tokeniza e analisa morfologicamente um texto."""
doc = nlp(text)
analysis = {
"tokens": [],
"pos_distribution": Counter(),
"lemmas": [],
"sentences": [],
}
for token in doc:
token_info = {
"text": token.text,
"lemma": token.lemma_, # Forma base
"pos": token.pos_, # Part-of-speech (universal)
"tag": token.tag_, # POS tag detalhada
"dep": token.dep_, # Dependência sintática
"shape": token.shape_, # Forma (Xxxxx, dd, etc.)
"is_alpha": token.is_alpha, # É alfanumérico?
"is_stop": token.is_stop, # É stop word?
"is_punct": token.is_punct, # É pontuação?
}
analysis["tokens"].append(token_info)
analysis["pos_distribution"][token.pos_] += 1
if not token.is_stop and not token.is_punct and token.is_alpha:
analysis["lemmas"].append(token.lemma_.lower())
# Sentenças
for sent in doc.sents:
analysis["sentences"].append(sent.text.strip())
return analysis
def print_token_table(text: str) -> None:
"""Imprime tabela detalhada de tokens."""
doc = nlp(text)
print(f"{'Token':<15} {'Lemma':<15} {'POS':<8} {'Dep':<10} {'Stop?':<6}")
print("-" * 60)
for token in doc:
print(
f"{token.text:<15} {token.lemma_:<15} {token.pos_:<8} "
f"{token.dep_:<10} {str(token.is_stop):<6}"
)
# Exemplo
text = "Os desenvolvedores brasileiros estão construindo aplicações incríveis de IA."
print_token_table(text)
analysis = tokenize_and_analyze(text)
print(f"\nDistribuição POS: {dict(analysis['pos_distribution'])}")
print(f"Lemmas (sem stops): {analysis['lemmas']}")
Análise de Stop Words e Frequência
def analyze_word_frequency(text: str, top_n: int = 20) -> dict:
"""Analisa frequência de palavras, removendo stop words."""
doc = nlp(text)
# Extrair tokens significativos (sem stop words, pontuação ou espaços)
meaningful_tokens = [
token.lemma_.lower()
for token in doc
if not token.is_stop
and not token.is_punct
and not token.is_space
and token.is_alpha
and len(token.text) > 2
]
freq = Counter(meaningful_tokens)
print(f"\nTop {top_n} palavras mais frequentes:")
for word, count in freq.most_common(top_n):
bar = "█" * count
print(f" {word:<20} {count:>4} {bar}")
return {
"total_tokens": len(doc),
"unique_meaningful": len(set(meaningful_tokens)),
"frequency": dict(freq.most_common(top_n)),
}
def generate_wordcloud(text: str, output_path: str = "output/wordcloud.png") -> None:
"""Gera uma nuvem de palavras a partir de um texto."""
from wordcloud import WordCloud
import matplotlib.pyplot as plt
from pathlib import Path
doc = nlp(text)
# Filtrar tokens
words = " ".join([
token.lemma_.lower()
for token in doc
if not token.is_stop and not token.is_punct
and token.is_alpha and len(token.text) > 2
])
wc = WordCloud(
width=800,
height=400,
background_color="white",
max_words=100,
colormap="viridis",
).generate(words)
Path(output_path).parent.mkdir(exist_ok=True)
plt.figure(figsize=(16, 8))
plt.imshow(wc, interpolation="bilinear")
plt.axis("off")
plt.tight_layout()
plt.savefig(output_path, dpi=150, bbox_inches="tight")
plt.close()
print(f"Word cloud salva em: {output_path}")
Parte 3: Reconhecimento de Entidades Nomeadas (NER)
O Que É NER
NER (Named Entity Recognition) identifica e classifica entidades mencionadas no texto — pessoas, organizações, locais, datas, valores monetários, etc.
"""Reconhecimento de Entidades Nomeadas (NER)."""
import spacy
from collections import defaultdict
nlp = spacy.load("pt_core_news_lg")
def extract_entities(text: str) -> dict:
"""Extrai entidades nomeadas de um texto."""
doc = nlp(text)
entities = defaultdict(list)
for ent in doc.ents:
entities[ent.label_].append({
"text": ent.text,
"start": ent.start_char,
"end": ent.end_char,
})
return dict(entities)
def print_entities(text: str) -> None:
"""Exibe entidades nomeadas de forma formatada."""
doc = nlp(text)
# Mapeamento de labels para português
label_names = {
"PER": "Pessoa",
"ORG": "Organização",
"LOC": "Local",
"MISC": "Diversos",
"DATE": "Data",
"MONEY": "Dinheiro",
"GPE": "Entidade Geopolítica",
"EVENT": "Evento",
}
print("Entidades encontradas:")
print("-" * 60)
if not doc.ents:
print(" Nenhuma entidade encontrada.")
return
for ent in doc.ents:
label_pt = label_names.get(ent.label_, ent.label_)
print(f" [{label_pt}] {ent.text}")
print(f"\nTotal: {len(doc.ents)} entidades")
# Exemplo com texto rico em entidades
texto_noticias = """
O presidente Lula se reuniu com o CEO da Microsoft, Satya Nadella,
em Brasília na última terça-feira. O encontro discutiu investimentos
de R$ 5 bilhões em inteligência artificial no Brasil. A Petrobras e
o Itaú também participaram das negociações. O acordo deve ser
formalizado durante o Fórum Econômico Mundial em Davos, na Suíça,
previsto para janeiro de 2027.
"""
print_entities(texto_noticias)
entities = extract_entities(texto_noticias)
print(f"\nEntidades por tipo: { {k: len(v) for k, v in entities.items()} }")
NER Customizado com Visualização
def visualize_entities_html(text: str, output_path: str = "output/entities.html") -> None:
"""Gera visualização HTML das entidades com displaCy."""
from spacy import displacy
from pathlib import Path
doc = nlp(text)
# Gerar HTML com displaCy
html = displacy.render(doc, style="ent", page=True, options={
"colors": {
"PER": "#feca74",
"ORG": "#7aecec",
"LOC": "#ff9561",
"MISC": "#c887fb",
}
})
Path(output_path).parent.mkdir(exist_ok=True)
Path(output_path).write_text(html)
print(f"Visualização salva em: {output_path}")
def extract_relationships(text: str) -> list[dict]:
"""Extrai relações simples entre entidades baseado em proximidade."""
doc = nlp(text)
relationships = []
entities = list(doc.ents)
for i, ent1 in enumerate(entities):
for ent2 in entities[i + 1:]:
# Verificar se estão na mesma sentença
sent1 = ent1.sent
sent2 = ent2.sent
if sent1 == sent2:
# Extrair texto entre as entidades
start = min(ent1.end_char, ent2.end_char)
end = max(ent1.start_char, ent2.start_char)
between = text[start:end].strip()
if len(between) < 100: # Proximidade razoável
relationships.append({
"entity1": {"text": ent1.text, "type": ent1.label_},
"entity2": {"text": ent2.text, "type": ent2.label_},
"context": between,
"sentence": sent1.text.strip(),
})
return relationships
Parte 4: Classificação de Texto
Classificação com Scikit-learn
"""Classificação de texto com TF-IDF e scikit-learn."""
import numpy as np
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.naive_bayes import MultinomialNB
from sklearn.linear_model import LogisticRegression
from sklearn.svm import LinearSVC
from sklearn.pipeline import Pipeline
from sklearn.metrics import classification_report, confusion_matrix
import spacy
nlp = spacy.load("pt_core_news_lg")
def preprocess_text(text: str) -> str:
"""Preprocessa texto para classificação."""
doc = nlp(text.lower())
tokens = [
token.lemma_
for token in doc
if not token.is_stop
and not token.is_punct
and not token.is_space
and token.is_alpha
and len(token.text) > 2
]
return " ".join(tokens)
def create_sample_dataset() -> pd.DataFrame:
"""Cria dataset de exemplo para classificação de notícias."""
data = {
"text": [
"O Flamengo venceu o Palmeiras por 3 a 1 no Maracanã",
"Seleção brasileira convocada para as eliminatórias",
"Novo técnico assume o comando do Corinthians",
"Campeonato Brasileiro tem rodada decisiva neste fim de semana",
"Jogador se lesiona e desfalca o time por três meses",
"Ibovespa fecha em alta de 2% com otimismo global",
"Banco Central mantém taxa Selic em 14,25%",
"Inflação acumula 5,2% nos últimos 12 meses",
"Dólar cai para R$ 5,10 com fluxo de capital estrangeiro",
"PIB cresce 2,8% no terceiro trimestre de 2025",
"Nova vacina contra dengue aprovada pela Anvisa",
"Pesquisadores descobrem tratamento promissor para Alzheimer",
"OMS alerta sobre nova variante do vírus da gripe",
"Hospital Einstein inaugura centro de medicina de precisão",
"Campanha de vacinação atinge 90% de cobertura no país",
"SpaceX lança novo lote de satélites Starlink",
"Apple apresenta novo chip M5 com IA integrada",
"Google anuncia avanço em computação quântica",
"Startup brasileira de IA recebe investimento de US$ 50 milhões",
"5G chega a mais 100 cidades brasileiras em 2026",
],
"category": [
"esportes", "esportes", "esportes", "esportes", "esportes",
"economia", "economia", "economia", "economia", "economia",
"saude", "saude", "saude", "saude", "saude",
"tecnologia", "tecnologia", "tecnologia", "tecnologia", "tecnologia",
],
}
return pd.DataFrame(data)
def train_text_classifier(df: pd.DataFrame) -> dict:
"""Treina e avalia classificadores de texto."""
# Preprocessar textos
df["processed"] = df["text"].apply(preprocess_text)
X = df["processed"]
y = df["category"]
# Split
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42, stratify=y
)
# Definir pipelines de classificação
classifiers = {
"Naive Bayes": Pipeline([
("tfidf", TfidfVectorizer(max_features=5000, ngram_range=(1, 2))),
("clf", MultinomialNB(alpha=0.1)),
]),
"Logistic Regression": Pipeline([
("tfidf", TfidfVectorizer(max_features=5000, ngram_range=(1, 2))),
("clf", LogisticRegression(max_iter=1000, C=1.0)),
]),
"SVM": Pipeline([
("tfidf", TfidfVectorizer(max_features=5000, ngram_range=(1, 2))),
("clf", LinearSVC(max_iter=1000)),
]),
}
results = {}
for name, pipeline in classifiers.items():
# Treinar
pipeline.fit(X_train, y_train)
# Avaliar
y_pred = pipeline.predict(X_test)
# Validação cruzada
cv_scores = cross_val_score(pipeline, X, y, cv=3, scoring="accuracy")
results[name] = {
"accuracy": float(np.mean(y_pred == y_test)),
"cv_accuracy": float(cv_scores.mean()),
"cv_std": float(cv_scores.std()),
"report": classification_report(y_test, y_pred, output_dict=True),
}
print(f"\n{'='*50}")
print(f"Classificador: {name}")
print(f"Acurácia: {results[name]['accuracy']:.2%}")
print(f"CV Acurácia: {results[name]['cv_accuracy']:.2%} "
f"(±{results[name]['cv_std']:.2%})")
print(classification_report(y_test, y_pred))
return results
def predict_category(pipeline, text: str) -> dict:
"""Classifica um novo texto."""
processed = preprocess_text(text)
prediction = pipeline.predict([processed])[0]
# Probabilidades (se disponível)
probabilities = {}
if hasattr(pipeline.named_steps["clf"], "predict_proba"):
probs = pipeline.predict_proba([processed])[0]
classes = pipeline.classes_
probabilities = {cls: float(prob) for cls, prob in zip(classes, probs)}
return {
"text": text,
"predicted_category": prediction,
"probabilities": probabilities,
}
Parte 5: Análise de Sentimento
Análise Básica com spaCy
"""Análise de sentimento com múltiplas abordagens."""
import spacy
nlp = spacy.load("pt_core_news_lg")
def simple_sentiment_lexicon(text: str) -> dict:
"""Análise de sentimento básica usando léxico."""
# Léxico simplificado de sentimento para português
positive_words = {
"bom", "ótimo", "excelente", "maravilhoso", "incrível", "fantástico",
"adorar", "amar", "gostar", "feliz", "alegre", "satisfeito",
"melhor", "sucesso", "positivo", "crescer", "ganhar", "lucro",
"inovar", "avançar", "conquistar", "realizar", "impressionante",
"eficiente", "revolucionário", "promissor", "benefício", "oportunidade",
}
negative_words = {
"ruim", "péssimo", "horrível", "terrível", "mau", "pior",
"odiar", "detestar", "triste", "infeliz", "frustrado", "decepcionado",
"fracasso", "negativo", "perder", "prejuízo", "crise", "problema",
"difícil", "complicado", "preocupante", "risco", "ameaça", "queda",
"falhar", "errar", "cancelar", "destruir", "piorar", "reclamar",
}
doc = nlp(text.lower())
pos_count = 0
neg_count = 0
pos_found = []
neg_found = []
for token in doc:
lemma = token.lemma_.lower()
if lemma in positive_words:
pos_count += 1
pos_found.append(token.text)
elif lemma in negative_words:
neg_count += 1
neg_found.append(token.text)
total = pos_count + neg_count
if total == 0:
sentiment = "neutral"
score = 0.0
elif pos_count > neg_count:
sentiment = "positive"
score = pos_count / total
else:
sentiment = "negative"
score = -neg_count / total
return {
"sentiment": sentiment,
"score": round(score, 4),
"positive_words": pos_found,
"negative_words": neg_found,
"positive_count": pos_count,
"negative_count": neg_count,
}
Análise de Sentimento com Transformers
"""Análise de sentimento avançada com Hugging Face Transformers."""
from transformers import pipeline as hf_pipeline
class SentimentAnalyzer:
"""Analisador de sentimento usando modelos Transformer."""
def __init__(self, model_name: str = "nlptown/bert-base-multilingual-uncased-sentiment"):
"""
Inicializa o analisador.
Modelos recomendados para português:
- nlptown/bert-base-multilingual-uncased-sentiment (multilíngue, 1-5 estrelas)
- cardiffnlp/twitter-xlm-roberta-base-sentiment (multilíngue, pos/neg/neu)
- lxyuan/distilbert-base-multilingual-cased-sentiments-student (multilíngue)
"""
self.classifier = hf_pipeline(
"sentiment-analysis",
model=model_name,
top_k=None,
)
self.model_name = model_name
def analyze(self, text: str) -> dict:
"""Analisa o sentimento de um texto."""
result = self.classifier(text[:512]) # Limitar tamanho
scores = {r["label"]: r["score"] for r in result[0]}
# Determinar sentimento dominante
top_label = max(scores, key=scores.get)
top_score = scores[top_label]
return {
"text": text[:100] + ("..." if len(text) > 100 else ""),
"sentiment": top_label,
"confidence": round(top_score, 4),
"all_scores": {k: round(v, 4) for k, v in scores.items()},
}
def analyze_batch(self, texts: list[str]) -> list[dict]:
"""Analisa sentimento de múltiplos textos."""
return [self.analyze(text) for text in texts]
def analyze_aspects(self, text: str, aspects: list[str]) -> dict:
"""Análise de sentimento por aspecto."""
results = {}
for aspect in aspects:
# Extrair sentenças que mencionam o aspecto
doc = nlp(text.lower())
relevant_sents = [
sent.text
for sent in doc.sents
if aspect.lower() in sent.text.lower()
]
if relevant_sents:
combined = " ".join(relevant_sents)
analysis = self.analyze(combined)
results[aspect] = analysis
else:
results[aspect] = {"sentiment": "not_mentioned", "confidence": 0.0}
return results
# Exemplo de uso
def demo_sentiment():
"""Demonstração de análise de sentimento."""
analyzer = SentimentAnalyzer()
reviews = [
"Produto excelente! Qualidade incrível e entrega super rápida. Recomendo muito!",
"Péssima experiência. O produto veio com defeito e o atendimento foi horrível.",
"O produto é razoável. Nada excepcional, mas cumpre o que promete.",
"Amei tudo! A embalagem linda, produto funciona perfeitamente. Nota 10!",
"Decepcionante. Paguei caro e a qualidade é muito abaixo do esperado.",
]
print("Análise de Sentimento de Reviews")
print("=" * 60)
for review in reviews:
result = analyzer.analyze(review)
emoji = {"positive": "😊", "negative": "😞", "neutral": "😐"}.get(
result["sentiment"].lower()[:3], "🤔"
)
print(f"\n{emoji} [{result['sentiment']}] (confiança: {result['confidence']:.2%})")
print(f" \"{result['text']}\"")
Parte 6: Similaridade Semântica
Similaridade com spaCy
"""Similaridade semântica entre textos."""
import spacy
import numpy as np
nlp = spacy.load("pt_core_news_lg")
def compute_similarity(text1: str, text2: str) -> float:
"""Calcula similaridade semântica entre dois textos usando spaCy."""
doc1 = nlp(text1)
doc2 = nlp(text2)
return doc1.similarity(doc2)
def find_most_similar(query: str, documents: list[str], top_k: int = 3) -> list[dict]:
"""Encontra os documentos mais similares a uma query."""
query_doc = nlp(query)
similarities = []
for i, doc_text in enumerate(documents):
doc = nlp(doc_text)
sim = query_doc.similarity(doc)
similarities.append({
"index": i,
"text": doc_text[:100] + ("..." if len(doc_text) > 100 else ""),
"similarity": round(sim, 4),
})
similarities.sort(key=lambda x: x["similarity"], reverse=True)
return similarities[:top_k]
def cluster_texts_by_similarity(texts: list[str], threshold: float = 0.8) -> list[list[int]]:
"""Agrupa textos similares baseado em um limiar de similaridade."""
n = len(texts)
docs = [nlp(text) for text in texts]
# Calcular matriz de similaridade
similarity_matrix = np.zeros((n, n))
for i in range(n):
for j in range(i, n):
sim = docs[i].similarity(docs[j])
similarity_matrix[i][j] = sim
similarity_matrix[j][i] = sim
# Clustering simples baseado em limiar
visited = set()
clusters = []
for i in range(n):
if i in visited:
continue
cluster = [i]
visited.add(i)
for j in range(i + 1, n):
if j not in visited and similarity_matrix[i][j] >= threshold:
cluster.append(j)
visited.add(j)
clusters.append(cluster)
return clusters
# Demonstração
def demo_similarity():
"""Demonstração de similaridade semântica."""
documents = [
"Python é uma linguagem de programação versátil e popular",
"Java é muito utilizado em aplicações empresariais",
"O gato dormiu no sofá durante toda a tarde",
"A linguagem Python é amplamente adotada por desenvolvedores",
"Cães e gatos são os animais de estimação mais comuns",
"JavaScript domina o desenvolvimento web front-end",
]
query = "Qual a melhor linguagem de programação?"
print(f"Query: \"{query}\"")
print("\nDocumentos mais similares:")
results = find_most_similar(query, documents, top_k=3)
for r in results:
print(f" [{r['similarity']:.4f}] {r['text']}")
print("\nClusters de similaridade (threshold=0.7):")
clusters = cluster_texts_by_similarity(documents, threshold=0.7)
for i, cluster in enumerate(clusters):
print(f" Cluster {i + 1}:")
for idx in cluster:
print(f" - {documents[idx][:60]}...")
Parte 7: NLP Moderno com Transformers
Classificação Zero-Shot
"""NLP avançado com Hugging Face Transformers."""
from transformers import pipeline as hf_pipeline
class ZeroShotClassifier:
"""Classificação zero-shot — classifica sem treinamento prévio."""
def __init__(self):
self.classifier = hf_pipeline(
"zero-shot-classification",
model="facebook/bart-large-mnli",
)
def classify(self, text: str, labels: list[str]) -> dict:
"""Classifica um texto nas categorias fornecidas."""
result = self.classifier(text, candidate_labels=labels, multi_label=False)
return {
"text": text[:100],
"labels": result["labels"],
"scores": [round(s, 4) for s in result["scores"]],
"best_label": result["labels"][0],
"best_score": round(result["scores"][0], 4),
}
def demo_zero_shot():
"""Demonstração de classificação zero-shot."""
classifier = ZeroShotClassifier()
texts = [
"O novo smartphone da Samsung tem uma câmera de 200 megapixels",
"Governo anuncia programa de habitação para famílias de baixa renda",
"Receita de bolo de chocolate com cobertura de brigadeiro",
]
categories = ["tecnologia", "política", "culinária", "esportes", "ciência"]
for text in texts:
result = classifier.classify(text, categories)
print(f"\nTexto: \"{result['text']}\"")
print(f"Categoria: {result['best_label']} ({result['best_score']:.2%})")
Geração de Texto
class TextGenerator:
"""Geração de texto com modelos Transformer."""
def __init__(self, model_name: str = "gpt2"):
self.generator = hf_pipeline(
"text-generation",
model=model_name,
)
def generate(
self,
prompt: str,
max_length: int = 200,
temperature: float = 0.7,
num_sequences: int = 1,
) -> list[str]:
"""Gera texto a partir de um prompt."""
results = self.generator(
prompt,
max_length=max_length,
temperature=temperature,
num_return_sequences=num_sequences,
do_sample=True,
top_p=0.95,
pad_token_id=50256,
)
return [r["generated_text"] for r in results]
Sumarização Automática
class TextSummarizer:
"""Sumarização automática de textos longos."""
def __init__(self, model_name: str = "facebook/bart-large-cnn"):
self.summarizer = hf_pipeline("summarization", model=model_name)
def summarize(
self,
text: str,
max_length: int = 150,
min_length: int = 30,
) -> str:
"""Gera um resumo do texto."""
result = self.summarizer(
text,
max_length=max_length,
min_length=min_length,
do_sample=False,
)
return result[0]["summary_text"]
def summarize_long_text(
self,
text: str,
chunk_size: int = 1000,
max_summary_length: int = 150,
) -> str:
"""Sumariza textos longos dividindo em chunks."""
# Dividir em chunks
words = text.split()
chunks = []
current_chunk = []
current_size = 0
for word in words:
current_chunk.append(word)
current_size += len(word) + 1
if current_size >= chunk_size:
chunks.append(" ".join(current_chunk))
current_chunk = []
current_size = 0
if current_chunk:
chunks.append(" ".join(current_chunk))
# Sumarizar cada chunk
summaries = []
for chunk in chunks:
if len(chunk.split()) > 20: # Mínimo de palavras
summary = self.summarize(chunk, max_length=max_summary_length)
summaries.append(summary)
# Se os resumos ainda forem longos, sumarizar novamente
combined = " ".join(summaries)
if len(combined.split()) > max_summary_length:
return self.summarize(combined, max_length=max_summary_length)
return combined
Question Answering
class QuestionAnswerer:
"""Responde perguntas baseado em contexto."""
def __init__(self, model_name: str = "deepset/roberta-base-squad2"):
self.qa = hf_pipeline("question-answering", model=model_name)
def answer(self, question: str, context: str) -> dict:
"""Responde uma pergunta dado um contexto."""
result = self.qa(question=question, context=context)
return {
"question": question,
"answer": result["answer"],
"confidence": round(result["score"], 4),
"start": result["start"],
"end": result["end"],
}
def demo_qa():
"""Demonstração de Question Answering."""
qa = QuestionAnswerer()
context = """
Python foi criado por Guido van Rossum e lançado pela primeira vez em 1991.
É uma linguagem de programação de alto nível, interpretada e de propósito geral.
Python enfatiza a legibilidade do código com sua notável indentação significativa.
A linguagem é mantida pela Python Software Foundation e sua versão atual é 3.12.
Python é amplamente usado em ciência de dados, inteligência artificial,
desenvolvimento web e automação.
"""
questions = [
"Quem criou Python?",
"Quando Python foi lançado?",
"Qual a versão atual do Python?",
"Para que Python é usado?",
]
print("Question Answering")
print("=" * 60)
for q in questions:
result = qa.answer(q, context)
print(f"\nQ: {result['question']}")
print(f"A: {result['answer']} (confiança: {result['confidence']:.2%})")
Parte 8: Pipeline NLP Completo
"""Pipeline NLP completo que combina todas as técnicas."""
import spacy
from dataclasses import dataclass
@dataclass
class NLPAnalysis:
"""Resultado completo da análise NLP."""
text: str
language: str
word_count: int
sentence_count: int
entities: dict
sentiment: dict
keywords: list[str]
summary: str | None
class NLPPipeline:
"""Pipeline completo de análise de texto."""
def __init__(self):
self.nlp = spacy.load("pt_core_news_lg")
def analyze(self, text: str) -> NLPAnalysis:
"""Executa análise NLP completa em um texto."""
doc = self.nlp(text)
# Contagens básicas
sentences = list(doc.sents)
word_count = len([t for t in doc if t.is_alpha])
# Entidades
entities = {}
for ent in doc.ents:
if ent.label_ not in entities:
entities[ent.label_] = []
entities[ent.label_].append(ent.text)
# Keywords (lemmas mais frequentes)
from collections import Counter
lemmas = [
t.lemma_.lower() for t in doc
if not t.is_stop and t.is_alpha and len(t.text) > 2
]
keywords = [word for word, _ in Counter(lemmas).most_common(10)]
# Sentimento simples
sentiment = simple_sentiment_lexicon(text)
return NLPAnalysis(
text=text[:200] + "..." if len(text) > 200 else text,
language="pt",
word_count=word_count,
sentence_count=len(sentences),
entities=entities,
sentiment=sentiment,
keywords=keywords,
summary=None,
)
Conclusão
Neste tutorial, percorremos o universo do NLP com Python:
- Tokenização e análise morfológica com spaCy — a base de todo processamento de texto.
- NER — identificação automática de pessoas, organizações, locais e mais.
- Classificação de texto — categorização automática usando TF-IDF e ML clássico.
- Análise de sentimento — tanto com léxico quanto com Transformers.
- Similaridade semântica — encontrar textos com significado similar.
- NLP moderno com Transformers — zero-shot classification, QA, sumarização.
- Pipeline completo — combinando tudo em uma análise unificada.
O NLP é um dos campos mais dinâmicos da IA, com novos modelos e técnicas surgindo constantemente. As bases que construímos aqui preparam você para qualquer desafio nessa área.
Próximos Passos
- Treinar modelos NER customizados com spaCy para domínios específicos.
- Explorar modelos multilíngues para tradução automática.
- Implementar chatbots com compreensão de linguagem natural.
- Fine-tuning de modelos Transformer para tarefas específicas em português.
- Explorar modelos de linguagem grandes (LLMs) como GPT e Claude para NLP avançado.
- Construir sistemas RAG (Retrieval Augmented Generation) para QA sobre documentos próprios.
Acompanhe o Inteligência em Código para mais tutoriais sobre NLP, IA e Python.