
Como parte de nossa série de posts sobre processamento de linguagem natural (PLN), apresentaremos um exemplo usando um modelo de PLN de reconhecimento de entidades nomeadas (REN) para localizar e extrair categorias predefinidas de entidades em campos de texto não estruturados. Usando um modelo disponível publicamente, mostraremos como implantar esse modelo no Elasticsearch, encontrar entidades nomeadas no texto com a nova API _infer e usar o modelo de REN em um pipeline de ingestão para extrair entidades à medida que os documentos são ingeridos no Elasticsearch.
Os modelos de REN são úteis quando se utiliza linguagem natural para extrair entidades como pessoas, lugares e organizações de campos de texto completo.
Neste exemplo, vamos passar parágrafos do livro Les Misérables por um modelo de REN, usar o modelo para extrair os personagens e locais do texto e visualizar as relações entre eles.
Primeiro, precisamos selecionar um modelo de REN que possa extrair os nomes dos personagens e locais dos campos de texto. Felizmente, existem alguns modelos de REN disponíveis em Hugging Face que podemos escolher. Ao verificar a documentação da Elastic, vemos um modelo da Elastic de REN sem diferenciação de maiúsculas e minúsculas para experimentar.
Uma vez selecionado o modelo de REN a ser usado, podemos usar o Eland para instalar o modelo. Neste exemplo, executaremos o comando do Eland por meio de uma imagem do Docker. No entanto, primeiro devemos construir a imagem do Docker clonando o repositório do Eland no GitHub e criar uma imagem do Docker do Eland no seu sistema cliente:
git clone git@github.com:elastic/eland.git
cd eland
docker build -t elastic/eland .
Agora que nosso cliente do Docker do Eland está pronto, podemos instalar o modelo de REN executando o seguinte comando eland_import_hub_model
na nova imagem do Docker:
docker run -it --rm elastic/eland \
eland_import_hub_model \
--url $ELASTICSEARCH_URL \
--hub-model-id elastic/distilbert-base-uncased-finetuned-conll03-english \
--task-type ner \
--start
Você precisará substituir ELASTICSEARCH_URL pelo URL do cluster do Elasticsearch. Para fins de autenticação, você precisará incluir um nome de usuário e uma senha de administrador no URL no formato https://username:password@host:port.
Como usamos a opção --start
no final do comando de importação do Eland, o Elasticsearch implantará o modelo em todos os nós de machine learning disponíveis e carregará o modelo na memória. Se tivéssemos vários modelos e quiséssemos selecionar qual modelo implantar, poderíamos usar a interface de usuário Machine Learning > Model Management (Gerenciamento de modelos) do Kibana para gerenciar o início e a interrupção dos modelos.
Os modelos implantados podem ser avaliados usando a nova API _infer. A entrada é a string que desejamos analisar. Na solicitação abaixo, text_field
é o nome do campo onde o modelo espera encontrar a entrada, conforme definido na configuração do modelo. Por padrão, se o modelo foi carregado via Eland, o campo de entrada é text_field
.
Tente este exemplo no Console do Dev Tools do Kibana:
POST _ml/trained_models/elastic__distilbert-base-uncased-finetuned-conll03-english/deployment/_infer
{
"docs": [
{
"text_field": "Hi my name is Josh and I live in Berlin"
}
]
}
O modelo encontrou duas entidades: a pessoa “Josh” e o local “Berlin”.
{
"predicted_value" : "Hi my name is [Josh](PER&Josh) and I live in [Berlin](LOC&Berlin)",
"entities" : {
"entity" : "Josh",
"class_name" : "PER",
"class_probability" : 0.9977303419824,
"start_pos" : 14,
"end_pos" : 18
},
{
"entity" : "Berlin",
"class_name" : "LOC",
"class_probability" : 0.9992474323902818,
"start_pos" : 33,
"end_pos" : 39
}
]
}
predicted_value
é a string de entrada no formato de texto anotado, class_name
é a classe prevista e class_probability
indica o nível de confiança na previsão. start_pos
e end_pos
são as posições dos caracteres inicial e final da entidade identificada.
A API _infer
é uma maneira divertida e fácil de começar, mas aceita apenas uma única entrada, e as entidades detectadas não são armazenadas no Elasticsearch. Uma alternativa é realizar inferência em massa nos documentos conforme são ingeridos por meio de um pipeline de ingestão com o processador inference.
Você pode definir um pipeline de ingestão na UI Stack Management (Gerenciamento da stack) ou configurá-lo no Console do Kibana; este contém vários processadores de ingestão:
PUT _ingest/pipeline/ner
{
"description": "NER pipeline",
"processors": [
{
"inference": {
"model_id": "elastic__distilbert-base-uncased-finetuned-conll03-english",
"target_field": "ml.ner",
"field_map": {
"paragraph": "text_field"
}
}
},
{
"script": {
"lang": "painless",
"if": "return ctx['ml']['ner'].containsKey('entities')",
"source": "Map tags = new HashMap(); for (item in ctx['ml']['ner']['entities']) { if (!tags.containsKey(item.class_name)) tags[item.class_name] = new HashSet(); tags[item.class_name].add(item.entity);} ctx['tags'] = tags;"
}
}
],
"on_failure": [
{
"set": {
"description": "Index document to 'failed-<index>'",
"field": "_index",
"value": "failed-{{{ _index }}}"
}
},
{
"set": {
"description": "Set error message",
"field": "ingest.failure",
"value": "{{_ingest.on_failure_message}}"
}
}
]
}
Começando com o processador inference
, o propósito de field_map
é mapear paragraph
(o campo a ser analisado nos documentos de origem) para text_field (o nome do campo que o modelo está configurado para usar). target_field
é o nome do campo no qual gravar os resultados da inferência.
O processador script
extrai as entidades e as agrupa por tipo. O resultado final são listas de pessoas, locais e organizações detectadas no texto de entrada. Estamos adicionando este script Painless para que possamos criar visualizações a partir dos campos criados.
A cláusula on_failure
existe para detectar erros. Ela define duas ações. Primeiro, define o metacampo _index
com um novo valor, e o documento agora será armazenado lá. Segundo, a mensagem de erro é gravada em um novo campo: ingest.failure
. A inferência pode falhar por vários motivos facilmente corrigíveis. Talvez o modelo não tenha sido implantado ou o campo de entrada esteja ausente em alguns dos documentos de origem. Com o redirecionamento dos documentos com falha para outro índice e a definição da mensagem de erro, essas inferências com falha não são perdidas e podem ser revisadas posteriormente. Depois que os erros forem corrigidos, reindexe a partir do índice com falha para recuperar as solicitações malsucedidas.
O REN pode ser aplicado a muitos conjuntos de dados. Como exemplo, escolhi Les Misérables, o clássico romance publicado em 1862 por Victor Hugo. Você pode carregar os parágrafos de Les Misérables do nosso arquivo json de amostra usando o recurso de upload de arquivo do Kibana. O texto é dividido em 14.021 documentos JSON, cada um contendo um único parágrafo. Vamos pegar um parágrafo aleatório como exemplo:
{
"paragraph": "Father Gillenormand did not do it intentionally, but inattention to proper names was an aristocratic habit of his.",
"line": 12700
}
Depois que o parágrafo é ingerido por meio do pipeline de REN, o documento resultante armazenado no Elasticsearch é marcado com uma única pessoa identificada.
{
"paragraph": "Father Gillenormand did not do it intentionally, but inattention to proper names was an aristocratic habit of his.",
"@timestamp": "2020-01-01T17:38:25",
"line": 12700,
"ml": {
"ner": {
"predicted_value": "Father [Gillenormand](PER&Gillenormand) did not do it intentionally, but inattention to proper names was an aristocratic habit of his.",
"entities": [{
"entity": "Gillenormand",
"class_name": "PER",
"class_probability": 0.9806354093873283,
"start_pos": 7,
"end_pos": 19
}],
"model_id": "elastic__distilbert-base-cased-finetuned-conll03-english"
}
},
"tags": {
"PER": [
"Gillenormand"
]
}
}
Uma nuvem de tags é uma visualização que dimensiona as palavras pela frequência com que ocorrem e é o infográfico perfeito para visualizar as entidades encontradas em Les Misérables. Abra o Kibana, crie uma nova visualização baseada em agregação e escolha Tag Cloud (Nuvem de tags). Selecione o índice que contém os resultados do REN e adicione uma agregação de termos no campo tags.PER.keyword
.

É fácil notar pela visualização que Cosette, Marius e Jean Valjean são os personagens mencionados com mais frequência no livro.
Voltando à UI Model Management (Gerenciamento de modelos), em Deployment stats (Estatísticas de implantação), você encontrará Avg Inference Time (Tempo médio de inferência). Esse é o tempo medido pelo processo nativo para realizar a inferência em uma única solicitação. Ao iniciar uma implantação, há dois parâmetros que controlam como os recursos da CPU são usados: inference_threads e model_threads.
inference_threads é o número de threads usados para executar o modelo por solicitação. O aumento de inference_threads reduz diretamente o tempo médio de inferência. O número de solicitações avaliadas em paralelo é controlado por model_threads. Essa configuração não reduzirá o tempo médio de inferência, mas aumentará a taxa de transferência.
Em geral, você ajusta a latência aumentando o número de inference_threads e aumenta a taxa de transferência elevando o número de model_threads. Ambas as configurações têm um único thread por padrão, portanto, pode-se obter um bom ganho de desempenho ao modificá-las. O efeito é demonstrado usando o modelo de REN.
Para alterar uma das configurações de thread, a implantação deve ser interrompida e reiniciada. O parâmetro ?force=true é passado para a API de interrupção porque a implantação é referenciada por um pipeline de ingestão que normalmente impediria a interrupção.
POST _ml/trained_models/elastic__distilbert-base-uncased-finetuned-conll03-english/deployment/_stop?force=true
Reinicie com quatro threads de inferência. O tempo médio de inferência é redefinido quando a implantação é reiniciada.
POST _ml/trained_models/elastic__distilbert-base-uncased-finetuned-conll03-english/deployment/_start?inference_threads=4
No processamento dos parágrafos de Les Misérables, o tempo médio de inferência cai para 55,84 milissegundos por solicitação, em comparação com 173,86 milissegundos para um único thread.
O REN é apenas uma das tarefas de PNL prontas para uso agora. Classificação de texto, classificação zero-shot e embeddings de texto também estão disponíveis. Mais exemplos podem ser encontrados na documentação de PLN, juntamente com uma lista de modelos (não exaustiva) que pode ser implantada no Elastic Stack.
A PLN é um novo recurso importante no Elastic Stack para a versão 8.0 com um roadmap muito interessante. Descubra novos recursos e acompanhe os desenvolvimentos mais recentes criando seu cluster no Elastic Cloud. Inscreva-se para fazer uma avaliação gratuita de 14 dias hoje mesmo e teste os exemplos deste post.
Se quiser ler mais sobre PNL:
- Como implantar o PLN: embeddings de texto e busca vetorial
- How to deploy NLP: Sentiment Analysis Example (Como implantar o PLN: exemplo de análise de sentimentos
- How to deploy natural language processing: Getting started (Como implantar o processamento de linguagem natural: uma introdução)