<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[Integrações - Elasticsearch Labs]]></title>
    <description><![CDATA[Articles and tutorials from the Search team at Elastic]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[Integrações - Elasticsearch Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1121c0bf0e8a6e65/6a88da6340a1841030ef456f/search-labs-thumbnail.png</url>
      <link>https://www.elastic.co/pt/search-labs/blog/category/integrations</link>
    </image>
    <link>https://www.elastic.co/pt/search-labs/blog/category/integrations</link>
    <atom:link href="https://www.elastic.co/pt/search-labs/rss/category/integrations.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[pt]]></language>
    <lastBuildDate>Sun, 20 Sep 2026 14:54:41 GMT</lastBuildDate>
  <item>
    <title><![CDATA[API do dashboard do Kibana: um contrato estável para todos os tipos de painéis, testado por mais de 50 equipes antes da disponibilidade geral (GA)]]></title>
    <description><![CDATA[Gerencie dashboards do Kibana como código: faça commit no Git, promova entre ambientes e automatize implantações com a API do Kibana e o Terraform.]]></description>
    <content:encoded><![CDATA[<p>As<a href="https://dashboardsapispec.kibana.dev/dashboards#tag/Dashboards"> APIs de dashboards e visualizações do Kibana</a> estão prontas para produção no Elastic 9.5, disponíveis em todos os níveis de assinatura, com total compatibilidade com versões anteriores. Defina seus dashboards como JSON, comprometa-os no Git e então implante em ambientes usando pipelines de integração contínua e implantação contínua (CI/CD),<a href="https://registry.terraform.io/providers/elastic/elasticstack/latest/docs/resources/kibana_dashboard"> Terraform</a> ou qualquer ferramenta que você já tenha. Mais de 50 equipes testaram a API durante<a href="https://www.elastic.co/search-labs/blog/kibana-dashboards-as-code-terraform-api"> a prévia técnica na versão 9.4</a>, algumas já a rodando em produção. A versão 9.5 também adiciona novos endpoints (em prévia técnica) para<a href="https://dashboardsapispec.kibana.dev/tags.html"> Tags</a>, com endpoints, <a href="https://dashboardsapispec.kibana.dev/markdowns.html"> dos painéis Markdown</a> e<a href="https://dashboardsapispec.kibana.dev/links.html#tag/Links"> Links</a> disponíveis agora no Elastic Cloud Serverless e chegando na versão 9.6.</p><h2>O que a compatibilidade com versões anteriores significa para a API do dashboard do Kibana</h2><p>Durante a prévia técnica, a configuração da API pode mudar entre os lançamentos.[1] Esse não é mais o caso. Disponibilidade geral (GA) significa:</p><ul><li><p><strong>Compatibilidade retrógrada completa.</strong> Novos campos e tipos de painel serão adicionados ao longo do tempo, mas os campos e comportamentos existentes permanecem inalterados. Quaisquer mudanças futuras que quebrem a compatibilidade seriam cuidadosamente consideradas e só seriam introduzidas em uma nova versão principal da pilha.</p></li><li><p><strong>Pronto para produção com suporte completo.</strong> A API oferece todas as garantias de compatibilidade da Elastic. Você pode usá-lo com segurança em ambientes de produção para implantações automatizadas, promoção de ambiente e gerenciamento programático do dashboard.</p></li></ul><h2>Novos endpoints da API Kibana para os painéis Tags, Markdown e Links</h2><p>O Elastic 9.5 também introduz um novo  endpoint independente para <a href="https://dashboardsapispec.kibana.dev/tags.html"><strong>Tags</strong></a>, que permite categorizar e filtrar painéis. Agora, você pode gerenciá-los programaticamente por meio de endpoints CRUD dedicados, facilitando a organização de painéis em escala entre ambientes.	</p><p>Os novos endpoints para os painéis <a href="https://dashboardsapispec.kibana.dev/markdowns.html"><strong>Markdown</strong></a> e <a href="https://dashboardsapispec.kibana.dev/links.html#tag/Links"><strong>Links</strong></a> já estão disponíveis no Serverless e serão lançados na próxima versão do stack (9.6).</p><h2>Com quais tipos de painel a API do dashboard do Kibana é compatível?</h2><p>A API do dashboard é compatível com todos os painéis <em>definidos por valor</em> na versão 9.5 (aqueles definidos diretamente em um dashboard, em oposição aos painéis da biblioteca salvos para reutilização). Cada tipo de painel compatível possui um esquema tipado e validado.</p><p><strong>Tipo de painel</strong></p><p><strong>Status</strong></p><p>Gráficos XY</p><p>Compatível</p><p>Métricas</p><p>Compatível</p><p>Pizza</p><p>Compatível</p><p>Medidor</p><p>Compatível</p><p>Heatmap</p><p>Compatível</p><p>Tabelas de dados</p><p>Compatível</p><p>Mapa de árvore</p><p>Compatível</p><p>Discover sessões</p><p>Compatível</p><p>Controles</p><p>Compatível</p><p>Markdown</p><p>Compatível</p><p>Links</p><p>Compatível</p><p>Painéis de ML</p><p>Compatível</p><p>Painéis de observabilidade</p><p>Compatível</p><p>Mapas</p><p>Em breve</p><p>Vega</p><p>Em breve</p><h2>Como gerenciar dashboards do Kibana como código</h2><p>A API de dashboards permite um fluxo de trabalho completo de dashboards como código: exportar um dashboard como JSON limpo e passível de comparação, enviá-lo ao Git como fonte de verdade, revisar mudanças em pull requests e implantar a mesma definição em desenvolvimento, staging e produção. Depois que um dashboard for gerenciado como código, trate o Git como a única fonte da verdade: as alterações feitas diretamente na UI serão substituídas na próxima vez que você implantar.</p><p>O principal desafio ao mover um dashboard entre espaços, clusters ou estágios é que os dashboards referenciam objetos como data view e visualizações da biblioteca por ID. Como esses IDs são gerados automaticamente e diferem entre ambientes, um dashboard exportado de um ambiente pode apontar para objetos que não existem em outro. Existem três maneiras de lidar com isso, listadas aqui da mais automatizada à menos automatizada:</p><ul><li><p><strong>Use Terraform.</strong> O <a href="https://registry.terraform.io/providers/elastic/elasticstack/latest/docs/resources/kibana_dashboard">provedor Terraform do Elastic Stack</a> acompanha cada recurso e mapeia os IDs automaticamente por ambiente, para que as referências permaneçam consistentes enquanto você promove um dashboard do desenvolvimento para a produção.</p></li><li><p><strong>Defina por-valor </strong><a href="https://www.elastic.co/docs/explore-analyze/visualize/esorql"><strong>a Linguagem de Consulta Elasticsearch (ES|QL)</strong></a><strong>.</strong> A maneira mais portátil de construir um painel é definir sua visualização com o ES|QL diretamente no dashboard. Uma consulta <a href="https://www.elastic.co/docs/explore-analyze/query-filter/languages/esql-kibana">ES|QL</a> lê os índices que você especificar nela; portanto, o painel não contém referências externas a data views ou objetos de biblioteca. O resultado é um dashboard portátil e totalmente independente.</p></li><li><p><strong>Atribua IDs correspondentes.</strong> Se você fizer referência a objetos salvos, como visualizações de dados ou visualizações de bibliotecas, crie-os com um ID escolhido usando PUT (upsert) em vez de POST (que gera automaticamente um ID). Use IDs legíveis por humanos, como logs-prod, para que sejam fáceis de reutilizar e reconhecer em diferentes ambientes.</p></li></ul><p>Para obter uma descrição detalhada desses padrões de portabilidade e do fluxo de trabalho completo de dashboards como código, consulte a documentação <a href="https://www.elastic.co/docs/explore-analyze/dashboards/manage-dashboards-as-code#dashboards-as-code-portability">Gerenciar dashboards como código</a>.</p><h3>Crie um dashboard do Kibana com a API Dashboards usando PUT</h3><p>Aqui está um exemplo rápido de criação de um dashboard com uma métrica usando PUT em vez de POST para atribuir um ID personalizado com o nome do dashboard (service-health-overview). A mesma lógica funciona para criar visualizações independentes salvas na biblioteca.</p>PUT kbn:/api/dashboards/service-health-overview
{
  "título": "Visão geral da saúde do serviço",
  "descrição": "Métricas principais do serviço — gerenciadas via API",
  "tags": [
    "produção",
    "equipe SRE"
  ],
  "painéis": [
    {
      "tipo": "vis",
      "grade": {
        "x": 0,
        "y": 0,
        "w": 12,
        "h": 8
      },
      "config": {
        "título": "Taxa de erro (5xx)",
        "tipo": "métrico",
        "data_source": {
          "type": "esql",
          "query": "FROM logs-* | WHERE http.response.status_code &gt;= 500 | STATS error_rate=count(*) BY host.name"
        },
        "métricas": [
          {
            "type": "primary",
            "column": "count"
          }
        ]
      }
    }
  ]
}<h2>Roadmap da API do dashboard do Kibana: Maps, Vega e endpoints independentes</h2><p>Estamos expandindo ativamente o escopo da API. Na sequência, compatibilidade com mapas e painéis Vega, adicionando esquemas tipados para eles. Também estamos construindo pontos finais CRUD independentes para sessões Discover (além do suporte existente como painéis de dashboard), Vega, maps e anotações, desacoplados do ciclo de vida do dashboard.</p><p>Para as definições completas de esquema, visite a <a href="https://dashboardsapispec.kibana.dev/dashboards#tag/Dashboards">documentação da API dos Dashboards</a>. Para usuários do Terraform, o <a href="https://registry.terraform.io/providers/elastic/elasticstack/latest/docs/resources/kibana_dashboard">provedor Terraform do Elastic Stack</a> é compatível com a API GA Dashboards.</p><h2>Nota</h2><ol><li><p>Os endpoints núcleos permanecem inalterados em relação à prévia técnica. Se você construiu integrações contra a 9.4, elas funcionam na 9.5. As únicas alterações que quebram a compatibilidade são duas pequenas que afetam os formatos de listagem do dashboard e dos formatos da unidade de duração, documentadas <a href="https://www.elastic.co/docs/release-notes/kibana/breaking-changes">aqui</a>.</p></li></ol>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/dashboards-as-code-kibana-api</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/dashboards-as-code-kibana-api</guid>
    <category><![CDATA[Kibana]]></category>
    <category><![CDATA[Experiência do Desenvolvedor]]></category>
    <category><![CDATA[Integrações]]></category>
    <dc:creator><![CDATA[Teresa Alvarez Soler]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8ed7e33de291f255/6a730619c8b7ac02b251f9d3/image1.png" length="0" type="image/png"/>
    <pubDate>Wed, 05 Aug 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[No local em menos de 5 minutos: modelos de embedding Jina agora disponíveis para implantação no local]]></title>
    <description><![CDATA[Todos os 28 modelos do Jina AI, incluindo rerankers, como containers do Docker prontos para implantação, com zero telemetria e sem servidor de licença. Compatível diretamente com as APIs da OpenAI, Cohere, Voyage AI e Elastic Inference Service.]]></description>
    <content:encoded><![CDATA[<p>Todos os 28 modelos de embedding e reclassificação do Jina AI agora são enviados como containers do Docker totalmente offline para implantação no local, incluindo <a href="https://www.elastic.co/pt/search-labs/blog/jina-embeddings-v5-omni-all-media-one-index">jina-embeddings-v5-omni</a><a href="https://www.elastic.co/pt/search-labs/blog/jina-embeddings-v5-omni-all-media-one-index"> </a>e <a href="https://www.elastic.co/pt/search-labs/tutorials/jina-tutorial/jina-reranker-v3">jina-reranker-v3</a>. Baixe um, transfira-o para um sistema air-gapped ou com firewall no local, e a inferência local estará em execução em menos de cinco minutos. Os containers são totalmente autocontidos e não fazem conexões externas. Não há chamadas para a Hugging Face nem para nenhum registro de modelos. Também não há servidor de licença, telemetria nem endpoints de logging. Para setores regulamentados, requisitos de soberania de dados ou ambientes em que o acesso à internet é instável ou simplesmente indisponível, isso elimina a dependência de serviços de IA de terceiros. O Jina On-Prem é compatível com os esquemas de API do Elastic Inference Service (EIS), da OpenAI, da Cohere, da Voyage AI e do Gemini, para que as aplicações existentes funcionem sem alterações de código.</p><p>Os modelos de IA mais poderosos são executados em instalações remotas na nuvem com acesso por meio de uma API web, o que significa que você precisa confiar no seu provedor de serviços de IA para segurança, disponibilidade do serviço e preços estáveis. Você não consegue alinhar facilmente demandas razoáveis de confiabilidade, privacidade, custos gerenciáveis e boa governança de dados com o uso de IA cada vez mais poderoso, sofisticado e intensivo em recursos.</p><p>Regulamentações governamentais, decisões judiciais e considerações comerciais feitas no interesse de terceiros recentemente resultaram na restrição do acesso a serviços específicos. E mesmo que você possa alternar para outros serviços, os modelos de IA não são componentes que podem simplesmente ser trocados sempre que você quiser. Aplicações que usam embeddings semânticos dependem de ter acesso aos mesmos modelos no momento da consulta e no momento da ingestão de dados. Perder o acesso ao seu modelo de embedding significa que seu sistema de busca para completamente.</p><p>Os modelos de precificação de IA agravam esse risco. Divulgações financeiras recentes de grandes fornecedores de IA dão aos clientes bons motivos para se preocuparem com potenciais aumentos de preços. A dependência de produtos com custos imprevisíveis adiciona mais risco a investimentos em IA que exigem uso intensivo de capital e podem não produzir retornos claros.</p><p>O Jina On-Prem é a resposta da Elastic para esses desafios.</p><h2>Quem precisa de IA no local?</h2><p>A hospedagem local e o controle direto sobre seus modelos de IA são compatíveis com uma variedade de demandas técnicas, requisitos do setor e interesses de negócios.</p><p>A instalação local reduz o que você paga aos seus provedores de serviços de IA, mas transfere o custo de hardware e de acesso confiável para a sua organização. Dependendo do seu volume de uso, pode simplesmente ser mais barato. Mas há outras razões urgentes para considerar a execução da sua própria IA. Se algum dos problemas descritos abaixo afetar a sua empresa, considere uma solução de IA local como o Jina On-Prem. Esta lista não é exaustiva.</p><p>Caso de uso</p><p>Por que no local</p><p>Exemplo</p><p>Air-gapped / alta segurança</p><p>Sem transmissão de dados de saída; isolamento completo de rede</p><p>Defesa, inteligência, pesquisas classificadas</p><p>Conformidade regulatória</p><p>Soberania de dados; sem transmissão transfronteiriça ou exposição a terceiros</p><p>Saúde (Health Insurance Portability and Accountability Act [HIPAA]), finanças, empresas da UE (Regulamento Geral de Proteção de Dados [GDPR])</p><p>Crítico para a latência</p><p>Zero dependência de rede; nenhuma tolerância a falhas de conexão</p><p>Robótica, computação de borda, veículos, navios</p><p>Previsibilidade de custo</p><p>Custo fixo de infraestrutura vs. preço por token com taxas futuras incertas</p><p>Cargas de trabalho de inferência contínua de alto volume</p><p>Redução de passivos</p><p>Sem exposição de dados a terceiros; mantém o privilégio legal e o dever de cuidado</p><p>Escritórios de advocacia, agências governamentais</p><h3>Por que sistemas air-gapped e com firewall precisam de IA no local</h3><p>Sistemas air-gapped e com firewall não podem usar APIs de IA externas. O Jina On-Prem é executado inteiramente em sua infraestrutura, sem conexões de saída.</p><p>Para organizações que gerenciam dados especialmente sensíveis, as considerações de segurança e privacidade são fundamentais. Pouco adianta investir na proteção dos seus dados sensíveis se você os entrega prontamente a terceiros remotos que podem ter segurança insuficiente ou estar sujeitos às exigências de um governo estrangeiro.</p><p>Funcionários de organizações que lidam com dados sensíveis costumam receber algum treinamento sobre o tratamento seguro de dados, mas isso não é muito eficaz quando todos eles têm navegadores web que podem estar abertos em qualquer página da internet enquanto lidam com esses dados. O isolamento é a medida de segurança mais eficaz disponível, seja por meio de air-gapping ou de firewalls muito restritivos, mas isso dificulta o uso de serviços externos de qualquer tipo.</p><h3>IA no local para sistemas sensíveis à latência e de alta disponibilidade</h3><p>O software como serviço e a computação em nuvem representam um meio-termo entre o custo de oferecer serviços altamente acessíveis e confiáveis em seus próprios computadores e a terceirização do problema para outra pessoa. Mas eles vêm acompanhados de latência variável, interrupções e uma perda total de controle quando algo dá errado. Os serviços de IA não são exceção. Se o seu sistema de busca ficar offline quando você não puder acessar seu modelo de embedding, isso pode não parecer mais um bom meio-termo.</p><p>Além disso, confiar em IA externa sempre envolverá riscos que você não pode prever ou gerenciar facilmente. O acesso à internet e a latência da rede podem se deteriorar sem aviso prévio, como resultado de eventos políticos, mau tempo ou navios arrastando suas âncoras sobre cabos de fibra óptica submarinos. Os governos podem, e recentemente o fizeram, usar proibições de exportação para bloquear de repente o acesso a modelos de IA. Às vezes, os provedores de serviços de IA descontinuam modelos para induzir você a mudar para outros mais recentes. A flexibilidade e os custos gerenciados dos serviços externos precisam ser ponderados em relação aos riscos de dependência.</p><h3>IA no local para conformidade com o GDPR, a HIPAA e a soberania dos dados</h3><p>Organizações que coletam dados pessoais estão sujeitas a regulamentações cada vez mais rigorosas, que geralmente diferem entre as jurisdições e podem ter requisitos contraditórios. Notavelmente, as <a href="https://www.hhs.gov/hipaa/for-professionals/privacy/laws-regulations/index.html">regras da HIPAA</a> impõem proteções de dados muito rigorosas aos provedores de saúde norte-americanos, e leis gerais de proteção de dados fortes no <a href="https://laws-lois.justice.gc.ca/eng/acts/p-8.6/">Canadá</a>, na <a href="https://gdpr-info.eu/">União Europeia</a> e em <a href="https://www.japaneselawtranslation.go.jp/en/laws/view/4241">muitas jurisdições asiáticas</a> exigem que todas as empresas que lidam com informações pessoais o façam de forma segura e limitem a transmissão desses dados a outras partes ou outras jurisdições. Essas regras podem até impor obrigações a entidades estrangeiras se elas tiverem clientes nessas jurisdições. As instituições financeiras estão frequentemente sujeitas a regras ainda mais rigorosas e possuem a mesma responsabilidade direta pela segurança da informação que têm para se protegerem contra outras formas de atividade criminosa.</p><p>A conformidade regulatória pode ser incompatível com serviços de IA de terceiros, especialmente se usá-los envolver a transmissão transfronteiriça de dados.</p><p>Além disso, eventos recentes mostram que regras que restringem a localização física dos armazenamentos de dados podem não ser uma fonte confiável de proteção quando operadores internacionais de nuvem estão sujeitos à pressão de governos estrangeiros. Leis locais podem entrar em conflito entre jurisdições, exigindo o armazenamento e processamento local de dados e tornando impossível o uso de serviços de terceiros. Em alguns casos, a única solução é internalizar todas as partes dos seus processos, incluindo seus sistemas de IA.</p><h3>Riscos de responsabilidade por IA na transmissão de dados de terceiros</h3><p>Leis de proteção de dados e deveres de cuidado reconhecidos em relação a dados sensíveis rotineiramente têm implicações de responsabilidade, às vezes muito severas. Você pode ser responsabilizado pelo tratamento dos seus dados por provedores de serviços terceirizados. Embora os tribunais e procedimentos legais possam fornecer algumas proteções retrospectivas contra provedores de serviços inseguros, esses recursos não estão disponíveis nem são geralmente eficazes contra agentes de segurança nacional, autoridades policiais ou hackers criminosos.</p><p>Para os governos, já houve casos em que provedores de serviços em nuvem internacionais liberaram informações estatais sensíveis para agentes estrangeiros.</p><p>Mas mesmo que você não se preocupe com governos estrangeiros ou hackers, e mesmo que seus provedores de serviços de IA externos sejam seguros, o simples fato de serem externos pode criar responsabilidades.</p><p>Por exemplo, na maioria das jurisdições, as comunicações dos advogados com seus clientes contam com proteções jurídicas especiais, e os escritórios de advocacia têm responsabilidades rígidas ao gravar ou armazenar essas informações. Nos Estados Unidos, esse "sigilo advogado-cliente" é tão famoso que é central nos enredos de filmes e séries de TV. Mas uma das maneiras pelas quais esse privilégio pode ser perdido é ao comunicar informações a alguém que não seja protegido por ele, e desenvolvimentos recentes sugerem que provedores externos de serviços de IA podem se enquadrar nisso.</p><p>É possível, pelo menos nos Estados Unidos, que o simples uso de serviços de IA de terceiros por meio de uma API de internet, como modelos de incorporação que oferecem serviços de indexação, viole regras críticas de confidencialidade. Um escritório de advocacia pode ser processado, punido disciplinarmente ou ter o registro cassado só por usar software hospedado externamente, mesmo que nenhuma violação de segurança ocorra.</p><h3>IA no local para sistemas offline, de borda e fisicamente isolados</h3><p>Os sistemas de computador não são isolados apenas por motivos de segurança. Por exemplo, veículos em movimento não podem depender do acesso à internet para nenhuma função essencial. Navios e aeronaves têm sistemas de computador de bordo muito extensos que precisam funcionar sem conexões com a internet e, portanto, não podem usar serviços de IA externos. Plataformas offshore, instalações remotas em áreas selvagens, serviços de computador no Ártico, na Antártida e em pequenas ilhas sem conexões físicas adequadas com redes globais são todos exemplos de instalações que se beneficiam ao hospedar localmente todos os serviços de que precisam. À medida que o papel da IA na computação empresarial cresce, torna-se mais importante abordar essas limitações.</p><p>Aplicações emergentes de IA em sistemas físicos (robótica e outros casos de uso delimitados espacialmente ou focados no mundo externo, como sistemas de gestão de logística ou até mesmo caixas de supermercado) podem estar conectadas à internet global, mas não têm tolerância a falhas de conexão ou picos de latência. Se elas dependem de um sistema de IA para operar, esse sistema de IA precisa ser o mais local e confiável possível.</p><h2>Quem não precisa de IA em ambiente local?</h2><p>Serviços de software remotos e IA fora do local têm benefícios. Executar modelos de IA pode exigir processadores caros, de alto consumo de energia e com vida útil notoriamente curta. O acesso a hardware de alta qualidade é particularmente difícil no momento devido a fatores de mercado e choques econômicos externos. Diante das circunstâncias, pode fazer sentido pagar por token para usar uma API externa em vez de arcar com os altos custos de capital da IA local.</p><p>APIs externas fazem mais sentido para usuários intermitentes. Se você usa modelos de IA principalmente para processar dados em lote para análise, em vez de executar um sistema de busca que precise ficar online o tempo todo, faz pouco sentido investir em hardware de alto custo de capital e instalações locais.</p><p>Além disso, quando o seu processamento de dados já é baseado na nuvem, por exemplo, um website de e-commerce hospedado na nuvem por motivos de confiabilidade e acessibilidade, usar serviços de IA localizados na mesma infraestrutura de nuvem pode proporcionar um melhor custo-benefício do que introduzir a sua própria implantação de modelo de IA licenciado. Você já depende do seu provedor de serviços em nuvem, então depender dos serviços de IA dele não adiciona muito risco.</p><p>Se o seu caso de uso se encaixa nessa descrição, os modelos Jina AI estão disponíveis no <a href="https://www.elastic.co/docs/explore-analyze/elastic-inference/eis">EIS</a>, no <a href="https://aws.amazon.com/marketplace/seller-profile?id=seller-stch2ludm6vgy">AWS Marketplace</a> e no <a href="https://console.cloud.google.com/marketplace/browse?q=jina">Google Cloud Platform</a> especificamente para atender às suas necessidades.</p><p>A tabela abaixo resume os principais fatores. Sua resposta depende dos seus dados, da sua infraestrutura e do seu padrão de uso.</p><p>Fator</p><p>No local preferido</p><p>API da Nuvem Preferida</p><p>Padrão de uso</p><p>Inferência contínua ou de alto volume</p><p>Processamento intermitente ou em lote</p><p>Sensibilidade dos dados</p><p>Regulado, soberano ou confidencial</p><p>Sem restrições transfronteiriças ou de terceiros</p><p>Ambiente de rede</p><p>Air-gapped, com firewall ou instáveis</p><p>Internet estável, sempre ativa</p><p>Infraestrutura existente</p><p>Possuir ou poder adquirir hardware de GPU</p><p>Já hospedado na nuvem com IA colocalizada</p><p>Modelo de custo</p><p>Hardware fixo + licença; previsível em escala</p><p>Por token; menor custo inicial, variável a longo prazo</p><p>Tolerância a latência</p><p>Nenhum (robótica, edge, tempo real)</p><p>A variabilidade da rede é aceitável</p><p>Responsabilidade operacional</p><p>Sua equipe gerencia o hardware e a disponibilidade</p><p>O provedor gerencia o hardware e as atualizações; você gerencia a integração</p><p>Você precisa considerar os custos e benefícios à luz de suas circunstâncias específicas e casos de uso, levando em consideração os problemas destacados na seção anterior que se aplicam a você. A análise de custo-benefício sem dúvida mudará ao longo do tempo. Não podemos prever o futuro do setor de IA ou os preços de hardware, mesmo no curto prazo.</p><h2>Apresentando Jina no Local</h2><p>Para usuários que podem se beneficiar de serviços de IA locais, estamos apresentando o <a href="https://github.com/jina-ai/jina-on-prem/wiki/">Jina On-Prem</a>, um conjunto de instalação totalmente independente para os modelos de alto desempenho da Jina AI.</p><p>Os modelos do Jina AI correspondem à precisão de modelos de embedding <a href="https://mteb-leaderboard.hf.space/benchmark/MTEB(Multilingual%2C%20v2)">muitas vezes maiores que eles</a>, reduzindo custos computacionais, uso de memória e requisitos de hardware. Isso os torna uma escolha ideal para usuários que desejam ou precisam manter sua IA no local. Licenças comerciais estão disponíveis com solutions escaláveis e de preços proporcionais para casos de uso de todos os tamanhos.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt190865fb3ebde472/6a6a33d0065b162508701ff9/02559ceca556a26c53eb703ae87d421452b27251-1374x1400.png" alt="MMTEB Multilingual v2 leaderboard showing Jina AI embedding model rankings: jina-embeddings-v5-omni-small and jina-embeddings-v5-text-small ranked 13th, jina-embeddings-v5-omni-nano and jina-embeddings-v5-text-nano ranked 19th, competing against models from Microsoft, Google, Tencent, NVIDIA and Qwen" /><h3>A quais esquemas de API o Jina no local oferece suporte?</h3><ul><li><p>Disponível como uma coleção completa de dependências para instalação local ou como um <a href="https://www.docker.com/">container do Docker</a> que você pode instalar e executar em minutos.</p></li><li><p>Instalações Jina no local <em>não</em> fazem chamadas para sistemas externos.</p><ul><li><p>Nenhuma chamada ao Hugging Face Hub ou a qualquer registro de modelo (HF_HUB_OFFLINE=1 e TRANSFORMERS_OFFLINE=1 estão embutidos).</p></li><li><p>Não há servidor de licença.</p></li><li><p>Não há endpoints de telemetria ou logging.</p></li></ul></li><li><p>Oferece suporte a hardware de CPU e GPU, com detecção automática de GPU.</p></li><li><p>Todos os 28 modelos Jina AI disponíveis, incluindo os mais recentes modelos de embedding multimodal <a href="https://www.elastic.co/pt/search-labs/blog/jina-embeddings-v5-omni-all-media-one-index">jina-embeddings-v5-omni</a> e o <a href="https://www.elastic.co/pt/search-labs/tutorials/jina-tutorial/jina-reranker-v3">jina-reranker-v3</a>.</p></li><li><p>Acesso via esquemas padrão de API de IA: <a href="https://jina.ai/api-dashboard">Jina API</a>, OpenAI, Cohere, Voyage AI e Gemini. O Jina On-Prem é uma solução de substituição direta para aplicações construídas com base nesses esquemas.</p></li><li><p>Substituição direta para modelos servidos pelo <a href="https://www.elastic.co/docs/explore-analyze/elastic-inference/eis">EIS</a>. O Jina On-Prem se integra diretamente com <a href="https://www.elastic.co/pt/blog/deploy-elastic-air-gapped-disconnected-environments">implantações da Elastic em ambientes isolados</a>.</p></li></ul><h2>Requisitos de hardware para modelos Jina AI no local</h2><p>Os requisitos de hardware variam para diferentes modelos Jina. A tabela abaixo mostra as recomendações para os modelos mais recentes usando configurações de GPU. Você não precisa de nada mais potente do que uma GPU NVIDIA L4, embora uma A100 seja recomendada para os modelos de embedding v5. Nosso modelo de embedding mais recente exige atualmente no mínimo 8 GB de VRAM.</p><p>Modelo</p><p>VRAM mínima</p><p>GPU Recomendada</p><p>jina-embeddings-v5-text-nano</p><p>2 GB</p><p>T4 / L4</p><p>jina-embeddings-v5-text-small</p><p>3 GB</p><p>L4 / A10G</p><p>jina-embeddings-v5-omni-small</p><p>8 GB</p><p>L4 / A10G / A100</p><p>jina-reranker-v3</p><p>3 GB</p><p>L4</p><p>jina-clip-v2</p><p>4 GB</p><p>L4</p><p>jina-code-embeddings-1.5b</p><p>4 GB</p><p>L4</p><p>ReaderLM-v2</p><p>4 GB</p><p>L4</p><p>Se você usar mais de um modelo por vez, os requisitos de VRAM aumentarão. Consulte a <a href="https://github.com/jina-ai/jina-on-prem/wiki/Sizing-And-Hardware">página de dimensionamento e hardware</a> para obter mais informações.</p><h2>Como Instalar o Jina no Local com o Docker</h2><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt20265d09e2d8d0f4/6a6a33d1065b162105701ffd/ada9881af407168298b1940f8537ad71a5411c89-1999x1200.png" alt="" /><p>A maneira mais rápida de começar é <a href="https://www.docker.com/get-started/">instalar o Docker</a> (se você ainda não o fez) e seguir as instruções na página do <a href="https://github.com/jina-ai/jina-on-prem/wiki/QuickStart">Guia rápido do Jina no local</a>.</p><p>Há containers do Docker pré-compostos para todos os 28 modelos Jina. Baixe um e transfira-o para o seu destino de instalação, e você poderá ter os modelos Jina AI em execução em menos de cinco minutos.</p><p>Para compilações multimodais ou personalizadas, ou para baixar o conjunto completo de dependências para instalação fora de um container, siga as etapas descritas no <a href="https://github.com/jina-ai/jina-on-prem/wiki/Bundling-Guide">guia de empacotamento</a>.</p><p>Sua instalação Jina no local oferece suporte a todas as funcionalidades da Jina API e do EIS e à geração de embeddings por meio das APIs da OpenAI, Cohere, Voyage AI e Gemini, de modo que ela pode ser integrada a aplicativos preexistentes usando interfaces padrão. Consulte a <a href="https://github.com/jina-ai/jina-on-prem/wiki/API-Reference">documentação da API</a> para obter mais informações.</p><p>Os modelos Jina, incluindo os modelos instalados com o Jina no local, estão disponíveis sob vários termos de licenciamento, sendo que os modelos mais recentes são gratuitos para uso não comercial sob uma licença <a href="https://creativecommons.org/licenses/by-nc/4.0/deed.en">CC BY-NC 4.0</a>. Para licenciar o Jina no local para uso comercial, entre em contato com as <a href="https://www.elastic.co/pt/contact">vendas da Elastic</a>.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/on-prem-ai-jina-embedding-models</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/on-prem-ai-jina-embedding-models</guid>
    <category><![CDATA[Jina AI]]></category>
    <category><![CDATA[Integrações]]></category>
    <dc:creator><![CDATA[Scott Martens]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt17731ab0c6ec66f6/6a6a33d140a4941014ca5c9a/09bc6dac4e6a86c7877f8ed78d68f5d581aeffa9-1999x1200.png" length="0" type="image/png"/>
    <pubDate>Thu, 23 Jul 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Impulsionando o Elasticsearch: adicionando suporte nativo à API do Prometheus]]></title>
    <description><![CDATA[Consulte o Elasticsearch diretamente de clientes compatíveis com Prometheus via endpoints nativos de PromQL, descoberta e metadados. Envie dados para o Elasticsearch com Prometheus Remote Write.]]></description>
    <content:encoded><![CDATA[<p>Aponte qualquer cliente compatível com Prometheus para o Elasticsearch e execute PromQL diretamente em suas métricas existentes. O Elasticsearch está adicionando endpoints nativos de consulta, descoberta e metadados do Prometheus como uma prévia técnica que funcionam com métricas ingeridas via Prometheus Remote Write, OpenTelemetry ou Bulk API. A API é executada sobre os fluxos de dados de série temporal (TSDS) do Elasticsearch, então não há uma camada de armazenamento específica do Prometheus para operar.</p><p>Este post explica como os endpoints de consulta, descoberta e metadados se baseiam no trabalho anterior de ingestão e consulta para formar esse conjunto de APIs. Posts complementares aprofundam tópicos específicos:</p><ul><li><p><a href="https://www.elastic.co/observability-labs/blog/elasticsearch-supports-promql">O suporte nativo ao PromQL no ES|QL</a> abrange como as consultas PromQL são traduzidas em planos de execução do ES|QL.</p></li><li><p><a href="https://www.elastic.co/observability-labs/blog/prometheus-remote-write-elasticsearch">Enviar métricas do Prometheus para o Elasticsearch com Remote Write</a> abrange a configuração da ingestão.</p></li><li><p><a href="https://www.elastic.co/observability-labs/blog/prometheus-remote-write-elasticsearch-architecture">Como funciona a ingestão de gravação remota do Prometheus no Elasticsearch</a> aborda os aspectos internos da gravação remota.</p></li></ul><p>Isso ainda está em desenvolvimento. As seções abaixo destacam o que é compatível atualmente e quais partes ainda estão evoluindo.</p><h2>A superfície da API</h2><p>Hoje, a interface de API compatível com Prometheus é dividida em três grupos.</p><h3>Endpoints de consulta</h3><p>Os endpoints de consulta permitem que clientes compatíveis com Prometheus avaliem expressões PromQL:</p><ul><li><p><code>GET /_prometheus/api/v1/query_range</code> avalia uma expressão de PromQL ao longo de uma janela de tempo (resultados matriciais).</p></li><li><p><code>GET /_prometheus/api/v1/query</code> avalia em um único ponto no tempo (resultados vetoriais). Atualmente implementado como uma consulta de curto alcance que retorna a última amostra.</p></li></ul><p>Atualmente, apenas GET é suportado para endpoints de consulta. Alguns clientes usam POST por padrão, então você pode precisar configurá-los para usar GET. A convenção POST do Prometheus usa payloads <code>application/x-www-form-urlencoded</code>, que a camada HTTP do Elasticsearch rejeita como uma proteção contra CSRF antes que a solicitação chegue ao manipulador.</p><p>Para o status completo de cobertura do PromQL, consulte a <a href="https://www.elastic.co/observability-labs/blog/elasticsearch-supports-promql">postagem complementar sobre PromQL em ES|QL</a>.</p><h3>Endpoints de metadados</h3><p>Os endpoints de metadados fornecem as informações necessárias para descoberta de que os clientes precisam para autocompletar, menus suspensos de variáveis e navegação de métricas.</p><p>Os endpoints de séries, rótulos e valores de rótulos aceitam <code>match[]</code> seletores e um intervalo de tempo (<code>start</code>/<code>end</code>). O parâmetro <code>match[]</code> aceita um seletor de séries do Prometheus como <code>http_requests_total{job="api"}</code> e restringe a resposta às séries temporais correspondentes. Isso mantém as respostas rápidas e relevantes em clusters com grande número de métricas. Por exemplo:</p>GET /_prometheus/api/v1/series?match[]=http_requests_total{job="api"}GET /_prometheus/api/v1/labels?match[]=http_requests_totalGET /_prometheus/api/v1/label/instance/values?match[]=http_requests_total{job="api"}<p>O primeiro retorna todas as séries para <code>http_requests_total</code> onde <code>job="api"</code>, com seus conjuntos de rótulos completos. O segundo retorna apenas os nomes dos rótulos que existem nas séries <code>http_requests_total</code> . O terceiro retorna apenas os valores <code>instance</code> que aparecem nas séries correspondentes.</p><p><code>GET /_prometheus/api/v1/metadata</code> é diferente: ele retorna tipo e unidade para cada métrica, opcionalmente filtrada por nome via um parâmetro <code>metric</code>.</p>GET /_prometheus/api/v1/metadata?metric=http_requests_total<p>Não aceita <code>match[]</code> seletores nem um intervalo de tempo. No Prometheus, os metadados são coletados de alvos ativos de coleta (as linhas <code>HELP</code>, <code>TYPE</code> e <code>UNIT</code> que eles expõem), então a resposta não envolve uma varredura de dados. O Elasticsearch não possui um repositório de metadados dedicado como esse, então a implementação atual descobre os metadados das métricas acessando os dados de séries temporais das últimas 24 horas. Isso mantém a consulta rápida sem exigir uma varredura completa do índice. Esse período retrospectivo de 24 horas é fixo atualmente: a API de metadados do Prometheus não expõe os parâmetros <code>start</code> ou <code>end</code> que o Elasticsearch poderia usar para torná-la ajustável pelo usuário.</p><p>A <a href="https://www.elastic.co/search-labs/blog//elasticsearch-native-prometheus-api#ts-info-and-metrics-info">seguir,</a> você verá como funcionam os endpoints de metadados, inclusive os comandos <code>TS_INFO</code> e <code>METRICS_INFO</code> que os sustentam.</p><h3>Pré-filtragem de índices</h3><p>Todos os endpoints de consulta e metadados aceitam um segmento de caminho opcional <code>{index}</code> após <code>/_prometheus/</code>:</p>GET /_prometheus/metrics-prod-*/api/v1/query_range?query=up&amp;start=...&amp;end=...<p>Isso restringe quais índices do Elasticsearch a consulta executa antes de qualquer avaliação de expressão começar. Em clusters com muitos fluxos de dados distribuídos entre equipes ou ambientes, isso evita a varredura de índices não relacionados e pode reduzir significativamente a latência da consulta. Você pode configurar fontes de dados separadas por padrão de indexação para fornecer às equipes acesso segmentado às suas próprias métricas.</p><h3>Uma nota sobre a Escrita Remota</h3><p>Para ingestão, o Elasticsearch também expõe o endpoint padrão Prometheus Remote Write:</p><ul><li><p><code>POST /_prometheus/api/v1/write</code> ingere séries temporais por meio do protocolo Prometheus Remote Write v1. A versão 2 ainda não é suportada.</p></li></ul><p>O Remote Write grava nos fluxos de dados de séries temporais (TSDS) existentes do Elasticsearch, não em uma camada de armazenamento separada específica do Prometheus. Os rótulos do Prometheus se tornam dimensões do TSDS e os nomes das métricas se tornam campos no mapeamento do índice. A <a href="https://www.elastic.co/observability-labs/blog/prometheus-remote-write-elasticsearch-architecture">publicação sobre a arquitetura de gravação remota</a> aborda o mapeamento completo em detalhes, inclusive como os tipos de métricas são deduzidos e como os rótulos são armazenados com um prefixo <code>labels.</code>.</p><h3>Como funciona</h3><p>Nos bastidores, todos os endpoints funcionam da mesma forma: analisam os parâmetros HTTP de entrada, constroem um plano de execução ES|QL, executam-no contra fluxos de dados de séries temporais e convertem o resultado colunar de volta para o formato JSON que os clientes do Prometheus esperam.</p><h2>TS_INFO e METRICS_INFO</h2><p>Os endpoints de metadados precisam responder a perguntas como "quais rótulos existem?" ou "quais tipos de métricas estão definidos?" em potencialmente milhões de séries temporais, sem varrer cada ponto de dados.</p><p>Internamente, os endpoints de metadados do Prometheus respondem a essas perguntas construindo planos ES|QL em torno de dois novos comandos de processamento: <code>METRICS_INFO</code> e <code>TS_INFO</code>. Você não precisa usar esses comandos diretamente para usar a API do Prometheus, mas eles são as primitivas centrais de execução por trás das respostas dos metadados. Ambos funcionam acessando apenas um documento por série temporal para extrair seus metadados, em vez de varrer todas as amostras. Isso significa que o custo deles escala de acordo com o número de séries temporais distintas, não com o número de pontos de dados.</p><p><code>METRICS_INFO</code> retorna uma linha por métrica distinta com seu nome, tipo, unidade e campos de dimensão associados. <code>TS_INFO</code> é mais detalhado: uma linha por combinação de métrica e série temporal, incluindo os valores reais das dimensões como objeto JSON.</p><p>Um post do blog dedicado sobre <code>TS_INFO</code> e <code>METRICS_INFO</code> será publicado em breve, abordando o modelo de execução em duas fases, como eles escalam e como usá-los diretamente no ES|QL além da API do Prometheus.</p><h3>Como os endpoints de metadados usam esses recursos</h3><p>Cada endpoint de metadados constrói um plano ES|QL com um desses comandos em seu núcleo.</p><p><code>/api/v1/labels</code> e <code>/api/v1/series</code> usam <code>TS_INFO</code>, já que precisam de detalhes por série temporal (quais rótulos existem, quais valores de dimensão identificam cada série). <code>/api/v1/metadata</code> e <code>/api/v1/label/__name__/values</code> usam <code>METRICS_INFO</code>, já que precisam apenas de informações por métrica (nomes de métricas, tipos, unidades).</p><p><code>/api/v1/label/{name}/values</code> para rótulos normais (qualquer coisa diferente de <code>__name__</code>) não usa nenhum dos comandos. Rótulos regulares como <code>job</code> ou <code>instance</code> são campos de dimensão reais no índice, portanto o endpoint pode consultá-los diretamente com uma agregação group-by. Quando <code>match[]</code> seletores são fornecidos, eles são convertidos em uma cláusula <code>WHERE</code> que filtra as séries temporais antes que a agregação seja executada.</p><p>O rótulo <code>__name__</code> precisa de uma estratégia diferente porque nem sempre está presente como um campo dimensional. O Prometheus Remote Write armazena <code>labels.__name__</code>, mas métricas ingeridas por meio de outros caminhos (OpenTelemetry, a Bulk API) não possuem isso. O nome da métrica é codificado no próprio nome do campo (por exemplo, <code>metrics.http_requests_total</code>). Você poderia olhar os mapeamentos de índice para enumerar nomes de campos, mas mapeamentos, por si só, não informam qual métrica tem quais dimensões, e eles não podem ser filtrados pelos valores de rótulos de um seletor <code>match[]</code>. <code>METRICS_INFO</code> pode fazer ambos: enumera nomes de métricas entre índices enquanto respeita os filtros upstream <code>WHERE</code>.</p><p>Em todos os casos, a camada da API lida com a tradução de volta para as convenções do Prometheus: removendo os prefixos de armazenamento <code>labels.</code> e <code>metrics.</code> e gerando automaticamente <code>__name__</code> para métricas não-Prometheus que não o possuem.</p><h2>Conclusão</h2><p>O resultado: qualquer cliente compatível com o Prometheus pode consultar e explorar as métricas do Elasticsearch por meio de endpoints que ele já entende. As métricas de gravação remota, as métricas do OpenTelemetry e as métricas indexadas por outros caminhos aparecem por meio da mesma API, com suporte dos mesmos índices TSDS.</p><p>Todas as APIs do Prometheus mencionadas aqui estão disponíveis como prévia técnica no Elasticsearch Serverless hoje. Para clusters autogerenciados e implantações hospedadas no Elastic Cloud Hosted, as APIs estão disponíveis como prévia técnica no Elasticsearch 9.4, com exceção de <code>GET /_prometheus/api/v1/metadata</code>. Para experimentar localmente, use <a href="https://www.elastic.co/docs/deploy-manage/deploy/self-managed/local-development-installation-quickstart">start-local</a>.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/elasticsearch-native-prometheus-api</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/elasticsearch-native-prometheus-api</guid>
    <category><![CDATA[Integrações]]></category>
    <dc:creator><![CDATA[Felix Barnsteiner]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt12b4e100d5bbb7f0/6a16f7a22b835ff747f4afdd/c7b333bd73e8a1f4e18486b2d692ba742788dcfd-1376x768.jpg" length="0" type="image/jpeg"/>
    <pubDate>Mon, 11 May 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Criando um servidor MCP do Elasticsearch com TypeScript]]></title>
    <description><![CDATA[Saiba como criar servidor MCP do Elasticsearch com TypeScript e Claude Desktop.]]></description>
    <content:encoded><![CDATA[<p>Ao trabalhar com grandes bases de conhecimento no Elasticsearch, encontrar informações é apenas metade da batalha. Engenheiros precisam sintetizar resultados de múltiplos documentos, gerar resumos e rastrear respostas até as fontes. Para isso, o Protocolo de Contexto do Modelo (MCP) oferece uma maneira padronizada de conectar o Elasticsearch a aplicativos baseados em grandes modelos de linguagem (LLM). Embora a Elastic ofereça soluções oficiais, como o Elastic Agent Builder (que inclui um <a href="https://www.elastic.co/docs/solutions/search/agent-builder/mcp-server">endpoint MCP</a> entre os recursos), a criação de um servidor MCP personalizado oferece controle total sobre a lógica de busca, a formatação dos resultados e como o conteúdo recuperado é passado para um LLM para síntese, resumos e citações.</p><p>Neste artigo, exploraremos os benefícios de criar um servidor MCP do Elasticsearch personalizado e mostraremos como criar um servidor em TypeScript que conecte o Elasticsearch a aplicativos com LLM.</p><h2>Por que criar um servidor MCP do Elasticsearch personalizado?</h2><p>A Elastic oferece algumas alternativas para <a href="https://www.elastic.co/docs/solutions/search/mcp">servidores MCP</a>:</p><ul><li><p><a href="https://www.elastic.co/docs/solutions/search/agent-builder/mcp-server">Servidor MCP do Elastic Agent Builder para Elasticsearch 9.2+</a></p></li><li><p><a href="https://github.com/elastic/mcp-server-elasticsearch?tab=readme-ov-file#elasticsearch-mcp-server">Servidor MCP do Elasticsearch para versões mais antigas (Python)</a></p></li></ul><p>Se você precisar de mais controle sobre como o servidor MCP interage com o Elasticsearch, a criação do seu próprio servidor personalizado oferece a flexibilidade de adaptá-lo exatamente às suas necessidades. Por exemplo, o endpoint MCP do Agent Builder é limitado a consultas em Elasticsearch Query Language (ES|QL), enquanto um servidor personalizado permite usar o Query DSL completo. Você também tem controle sobre como os resultados são formatados antes de serem passados para o LLM e pode integrar etapas adicionais de processamento, como o resumo com tecnologia OpenAI que implementaremos neste tutorial.</p><p>Ao final deste artigo, você terá um servidor MCP no TypeScript que busca informações armazenadas em um índice do Elasticsearch, resume essas informações e fornece citações. Usaremos o Elasticsearch para recuperação, o modelo <code>gpt-4o-mini</code> da OpenAI para resumir e gerar citações, e o Claude Desktop como cliente MCP e UI para receber consultas dos usuários e dar respostas. O resultado é um assistente de conhecimento interno que ajuda os engenheiros a entender e sintetizar as práticas recomendadas nos documentos técnicos de sua organização.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltad9133cb083ad352/6a170c19b0367d411e72bd5b/ec5771a874cf9740d4cac6888622cbe8cd6aede7-1999x1133.png" alt="Criando um servidor MCP Elastic com TypeScript e Claude Desktop." /><h2>Pré-requisitos:</h2><ul><li><p>Node.js 20 +</p></li><li><p>Elasticsearch</p></li><li><p>Chave de API da OpenAI</p></li><li><p>Claude Desktop</p></li></ul><h3>O que é MCP?</h3><p><a href="https://www.elastic.co/what-is/mcp">O MCP</a> é um padrão aberto, criado pela <a href="https://www.anthropic.com/news/model-context-protocol">Anthropic</a>, que oferece conexões seguras e bidirecionais entre LLMs e sistemas externos, como o Elasticsearch. Você pode ler mais sobre a situação atual do MCP <a href="https://www.elastic.co/search-labs/blog/mcp-current-state">neste artigo</a>.</p><p>O cenário de MCP está <a href="https://www.elastic.co/search-labs/blog/mcp-current-state#mcp-project-updates:-transport,-elicitation,-and-structured-tooling">em constante evolução</a>, com servidores disponíveis para uma ampla gama de casos de uso. Além disso, é fácil criar seu próprio servidor MCP personalizado, como mostraremos neste artigo.</p><h3>Clientes do MCP</h3><p>Há uma longa <a href="https://modelcontextprotocol.io/clients">lista de clientes MCP disponíveis</a>, cada um com as próprias características e limitações. Por simplicidade e popularidade, usaremos o <a href="https://claude.ai/download">Claude Desktop</a> como nosso cliente MCP. Ele servirá como interface de chat na qual os usuários poderão fazer perguntas em linguagem natural e que invocará automaticamente as ferramentas expostas pelo nosso servidor MCP para buscar documentos e gerar resumos.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt06fd7a02042094e1/6a170c1b14b2700024e3c651/66eb0b11473347b6cf2d85718251eeac38d6249d-1999x1491.png" alt="Página do Claude 4.5 Sonnet, com a observação, &quot;hora do café e do Claude? Como posso ajudar você hoje?&quot;" /><h2>Criando um servidor MCP do Elasticsearch</h2><p>Usando o <a href="https://github.com/modelcontextprotocol/typescript-sdk">TypeScript SDK</a>, podemos criar um servidor que entende como consultar nossos dados do Elasticsearch com base em uma entrada de consulta do usuário.</p><p>Aqui estão os passos deste artigo para integrar o servidor MCP do Elasticsearch com o cliente Claude Desktop:</p><ol><li><p><a href="https://www.elastic.co/search-labs/blog/elastic-mcp-server-typescript-claude#configure-mcp-server-for-elasticsearch">Configure o servidor MCP para o Elasticsearch.</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/elastic-mcp-server-typescript-claude#load-the-mcp-server-into-claude-desktop">Carregue o servidor MCP no Claude Desktop.</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/elastic-mcp-server-typescript-claude#test-it-out">Faça o teste.</a></p></li></ol><h3>Configure o servidor MCP para o Elasticsearch</h3><p>Para começar, vamos iniciar uma aplicação de nó:</p>npm init -y<p>Isso criará um arquivo <code>package.json</code> e, com ele, poderemos começar a instalar as dependências necessárias para essa aplicação.</p>npm install @elastic/elasticsearch @modelcontextprotocol/sdk openai zod &amp;&amp; npm install --save-dev ts-node @types/node typescript<ul><li><p><strong>@elastic/elasticsearch</strong> nos dará acesso à biblioteca Elasticsearch Node.js.</p></li><li><p><strong>@modelcontextprotocol/sdk</strong> fornece as ferramentas de núcleo para criar e gerenciar um servidor MCP, registrar ferramentas e lidar com a comunicação com clientes MCP.</p></li><li><p><strong>openai</strong> permite a interação com modelos OpenAI para gerar resumos ou respostas em linguagem natural.</p></li><li><p><a href="https://zod.dev/"><strong>zod</strong></a>ajuda a definir e validar esquemas estruturados para dados de entrada e saída em cada ferramenta.</p></li></ul><p><code>ts-node</code>, <code>@types/node</code>, e <code>typescript</code> serão usados durante o desenvolvimento para digitar o código e compilar os scripts.</p><h4>Configurar o conjunto de dados</h4><p>Para fornecer os dados que o Claude Desktop pode consultar usando nosso servidor MCP, usaremos um <a href="https://github.com/Delacrobix/typescript-elasticsearch-mcp/blob/main/dataset.json">conjunto de dados fictício de base de conhecimento interna</a>. Veja como será um documento desse conjunto de dados:</p>{
    "id": 5,
    "title": "Logging Standards for Microservices",
    "content": "Consistent logging across microservices helps with debugging and tracing. Use structured JSON logs and include request IDs and timestamps. Avoid logging sensitive information. Centralize logs in Elasticsearch or a similar system. Configure log rotation to prevent storage issues and ensure logs are searchable for at least 30 days.",
    "tags": ["logging", "microservices", "standards"]
}<p>Para ingerir os dados, preparamos um script que cria um índice no Elasticsearch e carrega o conjunto de dados nele. Você pode encontrá-lo <a href="https://github.com/Delacrobix/typescript-elasticsearch-mcp/blob/main/setup.ts">aqui</a>.</p><h4>Servidor MCP</h4><p>Crie um arquivo chamado <a href="https://github.com/Delacrobix/typescript-elasticsearch-mcp/blob/main/index.ts"><code>index.ts</code></a> e adicione o seguinte código para importar as dependências e lidar com as variáveis de ambiente:</p>// index.ts
import { z } from "zod";
import { Client } from "@elastic/elasticsearch";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import OpenAI from "openai";

const ELASTICSEARCH_ENDPOINT =
  process.env.ELASTICSEARCH_ENDPOINT ?? "http://localhost:9200";
const ELASTICSEARCH_API_KEY = process.env.ELASTICSEARCH_API_KEY ?? "";
const OPENAI_API_KEY = process.env.OPENAI_API_KEY ?? "";
const INDEX = "documents";<p>Além disso, vamos inicializar os clientes para lidar com as chamadas do Elasticsearch e do OpenAI:</p>const openai = new OpenAI({
  apiKey: OPENAI_API_KEY,
});

const _client = new Client({
  node: ELASTICSEARCH_ENDPOINT,
  auth: {
    apiKey: ELASTICSEARCH_API_KEY,
  },
});<p>Para tornar nossa implementação mais robusta e garantir entrada e saída estruturadas, definiremos esquemas usando <a href="https://zod.dev/"><code>zod</code></a>. Isso nos permite validar dados em tempo de execução, detectar erros com antecedência e facilitar o processamento de forma programática das respostas da ferramenta:</p>const DocumentSchema = z.object({
  id: z.number(),
  title: z.string(),
  content: z.string(),
  tags: z.array(z.string()),
});

const SearchResultSchema = z.object({
  id: z.number(),
  title: z.string(),
  content: z.string(),
  tags: z.array(z.string()),
  score: z.number(),
});

type Document = z.infer&lt;typeof DocumentSchema&gt;;
type SearchResult = z.infer&lt;typeof SearchResultSchema&gt;;<p>Saiba mais sobre saídas estruturadas <a href="https://www.elastic.co/search-labs/blog/structured-outputs-elasticsearch-guide">aqui</a>.</p><p>Agora vamos inicializar o servidor MCP:</p>const server = new McpServer({
  name: "Elasticsearch RAG MCP",
  description:
    "A RAG server using Elasticsearch. Provides tools for document search, result summarization, and source citation.",
  version: "1.0.0",
});<h4>Definição das ferramentas MCP</h4><p>Com tudo configurado, podemos começar a escrever as ferramentas que serão expostas pelo nosso servidor MCP. Esse servidor expõe duas ferramentas:</p><ul><li><p><strong><code>search_docs</code></strong><strong>: </strong>Busca por documentos no Elasticsearch usando busca de texto completo.</p></li><li><p><strong><code>summarize_and_cite</code></strong><strong>:</strong> Resume e sintetiza informações de documentos previamente recuperados para responder a uma pergunta do usuário. Essa ferramenta também adiciona citações que referenciam os documentos fonte.</p></li></ul><p>Juntas, essas ferramentas formam um fluxo de trabalho simples de "recuperar e resumir", em que uma ferramenta busca documentos relevantes e a outra usa esses documentos para gerar uma resposta resumida e citada.</p><h4>Formato de resposta da ferramenta</h4><p>Cada ferramenta pode aceitar parâmetros de entrada arbitrários, mas deve responder com a seguinte estrutura:</p><ul><li><p><strong>Conteúdo:</strong> esta é a resposta da ferramenta em um formato não estruturado. Este campo geralmente é usado para retornar texto, imagens, áudio, links ou embeddings. Para esta aplicação, ele será usado para retornar texto formatado com as informações geradas pelas ferramentas.</p></li><li><p><strong>structuredContent: </strong>Esse é um retorno opcional usado para fornecer os resultados de cada ferramenta em um formato estruturado. É útil para fins programáticos. Embora não seja usado neste servidor MCP, pode ser útil caso você queira desenvolver outras ferramentas ou processar os resultados programaticamente.</p></li></ul><p>Com essa estrutura em mente, vamos nos aprofundar em cada ferramenta em detalhes.</p><h4>Ferramenta de Busca de Documentos</h4><p>Esta ferramenta realiza uma <a href="https://www.elastic.co/docs/solutions/search/full-text">busca de texto completo</a> no índice do Elasticsearch para recuperar os documentos mais relevantes com base na consulta do usuário. Ele destaca correspondências-chave e oferece uma visão geral rápida com pontuações de relevância.</p>server.registerTool(
  "search_docs",
  {
    title: "Search Documents",
    description:
      "Search for documents in Elasticsearch using full-text search. Returns the most relevant documents with their content, title, tags, and relevance score.",
    inputSchema: {
      query: z
        .string()
        .describe("The search query terms to find relevant documents"),
      max_results: z
        .number()
        .optional()
        .default(5)
        .describe("Maximum number of results to return"),
    },
    outputSchema: {
      results: z.array(SearchResultSchema),
      total: z.number(),
    },
  },
  async ({ query, max_results }) =&gt; {
    if (!query) {
      return {
        content: [
          {
            type: "text",
            text: "Query parameter is required",
          },
        ],
        isError: true,
      };
    }

    try {
      const response = await _client.search({
        index: INDEX,
        size: max_results,
        query: {
          bool: {
            must: [
              {
                multi_match: {
                  query: query,
                  fields: ["title^2", "content", "tags"],
                  fuzziness: "AUTO",
                },
              },
            ],
            should: [
              {
                match_phrase: {
                  title: {
                    query: query,
                    boost: 2,
                  },
                },
              },
            ],
          },
        },
        highlight: {
          fields: {
            title: {},
            content: {},
          },
        },
      });

      const results: SearchResult[] = response.hits.hits.map((hit: any) =&gt; {
        const source = hit._source as Document;

        return {
          id: source.id,
          title: source.title,
          content: source.content,
          tags: source.tags,
          score: hit._score ?? 0,
        };
      });

      const contentText = results
        .map(
          (r, i) =&gt;
            `[${i + 1}] ${r.title} (score: ${r.score.toFixed(
              2,
            )})\n${r.content.substring(0, 200)}...`,
        )
        .join("\n\n");

      const totalHits =
        typeof response.hits.total === "number"
          ? response.hits.total
          : (response.hits.total?.value ?? 0);

      return {
        content: [
          {
            type: "text",
            text: `Found ${results.length} relevant documents:\n\n${contentText}`,
          },
        ],
        structuredContent: {
          results: results,
          total: totalHits,
        },
      };
    } catch (error: any) {
      console.log("Error during search:", error);

      return {
        content: [
          {
            type: "text",
            text: `Error searching documents: ${error.message}`,
          },
        ],
        isError: true,
      };
    }
  }
);<p><em>Configuramos </em><a href="https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-fuzzy-query"><em><code>fuzziness</code></em></a><em><code>: “AUTO”</code></em><em> para ter uma tolerância variável de erros de digitação com base no comprimento do token que está sendo analisado. Também definimos </em><em><code>title^2</code></em><em> para aumentar a pontuação dos documentos onde a correspondência ocorre no campo de título.</em></p><h4>Ferramenta summarize_and_cite</h4><p>Esta ferramenta gera um resumo baseado em documentos recuperados na busca anterior. Usa o modelo <code>gpt-4o-mini</code> da OpenAI para sintetizar as informações mais relevantes e responder à pergunta do usuário, fornecendo respostas derivadas diretamente dos resultados da busca. Além do resumo, também retorna metadados de citação para os documentos de origem usados.</p>server.registerTool(
  "summarize_and_cite",
  {
    title: "Summarize and Cite",
    description:
      "Summarize the provided search results to answer a question and return citation metadata for the sources used.",
    inputSchema: {
      results: z
        .array(SearchResultSchema)
        .describe("Array of search results from search_docs"),
      question: z.string().describe("The question to answer"),
      max_length: z
        .number()
        .optional()
        .default(500)
        .describe("Maximum length of the summary in characters"),
      max_docs: z
        .number()
        .optional()
        .default(5)
        .describe("Maximum number of documents to include in the context"),
    },
    outputSchema: {
      summary: z.string(),
      sources_used: z.number(),
      citations: z.array(
        z.object({
          id: z.number(),
          title: z.string(),
          tags: z.array(z.string()),
          relevance_score: z.number(),
        })
      ),
    },
  },
  async ({ results, question, max_length, max_docs }) =&gt; {
    if (!results || results.length === 0 || !question) {
      return {
        content: [
          {
            type: "text",
            text: "Both results and question parameters are required, and results must not be empty",
          },
        ],
        isError: true,
      };
    }

    try {
      const used = results.slice(0, max_docs);

      const context = used
        .map(
          (r: SearchResult, i: number) =&gt;
            `[Document ${i + 1}: ${r.title}]\\n${r.content}`
        )
        .join("\n\n---\n\n");

      // Generate summary with OpenAI
      const completion = await openai.chat.completions.create({
        model: "gpt-4o-mini",
        messages: [
          {
            role: "system",
            content:
              "You are a helpful assistant that answers questions based on provided documents. Synthesize information from the documents to answer the user's question accurately and concisely. If the documents don't contain relevant information, say so.",
          },
          {
            role: "user",
            content: `Question: ${question}\\n\\nRelevant Documents:\\n${context}`,
          },
        ],
        max_tokens: Math.min(Math.ceil(max_length / 4), 1000),
        temperature: 0.3,
      });

      const summaryText =
        completion.choices[0]?.message?.content ?? "No summary generated.";

      const citations = used.map((r: SearchResult) =&gt; ({
        id: r.id,
        title: r.title,
        tags: r.tags,
        relevance_score: r.score,
      }));

      const citationText = citations
        .map(
          (c: any, i: number) =&gt;
            `[${i + 1}] ID: ${c.id}, Title: "${c.title}", Tags: ${c.tags.join(
              ", ",
            )}, Score: ${c.relevance_score.toFixed(2)}`,
        )
        .join("\n");

      const combinedText = `Summary:\\n\\n${summaryText}\\n\\nSources used (${citations.length}):\\n\\n${citationText}`;

      return {
        content: [
          {
            type: "text",
            text: combinedText,
          },
        ],
        structuredContent: {
          summary: summaryText,
          sources_used: citations.length,
          citations: citations,
        },
      };
    } catch (error: any) {
      return {
        content: [
          {
            type: "text",
            text: `Error generating summary and citations: ${error.message}`,
          },
        ],
        isError: true,
      };
    }
  }
);<p>Por fim, precisamos iniciar o servidor usando <a href="https://github.com/modelcontextprotocol/typescript-sdk?tab=readme-ov-file#stdio">stdio</a>. Isso significa que o cliente MCP se comunicará com nosso servidor lendo e escrevendo nos fluxos padrão de entrada e saída. Stdio é a opção de transporte mais simples e funciona bem para servidores MCP locais lançados como subprocessos pelo cliente. Adicione o seguinte código ao final do arquivo:</p>const transport = new StdioServerTransport();
server.connect(transport);<p>Agora compile o projeto usando o seguinte comando:</p>npx tsc index.ts --target ES2022 --module node16 --moduleResolution node16 --outDir ./dist --strict --esModuleInterop<p>Isso criará uma pasta <code>dist</code> e, dentro dela, um arquivo <code>index.js</code>.</p><h3>Carregue o servidor MCP no Claude Desktop</h3><p>Siga <a href="https://modelcontextprotocol.io/docs/develop/connect-local-servers">este guia</a> para configurar o servidor MCP com o Claude Desktop. No arquivo de configuração Claude, precisamos definir os seguintes valores:</p>{
  "mcpServers": {
    "elasticsearch-rag-mcp": {
      "command": "node",
      "args": [   "/Users/user-name/app-dir/dist/index.js"
      ],
      "env": {
        "ELASTICSEARCH_ENDPOINT": "your-endpoint-here",
        "ELASTICSEARCH_API_KEY": "your-api-key-here",
        "OPENAI_API_KEY": "your-openai-key-here"
      }
    }
  }
}<p>O valor <code>args</code> deve apontar para o arquivo compilado na pasta <code>dist</code>. Você também precisa definir as variáveis de ambiente no arquivo de configuração com exatamente os mesmos nomes definidos no código.</p><h3>Faça o teste</h3><p>Antes de executar cada ferramenta, clique em <strong>Busca e Ferramentas</strong> para garantir que as ferramentas estejam ativadas. Aqui você também pode ativar ou desativar cada uma delas:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt395a7337021f9820/6a170c1c67045bb74d45c228/172981c2a54adabc70d5819013c3007670935605-1999x1002.png" alt="Página do Claude 4.5 Sonnet, com a observação, &quot;Boa tarde, Jeff. Como posso ajudar você hoje?&quot;" /><p>Por fim, vamos testar o servidor MCP no chat do Claude Desktop e começar a fazer perguntas:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf4ac458dc0206271/6a170c1e66c4f91328f8c072/03654c0f8c53c714f801fba8b25747071179209b-1999x1353.png" alt="Solicitação de pesquisa do usuário no chat do Claude Desktop para documentos sobre métodos de autenticação e controle de acesso por função (RBAC), junto com as respostas do Claude." /><p>Para a pergunta “<strong>Buscar documentos sobre métodos de autenticação e controle de acesso por função</strong>”, a ferramenta <code>search_docs</code> é executada e retorna os seguintes resultados:</p>Most Relevant Documents:
Access Control and Role Management (highest relevance) - This document covers role-based access control (RBAC) principles, including ensuring users only have necessary permissions, regular auditing of user roles, revoking inactive accounts, and implementing just-in-time access for sensitive operations.
User Authentication with OAuth 2.0 - This document explains OAuth 2.0 authentication, which enables secure delegated access without credential sharing. It covers configuring identity providers, token management with limited scope and lifetime, and secure storage of refresh tokens.
Container Security Guidelines - While primarily about container security, this document touches on access control aspects like running containers as non-root users and avoiding embedded credentials.
Incident Response Playbook - This mentions role assignment during incidents (incident commander, communications lead, etc.), which relates to access control in emergency scenarios.
Logging Standards for Microservices - This document includes guidance on avoiding logging sensitive information, which is relevant to authentication security.<p>A resposta é: "Ótimo! Encontrei 5 documentos relevantes sobre métodos de autenticação e controle de acesso por função. Eis o que foi encontrado:"</p><p>A chamada de ferramenta retorna os documentos fonte como parte da carga útil de resposta, que são posteriormente usados para gerar citações.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbaf48a9468770ce2/6a170c21509168bffee1bb14/25ff4c7e9563d99752f95540dafdc7fd211a66e3-800x530.gif" alt="Página do Claude 4.5 Sonnet, com respostas em rolagem que incluem os cinco documentos relevantes sobre métodos de autenticação e controle de acesso por função." /><p>Também é possível encadear várias ferramentas em uma única interação. Neste caso, o Claude Desktop analisa a pergunta do usuário e determina que precisa primeiro chamar <code>search_docs</code> para recuperar documentos relevantes e depois passar esses resultados para <code>summarize_and_cite</code> para gerar a resposta final, tudo isso sem exigir prompts separados do usuário:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta46ff45274e64192/6a170c230c4857a91501aac1/e6a8a46acb4236e77058f18bcd2f0737b5882c05-1999x1101.png" alt="Chat no Claude Desktop, com a observação &quot;Jeff está de volta&quot;, além de uma nova pergunta do usuário: &quot;Quais são as principais recomendações para melhorar a autenticação e o controle de acesso em nossos sistemas?&quot; Inclua referências.&quot;" /><p>Neste caso, para a consulta “<strong>Quais são as principais recomendações para melhorar a autenticação e o controle de acesso em nossos sistemas? Inclua referências.</strong>”, obtivemos os seguintes resultados:</p>Based on the documentation, here are the main recommendations to improve authentication and access control across your systems:

Key Recommendations

1. Implement Role-Based Access Control (RBAC)
Ensure users have only the permissions necessary for their job functions. This principle of least privilege minimizes security risks by limiting access to what's truly needed. [1]

2. Regular Access Audits
Conduct regular audits of user roles and promptly revoke access for inactive accounts. This helps prevent unauthorized access from dormant or compromised accounts. [1]

3. Just-in-Time (JIT) Access
Implement just-in-time access for sensitive operations, where permissions are granted only when needed and for a limited duration. This reduces the attack surface by minimizing standing privileges. [1]

4. OAuth 2.0 for Secure Authentication
Use OAuth 2.0 to enable secure delegated access without sharing user credentials. This protocol allows third-party applications to access resources on behalf of users without exposing passwords. [2]

5. Token Security and Management
Configure your identity provider to issue tokens with limited scope and lifetime

Store refresh tokens securely
Validate access tokens consistently to maintain security [2]
References

Access Control and Role Management (Tags: security, access-control)
User Authentication with OAuth 2.0 (Tags: authentication, oauth)
These recommendations work together to create a defense-in-depth approach, where multiple security layers protect your systems from unauthorized access.<p>Como na etapa anterior, podemos ver a resposta de cada ferramenta para esta pergunta:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8f633c518e708a99/6a170c25ab7f082991db9ed6/cb606d356b2f7d5e4878a5eff71bc881869ac0ee-800x585.gif" alt="Página de chat do Claude Desktop, com texto rolando que inclui a resposta de cada ferramenta para a pergunta: &quot;Quais são as principais recomendações para melhorar a autenticação e o controle de acesso em nossos sistemas? Inclua referências.&quot;" /><p><em>Nota: Se aparecer um submenu perguntando se você aprova o uso de cada ferramenta, selecione </em><em><strong>Permitir sempre</strong></em><em> ou </em><em><strong>Permitir uma vez</strong></em><em>.</em></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6627ee0bff1862df/6a170c266f7f040f6f91488c/aea942ba9b0037526ea215bec65690f1a5c3099c-1522x250.png" alt="Opções &quot;Sempre permitir&quot; e &quot;Permitir uma vez&quot; do Claude Desktop para o usuário escolher." /><h2>Conclusão</h2><p>Os servidores MCP representam um passo significativo rumo à padronização das ferramentas LLM para aplicações locais e remotas. Embora a compatibilidade total ainda esteja em andamento, estamos avançando nessa direção.</p><p>Neste artigo, aprendemos como criar um servidor MCP personalizado em TypeScript que conecta o Elasticsearch a aplicações baseadas em LLM. Nosso servidor expõe duas ferramentas: <code>search_docs</code> para recuperar documentos relevantes usando Query DSL; e <code>summarize_and_cite</code> para gerar resumos com citações via modelos OpenAI e Claude Desktop como UI.</p><p>O futuro da compatibilidade entre diferentes provedores de clientes e servidores parece promissor. As próximas etapas incluem adicionar mais funcionalidades e flexibilidade ao seu agente. Existe um <a href="https://www.elastic.co/search-labs/blog/llm-functions-elasticsearch-intelligent-query">artigo</a> prático sobre como parametrizar suas consultas usando modelos de pesquisa para ter precisão e flexibilidade.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/elastic-mcp-server-typescript-claude</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/elastic-mcp-server-typescript-claude</guid>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[Integrações]]></category>
    <dc:creator><![CDATA[Jeffrey Rengifo]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5600198cb47666a5/6a170c28509168ce3ae1bb18/0bb24c05fff391f42070c2883182ea6fe9cb9680-1280x720.png" length="0" type="image/png"/>
    <pubDate>Fri, 27 Mar 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Usando a API de Inferência Elasticsearch junto com modelos de Hugging Face]]></title>
    <description><![CDATA[Aprenda a conectar o Elasticsearch a modelos do Hugging Face usando endpoints de inferência e a construir um sistema multilíngue de recomendação de blogs com busca semântica e conclusões de chat.]]></description>
    <content:encoded><![CDATA[<p>Em atualizações recentes, o Elasticsearch introduziu uma integração nativa para conectar a modelos hospedados no <a href="https://endpoints.huggingface.co/">Hugging Face Inference Service</a>. Neste post, vamos explorar como configurar essa integração e realizar inferência por meio de chamadas simples de API usando um grande modelo de linguagem (LLM). Vamos usar <a href="https://huggingface.co/HuggingFaceTB/SmolLM3-3B">SmolLM3-3B</a>, um modelo leve de uso geral com bom equilíbrio entre uso de recursos e qualidade da resposta.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9094997548bd70f8/6a170d6a839dfa0ad6dcff54/7ddadf1976421a860a7d62087239adb9150d808b-1999x1388.png" alt="Gráfico de dispersão mostrando vários modelos de linguagem pequenos plotados pelo tamanho do modelo (em bilhões de parâmetros) no eixo x e a taxa de vitória (em porcentagem) no eixo y. O SmolLM3‑3B aparece no topo da tendência de eficiência, com uma taxa de vitória maior do que outros modelos de tamanho semelhante." /><h2>Pré-requisitos</h2><ul><li><p><strong>Elasticsearch 9.3 ou Elastic Cloud Serverless: </strong>você pode criar uma implantação na nuvem seguindo <a href="https://www.elastic.co/search-labs/tutorials/install-elasticsearch/elastic-cloud">essas instruções</a>, ou você pode usar o <a href="https://www.elastic.co/docs/deploy-manage/deploy/self-managed/local-development-installation-quickstart#local-dev-quick-start"><code>start-local</code></a> quickstart.</p></li><li><p><strong>Python 3.12: </strong>baixe o Python <a href="https://www.python.org/">aqui</a>.</p></li><li><p><strong>Hugging Face </strong><a href="https://huggingface.co/docs/hub/en/security-tokens">Token de acesso</a>.</p></li></ul><h2>Chat completions usando um endpoint de inferência do Hugging Face</h2><p>Primeiro, vamos construir um exemplo prático que conecta o Elasticsearch a um <a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put">endpoint de inferência</a> Hugging Face para gerar recomendações baseadas em IA a partir de uma coleção de artigos de blog. Para a base de conhecimento do app, usaremos um conjunto de dados de artigos de blog da empresa, que contém informações valiosas, mas frequentemente difíceis de navegar.</p><p>Com este endpoint, a <a href="https://www.elastic.co/docs/solutions/search/semantic-search">busca semântica</a> recupera os artigos mais relevantes para uma consulta específica, e um Hugging Face LLM gera recomendações curtas e contextuais com base nesses resultados.</p><p>Vamos dar uma olhada em uma visão geral do fluxo de informações que vamos criar:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf217b7b7db4e1e6c/6a170d6ca929cf8022ae0a3b/1dfbc2323438feaaa42e13ab242dd1f7166f74aa-1200x676.png" alt="Diagrama de fluxo mostrando um índice Elasticsearch que fornece resultados de busca semântica para um endpoint de inferência, que retorna recomendações de artigos." /><p>Neste artigo, testaremos a <strong>capacidade do SmolLM3-3B </strong>decombinar seu tamanho compacto com fortes capacidades de raciocínio multíngue e chamada de ferramentas. Com base em uma consulta de busca, enviaremos todo o conteúdo correspondente (em inglês e espanhol) para o LLM para gerar uma lista de artigos recomendados com uma descrição personalizada com base na consulta de busca e nos resultados.</p><p>Veja como poderia ser a UI de um site de artigos com um sistema de geração de recomendações por IA.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt20e69b9a06fecd65/6a170d6e839dfa6f97dcff58/8d3b86b212f28ff279f2da67a33e6134039f0e4e-1999x949.png" alt="UI de um site de artigos com um sistema de geração de recomendações por IA, listando três exemplos, com texto em inglês e títulos em inglês ou espanhol." /><p>Você pode encontrar a implementação completa desta aplicação no <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/elasticsearch-inference-api-and-hugging-face/notebook.ipynb">notebook</a> vinculado.</p><h3>Configuração de endpoints de inferência do Elasticsearch</h3><p>Para usar o <a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-hugging-face">endpoint de inferência do Hugging Face</a> no Elasticsearch, precisamos de dois elementos importantes: uma chave de API do Hugging Face e uma URL de endpoint do Hugging Face em execução. Ela deverá ficar assim:</p>PUT _inference/chat_completions/hugging-face-smollm3-3b
{
    "service": "hugging_face",
    "service_settings": {
        "api_key": "hugging-face-access-token", 
        "url": "url-endpoint" 
    }
}<p>O endpoint de inferência Hugging Face no Elasticsearch permite diferentes tipos de tarefas: <code>text_embedding</code>, <code>completion</code>, <code>chat_completion</code>, e <code>rerank</code>. Neste post do blog, usamos <code>chat_completion</code> porque precisamos que o modelo gere recomendações conversacionais baseadas nos resultados de busca e em um prompt do sistema. Esse endpoint nos permite realizar preenchimentos de chat diretamente do Elasticsearch de forma simples usando a API do Elasticsearch:</p>POST _inference/chat_completion/hugging-face-smollm3-3b/_stream
{
  "messages": [
      { "role": "user", "content": "&lt;user prompt&gt;" }
  ]
}<p>Isso servirá como o núcleo da aplicação, recebendo o prompt e os resultados de busca que passarão pelo modelo. Com a teoria explicada, vamos começar a implementar a aplicação.</p><h4>Configurando o endpoint de inferência no Hugging Face</h4><p>Para implantar o modelo Hugging Face, vamos usar <a href="https://huggingface.co/inference-endpoints/dedicated">implantações Hugging Face One-Click</a>, um serviço fácil e rápido para implantar endpoints de modelos. Lembre-se de que este é um serviço pago, e seu uso pode incorrer em custos adicionais. Esta etapa criará a instância do modelo que será usada para gerar as recomendações dos artigos.</p><p>Você pode escolher um modelo do catálogo de um clique.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta7bdfa43d6766324/6a170d6fb339d59e5476a039/b816e9fba1fe172687bf58f5143fb1f838c1077f-549x331.png" alt="Exibição da interface de um catálogo de modelos filtrado para &quot;smoll3&quot;, mostrando um modelo chamado &quot;smollm3‑3b&quot; com geração de texto, vLLM, GPU 1× Nvidia L4 e um preço listado de US$ 0,80, além de uma nota sugerindo que você amplie a busca para todos os modelos de Hugging Face." /><p>Vamos escolher o modelo <strong>SmolLM3-3B</strong> :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdb0a2e6ffd7deb20/6a170d710c48574b7401aafc/610d3aba0429f3666c2df3616d513eb6a4397c0c-502x478.png" alt="Interface para criar um endpoint para o modelo SmolLM3‑3B, mostrando o nome do modelo, uma nota &quot;verified by Hugging Face&quot;, um campo de nome de endpoint, um custo de US$ 0,80 por hora por réplica em execução, uma opção cURL e um botão &quot;Create Endpoint&quot;." /><p>A partir daqui, pegue o URL do endpoint do Hugging Face:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt25714021711ed6ff/6a170d72c1e8a54853f88336/025094ddb2cfbd1f0f216a5ec4e119b0f4fa2c42-646x328.png" alt="Visualização do **dashboard** de um endpoint de inferência Hugging Face chamado &quot;smollm3‑3b‑pnz&quot;, mostrando um status verde de execução, uma réplica ativa, zero solicitações na última hora, guias de navegação e o URL do endpoint exibido." /><p>Como mencionado na <a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-hugging-face">documentação de endpoints de inferência Hugging Face do Elasticsearch</a>, a geração de texto requer um modelo compatível com a API OpenAI. Por esse motivo, precisamos anexar o subcaminho <code>/v1/chat/completions</code> à URL do endpoint Hugging Face. O resultado final ficará assim:</p>https://j2g31h0futopfkli.us-east-1.aws.endpoints.huggingface.cloud/v1/chat/completions<p>Com isso pronto, podemos começar a programar em um notebook Python.</p><h4>Gerando a Chave API do Hugging Face</h4><p>Crie uma <a href="https://huggingface.co/join">conta Hugging Face</a> e obtenha um token de API seguindo <a href="https://huggingface.co/docs/hub/en/security-tokens#user-access-tokens">estas instruções</a>. Você pode escolher entre três tipos de token: <em>detalhado</em> (recomendado para produção, pois fornece acesso apenas a recursos específicos); <em>de leitura</em> (para acesso somente leitura); ou <em>de gravação</em> (para acesso de leitura e gravação). Para este tutorial, um token de leitura é suficiente, já que só precisamos chamar o endpoint de inferência. Guarde esta chave para o próximo passo.</p><h4>Configurando o endpoint de inferência do Elasticsearch</h4><p>Primeiro, vamos declarar um cliente Elasticsearch Python:</p>os.environ["ELASTICSEARCH_API_KEY"] = "your-elasticsearch-api-key"
os.environ["ELASTICSEARCH_URL"] = "https://xxxx.us-central1.gcp.cloud.es.io:443"

es_client = Elasticsearch(
    os.environ["ELASTICSEARCH_URL"], api_key=os.environ["ELASTICSEARCH_API_KEY"]
)<p>Em seguida, vamos criar um endpoint de inferência no Elasticsearch que use o modelo Hugging Face. Esse endpoint nos permitirá gerar respostas com base nos posts do blog e no prompt passado para o modelo.</p>INFERENCE_ENDPOINT_ID = "smollm3-3b-pnz"

os.environ["HUGGING_FACE_INFERENCE_ENDPOINT_URL"] = (
 "https://j2g31h0futopfkli.us-east-1.aws.endpoints.huggingface.cloud/v1/chat/completions"
)
os.environ["HUGGING_FACE_API_KEY"] = "hf_xxxxx"

resp = es_client.inference.put(
        task_type="chat_completion",
        inference_id=INFERENCE_ENDPOINT_ID,
        body={
            "service": "hugging_face",
            "service_settings": {
                "api_key": os.environ["HUGGING_FACE_API_KEY"],
                "url": os.environ["HUGGING_FACE_INFERENCE_ENDPOINT_URL"],
            },
        },
    )<h3>Conjunto de dados</h3><p>O conjunto de dados contém os <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/elasticsearch-inference-api-and-hugging-face/dataset.json">posts do blog</a> que serão consultados, representando um conjunto de conteúdo multilíngue usado em todo o fluxo de trabalho:</p>// Articles dataset document example: 
{
    "id": "6",
    "title": "Complete guide to the new API: Endpoints and examples",
    "author": "Tomas Hernandez",
    "date": "2025-11-06",
    "category": "tutorial",
    "content": "This guide describes in detail all endpoints of the new API v2. It includes code examples in Python, JavaScript, and cURL for each endpoint. We cover authentication, resource creation, queries, updates, and deletion. We also explain error handling, rate limiting, and best practices. Complete documentation is available on our developer portal."
  }<h4>Mapeamento do Elasticsearch</h4><p>Com o conjunto de dados definido, precisamos criar um esquema de dados que se ajuste adequadamente à estrutura do post do blog. Os seguintes <a href="https://www.elastic.co/docs/manage-data/data-store/mapping">mapeamentos de índice</a> serão usados para armazenar os dados no Elasticsearch:</p>INDEX_NAME = "blog-posts"

mapping = {
    "mappings": {
        "properties": {
            "id": {"type": "keyword"},
            "title": {
                "type": "object",
                "properties": {
                    "original": {
                        "type": "text",
                        "copy_to": "semantic_field",
                        "fields": {"keyword": {"type": "keyword"}},
                    },
                    "translated_title": {
                        "type": "text",
                        "fields": {"keyword": {"type": "keyword"}},
                    },
                },
            },
            "author": {"type": "keyword", "copy_to": "semantic_field"},
            "category": {"type": "keyword", "copy_to": "semantic_field"},
            "content": {"type": "text", "copy_to": "semantic_field"},
            "date": {"type": "date"},
            "semantic_field": {"type": "semantic_text"},
        }
    }
}


es_client.indices.create(index=INDEX_NAME, body=mapping)<p>Aqui, podemos ver com mais clareza como os dados são estruturados. Usaremos busca semântica para recuperar resultados baseados em linguagem natural, junto com a propriedade <a href="https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/copy-to"><code>copy_to</code></a> para copiar o conteúdo do campo para o campo <a href="https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/semantic-text"><code>semantic_text</code></a>. Além disso, o campo <code>title</code> contém dois subcampos: o subcampo <code>original</code> armazena o título em inglês ou espanhol, dependendo do idioma original do artigo; e o subcampo <code>translated_title</code> está presente apenas para artigos em espanhol e contém a tradução para o inglês do título original.</p><h3>Ingestão de dados</h3><p>O seguinte trecho de código ingere o conjunto de dados de postagens do blog no Elasticsearch usando a <a href="https://www.elastic.co/docs/reference/elasticsearch/clients/javascript/bulk_examples">bulk API</a>:</p>def build_data(json_file, index_name):
    with open(json_file, "r") as f:
        data = json.load(f)

    for doc in data:
        action = {"_index": index_name, "_source": doc}
        yield action


try:
    success, failed = helpers.bulk(
        es_client,
        build_data("dataset.json", INDEX_NAME),
    )
    print(f"{success} documents indexed successfully")

    if failed:
        print(f"Errors: {failed}")
except Exception as e:
    print(f"Error: {str(e)}")<p>Agora que os artigos já estão no Elasticsearch, precisamos criar uma função capaz de buscar no campo <code>semantic_text</code>:</p>def perform_semantic_search(query_text, index_name=INDEX_NAME, size=5):
    try:
        query = {
            "query": {
                "match": {
                    "semantic_field": {
                        "query": query_text,
                    }
                }
            },
            "size": size,
        }

        response = es_client.search(index=index_name, body=query)
        hits = response["hits"]["hits"]

        return hits
    except Exception as e:
        print(f"Semantic search error: {str(e)}")
        return []<p>Precisamos também de uma função que chame o endpoint de inferência. Neste caso, chamaremos o endpoint usando <strong><code>chat_completion</code></strong>tipo de tarefa para obter respostas de streaming:</p>def stream_chat_completion(messages: list, inference_id: str = INFERENCE_ENDPOINT_ID):
    url = f"{ELASTICSEARCH_URL}/_inference/chat_completion/{inference_id}/_stream"
    payload = {"messages": messages}
    headers = {
        "Authorization": f"ApiKey {ELASTICSEARCH_API_KEY}",
        "Content-Type": "application/json",
    }

    try:
        response = requests.post(url, json=payload, headers=headers, stream=True)
        response.raise_for_status()

        for line in response.iter_lines(decode_unicode=True):
            if line:
                line = line.strip()

                if line.startswith("event:"):
                    continue

                if line.startswith("data: "):
                    data_content = line[6:]

                    if not data_content.strip() or data_content.strip() == "[DONE]":
                        continue

                    try:
                        chunk_data = json.loads(data_content)

                        if "choices" in chunk_data and len(chunk_data["choices"]) &gt; 0:
                            choice = chunk_data["choices"][0]
                            if "delta" in choice and "content" in choice["delta"]:
                                content = choice["delta"]["content"]
                                if content:
                                    yield content

                    except json.JSONDecodeError as json_err:
                        print(f"\nJSON decode error: {json_err}")
                        print(f"Problematic data: {data_content}")
                        continue

    except requests.exceptions.RequestException as e:
        yield f"Error: {str(e)}"<p>Agora podemos escrever uma função que chama a função de busca semântica, junto com o endpoint de inferência <code>chat_completions</code> e o endpoint de recomendações, para gerar os dados que serão alocados nos cartões:</p>def recommend_articles(search_query, index_name=INDEX_NAME, max_articles=5):
    print(f"\n{'='*80}")
    print(f"🔍 Search Query: {search_query}")
    print(f"{'='*80}\n")

    articles = perform_semantic_search(search_query, index_name, size=max_articles)

    if not articles:
        print("❌ No relevant articles found.")
        return None, None

    print(f"✅ Found {len(articles)} relevant articles\n")

    # Build context with found articles
    context = "Available blog articles:\n\n"
    for i, article in enumerate(articles, 1):
        source = article.get("_source", article)
        context += f"Article {i}:\n"
        context += f"- Title: {source.get('title', 'N/A')}\n"
        context += f"- Author: {source.get('author', 'N/A')}\n"
        context += f"- Category: {source.get('category', 'N/A')}\n"
        context += f"- Date: {source.get('date', 'N/A')}\n"
        context += f"- Content: {source.get('content', 'N/A')}\n\n"

    system_prompt = """You are an expert content curator that recommends blog articles.

    Write recommendations in a conversational style starting with phrases like:
    - "If you're interested in [topic], this article..."
    - "This post complements your search with..."
    - "For those looking into [topic], this article provides..."


    FORMAT REQUIREMENTS:
    - Return ONLY a JSON array
    - Each element must have EXACTLY these three fields: "article_number", "title", "recommendation"
    - If the original title is in spanish, use the "translated_title" subfield in the "title" field

    Keep each recommendation concise (2-3 sentences max) and focused on VALUE to the reader.

    EXAMPLE OF CORRECT FORMAT:
    [
        {"article_number": 1, "title": "Article title in english", "recommendation": "If you are interested in [topic], this article provides..."},
        {"article_number": 2, "title": "Article title in english", "recommendation": " for those looking into [topic], this article provides..."}
    ]

    Return ONLY the JSON array following this exact structure."""

    user_prompt = f"""Search query: "{search_query}"

    Generate recommendations for the following articles: {context}
    """

    messages = [
        {"role": "system", "content": "/no_think"},
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": user_prompt},
    ]

    # LLM generation
    print(f"{'='*80}")
    print("🤖 Generating personalized recommendations...\n")

    full_response = ""

    for chunk in stream_chat_completion(messages):
        print(chunk, end="", flush=True)
        full_response += chunk

    return context, articles, full_response<p>Finalmente, precisamos extrair as informações e formatá-las para serem impressas:</p>def display_recommendation_cards(articles, recommendations_text):
    print("\n" + "=" * 100)
    print("📇 RECOMMENDED ARTICLES".center(100))
    print("=" * 100 + "\n")

    # Parse JSON recommendations - clean tags and extract JSON
    recommendations_list = []
    try:

        # Clean up &lt;think&gt; tags
        cleaned_text = re.sub(
            r"&lt;think&gt;.*?&lt;/think&gt;", "", recommendations_text, flags=re.DOTALL
        )
        # Remove markdown code blocks ( ... ``` or ``` ... ```)
        cleaned_text = re.sub(r"```(?:json)?", "", cleaned_text)
        cleaned_text = cleaned_text.strip()

        parsed = json.loads(cleaned_text)

        # Extract recommendations from list format
        for item in parsed:
            article_number = item.get("article_number")
            title = item.get("title", "")
            rec_text = item.get("recommendation", "")

            if article_number and rec_text:
                recommendations_list.append(
                    {
                        "article_number": article_number,
                        "title": title,
                        "recommendation": rec_text,
                    }
                )
    except json.JSONDecodeError as e:
        print(f"⚠️  Could not parse recommendations as JSON: {e}")
        return

    for i, article in enumerate(articles, 1):
        source = article.get("_source", article)

        # Card border
        print("┌" + "─" * 98 + "┐")

        # Find recommendation and title for this article number
        recommendation = None
        title = None
        for rec in recommendations_list:
            if rec.get("article_number") == i:
                recommendation = rec.get("recommendation")
                title = rec.get("title")
                break

        # Print title
        title_lines = textwrap.wrap(f"📌 {title}", width=94)
        for line in title_lines:
            print(f"│  {line}".ljust(99) + "│")

        # Card border
        print("├" + "─" * 98 + "┤")

        # Print recommendation
        if recommendation:
            recommendation_lines = textwrap.wrap(recommendation, width=94)
            for line in recommendation_lines:
                print(f"│  {line}".ljust(99) + "│")

        # Card bottom
        print("└" + "─" * 98 + "┘")<p>Vamos testar isso fazendo uma pergunta sobre as postagens do blog de segurança:</p>search_query = "Security and vulnerabilities"

context, articles, recommendations = recommend_articles(search_query)

print("\nElasticsearch context:\n", context)

# Display visual cards
display_recommendation_cards(articles, recommendations)<p>Aqui podemos ver os cartões no console gerados pelo fluxo de trabalho:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4aa221a08a51aeb3/6a170d7460084be1413c45d6/730d35212594bb3db30447c3ea7e2a92857287b7-1999x1515.png" alt="Seção intitulada &quot;Artigos Recomendados&quot; apresenta cinco resumos de artigos em caixa, incluindo tópicos sobre vulnerabilidade no sistema de autenticação, riscos de migração, desempenho da REST API v2 e melhorias na autenticação, mudanças no sistema de notificações e um guia completo para a nova API." /><p>Você pode ver os resultados completos, incluindo todos os acertos e a resposta do LLM, <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/elasticsearch-inference-api-and-hugging-face/results.md">neste arquivo</a>.</p><p>Estamos pedindo artigos relacionados a: "Segurança e vulnerabilidades." Esta pergunta é usada como consulta de busca nos documentos armazenados no Elasticsearch. Os resultados recuperados são então passados para o modelo, que gera recomendações com base em seu conteúdo. Como podemos ver, o modelo fez um ótimo trabalho criando textos curtos envolventes que podem motivar o leitor a clicar.</p><h2>Conclusão</h2><p>Este exemplo mostra como Elasticsearch e Hugging Face podem ser combinados para criar um sistema centralizado rápido e eficiente para aplicações de IA. Essa abordagem reduz o esforço manual e oferece flexibilidade, graças ao extenso catálogo de modelos da Hugging Face. O uso do SmolLM3-3B, em particular, demonstra como modelos compactos e multilíngues ainda podem fornecer raciocínio significativo e geração de conteúdo quando combinados com busca semântica. Juntas, essas ferramentas oferecem uma base escalável e eficaz para construir análises inteligentes de conteúdo e aplicações multilíngues.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/hugging-face-elasticsearch-inference-api</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/hugging-face-elasticsearch-inference-api</guid>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[Integrações]]></category>
    <dc:creator><![CDATA[Jeffrey Rengifo]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5f961af4cb26ec97/6a170d767d8d6790c770e790/1417d6ff033712206c9bd4bcc22074ee3437ce96-1999x1125.png" length="0" type="image/png"/>
    <pubDate>Mon, 23 Mar 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[A extensão Gemini CLI para Elasticsearch com ferramentas e recursos]]></title>
    <description><![CDATA[Apresentamos a extensão da Elastic para a CLI Gemini do Google, que permite buscar, extrair e analisar dados do Elasticsearch em fluxos de trabalho de desenvolvedores e agentes.
]]></description>
    <content:encoded><![CDATA[<p>Temos a satisfação de anunciar o lançamento da nossa extensão Elastic para a Gemini CLI do Google, trazendo toda a eficiência da <a href="https://www.elastic.co/elasticsearch">Elasticsearch</a> e <a href="https://www.elastic.co/elasticsearch/agent-builder">Elastic Agent Builder</a> diretamente para o seu fluxo de trabalho de desenvolvimento de IA. Essa extensão também oferece várias habilidades de agente recentemente desenvolvidas para interagir com o Elasticsearch.</p><p>A extensão está disponível como um projeto open source <a href="https://github.com/elastic/gemini-cli-elasticsearch">aqui</a>.</p><h2>O que é a Gemini CLI e como você a instala?</h2><p><a href="https://geminicli.com/">Gemini CLI</a> é um agente de IA open source que traz os modelos Gemini do Google diretamente para a linha de comando. Ele permite que os desenvolvedores interajam com a IA a partir do terminal para realizar tarefas como gerar código, editar arquivos, executar comandos do shell e recuperar informações da web.</p><p>Diferentemente das interfaces típicas de chat, a Gemini CLI se integra ao seu ambiente local de desenvolvimento, o que significa que ela pode entender o contexto do projeto, modificar arquivos, executar builds ou testes e automatizar fluxos de trabalho diretamente no terminal. Isso a torna útil para desenvolvedores, engenheiros de confiabilidade de sites (SREs) e outros profissionais que desejam codificação e automação assistidas por IA sem sair do fluxo de trabalho da linha de comando.</p><p>Você pode instalar a Gemini CLI usando vários gerenciadores de pacotes. O método mais comum é usar o npm:</p>npm install -g @google/gemini-cli<p>Para conhecer opções alternativas de instalação, consulte a <a href="https://geminicli.com/docs/get-started/installation/">página oficial de instalação</a>.</p><p>Após a instalação, inicie a CLI executando:</p>gemini<p>Você vê uma tela, conforme mostrado na Figura 1:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4ff43abe550941b4/6a17072ba29299fc2ad00fa4/6dfcec4a77b3dc83bf0d974417bf2e211abb1f4f-876x468.png" alt="Uma captura de tela da Gemini CLI." /><h2>Configurar o Elasticsearch</h2><p>Precisamos ter uma instância do Elasticsearch em execução. Se quiser usar o servidor MCP (Model Context Protocol), você também precisará ter o Kibana 9.3+ instalado. Para usar a habilidade da Elasticsearch linguagem de consulta (ES|QL) (<code>esql</code>) descrita abaixo, o Kibana não é necessário.</p><p>Você pode ativar um teste gratuito no <a href="https://www.elastic.co/cloud">Elastic Cloud</a> ou instalá-lo localmente usando o script <a href="https://github.com/elastic/start-local"><code>start-local</code></a> :</p>curl -fsSL https://elastic.co/start-local | sh<p>Isso instalará o Elasticsearch e o Kibana no seu computador e gerará uma chave API para ser usada na configuração da Gemini CLI.</p><p>A chave API será mostrada como saída do comando anterior e armazenada em um <strong>.env</strong> arquivo na pasta <strong><code>elastic-start-local</code></strong>.</p><p>Se você está usando o Elasticsearch no local (por exemplo, usando <code>start-local</code>), e quer usar o Elastic Agent Builder com MCP, também precisa conectar um grande modelo de linguagem (LLM). Você pode ler <a href="https://www.elastic.co/docs/explore-analyze/ai-features/llm-guides/llm-connectors">esta página de documentação</a> para entender as diferentes opções.</p><p>Se você estiver usando o Elastic Cloud (ou serverless), já tem uma conexão LLM pré-configurada.</p><h2>Instale a extensão do Elasticsearch</h2><p>Você pode instalar a extensão Elasticsearch para Gemini CLI com o seguinte comando:</p>gemini extensions install https://github.com/elastic/gemini-cli-elasticsearch<p>Você pode verificar se as extensões foram instaladas com sucesso abrindo o Gemini e executando o seguinte comando:</p>/extensions list<p>Você deverá ver a extensão Elasticsearch disponível.</p><p>Se quiser usar a integração MCP, precisa ter uma versão do Elasticsearch 9.3+ instalada. Você precisa da URL do seu servidor MCP do <a href="https://www.elastic.co/kibana">Kibana</a>:</p><ul><li><p>Obtenha a URL do seu servidor MCP em Agents &gt; View all tools &gt; Manage MCP &gt; Copy MCP Server URL (Agentes &gt; Ver todas as ferramentas &gt; Gerenciar MCP &gt; Copiar URL do Servidor MCP).</p></li><li><p>A URL ficará assim: https://your-kibana-instance/api/agent_builder/mcp</p></li></ul><p>Você precisa da URL do endpoint do Elasticsearch. Isso normalmente é relatado no topo da página do Kibana Elasticsearch. Se você está rodando o Elasticsearch com <code>start-local</code>, você já tem o endpoint na chave <code>ES_LOCAL_URL</code> no <code>start-local</code> .env. arquivo.</p><p>Também é necessário uma chave de API. Se estiver executando o Elasticsearch com <code>start-local</code>, você já tem a <code>ES_LOCAL_API_KEY</code> no arquivo<code>start-local</code> .env arquivo. Caso contrário, é possível criar uma chave de API usando a interface do Kibana, conforme <a href="https://www.elastic.co/docs/deploy-manage/api-keys/elasticsearch-api-keys">indicado aqui</a>:</p><ul><li><p>No Kibana: Stack Management &gt; Security &gt; API Keys &gt; Create API Key (Stack management &gt; Segurança &gt; Chaves de API &gt; Criar chave de API) .</p></li><li><p>Sugerimos definir apenas os privilégios de leitura para a chave API, habilitando o privilégio <code>feature_agentBuilder.read</code> conforme <a href="https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/permissions#grant-access-with-roles">reportado aqui</a>.</p></li><li><p>Copie o valor da chave de API codificada.</p></li></ul><p>Defina as variáveis de ambiente necessárias no seu shell:</p>export ELASTIC_URL="your-elasticsearch-url"
export ELASTIC_MCP_URL="your-elasticsearch-mcp-url"
export ELASTIC_API_KEY="your-encoded-api-key"<h2>Instale o conjunto de dados de exemplo</h2><p>Você pode instalar o conjunto de dados de <strong>pedidos de comércio eletrônico </strong>disponível no Kibana. Inclui um único índice chamado <strong><code>kibana_sample_data_ecommerce</code></strong>, contendo informações sobre 4.675 pedidos de um website. Para cada pedido, temos as seguintes informações:</p><ul><li><p>Informações do cliente (nome, ID, data de nascimento, e-mail e mais).</p></li><li><p>Data do pedido.</p></li><li><p>ID do pedido.</p></li><li><p>Produtos (lista de todos os produtos com preço, quantidade, ID, categoria, desconto e outros detalhes).</p></li><li><p>SKU.</p></li><li><p>Preço total (sem impostos, com impostos).</p></li><li><p>Quantidade total.</p></li><li><p>Informações geográficas (cidade, país, continente, localização, região).</p></li></ul><p>Para instalar os dados de exemplo, abra a página <strong>Integrações</strong> no Kibana (busque por “Integração” na barra de busca superior) e instale os <strong>Dados de Exemplo</strong>. Para mais detalhes, consulte a <a href="https://www.elastic.co/docs/explore-analyze/#gs-get-data-into-kibana">documentação aqui</a>.</p><p>O objetivo deste artigo é mostrar como é fácil configurar o Gemini CLI para se conectar ao Elasticsearch e interagir com o índice <strong><code>kibana_sample_data_ecommerce</code></strong>.</p><h2>Como usar o Elasticsearch MCP</h2><p>Você pode verificar a conexão usando o seguinte comando no Gemini:</p>/mcp list<p>Você deve ver o <strong><code>elastic-agent-builder</code></strong> ativado, como mostrado na Figura 2:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt52b85e7255360f3b/6a17072da929cf33d3ae08f5/1508423bc1d1bc3c04a1cb01e2d59495a3516ed1-1465x844.png" alt="O servidor MCP 'elastic-agent-builder' com a lista de ferramentas." /><p>O Elasticsearch fornece um conjunto padrão de ferramentas. Veja a descrição <a href="https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/tools/builtin-tools-reference">aqui</a>.</p><p>Usando essas ferramentas, você pode interagir com o Elasticsearch, fazendo perguntas como:</p><ul><li><p><code>Give me the list of all the indexes available in Elasticsearch.</code></p></li><li><p><code>How many customers are based in the USA in the kibana_sample_data_ecommerce index of Elasticsearch?</code></p></li></ul><p>Dependendo da pergunta, o Gemini usará uma ou mais ferramentas disponíveis para tentar respondê-la.</p><h2>Os comandos /elastic</h2><p>Na extensão Elasticsearch para Gemini CLI, também adicionamos<strong><code>/elastic</code></strong> comandos.</p><p>Se você executar o comando <strong><code>/help</code></strong>, verá todas as opções de <code>/elastic</code> disponíveis (Figura 3):</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt741c7451ecab10d2/6a17072ea6c2b9ccd6e79643/5b2a0727ce7a04354878dd048253d3f4d062324b-1983x230.png" alt="Os comandos '/elastic' disponíveis." /><p>Esses comandos podem ser úteis se você quiser executar diretamente uma ferramenta específica do servidor MCP.<code>elastic-agent-builder</code>  Por exemplo, usando o seguinte comando, você pode obter o mapeamento do <code>kibana_sample_data_ecommerce</code>:</p>/elastic:get-mapping kibana_sample_data_ecommerce<p>Esses comandos são essencialmente atalhos para executar ferramentas específicas, em vez de depender do modelo Gemini para determinar qual ferramenta deve ser usada.</p><h2>Como usar as habilidades do Elasticsearch</h2><p>Essa extensão também inclui uma <a href="https://github.com/elastic/gemini-cli-elasticsearch/tree/main/skills/esql">habilidade de agente para o ES|QL</a>, a <a href="https://www.elastic.co/docs/explore-analyze/discover/try-esql">Linguagem de Consulta Elasticsearch</a> disponível no Elasticsearch. <a href="https://agentskills.io/home">Agent Skills</a> é um formato aberto que fornece aos agentes de programação de IA, como o Gemini CLI, instruções personalizadas para tarefas específicas. Eles utilizam um conceito chamado <em>divulgação progressiva</em>, o que significa que apenas uma breve descrição da habilidade é adicionada ao prompt inicial do sistema. Quando você solicita que o agente execute uma tarefa, como consultar o Elasticsearch, ele associa a solicitação à habilidade relevante e carrega dinamicamente as instruções detalhadas. Essa é uma forma eficiente de gerenciar orçamentos de tokens enquanto fornece à IA exatamente o contexto que ela precisa.</p><p>A<strong> habilidade</strong> <strong><code>esql</code></strong>foi projetada para permitir que o Gemini CLI escreva e execute consultas ES|QL diretamente no seu cluster. ES|QL é uma poderosa linguagem de consulta encadeada que torna a exploração de dados, a análise de logs e as agregações altamente intuitivas. Com essa habilidade ativada, você não precisa pesquisar a sintaxe ES|QL; basta fazer perguntas em linguagem natural ao Gemini CLI sobre seus dados e o agente cuidará do resto.</p><p>As execuções são realizadas usando simples comandos <a href="https://curl.se/">curl</a> executados em um terminal. Isso é possível porque o Elasticsearch oferece um conjunto abrangente de APIs REST que podem ser facilmente usadas para integrar o sistema a qualquer arquitetura.</p><p><strong>O que a </strong><strong> habilidadeesqloferece:</strong></p><ul><li><p><strong>Descoberta de índices e esquemas:</strong> o agente pode usar as ferramentas integradas da habilidade para listar os índices disponíveis e buscar mapeamentos de campo. Por exemplo, antes de escrever uma consulta para o conjunto de dados de comércio eletrônico, o agente pode executar uma verificação de esquema em <strong><code>kibana_sample_data_ecommerce</code></strong> para entender os campos disponíveis, como <strong><code>taxful_total_price</code></strong> ou <strong><code>category</code></strong>.</p></li><li><p><strong>Tradução perfeita da linguagem natural:</strong> a habilidade dá ao agente mais do que um simples manual de referência; ela fornece um guia específico para interpretar a intenção do usuário. Quando você digita solicitações em linguagem natural, como "Mostrar tempo médio de resposta agrupado por serviço", o agente usa o padrão de correspondência da habilidade para traduzir instantaneamente suas palavras nas agregações, filtros e comandos ES|QL corretos.</p></li><li><p><strong>Autocorreção:</strong> Se uma consulta falhar (por exemplo, devido a uma incompatibilidade de tipo ou erro de sintaxe), a skill retorna a consulta gerada juntamente com a mensagem de erro exata do Elasticsearch, permitindo que o agente corrija instantaneamente a consulta e tente novamente sem que você precise intervir.</p></li></ul><p>Como a habilidade <code>esql</code> também está disponível como ferramenta no servidor MCP <code>elastic-agent-builder</code>, precisamos desativar esse servidor momentaneamente. Você pode usar o seguinte comando para desativá-lo:</p>/mcp disable elastic-agent-builder<p>Em seguida, você pode simplesmente digitar um prompt como esse em sua Gemini CLI:</p>Find the top 5 product categories by total sales revenue in the kibana_sample_data_ecommerce index<p>O agente irá:</p><ul><li><p>Reconheça a necessidade da habilidade <code>esql</code> .</p></li><li><p>Verifique o esquema do <strong><code>kibana_sample_data_ecommerce</code></strong>.</p></li><li><p>Crie uma consulta ES|QL, como: <code>FROM kibana_sample_data_ecommerce | STATS total_revenue = SUM(taxful_total_price) BY category.keyword | SORT total_revenue DESC | LIMIT 5</code>.</p></li><li><p>Execute a consulta na API do Elasticsearch.</p></li><li><p>Apresente a resposta final para você diretamente no terminal.</p></li></ul><p>Aqui, apresentamos um exemplo de resposta do Gemini ao prompt anterior:</p>───────────────────────────────────────────────────────────
&gt; Find the top 5 product categories by total sales revenue in the kibana_sample_data_ecommerce index   ───────────────────────────────────────────────────────────
✓  Activate Skill "esql": Interact with Elasticsearch using ES|QL and curl. Use when querying, managing indices,  …
Skill esql activated. Resources loaded from /home/user/.gemini/extensions/elasticsearch/skills/esql: 
Showing up to 200 items (files + folders).                                                                     /home/user/.gemini/extensions/elasticsearch/skills/esql/                                                            ├───SKILL.md 
└───references/
├───esql-reference.md 
├───generation-tips.md 
└───query-patterns.md

✦ I will start by exploring the mapping of the kibana_sample_data_ecommerce index to identify the fields for product category and sales revenue. Then, I will construct and execute an ES|QL query to determine the top 5 product categories by total sales revenue.

✓  Shell curl -s "${ELASTIC_URL%/}/kibana_sample_data_ecommerce/_mapping" -H "Authorization: ApiKey $(printenv ELAS…                                                                                                                       {  
   "kibana_sample_data_ecommerce": { 
     "mappings": { 
       "properties": {
         "category": { 
           "type": "text", 
           "fields": {
             "keyword": {
               "type": "keyword"
             }
           }
         }, 
         "currency": {
           "type": "keyword"
         }, 

✦ Okay, I have the mapping. The category is products.category.keyword and sales revenue is taxful_total_price. I'll now execute the ES|QL query to get the top 5 categories by revenue.

✓  Shell curl -s -X POST "${ELASTIC_URL%/}/_query" \  -H "Authorization: ApiKey $(printenv ELASTIC_API_KEY)" \  -H …
{ 
   "took": 62,
   "is_partial": false, 
   "completion_time_in_millis": 1772805644164,
   "documents_found": 4675,
   "values_loaded": 12084, 
   "start_time_in_millis": 1772805644102, 
   "expiration_time_in_millis": 1773237644087,  
   "columns": [ 
     { 
       "name": "total_revenue",    
       "type": "double"  
     }, 
     {   
       "name": "products.category.keyword",

✦ The query for top 5 product categories by revenue was successful. I'll format the returned JSON values into a   user-friendly list.

 ✓  Shell 
                             
 Top 5 product categories by total sales revenue: 
 1. Men's Clothing: 149393.91
 2. Women's Clothing: 135099.91
 3. Women's Shoes: 105479.17
 4. Men's Shoes: 91797.92
 5. Women's Accessories: 60830.31 

✦ I've found the answer; now I'll format it for clarity.

 ✓  Shell 

 Here are the top 5 product categories by total sales revenue:                                                        
                                                                      
 | Rank | Category              | Total Revenue | 
 |------|-----------------------|---------------| 
 | 1    | Men's Clothing        | 149,393.91    |
 | 2    | Women's Clothing      | 135,099.91    |
 | 3    | Women's Shoes         | 105,479.17    |
 | 4    | Men's Shoes           | 91,797.92     | 
 | 5    | Women's Accessories   | 60,830.31     | 

✦ I've formatted and presented the answer. I'm finished.
 ───────────────────────────────────────────────────────────<p>É interessante notar como o modelo Gemini gera a resposta final mostrando todos os passos que ele segue. Aqui, você pode ver claramente a influência da habilidade no processo de raciocínio do modelo. Na primeira vez que o modelo reconhece que precisa usar uma habilidade ou executar um comando shell, ele solicita permissão usando a abordagem baseada em intervenção humana.</p><p>Ao lidar com o trabalho pesado de descoberta de esquema, geração de consultas e execução, a habilidade <code>esql</code> permite que você se concentre inteiramente nas respostas, em vez da mecânica de obtê-las. Você obterá os dados de que precisa, formatados corretamente e diretamente no seu terminal, tudo isso sem precisar escrever uma única linha de código ou alternar para outro aplicativo.</p><h2>Conclusão</h2><p>Neste artigo, apresentamos a extensão Elasticsearch para Gemini CLI que lançamos recentemente. Essa extensão oferece a você a capacidade de interagir com a instância do Elasticsearch usando o Gemini e o servidor Elasticsearch MCP fornecido pelo Elastic Agent Builder, disponível a partir da versão 9.3.0, bem como o comando <code>/elastic</code>.</p><p>Além disso, a extensão também inclui uma habilidade <code>esql</code> que converte a solicitação do usuário de linguagem natural em uma consulta ES|QL. Essa habilidade pode ser particularmente útil quando o servidor MCP não pode ser usado, pois a comunicação subjacente é conduzida por comandos curl simples executados em um terminal. O Elasticsearch oferece um conjunto abrangente de APIs REST que podem ser facilmente integradas a qualquer projeto. Isso é especialmente útil ao desenvolver aplicações de IA agêntica.</p><p>Para mais informações sobre nossa extensão Gemini CLI, acesse o repositório do projeto <a href="https://github.com/elastic/gemini-cli-elasticsearch">aqui</a>.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/gemini-cli-extension-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/gemini-cli-extension-elasticsearch</guid>
    <category><![CDATA[Integrações]]></category>
    <category><![CDATA[IA agêntica]]></category>
    <dc:creator><![CDATA[Walter Rafelsberger,Enrico Zimuel]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4ff43abe550941b4/6a17072ba29299fc2ad00fa4/6dfcec4a77b3dc83bf0d974417bf2e211abb1f4f-876x468.png" length="0" type="image/png"/>
    <pubDate>Tue, 17 Mar 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Uma introdução aos modelos Jina, sua funcionalidade e seus usos no Elasticsearch]]></title>
    <description><![CDATA[Confira os embeddings multimodais Jina, o Reranker v3 e os modelos semânticos de embedding, além de como usá-los nativamente no Elasticsearch.]]></description>
    <content:encoded><![CDATA[<p>O Jina by Elastic fornece modelos de base para busca voltados a aplicações e automação de processos de negócio. Esses modelos oferecem funcionalidades essenciais para levar IA a aplicações no Elasticsearch e a projetos inovadores baseados em IA.</p><p>Os modelos Jina se enquadram em três grandes categorias, projetadas para dar suporte ao processamento, à organização e à recuperação de informações:</p><ul><li><p>Modelos de embedding semântico</p></li><li><p>Modelos de reclassificação</p></li><li><p>Modelos de linguagem generativos de pequeno porte</p></li></ul><h2>Modelos de embedding semântico</h2><p>A ideia por trás dos embeddings semânticos é que um modelo de IA pode aprender a representar aspectos do significado de suas entradas em termos da geometria de espaços de alta dimensionalidade.</p><p>É possível pensar em um embedding semântico como um ponto (tecnicamente, um <em>vetor</em>) em um espaço de alta dimensionalidade. Um modelo de embedding é uma rede neural que recebe algum tipo de dado digital como entrada, potencialmente qualquer tipo, mas mais comumente texto ou imagem, e produz a localização de um ponto correspondente em um espaço de alta dimensionalidade, representada por um conjunto de coordenadas numéricas. Quando o modelo executa bem sua função, a distância entre dois embeddings semânticos é proporcional ao quanto os objetos digitais correspondentes compartilham o mesmo significado.</p><p>Para entender por que isso é importante para aplicações de busca, imagine um embedding para a palavra “cão” e outro para a palavra “gato” como pontos em um espaço.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbad74e5d8292a60e/6a17db73abe0f2114edfe8d2/802cf9bbcb82180d3fc91009f9f62027eee8f031-615x615.png" alt="" /><p>Um bom modelo de embedding deve gerar um embedding para a palavra “felino” muito mais próximo de “gato” do que de “cão”, e “canino” deve ter um embedding muito mais próximo de “cão” do que de “gato”, porque essas palavras têm praticamente o mesmo significado.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdb2b25691801a881/6a17db747b54f946d28b37a5/bce49daf9a31b8fb7ce1c6ef7ae4e8117a4e8b33-615x615.png" alt="" /><p>Se um modelo for multilíngue, espera-se o mesmo comportamento para traduções de “gato” e “cão” em outros idiomas.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt976ba40be7776449/6a17db75be6086c2bd0045f2/ce4d030385324526cbd7539140e0e634d939371c-615x615.png" alt="" /><p>Modelos de embedding traduzem similaridade ou dissimilaridade de significado entre elementos em relações espaciais entre embeddings. As imagens acima têm apenas duas dimensões para que seja possível visualizá-las na tela, mas modelos de embedding produzem vetores com dezenas a milhares de dimensões. Isso permite codificar sutilezas de significado para textos inteiros, atribuindo um ponto em um espaço com centenas ou milhares de dimensões a documentos com milhares de palavras ou mais.</p><h2>Embeddings multimodais</h2><p>Modelos multimodais estendem o conceito de embeddings semânticos para além de textos, especialmente para imagens. Espera-se que o embedding de uma imagem fique próximo ao embedding de uma descrição fiel dessa imagem.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt66dc8895485734ec/6a17db77b1e11318d279f155/1ac6aef5b1423e5fe4853e8a547a74e66b0885c2-615x615.png" alt="" /><p>Embeddings semânticos têm muitos usos. Entre outras aplicações, é possível usá-los para criar classificadores eficientes, realizar clustering de dados e executar diversas tarefas, como deduplicação de dados e investigação da diversidade dos dados, ambas importantes para aplicações de big data que lidam com volumes de informação grandes demais para serem gerenciados manualmente.</p><p>O principal uso direto de embeddings está na recuperação de informações. O Elasticsearch pode armazenar objetos de recuperação com embeddings como chaves. As consultas são convertidas em vetores de embedding, e a busca retorna os objetos armazenados cujas chaves estão mais próximas do embedding da consulta.</p><p>Enquanto <em>a recuperação tradicional baseada em vetores</em> (às vezes chamada de <em>recuperação por vetores esparsos</em>) usa vetores baseados em palavras ou metadados presentes em documentos e consultas, a <em>recuperação baseada em embeddings</em> (também conhecida como <em>recuperação por vetores densos</em>) usa significados avaliados por IA em vez de palavras. Isso a torna, em geral, muito mais flexível e mais precisa do que métodos tradicionais de busca.</p><h2>Aprendizado de representação Matryoshka</h2><p>O número de dimensões de um embedding, assim como a precisão dos valores numéricos que o compõem, tem impactos significativos na performance. Espaços de dimensionalidade muito alta e números de precisão extremamente elevada podem representar informações altamente detalhadas e complexas, mas exigem modelos de IA maiores, mais caros para treinar e para executar. Os vetores que esses modelos geram requerem mais espaço de armazenamento, e são necessários mais ciclos de computação para calcular as distâncias entre eles. Usar modelos de embedding semântico envolve fazer concessões importantes entre precisão e consumo de recursos.</p><p>Para maximizar a flexibilidade para os usuários, os modelos Jina são treinados com uma técnica chamada <a href="https://arxiv.org/abs/2205.13147">Aprendizado de Representação Matryoshka</a>. Essa abordagem faz com que os modelos concentrem as distinções semânticas mais importantes nas primeiras dimensões do vetor de embedding, de modo que seja possível descartar as dimensões mais altas e ainda assim obter bom desempenho.</p><p>Na prática, isso significa que usuários dos modelos Jina podem escolher quantas dimensões desejam que seus embeddings tenham. Escolher menos dimensões reduz a precisão, mas a degradação de performance é pequena. Na maioria das tarefas, as métricas de performance dos modelos Jina caem entre 1% e 2% sempre que o tamanho do embedding é reduzido em 50%, até uma redução total de cerca de 95% no tamanho.</p><h2>Recuperação assimétrica</h2><p>A similaridade semântica geralmente é medida de forma simétrica. O valor obtido ao comparar “gato” com “cão” é o mesmo que ao comparar “cão” com “gato”. No entanto, quando embeddings são usados para recuperação de informações, o desempenho melhora quando essa simetria é quebrada e as consultas são codificadas de forma diferente dos objetos de recuperação.</p><p>Isso ocorre por causa da forma como treinamos modelos de embedding. Os dados de treinamento contêm ocorrências dos mesmos elementos, como palavras, em muitos contextos diferentes, e os modelos aprendem semântica comparando similaridades e diferenças contextuais entre esses elementos.</p><p>Assim, por exemplo, pode acontecer de a palavra “animal” não aparecer em muitos dos mesmos contextos que “gato” ou “cão”, e, portanto, o embedding de “animal” não ficar particularmente próximo de “gato” ou “cão”.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf219074e18a6290a/6a17db78be6086cf060045f6/9a33163405af6c71ee7f4ba8ebc86af39e295a69-615x615.png" alt="" /><p>Isso torna menos provável que uma consulta por “animal” recupere documentos sobre gatos e cães — justamente o oposto do nosso objetivo. Por isso, em vez disso, codificamos “animal” de forma diferente quando ele aparece como consulta do que quando é um alvo de recuperação.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt33438b4964001467/6a17db79b1e113101c79f159/363992d4f0affba7937c0c8a9f82c9a531fcd3ba-615x615.png" alt="" /><p><em>Recuperação assimétrica</em> significa usar um modelo diferente para consultas ou treinar especificamente um modelo de embedding para codificar os dados de uma forma quando são armazenados para recuperação e de outra forma quando são usados como consultas.</p><h2>Embeddings multivetoriais</h2><p>Embeddings únicos funcionam bem para recuperação de informações porque se encaixam no modelo básico de um banco de dados indexado: armazenamos objetos para recuperação usando um único vetor de embedding como chave de recuperação. Quando usuários consultam o repositório de documentos, suas consultas são traduzidas em vetores de embedding, e os documentos cujas chaves estão mais próximas do embedding da consulta, no espaço de embeddings de alta dimensionalidade, são recuperados como candidatos.</p><p>Embeddings multivetoriais funcionam de forma um pouco diferente. Em vez de gerar um vetor de comprimento fixo para representar uma consulta e um objeto armazenado inteiro, eles produzem uma sequência de embeddings que representam partes menores desses elementos. Essas partes geralmente são tokens ou palavras no caso de textos, e blocos de imagem no caso de dados visuais. Esses embeddings refletem o significado de cada parte dentro de seu contexto.</p><p>Por exemplo, considere estas frases:</p><ul><li><p>Ela tinha um coração de ouro.</p></li><li><p>Ela fez das tripas coração.</p></li><li><p>Ela teve um ataque do coração.</p></li></ul><p>Superficialmente, essas frases parecem muito semelhantes, mas um modelo multivetorial provavelmente geraria embeddings bem diferentes para cada ocorrência de “coração”, representando como cada uma assume um significado distinto no contexto da frase como um todo.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5c81f089771e6029/6a17db7b7f6f157601c099ec/a33e60c8d8ee3d312bca8375ca2a8b0a0cd40ba9-615x615.png" alt="" /><p>Comparar dois objetos por meio de seus embeddings multivetoriais geralmente envolve medir a distância de Chamfer: comparar cada parte de um embedding multivetorial com cada parte de outro e somar as menores distâncias entre elas. Outros sistemas, incluindo os reclassificadores Jina descritos abaixo, usam esses embeddings como entrada para um modelo de IA treinado especificamente para avaliar sua similaridade. Ambas as abordagens normalmente apresentam maior precisão do que a simples comparação de embeddings de vetor único, porque embeddings multivetoriais contêm informações muito mais detalhadas do que embeddings de vetor único.</p><p>No entanto, embeddings multivetoriais não são adequados para indexação. Eles costumam ser usados em tarefas de reclassificação, conforme descrito para o modelo <code>jina-colbert-v2</code> na próxima seção.</p><h2>Modelos de embedding Jina</h2><h3>Jina embeddings v4</h3><p><a href="https://jina.ai/news/jina-embeddings-v4-universal-embeddings-for-multimodal-multilingual-retrieval/"><strong>jina-embeddings-v4</strong></a> é um modelo de embedding multilíngue e multimodal, com 3,8 bilhões (3,8 × 10⁹) de parâmetros, que oferece suporte a imagens e textos em diversos idiomas amplamente utilizados. Ele utiliza uma arquitetura inédita para aproveitar conhecimento visual e conhecimento linguístico, melhorando o desempenho em ambas as tarefas e permitindo que o modelo se destaque na recuperação de imagens e, especialmente, na <a href="https://huggingface.co/tasks/visual-document-retrieval">recuperação de documentos visuais</a>. Isso significa que ele lida bem com imagens como gráficos, slides, mapas, capturas de tela, digitalizações de páginas e diagramas — tipos comuns de imagens que muitas vezes contêm texto incorporado importante e que ficam fora do escopo de modelos de visão computacional treinados apenas com imagens de cenas do mundo real.</p><p>Otimizamos esse modelo para diversas tarefas diferentes usando <a href="https://huggingface.co/docs/peft/en/package_reference/lora">adaptadores compactos de Low-Rank Adaptation (LoRA)</a>. Isso nos permite treinar um único modelo para se especializar em múltiplas tarefas, sem comprometer o desempenho em nenhuma delas, com um custo adicional mínimo de memória ou processamento.</p><p>Os principais recursos incluem:</p><ul><li><p>Desempenho de ponta na recuperação de documentos visuais, além de suporte a texto multilíngue e imagens comuns com resultados que superam significativamente modelos muito maiores.</p></li><li><p>Suporte a grandes tamanhos de contexto de entrada: 32.768 tokens equivalem aproximadamente a 80 páginas de texto em inglês com espaçamento duplo, e 20 megapixels equivalem a uma imagem de 4.500 × 4.500 pixels.</p></li><li><p>Tamanhos de embedding selecionáveis pelo usuário, de um máximo de 2.048 dimensões até 128 dimensões. Constatamos empiricamente que o desempenho se degrada de forma acentuada abaixo desse limite.</p></li><li><p>Suporte tanto a embeddings únicos quanto a embeddings multivetoriais. Para textos, a saída multivetorial consiste em um embedding de 128 dimensões para cada token de entrada. Para imagens, é gerado um embedding de 128 dimensões para cada bloco de 28 × 28 pixels necessário para cobrir a imagem.</p></li><li><p>Otimização para recuperação assimétrica por meio de um par de adaptadores LoRA treinados especificamente para esse propósito.</p></li><li><p>Um adaptador LoRA otimizado para cálculo de similaridade semântica.</p></li><li><p>Suporte especial a linguagens de programação e estruturas de TI, também por meio de um adaptador LoRA.</p></li></ul><p>Desenvolvemos <code>jina-embeddings-v4</code> para atuar como uma ferramenta geral e multifuncional para uma ampla gama de tarefas comuns de busca, compreensão de linguagem natural e análise com IA. Apesar de ser relativamente pequeno considerando suas capacidades, ainda exige recursos significativos para implantação e é mais adequado para uso por meio de uma API em nuvem ou em ambientes de alto volume.</p><h3>Jina embeddings v3</h3><p><a href="https://jina.ai/news/jina-embeddings-v3-a-frontier-multilingual-embedding-model/"><strong>jina-embeddings-V3</strong></a> é um modelo de embedding compacto, multilíngue, somente para texto, com alto desempenho e menos de 600 milhões de parâmetros. Ele oferece suporte a até 8.192 tokens de texto de entrada e gera embeddings de vetor único com tamanhos escolhidos pelo usuário, desde o padrão de 1.024 dimensões até 64.</p><p>Treinamos <code>jina-embeddings-v3</code> para uma variedade de tarefas de texto — não apenas recuperação de informações e similaridade semântica, mas também tarefas de classificação, como análise de sentimento e moderação de conteúdo, além de tarefas de clusterização, como agregação de notícias e recomendação. Assim como <code>jina-embeddings-v4</code>, esse modelo oferece adaptadores LoRA especializados para as seguintes categorias de uso:</p><ul><li><p>Recuperação assimétrica</p></li><li><p>Similaridade semântica</p></li><li><p>Classificação</p></li><li><p>Clustering</p></li></ul><p><code>jina-embeddings-v3</code> é um modelo muito menor do que <code>jina-embeddings-v4</code> com um tamanho de contexto de entrada significativamente reduzido, mas com custo operacional mais baixo. Ainda assim, apresenta desempenho bastante competitivo, embora apenas para textos, e é uma escolha melhor para muitos casos de uso.</p><h3>Incorporações de código Jina</h3><p>Os modelos especializados de embedding de código da Jina — <a href="https://jina.ai/models/jina-code-embeddings-1.5b"><strong>jina-code-embeddings (0.5b e 1.5b)</strong></a> — oferecem suporte a 15 esquemas de programação e estruturas, além de textos em inglês relacionados a computação e tecnologia da informação. São modelos compactos, com meio bilhão (0,5 × 10⁹) e um bilhão e meio (1,5 × 10⁹) de parâmetros, respectivamente. Ambos oferecem suporte a tamanhos de contexto de entrada de até 32.768 tokens e permitem que os usuários escolham os tamanhos dos embeddings de saída, de 896 a 64 dimensões no modelo menor e de 1.536 a 128 no modelo maior.</p><p>Esses modelos oferecem suporte a recuperação assimétrica para cinco especializações específicas de tarefa, usando <a href="https://arxiv.org/abs/2101.00190">ajuste de prefixo</a> em vez de adaptadores LoRA:</p><ul><li><p><strong>Código para código.</strong> Recuperar código semelhante entre diferentes linguagens de programação. Isso é usado para alinhamento de código, deduplicação de código e suporte a portabilidade e refatoração.</p></li><li><p><strong>Linguagem natural para código.</strong> Recuperar código que corresponda a consultas em linguagem natural, comentários, descrições e documentação.</p></li><li><p><strong>Código para linguagem natural. </strong>Associar código a documentação ou a outros textos em linguagem natural.</p></li><li><p><strong>Conclusão de código para código.</strong> Sugerir código relevante para completar ou aprimorar código existente.</p></li><li><p><strong>Perguntas e respostas técnicas.</strong> Identificar respostas em linguagem natural para perguntas sobre tecnologias da informação, sendo ideal para casos de uso de suporte técnico.</p></li></ul><p>Esses modelos oferecem performance superior em tarefas que envolvem documentação técnica e materiais de programação, com um custo computacional relativamente baixo. Eles são bem adequados para integração em ambientes de desenvolvimento e assistentes de código.</p><h3>Jina ColBERT v2</h3><p><a href="https://jina.ai/models/jina-colbert-v2"><strong>jina-colbert-v2</strong></a> é um modelo de embedding de texto multivetorial com 560 milhões de parâmetros. Ele é multilíngue, treinado com materiais em 89 idiomas, e oferece suporte a tamanhos variáveis de embedding e recuperação assimétrica.</p><p>Como observado anteriormente, embeddings multivetoriais não são adequados para indexação, mas são muito úteis para aumentar a precisão dos resultados de outras estratégias de busca. Com <code>jina-colbert-v2</code><strong>,</strong> é possível calcular embeddings multivetoriais antecipadamente e usá-los para reclassificar candidatos à recuperação no momento da consulta. Essa abordagem é menos precisa do que usar um dos modelos de reclassificação descritos na próxima seção, mas é muito mais eficiente, pois envolve apenas a comparação de embeddings multivetoriais armazenados, em vez de invocar todo o modelo de IA para cada consulta e cada correspondência candidata. Ela é especialmente adequada para casos de uso em que a latência e a sobrecarga computacional dos modelos de reclassificação são excessivas ou em que o número de candidatos a comparar é grande demais para esse tipo de modelo.</p><p>Esse modelo gera uma sequência de embeddings, um por token de entrada, e os usuários podem selecionar embeddings de tokens com 128, 96 ou 64 dimensões. As correspondências de texto candidatas são limitadas a 8.192 tokens. As consultas são codificadas de forma assimétrica, portanto é necessário especificar se um texto é uma consulta ou uma correspondência candidata, além de limitar consultas a 32 tokens.</p><h3>Jina CLIP v2</h3><p><a href="https://jina.ai/news/jina-clip-v2-multilingual-multimodal-embeddings-for-text-and-images/"><strong>jina-clip-v2</strong></a> é um modelo de embedding multimodal com 900 milhões de parâmetros, treinado para que textos e imagens gerem embeddings próximos entre si quando o texto descreve o conteúdo da imagem. Seu uso principal é a recuperação de imagens com base em consultas textuais, mas ele também é um modelo somente de texto com alto desempenho, reduzindo custos para os usuários, já que não é necessário manter modelos separados para recuperação de texto para texto e de texto para imagem.</p><p>Esse modelo oferece suporte a um contexto de entrada de texto de 8.192 tokens, e as imagens são redimensionadas para 512 × 512 pixels antes da geração dos embeddings.</p><p>Arquiteturas de pré-treinamento contrastivo de linguagem e imagem (CLIP) são fáceis de treinar e operar e podem gerar modelos muito compactos, mas apresentam algumas limitações fundamentais. Eles não conseguem usar conhecimento de um meio para melhorar seu desempenho em outro. Ou seja, não conseguem aproveitar informações de um meio para aprimorar o desempenho em outro. Assim, embora um modelo possa saber que as palavras “cão” e “gato” são mais próximas em significado entre si do que qualquer uma delas em relação a “carro”, ele não necessariamente saberá que a imagem de um cão e a imagem de um gato são mais relacionadas entre si do que qualquer uma delas em relação à imagem de um carro.</p><p>Esses modelos também sofrem do que se chama de <em>lacuna de modalidade</em>: um embedding de um texto sobre cães tende a ficar mais próximo de um embedding de um texto sobre gatos do que de um embedding de uma imagem de cães. Por causa dessa limitação, recomendamos usar CLIP como um modelo de recuperação de texto para imagem ou como um modelo somente de texto, mas não misturar os dois em uma única consulta.</p><h2>Modelos de reclassificação</h2><p>Modelos de reclassificação recebem como entrada uma consulta e uma ou mais correspondências candidatas e as comparam diretamente, produzindo correspondências com precisão muito maior.</p><p>Em princípio, seria possível usar um reclassificador diretamente para recuperação de informações, comparando cada consulta com cada documento armazenado, mas isso seria computacionalmente muito caro e impraticável para qualquer coleção que não seja muito pequena. Por isso, reclassificadores tendem a ser usados para avaliar listas relativamente curtas de correspondências candidatas encontradas por outros meios, como busca baseada em embeddings ou outros algoritmos de recuperação. Modelos de reclassificação são ideais para esquemas de busca híbrida e federada, nos quais executar uma busca pode significar enviar consultas a sistemas de busca separados, com conjuntos de dados distintos, cada um retornando resultados diferentes. Eles funcionam muito bem para combinar resultados diversos em um único resultado de alta qualidade.</p><p>A busca baseada em embeddings pode exigir um grande investimento, envolvendo a reindexação de todos os dados armazenados e a mudança das expectativas dos usuários em relação aos resultados. Adicionar um reclassificador a um esquema de busca existente pode trazer muitos dos benefícios da IA sem a necessidade de reestruturar toda a solução de busca.</p><h2>Modelos de reclassificação Jina</h2><h3>Jina Reranker m0</h3><p><a href="https://jina.ai/models/jina-reranker-m0/"><strong>jina-reranker-m0</strong></a> é um reclassificador multimodal com 2,4 bilhões (2,4 × 10⁹) de parâmetros, que oferece suporte a consultas textuais e a correspondências candidatas compostas por textos e/ou imagens. Ele é o principal modelo para recuperação de documentos visuais, o que o torna uma solução ideal para repositórios de PDFs, digitalizações de texto, capturas de tela e outras imagens geradas ou modificadas por computador que contêm texto ou outras informações semiestruturadas, bem como para dados mistos compostos por documentos de texto e imagens.</p><p>Esse modelo recebe uma única consulta e uma correspondência candidata e retorna uma pontuação. Quando a mesma consulta é usada com diferentes candidatos, as pontuações são comparáveis e podem ser usadas para ranqueá-los. Ele oferece suporte a um tamanho total de entrada de até 10.240 tokens, incluindo o texto da consulta e o texto ou imagem candidata. Cada bloco de 28 × 28 pixels necessário para cobrir uma imagem conta como um token no cálculo do tamanho de entrada.</p><h3>Jina Reranker v3</h3><p><a href="https://jina.ai/models/jina-reranker-v3/"><strong>jina-reranker-v3</strong></a> é um reclassificador de texto com 600 milhões de parâmetros, com desempenho de ponta entre modelos de tamanho comparável. Ao contrário de <code>jina-reranker-m0</code>, ele recebe uma única consulta e uma lista de até 64 correspondências candidatas e retorna a ordem de ranqueamento. Ele tem um contexto de entrada de 131.000 tokens, incluindo a consulta e todos os candidatos de texto.</p><h3>Jina Reranker v2</h3><p><a href="https://jina.ai/models/jina-reranker-v2"><strong>jina-reranker-v2-base-multilingual</strong></a> é um reclassificador multifuncional, de uso geral, muito compacto, com recursos adicionais projetados para oferecer suporte a chamadas de função e consultas SQL. Com menos de 300 milhões de parâmetros, ele fornece reclassificação de texto multilíngue rápida, eficiente e precisa, com suporte adicional para selecionar tabelas SQL e funções externas que correspondam a consultas de texto, o que o torna adequado para casos de uso com IA agêntica.</p><h2>Modelos de linguagem generativos de pequeno porte</h2><p>Modelos de linguagem generativos são modelos como o ChatGPT da OpenAI, o Google Gemini e o Claude, da Anthropic, que recebem entradas em texto ou multimídia e respondem com saídas em texto. Não existe um limite bem definido que separe modelos de linguagem <em>grandes</em> (LLMs) de modelos de linguagem <em>pequenos</em> (SLMs), mas os desafios práticos de desenvolver, operar e usar LLMs de ponta são bem conhecidos. Os modelos mais conhecidos não são distribuídos publicamente, portanto só é possível estimar seu tamanho, mas espera-se que ChatGPT, Gemini e Claude estejam na faixa de 1 a 3 trilhões (1–3 × 10¹²) de parâmetros.</p><p>Executar esses modelos, mesmo quando estão disponíveis publicamente, está muito além do alcance de hardware convencional, exigindo os chips mais avançados organizados em grandes arranjos paralelos. É possível acessar LLMs por meio de APIs pagas, mas isso envolve custos significativos, alta latência e dificuldades para atender a exigências de proteção de dados, soberania digital e repatriação de nuvem. Além disso, os custos relacionados ao treinamento e à personalização de modelos desse porte podem ser consideráveis.</p><p>Consequentemente, uma grande quantidade de pesquisa tem se concentrado no desenvolvimento de modelos menores que, embora não tenham todas as capacidades dos maiores LLMs, conseguem executar tipos específicos de tarefas com a mesma qualidade, a um custo reduzido. Empresas normalmente implantam software para resolver problemas específicos, e com software de IA não é diferente; por isso, soluções baseadas em SLMs costumam ser preferíveis às baseadas em LLMs. Elas geralmente podem ser executadas em hardware comum, são mais rápidas, consomem menos energia e são muito mais fáceis de personalizar.</p><p>As ofertas de SLM da Jina estão crescendo à medida que nos concentramos em como levar IA da melhor forma possível a soluções práticas de busca.</p><h2>Jina SLMs</h2><h3>ReaderLM v2</h3><p><a href="https://jina.ai/models/ReaderLM-v2"><strong>ReaderLM-v2</strong></a> é um modelo de linguagem generativo que converte HTML em Markdown ou em JSON, de acordo com esquemas JSON fornecidos pelo usuário e instruções em linguagem natural.</p><p>O pré-processamento e a normalização de dados são uma parte essencial do desenvolvimento de boas soluções de busca para dados digitais, mas dados do mundo real, especialmente informações derivadas da web, costumam ser caóticos, e estratégias simples de conversão frequentemente se mostram frágeis. Em vez disso, <code>ReaderLM-v2</code> oferece uma solução inteligente baseada em modelo de IA, capaz de entender o caos de um dump de árvore DOM de uma página da web e identificar, de forma robusta, elementos úteis.</p><p>Com 1,5 bilhão (1,5 × 10⁹) de parâmetros, esse modelo é três ordens de magnitude mais compacto do que LLMs de última geração, mas apresenta desempenho equivalente a eles nessa tarefa específica e bastante restrita.</p><h3>Jina VLM</h3><p><a href="https://jina.ai/models/jina-vlm"><strong>jina-VLC</strong></a> é um modelo de linguagem generativo com 2,4 bilhões (2,4 × 10⁹) de parâmetros, treinado para responder a perguntas em linguagem natural sobre imagens. Ele oferece suporte muito robusto a análise de documentos visuais, isto é, responder a perguntas sobre digitalizações, capturas de tela, slides, diagramas e dados de imagem semelhantes que não são naturais.</p><p>Por exemplo:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt124b9932e01dcd40/6a17db7d4202291eca29f4bc/adfa1420d079ca4fd5582eef4349b1265b378e76-950x500.png" alt="" /><p>Ele também é muito eficiente na leitura de texto em imagens:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1a862a9c9a0e42ce/6a17db7fb1e1133a2979f15d/ea3956e7ad86f8e171841cab2c28c8b3498da1d4-1002x500.png" alt="" /><p>Mas é na compreensão do conteúdo de imagens informativas e produzidas pelo ser humano que <code>jina-vlm</code> realmente se destaca:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt761cf621ea32e4ae/6a17db8163baff7730741b26/f68606f9d2d99e2cd616d4ff81db3574dc4e26a5-1020x700.png" alt="" /><p>Ou:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4df4d31e574df7e3/6a17db82e3179134e02d56e9/297e85e7e78f296388a02301e1e08fed70827423-1000x500.png" alt="" /><p><code>jina-vlm</code> é especialmente adequado para geração automática de legendas, descrições de produtos, texto alternativo de imagens e aplicações de acessibilidade para pessoas com deficiência visual. Além disso, cria novas possibilidades para sistemas de geração aumentada por recuperação (RAG) utilizarem informações visuais e para agentes de IA processarem imagens sem assistência humana.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/jina-models-elasticsearch-guide</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/jina-models-elasticsearch-guide</guid>
    <category><![CDATA[Integrações]]></category>
    <category><![CDATA[Jina AI]]></category>
    <dc:creator><![CDATA[Scott Martens]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta03919124faf767a/6a17db84ec0f89b8fe5a64d8/407b4c862b51ebdfc7f26db4e25950a65caf1673-656x442.png" length="0" type="image/png"/>
    <pubDate>Thu, 01 Jan 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Construindo um agente de conhecimento com recuperação semântica usando Mastra e Elasticsearch.]]></title>
    <description><![CDATA[Aprenda como construir um agente de conhecimento com recuperação semântica usando Mastra e Elasticsearch como armazenamento vetorial para memória e recuperação de informações.]]></description>
    <content:encoded><![CDATA[<p><a href="https://www.elastic.co/search-labs/blog/context-engineering-overview">A Engenharia de Contexto</a> está se tornando cada vez mais importante na construção de agentes e arquiteturas de IA confiáveis. À medida que os modelos se tornam cada vez melhores, sua eficácia e confiabilidade dependem menos dos dados de treinamento e mais de quão bem eles estão fundamentados no contexto correto. Agentes que conseguem recuperar e aplicar as informações mais relevantes no momento certo têm muito mais probabilidade de produzir resultados precisos e confiáveis.</p><p>Neste blog, usaremos <a href="https://mastra.ai/">o Mastra</a> para construir um agente de conhecimento que memoriza o que os usuários dizem e consegue recuperar informações relevantes posteriormente, utilizando o Elasticsearch como backend de memória e recuperação. Você pode facilmente estender esse mesmo conceito a casos de uso do mundo real, como agentes de suporte que conseguem se lembrar de conversas e soluções anteriores, permitindo que eles personalizem as respostas para usuários específicos ou apresentem soluções mais rapidamente com base no contexto prévio.</p><p>Acompanhe aqui como construir isso passo a passo. Se você se perder ou simplesmente quiser executar um exemplo finalizado, confira o repositório <a href="https://github.com/jdarmada/getting-started-mastra-elastic/tree/main">aqui</a>.</p><h2>O que é Mastra?</h2><p>Mastra é um framework TypeScript de código aberto para a construção de agentes de IA com componentes intercambiáveis para raciocínio, memória e ferramentas. Seu recurso <a href="https://mastra.ai/docs/memory/semantic-recall">de recuperação semântica</a> permite que os agentes se lembrem e recuperem interações passadas, armazenando mensagens como representações vetoriais em um banco de dados vetorial. Isso permite que os agentes mantenham o contexto e a continuidade da conversa a longo prazo. O Elasticsearch é um excelente armazenamento de vetores para habilitar esse recurso, pois oferece suporte a buscas vetoriais densas e eficientes. Quando a recuperação semântica é acionada, o agente extrai mensagens relevantes do passado para a janela de contexto do modelo, permitindo que o modelo use esse contexto recuperado como base para seu raciocínio e respostas.</p><h2>O que você precisa para começar</h2><ul><li><p>Node v18+</p></li><li><p>Elasticsearch (versão 8.15 ou mais recente)</p></li><li><p>Chave da API do Elasticsearch</p></li><li><p><a href="https://help.openai.com/en/articles/4936850-where-do-i-find-my-openai-api-key">Chave da API OpenAI</a></p></li></ul><p>Observação: você precisará disso porque a demonstração usa o provedor OpenAI, mas o Mastra é compatível com outros SDKs de IA e provedores de modelos da comunidade, então você pode facilmente trocá-lo dependendo da sua configuração.</p><h2>Construindo um projeto Mastra</h2><p>Usaremos a CLI integrada do Mastra para fornecer a estrutura básica do nosso projeto. Execute o comando:</p>npm create mastra@latest<p>Você receberá uma série de instruções, começando com:</p><p>1. Dê um nome ao seu projeto.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt87f941f654d03827/6a16f7af67045b214d45bfa1/2b9fe559e0276140dd539e24f916a73c60870405-620x84.png" alt="Como nomear um prompt no aplicativo Mastra" /><p>2. Podemos manter esta opção padrão; fique à vontade para deixar este campo em branco.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7dbb3d4f27435cac/6a16f7b0cdacbf29497d27de/e04729eb03bce8499e973e18c28642402340d0e5-852x68.png" alt="Indicar à Mastra onde guardar os arquivos de prompts." /><p>3. Para este projeto, usaremos um modelo fornecido pela OpenAI.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1f654f6cb9397e94/6a16f7b2964cea899a08b942/a86596a469a71bdf8bd99cbaf528d0f0cf7272c0-436x222.png" alt="Selecionando um modelo fornecido pela OpenAI no Mastra" /><p>4. Selecione a opção “Ignorar por enquanto”, pois armazenaremos todas as nossas variáveis de ambiente em um arquivo `.env` que configuraremos em uma etapa posterior.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltff106117521a3519/6a16f7b3c1e8a5031af880d8/02b19ccc34af0bdacf52fd94b519d036540ca2e6-426x114.png" alt="Por enquanto, vou optar por ignorar a chave da OpenAI." /><p>5. Também podemos ignorar esta opção.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcda7d9c51c3878d7/6a16f7b450916809dbe1b892/b3fe63d19d270bc2e0de1dd92033bf8b26750819-990x208.png" alt="" /><p>Assim que a inicialização estiver concluída, podemos passar para a próxima etapa.</p><h3>Instalando dependências</h3><p>Em seguida, precisamos instalar algumas dependências:</p>npm install ai @ai-sdk/openai @elastic/elasticsearch dotenv<ul><li><p><code>ai</code> - Pacote Core AI SDK que fornece ferramentas para gerenciar modelos de IA, prompts e fluxos de trabalho em JavaScript/TypeScript. O Mastra é construído sobre o <a href="https://ai-sdk.dev/">SDK de IA</a> da Vercel, portanto, precisamos dessa dependência para permitir as interações do modelo com o seu agente.</p></li><li><p><code>@ai-sdk/openai</code> - Plugin que conecta o SDK de IA aos modelos da OpenAI (como GPT-4, GPT-4o, etc.), permitindo chamadas à API usando sua chave de API da OpenAI.</p></li><li><p><code>@elastic/elasticsearch</code> - <a href="https://www.elastic.co/docs/reference/elasticsearch/clients/javascript">Cliente oficial do Elasticsearch para Node.js</a>, Utilizado para conectar-se ao seu Elastic Cloud ou cluster local para indexação, pesquisa e operações vetoriais.</p></li><li><p><code>dotenv</code> - Carrega variáveis de ambiente de um arquivo .env arquivo em process.env, permitindo que você insira credenciais com segurança, como chaves de API e endpoints do Elasticsearch.</p></li></ul><h3>Configurando variáveis de ambiente</h3><p>Crie um arquivo <code>.env</code> no diretório raiz do seu projeto, caso ainda não exista um. Alternativamente, você pode copiar e renomear o exemplo <code>.env</code> que eu forneci no <a href="https://github.com/jdarmada/getting-started-mastra-elastic/blob/main/.env.example">repositório</a>. Neste arquivo, podemos adicionar as seguintes variáveis:</p>ELASTICSEARCH_ENDPOINT="your-endpoint-here"
ELASTICSEARCH_API_KEY="your-key-here"
OPENAI_API_KEY="your-key-here"<p>Isso conclui a configuração básica. A partir daqui, você já pode começar a construir e orquestrar agentes. Vamos dar um passo além e adicionar o Elasticsearch como camada de armazenamento e busca vetorial.</p><h2>Adicionando o Elasticsearch como armazenamento vetorial.</h2><p>Crie uma nova pasta chamada <code>stores</code> e, dentro dela, adicione este <a href="https://github.com/jdarmada/getting-started-mastra-elastic/blob/main/src/mastra/stores/elastic-store.ts">arquivo</a>. Antes que a Mastra e a Elastic lancem uma integração oficial de armazenamento vetorial do Elasticsearch, <a href="https://github.com/abhiaiyer91">Abhi Aiyer</a>(CTO da Mastra) compartilhou esta classe protótipo inicial chamada <code>ElasticVector</code>. Em termos simples, ele conecta a abstração de memória do Mastra aos recursos de vetores densos do Elasticsearch, permitindo que os desenvolvedores utilizem o Elasticsearch como banco de dados de vetores para seus agentes.</p><p>Vamos analisar mais detalhadamente as partes importantes da integração:</p><h3>Ingestão do cliente Elasticsearch</h3><p>Esta seção define a classe <code>ElasticVector</code> e configura a conexão do cliente Elasticsearch com suporte para implantações padrão e sem servidor.</p>export interface ElasticVectorConfig extends ClientOptions {
    /**
     * Explicitly specify if connecting to Elasticsearch Serverless.
     * If not provided, will be auto-detected on first use.
     */
    isServerless?: boolean;
    
    /**
     * Maximum documents to count accurately when describing indices.
     * Higher values provide accurate counts but may impact performance on large indices.
     * 
     * @default 10000
     */
    maxCountAccuracy?: number;
}

export class ElasticVector extends MastraVector {
    private client: Client;
    private isServerless: boolean | undefined;
    private deploymentChecked: boolean = false;
    private readonly maxCountAccuracy: number;

    constructor(config: ElasticVectorConfig) {
        super();
        this.client = new Client(config);
        this.isServerless = config.isServerless;
        this.maxCountAccuracy = config.maxCountAccuracy ?? 10000;
    }
}<ul><li><p><code>ElasticVectorConfig extends ClientOptions</code>Isso cria uma nova interface de configuração que herda todas as opções do cliente Elasticsearch (como <code>node</code>, <code>auth</code>, <code>requestTimeout</code>) e adiciona nossas propriedades personalizadas. Isso significa que os usuários podem passar qualquer configuração válida do Elasticsearch juntamente com nossas opções específicas para ambientes sem servidor.</p></li><li><p><code>extends MastraVector</code>Isso permite que <code>ElasticVector</code> herde da classe base <code>MastraVector</code> do Mastra, que é uma interface comum à qual todas as integrações de armazenamento vetorial estão em conformidade. Isso garante que o Elasticsearch se comporte como qualquer outro backend vetorial do Mastra da perspectiva do agente.</p></li><li><p><code>private client: Client</code>Esta é uma propriedade privada que contém uma instância do cliente JavaScript do Elasticsearch. Isso permite que a classe se comunique diretamente com o seu cluster.</p></li><li><p><code>isServerless</code> e <code>deploymentChecked</code>: Essas propriedades funcionam em conjunto para detectar e armazenar em cache se estamos conectados a uma implantação do Elasticsearch sem servidor ou padrão. Essa detecção ocorre automaticamente no primeiro uso ou pode ser configurada explicitamente.</p></li><li><p><code>constructor(config: ClientOptions)</code>: Este construtor recebe um objeto de configuração (contendo suas credenciais do Elasticsearch e configurações opcionais sem servidor) e o usa para inicializar o cliente na linha <code>this.client = new Client(config)</code>.</p></li><li><p><code>super()</code>Isso chama o construtor base do Mastra, portanto, ele herda o registro de logs, os auxiliares de validação e outros recursos internos.</p></li></ul><p>Neste ponto, Mastra sabe que existe uma nova loja de vetores chamada <code>ElasticVector</code></p><h3>Detecção do tipo de implantação</h3><p>Antes de criar os índices, o adaptador detecta automaticamente se você está usando o Elasticsearch padrão ou o Elasticsearch Serverless. Isso é importante porque as implantações sem servidor não permitem a configuração manual de shards.</p>private async detectServerless(): Promise&lt;boolean&gt; {
    // Return cached result if already detected
    if (this.deploymentChecked) {
        return this.isServerless ?? false;
    }

    // Use explicit configuration if provided
    if (this.isServerless !== undefined) {
        this.deploymentChecked = true;
        this.logger?.info(
            `Using explicit deployment type: ${this.isServerless ? 'Serverless' : 'Standard'}`
        );
        return this.isServerless;
    }

    try {
        const info = await this.client.info();
        
        // Primary detection: build flavor (most reliable)
        const isBuildFlavorServerless = info.version?.build_flavor === 'serverless';
        
        // Secondary detection: tagline (fallback)
        const isTaglineServerless = info.tagline?.toLowerCase().includes('serverless') ?? false;
        
        this.isServerless = isBuildFlavorServerless || isTaglineServerless;
        this.deploymentChecked = true;
        
        this.logger?.info(
            `Auto-detected ${this.isServerless ? 'Serverless' : 'Standard'} Elasticsearch deployment`,
            { 
                buildFlavor: info.version?.build_flavor, 
                version: info.version?.number,
                detectionMethod: isBuildFlavorServerless ? 'build_flavor' : 'tagline'
            }
        );
        
        return this.isServerless;
    } catch (error) {
        this.logger?.warn(
            'Could not auto-detect deployment type, assuming Standard Elasticsearch. ' +
            'Set isServerless: true explicitly in config if using Serverless.',
            { error: error instanceof Error ? error.message : String(error) }
        );
        this.isServerless = false;
        this.deploymentChecked = true;
        return false;
    }
}<p>O que está acontecendo:</p><ul><li><p>Primeiro verifica se você definiu explicitamente <code>isServerless</code> na configuração (ignora a detecção automática).</p></li><li><p>Chama a API <code>info()</code> do Elasticsearch para obter informações do cluster.</p></li><li><p>Verifica o <code>build_flavor field</code> (implantações sem servidor retornam <code>serverless</code>)</p></li><li><p>Se a opção de build não estiver disponível, a solução é verificar a descrição da versão.</p></li><li><p>Armazena o resultado em cache para evitar chamadas repetidas à API.</p></li><li><p>Se a detecção falhar, a implantação padrão será utilizada por padrão.</p></li></ul><p> Exemplo de uso:</p>// Option 1: Auto-detect (recommended)
const vector = new ElasticVector({
    node: 'https://your-cluster.es.cloud',
    auth: { apiKey: 'your-api-key' }
});
// Detection happens automatically on first index operation

// Option 2: Explicit configuration (faster startup)
const vector = new ElasticVector({
    node: 'https://your-serverless.es.cloud',
    auth: { apiKey: 'your-api-key' },
    isServerless: true  // Skips auto-detection
});<h3>Criando o armazenamento de “memória” no Elasticsearch</h3><p>A função abaixo configura um índice Elasticsearch para armazenar embeddings. Verifica se o índice já existe. Caso contrário, cria um com o mapeamento abaixo que contém um campo <code>dense_vector</code> para armazenar embeddings e métricas de similaridade personalizadas.</p><p>Algumas coisas a ter em conta:</p><ul><li><p>O parâmetro <code>dimension</code> representa o comprimento de cada vetor de incorporação, que depende do modelo de incorporação que você está usando. Em nosso caso, geraremos embeddings usando o modelo <code>text-embedding-3-small</code> da OpenAI, que produz vetores de tamanho <code>1536</code>. Usaremos esse valor como padrão.</p></li><li><p>A variável <code>similarity</code> usada no mapeamento abaixo é definida pela função auxiliar c<code>onst similarity = this.mapMetricToSimilarity(metric)</code>, que recebe o valor do parâmetro <code>metric</code> e o converte em uma palavra-chave compatível com o Elasticsearch para a métrica de distância escolhida.</p><ul><li><p>Por exemplo: Mastra usa termos gerais para similaridade de vetores como <code>cosine</code>, <code>euclidean</code> e <code>dotproduct</code>. Se passássemos a métrica <code>euclidean</code> diretamente para o mapeamento do Elasticsearch, ele geraria um erro porque o Elasticsearch espera que a palavra-chave <code>l2_norm</code> represente a distância euclidiana.</p></li></ul></li><li><p>Compatibilidade com ambientes sem servidor: o código omite automaticamente as configurações de shard e réplica para implantações sem servidor, pois estas são gerenciadas automaticamente pelo Elasticsearch Serverless.</p></li></ul>async createIndex(params: CreateIndexParams): Promise&lt;void&gt; {
    const { indexName, dimension = 1536, metric = 'cosine' } = params;

    try {
        const exists = await this.client.indices.exists({ index: indexName });

        if (exists) {
            try {
                await this.validateExistingIndex(indexName, dimension, metric);
                this.logger?.info(`Index "${indexName}" already exists and is valid`);
                return;
            } catch (validationError) {
                throw new Error(
                    `Index "${indexName}" exists but does not match the required configuration: ${
                        validationError instanceof Error ? validationError.message : String(validationError)
                    }`
                );
            }
        }

        const isServerless = await this.detectServerless();
        const similarity = this.mapMetricToSimilarity(metric);

        const indexConfig: any = {
            index: indexName,
            mappings: {
                properties: {
                    vector: {
                        type: 'dense_vector',
                        dims: dimension,
                        index: true,
                        similarity: similarity,
                    },
                    metadata: {
                        type: 'object',
                        enabled: true,
                        dynamic: true, // Allows flexible metadata structures
                    },
                },
            },
        };

        // Only configure shards/replicas for non-serverless deployments
        // Serverless manages infrastructure automatically
        if (!isServerless) {
            indexConfig.settings = {
                number_of_shards: 1,
                number_of_replicas: 0, // Increase for production HA deployments
            };
        }

        await this.client.indices.create(indexConfig);

        this.logger?.info(
            `Created ${isServerless ? 'Serverless' : 'Standard'} Elasticsearch index "${indexName}"`,
            { dimension, metric, similarity }
        );
    } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        this.logger?.error(`Failed to create index "${indexName}": ${errorMessage}`);
        throw new Error(`Failed to create index "${indexName}": ${errorMessage}`);
    }
}<h3>Armazenar uma nova memória ou anotação após uma interação.</h3><p>Esta função recebe novos embeddings gerados após cada interação, juntamente com os metadados, e os insere ou atualiza no índice usando a API <code>bulk</code> do Elastic. A API <code>bulk</code> agrupa várias operações de gravação em uma única solicitação; essa melhoria no desempenho de indexação garante que as atualizações permaneçam eficientes à medida que a memória do nosso agente continua a crescer.</p>async upsert(params: UpsertVectorParams): Promise&lt;string[]&gt; {
    const { indexName, vectors, metadata = [], ids } = params;

    try {
        // Generate unique IDs if not provided
        const vectorIds = ids || vectors.map((_, i) =&gt; 
            `vec_${Date.now()}_${i}_${Math.random().toString(36).substr(2, 9)}`
        );

        const operations = vectors.flatMap((vec, index) =&gt; [
            { index: { _index: indexName, _id: vectorIds[index] } },
            {
                vector: vec,
                metadata: metadata[index] || {},
            },
        ]);

        const response = await this.client.bulk({
            refresh: true,
            operations,
        });

        if (response.errors) {
            const erroredItems = response.items.filter((item: any) =&gt; item.index?.error);
            const erroredIds = erroredItems.map((item: any) =&gt; item.index?._id);
            const errorDetails = erroredItems.slice(0, 3).map((item: any) =&gt; ({
                id: item.index?._id,
                error: item.index?.error?.reason || item.index?.error,
                type: item.index?.error?.type
            }));
            
            const errorMessage = `Failed to upsert ${erroredIds.length}/${vectors.length} vectors`;
            console.error(`${errorMessage}. Sample errors:`, JSON.stringify(errorDetails, null, 2));
            this.logger?.error(errorMessage, { 
                failedCount: erroredIds.length, 
                totalCount: vectors.length,
                sampleErrors: errorDetails 
            });
            
            // Still return successfully inserted IDs
            const successfulIds = vectorIds.filter((id, idx) =&gt; 
                !erroredIds.includes(id)
            );
            
            if (successfulIds.length === 0) {
                throw new Error(`${errorMessage}. All operations failed. See logs for details.`);
            }
            
            return successfulIds;
        }

        this.logger?.info(`Successfully upserted ${vectors.length} vectors to "${indexName}"`);
        return vectorIds;
    } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        this.logger?.error(`Failed to upsert vectors to "${indexName}": ${errorMessage}`);
        throw new Error(`Failed to upsert vectors to "${indexName}": ${errorMessage}`);
    }
}<h3>Consultar vetores semelhantes para recuperação semântica</h3><p>Essa função é o núcleo do recurso de recuperação semântica. O agente utiliza a busca vetorial para encontrar incorporações armazenadas semelhantes em nosso índice.</p>async query(params: QueryVectorParams&lt;any&gt;): Promise&lt;QueryResult[]&gt; {
    const { indexName, queryVector, topK = 10, filter, includeVector = false } = params;

    try {
        const knnQuery: any = {
            field: 'vector',
            query_vector: queryVector,
            k: topK,
            num_candidates: Math.max(topK * 10, 100), // Search more candidates for better recall
        };

        // Apply metadata filters if provided
        if (filter) {
            knnQuery.filter = this.buildElasticFilter(filter);
        }

        const sourceFields = ['metadata'];
        if (includeVector) {
            sourceFields.push('vector');
        }

        const response = await this.client.search({
            index: indexName,
            knn: knnQuery,
            size: topK,
            _source: sourceFields,
        });

        const results = response.hits.hits.map((hit: any) =&gt; ({
            id: hit._id,
            score: hit._score || 0,
            metadata: hit._source?.metadata || {},
            vector: includeVector ? hit._source?.vector : undefined,
        }));

        this.logger?.debug(`Query returned ${results.length} results from "${indexName}"`);
        return results;
    } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        this.logger?.error(`Failed to query vectors from "${indexName}": ${errorMessage}`);
        throw new Error(`Failed to query vectors from "${indexName}": ${errorMessage}`);
    }
}<p>Por dentro do capô:</p><ul><li><p>Executa uma consulta <a href="https://www.elastic.co/docs/solutions/search/vector/knn">kNN</a> (k-vizinhos mais próximos) usando a API <code>knn</code> no Elasticsearch.</p></li><li><p>Recupera os K vetores mais semelhantes ao vetor de consulta de entrada.</p></li><li><p>Opcionalmente, aplica filtros de metadados para refinar os resultados (por exemplo, pesquisar apenas dentro de uma categoria ou intervalo de tempo específico).</p></li><li><p>Retorna resultados estruturados, incluindo o ID do documento, a pontuação de similaridade e os metadados armazenados.</p></li></ul><h2>Criando o agente de conhecimento</h2><p>Agora que vimos a conexão entre Mastra e Elasticsearch por meio da integração <code>ElasticVector</code> , vamos criar o próprio Agente de Conhecimento.</p><p>Dentro da pasta <code>agents</code>, crie um arquivo chamado <code>knowledge-agent.ts</code>. Podemos começar conectando nossas variáveis de ambiente e inicializando o cliente Elasticsearch.</p>import { Agent } from '@mastra/core/agent';
import { Memory } from '@mastra/memory';
import { openai } from '@ai-sdk/openai';
import { Client } from '@elastic/elasticsearch';
import { ElasticVector } from '../stores/elastic-store';
import dotenv from "dotenv";

dotenv.config();

const ELASTICSEARCH_ENDPOINT = process.env.ELASTICSEARCH_ENDPOINT;
const ELASTICSEARCH_API_KEY = process.env.ELASTICSEARCH_API_KEY;

//Error check for undefined credentials
if (!ELASTICSEARCH_ENDPOINT || !ELASTICSEARCH_API_KEY) {
  throw new Error('Missing Elasticsearch credentials');
}

//Check to see if a connection can be established
const testClient = new Client({
  node: ELASTICSEARCH_ENDPOINT,
  auth: { 
    apiKey: ELASTICSEARCH_API_KEY 
  },
});

try {
  await testClient.ping();
  console.log('Connected to Elasticsearch successfully');
} catch (error: unknown) {
  if (error instanceof Error) {
    console.error('Failed to connect to Elasticsearch:', error.message);
  } else {
    console.error('Failed to connect to Elasticsearch:', error);
  }
  process.exit(1);
}
//Initialize the Elasticsearch vector store
const vectorStore = new ElasticVector({
  node: ELASTICSEARCH_ENDPOINT,
  auth: {
    apiKey: ELASTICSEARCH_API_KEY,
  },
//Optional: Explicitly set to true if using Elasticsearch Serverless to skip auto-detection and improve startup time
//isServerless: true,
});<p>Aqui, nós:</p><ul><li><p>Use <code>dotenv</code> para carregar nossas variáveis do nosso arquivo <code>.env</code> .</p></li><li><p>Verifique se as credenciais do Elasticsearch estão sendo inseridas corretamente e, em seguida, poderemos estabelecer uma conexão bem-sucedida com o cliente.</p></li><li><p>Passe o endpoint do Elasticsearch e a chave da API para o construtor <code>ElasticVector</code> para criar uma instância do nosso armazenamento de vetores que definimos anteriormente.</p></li><li><p>Opcionalmente, especifique <code>isServerless: true</code> se estiver usando o Elasticsearch Serverless. Isso elimina a etapa de detecção automática e melhora o tempo de inicialização. Caso seja omitido, o adaptador detectará automaticamente o seu tipo de implantação na primeira utilização.</p></li></ul><p>Em seguida, podemos definir o agente usando a classe <code>Agent</code> do Mastra.</p>export const knowledgeAgent = new Agent({
    name: 'KnowledgeAgent',
    instructions: 'You are a helpful knowledge assistant.',
    model: openai('gpt-4o'),
    memory: new Memory({

        vector: vectorStore,

        //embedder used to create embeddings for each message
        embedder: 'openai/text-embedding-3-small',

        //set semantic recall options
        options: {
            semanticRecall: {
                topK: 3, // retrieve 3 similar messages
                messageRange: 2, // include 2 messages before/after each match
                scope: 'resource',
            },
        },
    }),
});<p>Os campos que podemos definir são:</p><ul><li><p><code>name</code> e <code>instructions</code>: Dê a ele uma identidade e uma função primária.</p></li><li><p><code>model</code>Estamos usando o <code>gpt-4o</code> da OpenAI por meio do pacote <code>@ai-sdk/openai</code> .</p></li><li><p><code>memory</code>:</p><ul><li><p><code>vector</code>: Aponta para o nosso armazenamento Elasticsearch, de onde os embeddings são armazenados e recuperados.</p></li><li><p><code>embedder</code>Qual modelo usar para gerar embeddings?</p></li><li><p><code>semanticRecall</code> As opções definem como funciona o recall:</p><ul><li><p><code>topK</code>Quantas mensagens semanticamente semelhantes devem ser recuperadas?</p></li><li><p><code>messageRange</code>: Qual a extensão da conversa a ser incluída em cada interação?</p></li><li><p><code>scope</code>Define o limite da memória.</p></li></ul></li></ul></li></ul><p>Quase pronto. Basta adicionarmos esse agente recém-criado à nossa configuração do Mastra. No arquivo chamado <a href="http://index.ts/"><code>index.ts</code></a>, importe o agente de conhecimento e insira-o no campo <code>agents</code> .</p>export const mastra = new Mastra({
  agents: { knowledgeAgent },
  storage: new LibSQLStore({
    // stores observability, scores, ... into memory storage, if it needs to persist, change to file:../mastra.db
    url: ":memory:",
  }),
  logger: new PinoLogger({
    name: 'Mastra',
    level: 'info',
  }),
  telemetry: {
    // Telemetry is deprecated and will be removed in the Nov 4th release
    enabled: false, 
  },
  observability: {
    // Enables DefaultExporter and CloudExporter for AI tracing
    default: { enabled: true }, 
  },
});<p>Os outros campos incluem:</p><ul><li><p><code>storage</code>Este é o repositório de dados interno do Mastra para histórico de execuções, métricas de observabilidade, pontuações e caches. Para obter mais informações sobre o sistema de armazenamento Mastra, visite <a href="https://mastra.ai/docs/server-db/storage">aqui</a>.</p></li><li><p><code>logger</code>O Mastra utiliza <a href="https://github.com/pinojs/pino">o Pino</a>, que é um registrador JSON estruturado e leve. Ele registra eventos como início e término de agentes, chamadas e resultados de ferramentas, erros e tempos de resposta do LLM.</p></li><li><p><code>observability</code>Controla o rastreamento de IA e a visibilidade da execução de agentes. Ele rastreia:</p><ul><li><p>Início/fim de cada etapa de raciocínio.</p></li><li><p>Qual modelo ou ferramenta foi utilizada?</p></li><li><p>Entradas e saídas.</p></li><li><p>Pontuações e avaliações</p></li></ul></li></ul><h3>Testando o agente com o Mastra Studio</h3><p>Parabéns! Se você chegou até aqui, está pronto para executar este agente e testar suas capacidades de recuperação semântica. Felizmente, o Mastra oferece uma interface de chat integrada, então não precisamos criar a nossa própria.</p><p>Para iniciar o servidor de desenvolvimento do Mastra, abra um terminal e execute o seguinte comando:</p>npm run dev<p>Após a inicialização e o empacotamento iniciais do servidor, você deverá receber um endereço para o Playground.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte5f857fddc74ffc9/6a16f7b6a6c2b995d5e794c0/8b045f70008d26aec4d2e6b59d61085555b9c5b2-686x116.png" alt="Endereço do servidor para Playground" /><p>Cole este endereço no seu navegador e você será direcionado para o Mastra Studio.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc7fdda6ce46ce068/6a16f7b7b0367d4f7672bacf/69bc80fe8486edd9e0cf91d87b39f465aeb23111-1600x438.png" alt="Colar o endereço do Playground para acessar o Mastra Studio" /><p>Selecione a opção <code>knowledgeAgent</code> e comece a conversar.</p><p>Para um teste rápido para verificar se tudo está conectado corretamente, forneça algumas informações como: "A equipe anunciou que o desempenho de vendas em outubro aumentou 12%, impulsionado principalmente por renovações de contratos corporativos." O próximo passo é expandir o alcance aos clientes de médio porte.” Em seguida, inicie um novo bate-papo e faça uma pergunta como: "Em qual segmento de clientes dissemos que precisamos nos concentrar a seguir?" O agente de conhecimento deve ser capaz de recordar as informações que você lhe forneceu na primeira conversa. Você deverá ver uma resposta semelhante a esta:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfec3266e81a7213b/6a16f7b92b835f6f70f4afe2/da8ebddad89874023ed440a8f1ad2cb04ed043f4-1070x288.png" alt="Ao conversar com um agente de conhecimento no Mastra Studio, o agente consegue recuperar informações." /><p>Ao recebermos uma resposta como essa, significa que o agente armazenou com sucesso nossa mensagem anterior como embeddings no Elasticsearch e a recuperou posteriormente usando a busca vetorial.</p><h3>Inspecionando o armazenamento de memória de longo prazo do agente.</h3><p>Acesse a aba <code>memory</code> na configuração do seu agente no Mastra Studio. Isso permite que você veja o que seu agente aprendeu ao longo do tempo. Cada mensagem, resposta e interação que é incorporada e armazenada no Elasticsearch passa a fazer parte dessa memória de longo prazo. Você pode realizar buscas semânticas em interações passadas para encontrar rapidamente informações ou contextos que o agente aprendeu anteriormente. Este é essencialmente o mesmo mecanismo que o agente usa durante a recuperação semântica, mas aqui você pode inspecioná-lo diretamente. No exemplo abaixo, estamos pesquisando o termo "vendas" e obtendo como resultado todas as interações que incluíram algo relacionado a vendas.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte428134d7bf2a43a/6a16f7bbb0367d185872bad3/3decaa0c332d288c5ae0b11c25f592c7d50c2f0f-1104x1320.png" alt="Como inspecionar o armazenamento de memória de longo prazo dos agentes de conhecimento" /><h2>Conclusão</h2><p>Ao conectar o Mastra e o Elasticsearch, podemos fornecer memória aos nossos agentes, o que é uma camada fundamental na engenharia de contexto. Com a recuperação semântica, os agentes podem construir contexto ao longo do tempo, fundamentando suas respostas no que aprenderam. Isso significa interações mais precisas, confiáveis e naturais.</p><p>Essa integração inicial é apenas o ponto de partida. O mesmo padrão pode permitir que agentes de suporte se lembrem de chamados anteriores, bots internos recuperem documentação relevante ou assistentes de IA consigam recordar detalhes do cliente no meio da conversa. Também estamos trabalhando para uma integração oficial com o Mastra, tornando essa combinação ainda mais perfeita em um futuro próximo.</p><p>Estamos ansiosos para ver o que você vai construir em seguida. Experimente, explore <a href="https://mastra.ai/">o Mastra</a> e seus recursos de memória e sinta-se à vontade para compartilhar suas descobertas com a comunidade.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/knowledge-agent-semantic-recall-mastra-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/knowledge-agent-semantic-recall-mastra-elasticsearch</guid>
    <category><![CDATA[IA agêntica]]></category>
    <category><![CDATA[Experiência do Desenvolvedor]]></category>
    <category><![CDATA[Integrações]]></category>
    <dc:creator><![CDATA[JD Armada]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt09afdbff05603865/6a16f7bd839dfabbf2dcfcb5/b8d51c2726d5573385c9246a7821d12ade4f1b0e-720x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Thu, 06 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>