Auto-hospedando Embeddings para DiscourseAI

O plugin Discourse AI possui muitos recursos que exigem embeddings (incorporações) para funcionar, como Tópicos Relacionados, Pesquisa por IA, Sugestão de Categoria e Tag pelo Auxiliar de IA, etc. Embora você possa usar uma API de terceiros, como Configurar Chaves de API para OpenAI, Configurar Chaves de API para Cloudflare Workers AI ou Configurar Chaves de API para Google Gemini, nós construímos o Discourse AI desde o primeiro dia para não ficarmos presos a eles.

Executando com HuggingFace TEI

O HuggingFace fornece uma imagem de contêiner incrível que pode colocá-lo em funcionamento rapidamente.

Por exemplo:

mkdir -p /opt/tei-cache
docker run --rm --gpus all --shm-size 1g -p 8081:80 \
  -v /opt/tei-cache:/data \
  ghcr.io/huggingface/text-embeddings-inference:latest \
  --model-id BAAI/bge-large-en-v1.5

Isso deve colocá-lo em funcionamento com uma instância local do BAAI/bge-large-en-v1.5, um modelo de código aberto com ótimo desempenho.

Você pode verificar se está funcionando com

curl -X POST \
  'http://localhost:8081/embed' \
  -H 'Content-Type: application/json' \
  -d '{ "inputs": "Testing string for embeddings" }'

O que deve retornar um array de floats em operação normal.

Tornando-o disponível para sua instância do Discourse

Na maioria das vezes, você estará executando isso em um servidor dedicado por causa do aumento de velocidade da GPU. Ao fazer isso, recomendo executar um proxy reverso, realizando terminação TLS e protegendo o endpoint para que ele só possa ser acessado pela sua instância do Discourse.

Configurando o DiscourseAI

O Discourse AI agora usa um sistema de definição de embedding totalmente configurável, semelhante à forma como os LLMs são configurados. Para configurar seu endpoint auto-hospedado:

  1. Navegue até Admin → Plugins → Discourse AI → Embeddings.
  2. Clique em New (Novo) para criar uma nova definição de embedding.
  3. Selecione um preset (predefinição) que corresponda ao seu modelo (ex: bge-large-en, bge-m3 ou multilingual-e5-large), ou escolha Configure manually (Configurar manualmente) para qualquer outro modelo.
  4. Defina a URL para apontar para seu servidor TEI auto-hospedado (ex: https://seu-servidor-tei:8081).
  5. Use o botão Test (Testar) para verificar a conectividade antes de salvar.
  6. Após salvar, defina ai_embeddings_selected_model para sua nova definição de embedding.

Após a configuração, o Discourse preencherá automaticamente os embeddings para tópicos existentes por meio de um trabalho em segundo plano agendado. Se você tiver um grande volume pendente, poderá aumentar a configuração oculta ai_embeddings_backfill_batch_size (padrão: 250) para processar os tópicos mais rapidamente.

11 curtidas

O modelo bge-m3 deve funcionar para sites multilíngues (ou não em inglês)?

Sim, joguei com ele na semana em que foi compartilhado silenciosamente no GitHub e funciona bem. Ainda estou esperando para ver como ele se sairá nos placares do MTEB, pois não estava lá na última vez que olhei.

Dito isso, temos grandes instâncias hospedadas do Discourse usando o plugin multilíngue que ele envia, e5, e ele tem um desempenho muito bom.

1 curtida

Obrigado, você tinha planos de habilitar endpoints personalizados de código aberto para incorporações? Estou tentando usar esses modelos no Huggingface.

Desculpe, não entendi o que você está tentando transmitir aqui. Este tópico é um guia sobre como executar modelos de código aberto para incorporações de IA do Discourse.

Ah, desculpe por isso. Estou tentando usar um modelo de código aberto do HuggingFace em um endpoint personalizado e me pergunto se isso é possível ou se está nos planos para habilitar em um futuro próximo :slight_smile:

Para verificar se está funcionando, o seguinte comando funciona para mim (com o modelo BAAI/bge-m3):

curl -X 'POST' \
  'http://localhost:8081/embed' \
  -H 'Content-Type: application/json' \
  -d '{ "inputs": "Testing string for embeddings"}'

Aliás, você também pode usar a interface web do Swagger em http://localhost:8081/docs/.

2 curtidas

Este também é um bom servidor de embeddings:

1 curtida

Para economizar espaço, é possível usar embeddings quantizados? Gostaria de usar embeddings quantizados binários para realmente reduzir o tamanho de armazenamento. Tendo feito alguns testes, obtenho mais de 90% de desempenho com 32x menos armazenamento!

1 curtida

Estamos armazenando embeddings usando meia precisão (metade do espaço de armazenamento) e usando quantização binária para índices (32x menores) por padrão há algumas semanas, portanto, basta atualizar seu site para a versão mais recente para obter uma redução considerável no uso de disco.

3 curtidas

Você poderia, por favor, também adicionar:

aos modelos de embedding suportados?

Planejamos tornar os embeddings configuráveis da mesma forma que fizemos com os LLMs, para que qualquer modelo seja compatível em breve.

4 curtidas

Se mais alguém tiver problemas com endpoints na rede local, por exemplo, 192.168.x.x - parece que eles são bloqueados pelo discourse (presumivelmente por razões de segurança) e o bloqueio precisa ser contornado. Perdi algumas horas descobrindo isso!

1 curtida

@Falco isso seria ótimo. Enquanto isso, se eu quisesse tentar adicionar um novo modelo de embedding, eu só preciso adicionar:

 lib/embeddings/vector_representations/mxbai-embed-xsmall-v1.rb
 lib/tokenizer/mxbai-embed-xsmall-v1.rb
 tokenizers/mxbai-embed-xsmall-v1.json

e modificar lib/embeddings/vector_representations/base.rb para incluir o novo modelo, ou há algo mais que eu precise mudar também?

@Falco Tentei adicionar o modelo e enviei um pull request. Desculpe se fiz algo errado, pois não sou realmente um desenvolvedor de SW. Eu esperava que você pudesse dar uma olhada e ver se está OK para inclusão.

Infelizmente, não consegui fazê-lo funcionar com o TEI. Consegui fazer o all-mpnet funcionar com o TEI, mas acho que há algo errado com o que fiz para fazer o mxbai funcionar.

Aliás, há alguma chance de dar suporte a https://github.com/michaelfeil/infinity como um servidor de embedding?

EDIT: Vejo que isso vai ser complicado, pois os índices HNSW no banco de dados parecem ser codificados, então novos modelos precisam ser anexados no final para evitar a interrupção da ordem e cada novo modelo precisa adicionar seu próprio índice.

Eu realmente recomendo esperar algumas semanas até que enviemos o suporte para embeddings configuráveis.

Isso deve funcionar bem quando enviarmos os embeddings configuráveis, mas por curiosidade, o que isso traria em relação a GitHub - huggingface/text-embeddings-inference: A blazing fast inference solution for text embeddings models?

Não acompanhei o TEI, então não mencionarei as vantagens que não testei recentemente, mas das coisas que vi recentemente:

  • Suporte de hardware: o infinity tem melhor suporte de GPU que o TEI
  • O servidor infinity pode hospedar múltiplos modelos de embedding em um único servidor (a menos que eu tenha perdido isso no TEI)

É muito bom. Se você ainda não experimentou, deveria dar uma olhada!

1 curtida

Um amigo acabou de me enviar este tópico por DM.

Alguns Prós/Contras:

  • o infinity suporta embeddings multimodais (ou seja, enviar imagens/áudio) para o
  • suporte a GPU amd
  • vários modelos suportados no mesmo contêiner (controle o modelo via parâmetro model).
  • mais dtypes, por exemplo, quantização int8 dos pesos (principalmente isso é irrelevante, a memória de ativação é maior)
  • novos modelos frequentemente são lançados via “código de modelagem personalizado” enviado no repositório huggingface. O Infinity lê este código pytorch, se necessário. Isso o ajudará a evitar o “você pode suportar modelos xyz” de forma contínua)
  • mais modelos suportados (por exemplo, debertav2 para mixedbread)

Contras:

  • o tempo de inicialização a frio do TEI é melhor
3 curtidas

Olá Michael :wave:

@roman tem estado ocupado reestruturando nossa configuração de embedding em:

Estaremos prontos muito em breve, e assim que isso for feito, adicionar suporte para infinity será trivial.

Ainda penso muito sobre embedding multimodel, ele te dá um atalho ao tentar fazer RAG em PDFs, pois você simplesmente o processa em imagens e incorpora cada imagem, evitando a necessidade de OCR ou caro processamento de imagem para texto com o LLM.

Assim que concluirmos este PR, ficaremos muito felizes em adicionar suporte para infinity (e suporte multimodel) à configuração de embedding.

Obrigado por aparecer :hugs:

4 curtidas

Fico imaginando se a criação de suporte ao litellm pode oferecer um atalho, pois assim você se beneficia de todos os modelos suportados via litellm. Outros projetos parecem incorporar isso.