Entity Linker
Índice
O que é Entity Linking
Entity Linking é o processo de mapear menções textuais livres (extraídas por modelos de linguagem) a partir de currículos e vagas para entidades canônicas em uma base de conhecimento estruturada. No sistema, essa etapa vincula termos como "Python", "Comunicação" ou "Power BI" aos respectivos conceitos na ontologia ESCO.
O Entity Linker implementado no serviço processor-entity-linker que recebe os termos candidatos gerados pelo modelo de linguagem e identifica, para cada candidato, o conceito correspondente na ontologia ESCO.
LLM extrai: "Python"
Entity Linker resolve: "Python" -(fuzzy match)-> "Python (programação informática)" (score = 1.0)
LLM extrai: "Comunicação"
Entity Linker resolve: "Comunicação" -(KNN + PPR)-> "comunicar com colegas e clientes" (score = 0.66)
LLM extrai: "Power BI"
Entity Linker resolve: "Power BI" -(fuzzy match)-> SkillCustom (termo não identificado na ontologia)
Como Funciona
Eventos processados pelo serviço:
| Direção | Evento | Conteúdo |
|---|---|---|
| Consumidor | OpportunitySkillCandidateExtracted | Lista de candidatos com type (hard/soft/knowledge) para uma vaga |
| Consumidor | ResumeSkillCandidateExtracted | Lista de candidatos com type (hard/soft/knowledge) para um currículo |
| Produtor | OpportunitySkillLinked | Skill da vaga vinculada a um conceito da ESCO |
| Produtor | OpportunitySkillCustom | Skill da vaga sem correspondência na ESCO |
| Produtor | ResumeSkillLinked | Skill do currículo vinculada a um conceito da ESCO |
| Produtor | ResumeSkillCustom | Skill do currículo sem correspondência na ESCO |
| Produtor | EntityLinkingAnalysisRecorded | Resultado intermediário do processo de ancoragem com a ESCO (fuzzy, KNN e PPR) persistido para posterior análise humana |
As habilidades classificadas como Custom Skill não são descartadas. Elas são persistidas no Neo4j sob o tipo do nó (:CustomSkill) e podem representar termos legítimos ainda não catalogados na ontologia ESCO, comuns no mercado de trabalho de tecnologia, porém elas também podem representar alucinações do modelo generativo.
Escolhas de Implementação
Roteamento do método de ancoragem por tipo de competência: as hard skills são processadas inicialmente pelo FuzzyMatcher (com limiar de 0,9), com redirecionamento para o método Duplo Diamante apenas se a pontuação obtida for menor que o limiar. As soft skills e as áreas de conhecimento são enviadas diretamente para o método Duplo Diamante. Esse fluxo compensa a assimetria de representação dos embeddings da ontologia ESCO, cujo índice foi gerado utilizando o formato {label}\n{description}\n{alt_labels}, enquanto a busca em tempo de execução utiliza somente o texto extraído da skill. Essa diferença de formato reduz a similaridade de termos curtos e canônicos, como "Python", no espaço vetorial.
Pesos uniformes 1/K no vetor de personalização do PPR: em vez de adotar os valores de similaridade de cosseno do KNN como pesos (devido à proximidade numérica desses valores entre posições adjacentes no ranking), distribui-se peso igual entre os candidatos. Esse procedimento impede que pequenas variações na métrica de cosseno influenciem excessivamente o resultado do Personalized PageRank (PPR).
Fórmula de pontuação final (PPR / PR_global) * cosine_similarity: o valor bruto do PPR é normalizado pela divisão pelo PageRank global de cada nó e, em seguida, multiplicado pela similaridade de cosseno. Essa normalização reduz a influência de nós centrais (hubs) na ontologia (conceitos com alto grau de conectividade que receberiam pontuações elevadas independentemente da pertinência direta com a consulta).
Fuzzy Matching (Hard Skills)
O FuzzyMatcher carrega as propriedades preferredLabel do dataset digitalSkillsCollection_pt.csv em memória durante a inicialização do serviço. A busca textual utiliza o algoritmo token_set_ratio da biblioteca RapidFuzz, que ignora a ordenação das palavras e suporta substrings:
| Scorer | Exemplo | Pontuação Esperada |
|---|---|---|
token_set_ratio | "Python" vs "Python (Linguagem de Programação)" | 100 |
token_set_ratio | "design responsivo" vs "responsive design" | 100 |
token_set_ratio | "Docker" vs "Docker" | 100 |
O fluxo de comparação para as hard skills é estruturado em três níveis de contingência:
- Correspondência exata (case-insensitive) -> score = 1.00
- Busca difusa (
token_set_ratio>= 0.9) -> score = [0.9 .. 0.99] - Fallback (score < 0.9) -> redireciona para método de Duplo Diamante
Método Duplo Diamante (KNN e PPR)
KNN (Expansão Semântica)
O vetor de embedding da skill candidata (768 dimensões, gerado pelo Ollama com o modelo embeddinggemma) é comparado com o índice vetorial HNSW do Neo4j. O índice retorna os K nós (:Skill) com maior similaridade de cosseno, que constituem o conjunto inicial de candidatos.
PPR (Convergência Topológica)
Utilizando os candidatos retornados pelo KNN como nós de ativação inicial (seeds), o algoritmo Personalized PageRank navega pelo grafo de conhecimento por meio dos relacionamentos ([:BROADER], [:NARROWER] e [:ESSENTIAL]) e também através do teleporte. Os candidatos que apresentam maior proximidade topológica em relação à vizinhança ativa obtêm pontuações mais elevadas. O nó com maior pontuação calculada é selecionado para o vínculo.
| Aspecto | KNN (Expansão) | PPR (Convergência) |
|---|---|---|
| Objetivo | Identificar candidatos potenciais | Selecionar nó com maior coerência topológica |
| Entrada | Embedding de 768 dimensões | Candidatos do KNN e topologia do grafo |
| Métrica | Similaridade de cosseno | Pontuação do PageRank personalizado |
| Requisitos | Índice vetorial do Neo4j | Neo4j Graph Data Science (GDS) |
Abaixo o fluxo completo do método Duplo Diamante:
1. Limiar do KNN: os candidatos retornados pelo índice HNSW são filtrados com base em um valor limite de similaridade de cosseno (definido em knn_pruning). Candidatos com valores inferiores são excluídos antes da execução do PPR para evitar distorções na propagação de pesos.
2. Distribuição de pesos uniformes: para neutralizar diferenças pequenas nas pontuações de similaridade de cosseno entre candidatos adjacentes, adota-se um vetor de personalização com pesos uniformes equivalentes a para todos os nós sementes. Esse ajuste previne que flutuações discretas da similaridade semântica determinem o resultado da análise topológica.
3. Execução do PPR: o algoritmo é executado utilizando a biblioteca Neo4j Graph Data Science (GDS) por meio do procedimento gds.pageRank.stream com o parâmetro sourceNodes. A distribuição de probabilidade propaga-se a partir dos nós sementes pelas conexões da ontologia.
4. Normalização pelo PageRank global: a pontuação obtida pelo PPR é dividida pelo PageRank global correspondente a cada nó (calculado previamente sem personalização). Essa etapa reduz a pontuação de conceitos que possuem alta centralidade na ontologia (nós de alto grau de entrada e saída), os quais tenderiam a atrair peso independentemente do contexto específico da busca.
5. Ponderação final: o resultado da análise topológica é multiplicado pelo valor original da similaridade de cosseno:
score_final = (PPR / PR_global) * cosine_similarity
Evolução do processor-entity-linker
O algoritmo de vinculação foi desenvolvido em três etapas distintas:
Fase 1 - String Matching com RapidFuzz
Abordagem inicial baseada na comparação hierárquica de strings com a biblioteca RapidFuzz utilizando a métrica fuzz.ratio (desempenho médio de 135 milhões de operações por segundo).
O fluxo de comparação ocorria em quatro níveis:
- Correspondência exata (score = 1.00)
- Correspondência insensível a maiúsculas (score = 0.95)
- Correspondência difusa (distância de Levenshtein normalizada) com limiar de 0.85
- Ausência de correspondência (classificação como
CustomSkill)
A função fuzz.ratio foi selecionada devido à sua sensibilidade em relação à ordem das palavras (por exemplo, diferenciação entre "Python Developer" e "Developer Python").
Fase 2 - Modelo Duplo Diamante
Substituição da lógica estritamente lexical por um modelo semântico estruturado em duas etapas:
Expansão (KNN): conversão da competência candidata em um vetor de 768 dimensões. A busca KNN no índice HNSW do Neo4j identifica os K candidatos com maior similaridade de cosseno, visando maximizar o índice de recuperação (recall).
Convergência (PPR): reordenação dos candidatos obtidos por meio do algoritmo Personalized PageRank (PPR) no grafo de conhecimento, utilizando as relações de dependência [:BROADER], [:NARROWER] e [:ESSENTIAL] e o mecanismo de teleporte para assegurar a coerência conceitual.
Esse método permite associar termos semanticamente semelhantes que não possuem correspondência textual direta, como "Dev" e "Desenvolvedor".
Fase 3 - Especialização por Tipo de Competência
Identificou-se uma redução na precisão do modelo Duplo Diamante para hard skills representadas por termos curtos e padronizados, tais como "Python" ou "DevOps". A discrepância ocorreu porque os embeddings armazenados foram gerados com o formato {label}\n{description}\n{alt_labels}, ao passo que a consulta em execução utiliza apenas o texto cru do termo extraído, gerando assimetria na representação vetorial.
A solução implementada consiste no roteamento conforme a categoria da competência no método resolve:
- Hard skills: são processadas preliminarmente pelo
FuzzyMatcher. Se a pontuação obtida for maior ou igual a 0.9, a associação é concluída. Caso contrário, aplica-se o métododouble_diamond(KNN e PPR). - Soft skills e áreas de conhecimento: são direcionadas diretamente para o método
double_diamond.
Demonstração
Os exemplos apresentados a seguir foram extraídos de execuções do componente com os seguintes parâmetros de configuração:
| Componente | Parâmetro | Valor |
|---|---|---|
| Fuzzy | threshold | 0.9 |
| KNN | threshold | 0.72 |
| KNN | top_k | 10 |
| PPR | damping | 0.6 |
| PPR | iterations | 25 |
| PPR | threshold | 0.59 |
Hard Skill: Aceita pelo FuzzyMatcher
A skill "SQL" é identificada como correspondência exata na ontologia. O processamento por busca difusa resolve o termo com pontuação máxima, sem executar as etapas de KNN e PPR:
{
"target_skill": "SQL",
"target_skill_type": "hard",
"fuzzy": {
"uri": "http://data.europa.eu/esco/skill/598de5b0-5b58-4ea7-8058-a4bc4d18c742",
"label": "SQL",
"score": 1
},
"knn": [],
"ppr": []
}
Hard Skill: Falhou no FuzzyMatcher e resolvida pelo método Duplo Diamante
A expressão "Open-Source Projects" não possui correspondência textual direta. O módulo de comparação difusa retorna nulo, acionando a busca semântica do KNN e a convergência topológica do PPR para localizar o nó correspondente na estrutura do grafo:
{
"target_skill": "Open-Source Projects",
"target_skill_type": "hard",
"fuzzy": null,
"knn": [
{ "label": "programar software de código-fonte aberto", "score": 0.760 },
{ "label": "modelo open source", "score": 0.756 },
{ "label": "dirigir, supervisionar e coordenar projetos", "score": 0.725 }
],
"ppr": [
{ "label": "programar software de código-fonte aberto", "score": 0.662 }
]
}
A etapa do PPR descartou os candidatos "modelo open source" e "coordenar projetos" em virtude da distância topológica na ontologia em relação ao conceito mais próximo. O resultado final corresponde ao nó selecionado no segundo estágio do fluxo.
Soft Skill: Método Duplo Diamante com Múltiplos Candidatos
O termo "Gestão de Stakeholders" não possui correspondência textual direta na ontologia. A busca KNN retorna dez candidatos relacionados ao termo "gestão", enquanto o PPR atua na filtragem com base na estrutura de relações, identificando os dois conceitos mais próximos:
{
"target_skill": "Gestão de Stakeholders",
"target_skill_type": "soft",
"fuzzy": null,
"knn": [
{ "label": "competências de gestão", "score": 0.778 },
{ "label": "competências de gestão", "score": 0.778 },
{ "label": "competências de gestão", "score": 0.776 },
{ "label": "gerir e administrar recursos humanos", "score": 0.764 },
{ "label": "gerir o sistema de gestão ambiental", "score": 0.754 }
],
"ppr": [
{ "label": "gerir e administrar recursos humanos", "score": 0.655 },
{ "label": "gerir o sistema de gestão ambiental", "score": 0.633 }
]
}
Os três nós com a descrição "competências de gestão" identificados no KNN correspondem a registros distintos com diferentes URIs. Após a execução do PPR, estes nós são descartados. Apesar da similaridade de cosseno elevada, são classificados como hubs com alto grau de conectividade, sendo penalizados pelo fator de normalização entre o PPR e o PageRank global.
Knowledge Skill: PPR Reordena o KNN
A entrada "Gerenciamento de Projetos" ilustra a reordenação promovida pelo PPR sobre o ranking inicial do KNN. O candidato posicionado em oitavo lugar na busca por similaridade é reordenado para a primeira posição após a análise topológica:
{
"target_skill": "Gerenciamento de Projetos",
"target_skill_type": "knowledge",
"knn": [
{ "label": "dirigir, supervisionar e coordenar projetos", "score": 0.821 },
{ "label": "gestão de projetos informáticos", "score": 0.818 },
{ "label": "gestão ágil de projetos", "score": 0.816 },
{ "label": "gestão de projetos lean", "score": 0.815 },
{ "label": "metodologias de gestão de projetos de informática", "score": 0.797 },
{ "label": "gestão de projetos Prince2", "score": 0.792 },
{ "label": "gestão de processos", "score": 0.791 },
{ "label": "gerir projetos de desenvolvimento de conteúdos", "score": 0.787 }
],
"ppr": [
{ "label": "gerir projetos de desenvolvimento de conteúdos", "score": 0.918 },
{ "label": "gerir um repositório central de projetos", "score": 0.811 },
{ "label": "dirigir, supervisionar e coordenar projetos", "score": 0.702 },
{ "label": "gestão de projetos informáticos", "score": 0.591 }
]
}
O conceito "Gerir projetos de desenvolvimento de conteúdos", posicionado em oitavo lugar no KNN (similaridade de 0,787), obteve pontuação PPR de 0,918. Esse valor indica maior centralidade topológica do nó em relação aos demais candidatos na subestrutura de gestão de projetos da ontologia.
Custom Skills: Limitações do Sistema
Apresentam-se a seguir dois cenários em que o vínculo não é estabelecido devido a limitações estruturais distintas:
Inconsistência na classificação de categoria pelo extrator de habilidades: o termo "Desenvolvimento iOS" foi classificado como do tipo knowledge em vez de hard. O KNN retorna apenas um candidato acima do limiar estabelecido, e a estrutura local do grafo não fornece conexões suficientes para a propagação no PPR, resultando em uma CustomSkill.
Ausência do conceito na ontologia: o termo "TensorFlow" não está catalogado na base ESCO (versão de 2023). Nenhum candidato atinge os limiares mínimos de similaridade na busca difusa ou no KNN, classificando o termo como CustomSkill.
Embora ambos os cenários resultem em uma CustomSkill, as causas são distintas. O primeiro decorre de uma inconsistência de classificação no estágio anterior de extração, enquanto o segundo indica limitação de cobertura da base de conhecimento. Os registros de processamento são persistidos para subsidiar futuras análises e updates da base.
ADRs Relacionadas
| Identificador | Data | Descrição da Decisão |
|---|---|---|
| ADR-014 | Janeiro de 2026 | Adoção da biblioteca RapidFuzz como mecanismo inicial de vinculação. |
| ADR-034 | Abril de 2026 | Implementação do fluxo de dois estágios (KNN e PPR). |
| ADR-045 | Junho de 2026 | Configuração de roteamento dual por categoria de skill. |