mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-04-25 16:36:21 +02:00
Native CLI i18n: The TrustGraph CLI has built-in translation support that dynamically loads language strings. You can test and use different languages by simply passing the --lang flag (e.g., --lang es for Spanish, --lang ru for Russian) or by configuring your environment's LANG variable. Automated Docs Translations: This PR introduces autonomously translated Markdown documentation into several target languages, including Spanish, Swahili, Portuguese, Turkish, Hindi, Hebrew, Arabic, Simplified Chinese, and Russian.
675 lines
22 KiB
Markdown
675 lines
22 KiB
Markdown
---
|
|
layout: default
|
|
title: "Especificação Técnica de Processamento em Lote de Embeddings"
|
|
parent: "Portuguese (Beta)"
|
|
---
|
|
|
|
# Especificação Técnica de Processamento em Lote de Embeddings
|
|
|
|
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
|
|
|
## Visão Geral
|
|
|
|
Esta especificação descreve otimizações para o serviço de embeddings para suportar o processamento em lote de vários textos em um único pedido. A implementação atual processa um texto por vez, perdendo os benefícios de desempenho significativos que os modelos de embedding oferecem ao processar lotes.
|
|
|
|
1. **Ineficiência no Processamento de Texto Único**: A implementação atual envolve textos únicos em uma lista, subutilizando as capacidades de lote do FastEmbed.
|
|
2. **Sobrecarga de Pedido por Texto**: Cada texto requer uma viagem de ida e volta separada do Pulsar.
|
|
3. **Ineficiência na Inferência do Modelo**: Os modelos de embedding têm uma sobrecarga fixa por lote; lotes pequenos desperdiçam recursos de GPU/CPU.
|
|
4. **Processamento Serial nos Clientes**: Serviços importantes fazem loop sobre itens e chamam embeddings um de cada vez.
|
|
|
|
## Objetivos
|
|
|
|
**Suporte para API de Lote**: Permitir o processamento de vários textos em um único pedido.
|
|
**Compatibilidade com Versões Anteriores**: Manter o suporte para pedidos de texto único.
|
|
**Melhora Significativa no Desempenho**: Almejar uma melhora de desempenho de 5 a 10 vezes para operações em lote.
|
|
**Latência Reduzida por Texto**: Diminuir a latência amortizada ao incorporar vários textos.
|
|
**Eficiência de Memória**: Processar lotes sem consumo excessivo de memória.
|
|
**Independente do Provedor**: Suportar o processamento em lote em FastEmbed, Ollama e outros provedores.
|
|
**Migração do Cliente**: Atualizar todos os clientes de embedding para usar a API de lote sempre que for benéfico.
|
|
|
|
## Contexto
|
|
|
|
### Implementação Atual - Serviço de Embeddings
|
|
|
|
A implementação de embeddings em `trustgraph-flow/trustgraph/embeddings/fastembed/processor.py` apresenta uma ineficiência de desempenho significativa:
|
|
|
|
```python
|
|
# fastembed/processor.py line 56
|
|
async def on_embeddings(self, text, model=None):
|
|
use_model = model or self.default_model
|
|
self._load_model(use_model)
|
|
|
|
vecs = self.embeddings.embed([text]) # Single text wrapped in list
|
|
|
|
return [v.tolist() for v in vecs]
|
|
```
|
|
|
|
**Problemas:**
|
|
|
|
1. **Tamanho do Lote 1**: O método `embed()` do FastEmbed é otimizado para processamento em lote, mas sempre o chamamos com `[text]` - um lote de tamanho 1.
|
|
|
|
2. **Sobrecarga por Requisição**: Cada solicitação de incorporação incorre em:
|
|
Serialização/desserialização de mensagens Pulsar
|
|
Latência de ida e volta da rede
|
|
Sobrecarga de inicialização da inferência do modelo
|
|
Sobrecarga de agendamento assíncrono do Python
|
|
|
|
3. **Limitação do Esquema**: O esquema `EmbeddingsRequest` suporta apenas um único texto:
|
|
```python
|
|
@dataclass
|
|
class EmbeddingsRequest:
|
|
text: str = "" # Single text only
|
|
```
|
|
|
|
### Clientes Atuais - Processamento Serial
|
|
|
|
#### 1. Gateway de API
|
|
|
|
**Arquivo:** `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
|
|
|
O gateway aceita solicitações de incorporação de texto único via HTTP/WebSocket e as encaminha para o serviço de incorporação. Atualmente, não existe um endpoint para processamento em lote.
|
|
|
|
```python
|
|
class EmbeddingsRequestor(ServiceRequestor):
|
|
# Handles single EmbeddingsRequest -> EmbeddingsResponse
|
|
request_schema=EmbeddingsRequest, # Single text only
|
|
response_schema=EmbeddingsResponse,
|
|
```
|
|
|
|
**Impacto:** Clientes externos (aplicativos web, scripts) devem fazer N requisições HTTP para incorporar N textos.
|
|
|
|
#### 2. Serviço de Incorporação de Documentos
|
|
|
|
**Arquivo:** `trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
|
|
|
Processa blocos de documentos um de cada vez:
|
|
|
|
```python
|
|
async def on_message(self, msg, consumer, flow):
|
|
v = msg.value()
|
|
|
|
# Single chunk per request
|
|
resp = await flow("embeddings-request").request(
|
|
EmbeddingsRequest(text=v.chunk)
|
|
)
|
|
vectors = resp.vectors
|
|
```
|
|
|
|
**Impacto:** Cada trecho de documento requer uma chamada de embedding separada. Um documento com 100 trechos = 100 requisições de embedding.
|
|
|
|
#### 3. Serviço de Embeddings de Grafos
|
|
|
|
**Arquivo:** `trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
|
|
|
Percorre as entidades e incorpora cada uma sequencialmente:
|
|
|
|
```python
|
|
async def on_message(self, msg, consumer, flow):
|
|
for entity in v.entities:
|
|
# Serial embedding - one entity at a time
|
|
vectors = await flow("embeddings-request").embed(
|
|
text=entity.context
|
|
)
|
|
entities.append(EntityEmbeddings(
|
|
entity=entity.entity,
|
|
vectors=vectors,
|
|
chunk_id=entity.chunk_id,
|
|
))
|
|
```
|
|
|
|
**Impacto:** Uma mensagem com 50 entidades = 50 solicitações de incorporação serial. Isso é um grande gargalo durante a construção do grafo de conhecimento.
|
|
|
|
#### 4. Serviço de Incorporação de Linhas
|
|
|
|
**Arquivo:** `trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
|
|
|
Percorre textos únicos e incorpora cada um serialmente:
|
|
|
|
```python
|
|
async def on_message(self, msg, consumer, flow):
|
|
for text, (index_name, index_value) in texts_to_embed.items():
|
|
# Serial embedding - one text at a time
|
|
vectors = await flow("embeddings-request").embed(text=text)
|
|
|
|
embeddings_list.append(RowIndexEmbedding(
|
|
index_name=index_name,
|
|
index_value=index_value,
|
|
text=text,
|
|
vectors=vectors
|
|
))
|
|
```
|
|
|
|
**Impacto:** Processar uma tabela com 100 valores indexados únicos = 100 solicitações de incorporação seriais.
|
|
|
|
#### 5. EmbeddingsClient (Cliente Base)
|
|
|
|
**Arquivo:** `trustgraph-base/trustgraph/base/embeddings_client.py`
|
|
|
|
O cliente usado por todos os processadores de fluxo suporta apenas a incorporação de texto único:
|
|
|
|
```python
|
|
class EmbeddingsClient(RequestResponse):
|
|
async def embed(self, text, timeout=30):
|
|
resp = await self.request(
|
|
EmbeddingsRequest(text=text), # Single text
|
|
timeout=timeout
|
|
)
|
|
return resp.vectors
|
|
```
|
|
|
|
**Impacto:** Todos os clientes que utilizam este componente estão limitados a operações de texto único.
|
|
|
|
#### 6. Ferramentas de Linha de Comando
|
|
|
|
**Arquivo:** `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
|
|
|
A ferramenta de linha de comando aceita um único argumento de texto:
|
|
|
|
```python
|
|
def query(url, flow_id, text, token=None):
|
|
result = flow.embeddings(text=text) # Single text
|
|
vectors = result.get("vectors", [])
|
|
```
|
|
|
|
**Impacto:** Os usuários não podem realizar incorporações em lote a partir da linha de comando. O processamento de um arquivo de textos requer N invocações.
|
|
|
|
#### 7. SDK Python
|
|
|
|
O SDK Python fornece duas classes de cliente para interagir com os serviços da TrustGraph. Ambas suportam apenas a incorporação de um único texto.
|
|
|
|
**Arquivo:** `trustgraph-base/trustgraph/api/flow.py`
|
|
|
|
```python
|
|
class FlowInstance:
|
|
def embeddings(self, text):
|
|
"""Get embeddings for a single text"""
|
|
input = {"text": text}
|
|
return self.request("service/embeddings", input)["vectors"]
|
|
```
|
|
|
|
**Arquivo:** `trustgraph-base/trustgraph/api/socket_client.py`
|
|
|
|
```python
|
|
class SocketFlowInstance:
|
|
def embeddings(self, text: str, **kwargs: Any) -> Dict[str, Any]:
|
|
"""Get embeddings for a single text via WebSocket"""
|
|
request = {"text": text}
|
|
return self.client._send_request_sync(
|
|
"embeddings", self.flow_id, request, False
|
|
)
|
|
```
|
|
|
|
**Impacto:** Desenvolvedores Python que usam o SDK precisam iterar sobre textos e fazer N chamadas de API separadas. Não existe suporte para processamento em lote de embeddings para usuários do SDK.
|
|
|
|
### Impacto no Desempenho
|
|
|
|
Para ingestão típica de documentos (1000 trechos de texto):
|
|
**Atual:** 1000 requisições separadas, 1000 chamadas de inferência de modelo
|
|
**Em lote (batch_size=32):** 32 requisições, 32 chamadas de inferência de modelo (redução de 96,8%)
|
|
|
|
Para embedding de grafos (mensagem com 50 entidades):
|
|
**Atual:** 50 chamadas `await` sequenciais, ~5-10 segundos
|
|
**Em lote:** 1-2 chamadas em lote, ~0,5-1 segundo (melhora de 5-10x)
|
|
|
|
Bibliotecas como FastEmbed e similares alcançam escalabilidade quase linear no throughput com o tamanho do lote, até os limites do hardware (tipicamente 32-128 textos por lote).
|
|
|
|
## Design Técnico
|
|
|
|
### Arquitetura
|
|
|
|
A otimização de processamento em lote de embeddings requer alterações nos seguintes componentes:
|
|
|
|
#### 1. **Aprimoramento do Esquema**
|
|
Estender `EmbeddingsRequest` para suportar múltiplos textos
|
|
Estender `EmbeddingsResponse` para retornar múltiplos conjuntos de vetores
|
|
Manter a compatibilidade retroativa com requisições de texto único
|
|
|
|
Módulo: `trustgraph-base/trustgraph/schema/services/llm.py`
|
|
|
|
#### 2. **Aprimoramento do Serviço Base**
|
|
Atualizar `EmbeddingsService` para lidar com requisições em lote
|
|
Adicionar configuração do tamanho do lote
|
|
Implementar tratamento de requisições com suporte a lote
|
|
|
|
Módulo: `trustgraph-base/trustgraph/base/embeddings_service.py`
|
|
|
|
#### 3. **Atualizações do Processador do Provedor**
|
|
Atualizar o processador FastEmbed para passar o lote completo para `embed()`
|
|
Atualizar o processador Ollama para lidar com lotes (se suportado)
|
|
Adicionar processamento sequencial como fallback para provedores sem suporte a lote
|
|
|
|
Módulos:
|
|
`trustgraph-flow/trustgraph/embeddings/fastembed/processor.py`
|
|
`trustgraph-flow/trustgraph/embeddings/ollama/processor.py`
|
|
|
|
#### 4. **Aprimoramento do Cliente**
|
|
Adicionar método de embedding em lote para `EmbeddingsClient`
|
|
Suportar APIs de texto único e em lote
|
|
Adicionar agrupamento automático para grandes entradas
|
|
|
|
Módulo: `trustgraph-base/trustgraph/base/embeddings_client.py`
|
|
|
|
#### 5. **Atualizações do Chamador - Processadores de Fluxo**
|
|
Atualizar `graph_embeddings` para agrupar contextos de entidades
|
|
Atualizar `row_embeddings` para agrupar textos de índice
|
|
Atualizar `document_embeddings` se o agrupamento de mensagens for viável
|
|
|
|
Módulos:
|
|
`trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
|
`trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
|
`trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
|
|
|
#### 6. **Aprimoramento do Gateway de API**
|
|
Adicionar endpoint de embedding em lote
|
|
Suportar array de textos no corpo da requisição
|
|
|
|
Módulo: `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
|
|
|
#### 7. **Aprimoramento da Ferramenta de Linha de Comando (CLI)**
|
|
Adicionar suporte para múltiplos textos ou entrada de arquivo
|
|
Adicionar parâmetro de tamanho do lote
|
|
|
|
Módulo: `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
|
|
|
#### 8. **Aprimoramento do SDK Python**
|
|
Adicionar método `embeddings_batch()` para `FlowInstance`
|
|
Adicionar método `embeddings_batch()` para `SocketFlowInstance`
|
|
Suportar APIs de texto único e em lote para usuários do SDK
|
|
|
|
Módulos:
|
|
`trustgraph-base/trustgraph/api/flow.py`
|
|
`trustgraph-base/trustgraph/api/socket_client.py`
|
|
|
|
### Modelos de Dados
|
|
|
|
#### EmbeddingsRequest
|
|
|
|
```python
|
|
@dataclass
|
|
class EmbeddingsRequest:
|
|
texts: list[str] = field(default_factory=list)
|
|
```
|
|
|
|
Uso:
|
|
Texto único: `EmbeddingsRequest(texts=["hello world"])`
|
|
Lote: `EmbeddingsRequest(texts=["text1", "text2", "text3"])`
|
|
|
|
#### EmbeddingsResponse
|
|
|
|
```python
|
|
@dataclass
|
|
class EmbeddingsResponse:
|
|
error: Error | None = None
|
|
vectors: list[list[list[float]]] = field(default_factory=list)
|
|
```
|
|
|
|
Estrutura da resposta:
|
|
`vectors[i]` contém o conjunto de vetores para `texts[i]`
|
|
Cada conjunto de vetores é `list[list[float]]` (os modelos podem retornar vários vetores por texto)
|
|
Exemplo: 3 textos → `vectors` tem 3 entradas, cada uma contendo os embeddings desse texto
|
|
|
|
### APIs
|
|
|
|
#### EmbeddingsClient
|
|
|
|
```python
|
|
class EmbeddingsClient(RequestResponse):
|
|
async def embed(
|
|
self,
|
|
texts: list[str],
|
|
timeout: float = 300,
|
|
) -> list[list[list[float]]]:
|
|
"""
|
|
Embed one or more texts in a single request.
|
|
|
|
Args:
|
|
texts: List of texts to embed
|
|
timeout: Timeout for the operation
|
|
|
|
Returns:
|
|
List of vector sets, one per input text
|
|
"""
|
|
resp = await self.request(
|
|
EmbeddingsRequest(texts=texts),
|
|
timeout=timeout
|
|
)
|
|
if resp.error:
|
|
raise RuntimeError(resp.error.message)
|
|
return resp.vectors
|
|
```
|
|
|
|
#### Endpoint de Incorporação do Gateway de API
|
|
|
|
Endpoint atualizado que suporta incorporação única ou em lote:
|
|
|
|
```
|
|
POST /api/v1/embeddings
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"texts": ["text1", "text2", "text3"],
|
|
"flow_id": "default"
|
|
}
|
|
|
|
Response:
|
|
{
|
|
"vectors": [
|
|
[[0.1, 0.2, ...]],
|
|
[[0.3, 0.4, ...]],
|
|
[[0.5, 0.6, ...]]
|
|
]
|
|
}
|
|
```
|
|
|
|
### Detalhes de Implementação
|
|
|
|
#### Fase 1: Alterações no Esquema
|
|
|
|
**EmbeddingsRequest:**
|
|
```python
|
|
@dataclass
|
|
class EmbeddingsRequest:
|
|
texts: list[str] = field(default_factory=list)
|
|
```
|
|
|
|
**EmbeddingsResponse:**
|
|
```python
|
|
@dataclass
|
|
class EmbeddingsResponse:
|
|
error: Error | None = None
|
|
vectors: list[list[list[float]]] = field(default_factory=list)
|
|
```
|
|
|
|
**Atualizado EmbeddingsService.on_request:**
|
|
```python
|
|
async def on_request(self, msg, consumer, flow):
|
|
request = msg.value()
|
|
id = msg.properties()["id"]
|
|
model = flow("model")
|
|
|
|
vectors = await self.on_embeddings(request.texts, model=model)
|
|
response = EmbeddingsResponse(error=None, vectors=vectors)
|
|
|
|
await flow("response").send(response, properties={"id": id})
|
|
```
|
|
|
|
#### Fase 2: Atualização do Processador FastEmbed
|
|
|
|
**Atual (Ineficiente):**
|
|
```python
|
|
async def on_embeddings(self, text, model=None):
|
|
use_model = model or self.default_model
|
|
self._load_model(use_model)
|
|
vecs = self.embeddings.embed([text]) # Batch of 1
|
|
return [v.tolist() for v in vecs]
|
|
```
|
|
|
|
**Atualizado:**
|
|
```python
|
|
async def on_embeddings(self, texts: list[str], model=None):
|
|
"""Embed texts - processes all texts in single model call"""
|
|
if not texts:
|
|
return []
|
|
|
|
use_model = model or self.default_model
|
|
self._load_model(use_model)
|
|
|
|
# FastEmbed handles the full batch efficiently
|
|
all_vecs = list(self.embeddings.embed(texts))
|
|
|
|
# Return list of vector sets, one per input text
|
|
return [[v.tolist()] for v in all_vecs]
|
|
```
|
|
|
|
#### Fase 3: Atualização do Serviço de Incorporação de Grafos
|
|
|
|
**Atual (Serial):**
|
|
```python
|
|
async def on_message(self, msg, consumer, flow):
|
|
entities = []
|
|
for entity in v.entities:
|
|
vectors = await flow("embeddings-request").embed(text=entity.context)
|
|
entities.append(EntityEmbeddings(...))
|
|
```
|
|
|
|
**Atualizado (Lote):**
|
|
```python
|
|
async def on_message(self, msg, consumer, flow):
|
|
# Collect all contexts
|
|
contexts = [entity.context for entity in v.entities]
|
|
|
|
# Single batch embedding call
|
|
all_vectors = await flow("embeddings-request").embed(texts=contexts)
|
|
|
|
# Pair results with entities
|
|
entities = [
|
|
EntityEmbeddings(
|
|
entity=entity.entity,
|
|
vectors=vectors[0], # First vector from the set
|
|
chunk_id=entity.chunk_id,
|
|
)
|
|
for entity, vectors in zip(v.entities, all_vectors)
|
|
]
|
|
```
|
|
|
|
#### Fase 4: Atualização do Serviço de Incorporação de Dados
|
|
|
|
**Atual (Serial):**
|
|
```python
|
|
for text, (index_name, index_value) in texts_to_embed.items():
|
|
vectors = await flow("embeddings-request").embed(text=text)
|
|
embeddings_list.append(RowIndexEmbedding(...))
|
|
```
|
|
|
|
**Atualizado (Lote):**
|
|
```python
|
|
# Collect texts and metadata
|
|
texts = list(texts_to_embed.keys())
|
|
metadata = list(texts_to_embed.values())
|
|
|
|
# Single batch embedding call
|
|
all_vectors = await flow("embeddings-request").embed(texts=texts)
|
|
|
|
# Pair results
|
|
embeddings_list = [
|
|
RowIndexEmbedding(
|
|
index_name=meta[0],
|
|
index_value=meta[1],
|
|
text=text,
|
|
vectors=vectors[0] # First vector from the set
|
|
)
|
|
for text, meta, vectors in zip(texts, metadata, all_vectors)
|
|
]
|
|
```
|
|
|
|
#### Fase 5: Melhoria da Ferramenta de Linha de Comando (CLI)
|
|
|
|
**CLI Atualizado:**
|
|
```python
|
|
def main():
|
|
parser = argparse.ArgumentParser(...)
|
|
|
|
parser.add_argument(
|
|
'text',
|
|
nargs='*', # Zero or more texts
|
|
help='Text(s) to convert to embedding vectors',
|
|
)
|
|
|
|
parser.add_argument(
|
|
'-f', '--file',
|
|
help='File containing texts (one per line)',
|
|
)
|
|
|
|
parser.add_argument(
|
|
'--batch-size',
|
|
type=int,
|
|
default=32,
|
|
help='Batch size for processing (default: 32)',
|
|
)
|
|
```
|
|
|
|
Uso:
|
|
```bash
|
|
# Single text (existing)
|
|
tg-invoke-embeddings "hello world"
|
|
|
|
# Multiple texts
|
|
tg-invoke-embeddings "text one" "text two" "text three"
|
|
|
|
# From file
|
|
tg-invoke-embeddings -f texts.txt --batch-size 64
|
|
```
|
|
|
|
#### Fase 6: Melhoria do SDK Python
|
|
|
|
**FlowInstance (cliente HTTP):**
|
|
|
|
```python
|
|
class FlowInstance:
|
|
def embeddings(self, texts: list[str]) -> list[list[list[float]]]:
|
|
"""
|
|
Get embeddings for one or more texts.
|
|
|
|
Args:
|
|
texts: List of texts to embed
|
|
|
|
Returns:
|
|
List of vector sets, one per input text
|
|
"""
|
|
input = {"texts": texts}
|
|
return self.request("service/embeddings", input)["vectors"]
|
|
```
|
|
|
|
**SocketFlowInstance (cliente WebSocket):**
|
|
|
|
```python
|
|
class SocketFlowInstance:
|
|
def embeddings(self, texts: list[str], **kwargs: Any) -> list[list[list[float]]]:
|
|
"""
|
|
Get embeddings for one or more texts via WebSocket.
|
|
|
|
Args:
|
|
texts: List of texts to embed
|
|
|
|
Returns:
|
|
List of vector sets, one per input text
|
|
"""
|
|
request = {"texts": texts}
|
|
response = self.client._send_request_sync(
|
|
"embeddings", self.flow_id, request, False
|
|
)
|
|
return response["vectors"]
|
|
```
|
|
|
|
**Exemplos de uso do SDK:**
|
|
|
|
```python
|
|
# Single text
|
|
vectors = flow.embeddings(["hello world"])
|
|
print(f"Dimensions: {len(vectors[0][0])}")
|
|
|
|
# Batch embedding
|
|
texts = ["text one", "text two", "text three"]
|
|
all_vectors = flow.embeddings(texts)
|
|
|
|
# Process results
|
|
for text, vecs in zip(texts, all_vectors):
|
|
print(f"{text}: {len(vecs[0])} dimensions")
|
|
```
|
|
|
|
## Considerações de Segurança
|
|
|
|
**Limites de Tamanho da Requisição**: Impor o tamanho máximo do lote para evitar o esgotamento de recursos.
|
|
**Tratamento de Tempo Limite (Timeout)**: Ajustar os tempos limite de acordo com o tamanho do lote.
|
|
**Limites de Memória**: Monitorar o uso de memória para grandes lotes.
|
|
**Validação de Entrada**: Validar todos os textos no lote antes do processamento.
|
|
|
|
## Considerações de Desempenho
|
|
|
|
### Melhorias Esperadas
|
|
|
|
**Taxa de Transferência (Throughput):**
|
|
Texto único: ~10-50 textos/segundo (dependendo do modelo)
|
|
Lote (tamanho 32): ~200-500 textos/segundo (melhora de 5 a 10 vezes)
|
|
|
|
**Latência por Texto:**
|
|
Texto único: 50-200ms por texto
|
|
Lote (tamanho 32): 5-20ms por texto (média)
|
|
|
|
**Melhorias Específicas do Serviço:**
|
|
|
|
| Serviço | Atual | Em Lote | Melhoria |
|
|
|---------|---------|---------|-------------|
|
|
| Incorporações de Grafos (50 entidades) | 5-10s | 0,5-1s | 5-10x |
|
|
| Incorporações de Linhas (100 textos) | 10-20s | 1-2s | 5-10x |
|
|
| Ingestão de Documentos (1000 fragmentos) | 100-200s | 10-30s | 5-10x |
|
|
|
|
### Parâmetros de Configuração
|
|
|
|
```python
|
|
# Recommended defaults
|
|
DEFAULT_BATCH_SIZE = 32
|
|
MAX_BATCH_SIZE = 128
|
|
BATCH_TIMEOUT_MULTIPLIER = 2.0
|
|
```
|
|
|
|
## Estratégia de Testes
|
|
|
|
### Testes Unitários
|
|
Incorporação de texto única (compatibilidade com versões anteriores)
|
|
Tratamento de lotes vazios
|
|
Imposição do tamanho máximo do lote
|
|
Tratamento de erros para falhas parciais do lote
|
|
|
|
### Testes de Integração
|
|
Incorporação de lote de ponta a ponta através do Pulsar
|
|
Processamento de lote do serviço de incorporação de grafos
|
|
Processamento de lote do serviço de incorporação de linhas
|
|
Endpoint de lote do gateway de API
|
|
|
|
### Testes de Desempenho
|
|
Comparação de benchmark de taxa de transferência única versus lote
|
|
Uso de memória sob vários tamanhos de lote
|
|
Análise da distribuição de latência
|
|
|
|
## Plano de Migração
|
|
|
|
Esta é uma versão que introduz alterações significativas. Todas as fases são implementadas juntas.
|
|
|
|
### Fase 1: Alterações no Esquema
|
|
Substituir `text: str` por `texts: list[str]` em EmbeddingsRequest
|
|
Alterar o tipo de `vectors` para `list[list[list[float]]]` em EmbeddingsResponse
|
|
|
|
### Fase 2: Atualizações do Processador
|
|
Atualizar a assinatura de `on_embeddings` nos processadores FastEmbed e Ollama
|
|
Processar o lote completo em uma única chamada de modelo
|
|
|
|
### Fase 3: Atualizações do Cliente
|
|
Atualizar `EmbeddingsClient.embed()` para aceitar `texts: list[str]`
|
|
|
|
### Fase 4: Atualizações do Chamador
|
|
Atualizar graph_embeddings para incorporar contextos de entidades em lote
|
|
Atualizar row_embeddings para incorporar textos de índice em lote
|
|
Atualizar document_embeddings para usar o novo esquema
|
|
Atualizar a ferramenta de linha de comando (CLI)
|
|
|
|
### Fase 5: Gateway de API
|
|
Atualizar o endpoint de incorporação para o novo esquema
|
|
|
|
### Fase 6: SDK Python
|
|
Atualizar a assinatura de `FlowInstance.embeddings()`
|
|
Atualizar a assinatura de `SocketFlowInstance.embeddings()`
|
|
|
|
## Perguntas Abertas
|
|
|
|
**Incorporação de Lotes Grandes em Streaming**: Devemos suportar o streaming de resultados para lotes muito grandes (>100 textos)?
|
|
**Limites Específicos do Provedor**: Como devemos lidar com provedores com tamanhos máximos de lote diferentes?
|
|
**Tratamento de Falhas Parciais**: Se um texto em um lote falhar, devemos falhar o lote inteiro ou retornar resultados parciais?
|
|
**Incorporação em Lote de Documentos**: Devemos incorporar em lote em várias mensagens de Chunk ou manter o processamento por mensagem?
|
|
|
|
## Referências
|
|
|
|
[Documentação do FastEmbed](https://github.com/qdrant/fastembed)
|
|
[API de Incorporação do Ollama](https://github.com/ollama/ollama)
|
|
[Implementação do Serviço de Incorporação](trustgraph-base/trustgraph/base/embeddings_service.py)
|
|
[Otimização de Desempenho do GraphRAG](graphrag-performance-optimization.md)
|