mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-04-25 08:26: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
30 KiB
Markdown
675 lines
30 KiB
Markdown
---
|
||
layout: default
|
||
title: "Техническая спецификация пакетной обработки эмбеддингов"
|
||
parent: "Russian (Beta)"
|
||
---
|
||
|
||
# Техническая спецификация пакетной обработки эмбеддингов
|
||
|
||
> **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.
|
||
|
||
## Обзор
|
||
|
||
Эта спецификация описывает оптимизации для сервиса эмбеддингов, предназначенные для поддержки пакетной обработки нескольких текстов в одном запросе. Текущая реализация обрабатывает один текст за раз, что не позволяет использовать значительные преимущества, которые предоставляют модели эмбеддингов при обработке пакетов.
|
||
|
||
1. **Неэффективность обработки одного текста**: Текущая реализация оборачивает отдельные тексты в список, что не позволяет в полной мере использовать возможности пакетной обработки FastEmbed.
|
||
2. **Накладные расходы на запрос для каждого текста**: Для каждого текста требуется отдельная передача сообщения Pulsar.
|
||
3. **Неэффективность вывода модели**: Модели эмбеддингов имеют фиксированные накладные расходы на пакет; небольшие пакеты приводят к неэффективному использованию ресурсов GPU/CPU.
|
||
4. **Последовательная обработка в вызывающих сервисах**: Основные сервисы перебирают элементы и вызывают эмбеддинги по одному.
|
||
|
||
## Цели
|
||
|
||
**Поддержка пакетного API**: Обеспечить возможность обработки нескольких текстов в одном запросе.
|
||
**Обратная совместимость**: Сохранить поддержку запросов для обработки одного текста.
|
||
**Значительное повышение производительности**: Стремиться к увеличению производительности в 5-10 раз для массовых операций.
|
||
**Снижение задержки на текст**: Уменьшить среднюю задержку при создании эмбеддингов для нескольких текстов.
|
||
**Эффективность использования памяти**: Обрабатывать пакеты без чрезмерного потребления памяти.
|
||
**Независимость от провайдера**: Поддерживать пакетную обработку для FastEmbed, Ollama и других провайдеров.
|
||
**Миграция вызывающих сервисов**: Обновить все сервисы, вызывающие эмбеддинги, для использования пакетного API, где это целесообразно.
|
||
|
||
## Контекст
|
||
|
||
### Текущая реализация - Сервис эмбеддингов
|
||
|
||
Реализация эмбеддингов в `trustgraph-flow/trustgraph/embeddings/fastembed/processor.py` демонстрирует значительную неэффективность:
|
||
|
||
```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]
|
||
```
|
||
|
||
**Проблемы:**
|
||
|
||
1. **Размер пакета 1**: Метод `embed()` FastEmbed оптимизирован для пакетной обработки, но мы всегда вызываем его с `[text]` - пакетом размера 1.
|
||
|
||
2. **Накладные расходы на каждый запрос**: Каждый запрос на получение эмбеддингов влечет за собой:
|
||
Сериализацию/десериализацию сообщения Pulsar.
|
||
Задержку сетевого обмена.
|
||
Накладные расходы на запуск инференса модели.
|
||
Накладные расходы на асинхронное планирование Python.
|
||
|
||
3. **Ограничение схемы**: Схема `EmbeddingsRequest` поддерживает только один текстовый фрагмент:
|
||
```python
|
||
@dataclass
|
||
class EmbeddingsRequest:
|
||
text: str = "" # Single text only
|
||
```
|
||
|
||
### Текущие вызывающие стороны - последовательная обработка
|
||
|
||
#### 1. API-шлюз
|
||
|
||
**Файл:** `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
||
|
||
Шлюз принимает запросы на однострочное создание векторных представлений через HTTP/WebSocket и перенаправляет их в сервис создания векторных представлений. В настоящее время нет пакетного интерфейса.
|
||
|
||
```python
|
||
class EmbeddingsRequestor(ServiceRequestor):
|
||
# Handles single EmbeddingsRequest -> EmbeddingsResponse
|
||
request_schema=EmbeddingsRequest, # Single text only
|
||
response_schema=EmbeddingsResponse,
|
||
```
|
||
|
||
**Влияние:** Внешние клиенты (веб-приложения, скрипты) должны выполнять N HTTP-запросов для встраивания N текстов.
|
||
|
||
#### 2. Сервис встраивания документов
|
||
|
||
**Файл:** `trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
||
|
||
Обрабатывает фрагменты документов по одному.
|
||
|
||
```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
|
||
```
|
||
|
||
**Влияние:** Каждый фрагмент документа требует отдельного вызова для создания эмбеддинга. Документ, состоящий из 100 фрагментов, = 100 запросов на создание эмбеддингов.
|
||
|
||
#### 3. Сервис создания графовых эмбеддингов
|
||
|
||
**Файл:** `trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
||
|
||
Выполняет итерации по сущностям и создает эмбеддинг для каждой из них последовательно:
|
||
|
||
```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,
|
||
))
|
||
```
|
||
|
||
**Влияние:** Сообщение, содержащее 50 сущностей, приводит к 50 последовательным запросам на создание векторных представлений. Это серьезное препятствие при построении графа знаний.
|
||
|
||
#### 4. Сервис создания векторных представлений строк
|
||
|
||
**Файл:** `trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
||
|
||
Выполняет итерации по уникальным текстам и создает векторное представление для каждого из них последовательно:
|
||
|
||
```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
|
||
))
|
||
```
|
||
|
||
**Влияние:** Обработка таблицы с 100 уникальными индексированными значениями = 100 последовательных запросов на создание векторных представлений.
|
||
|
||
#### 5. EmbeddingsClient (Базовый клиент)
|
||
|
||
**Файл:** `trustgraph-base/trustgraph/base/embeddings_client.py`
|
||
|
||
Клиент, используемый всеми процессорами потоков, поддерживает только создание векторных представлений для одного текстового фрагмента:
|
||
|
||
```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
|
||
```
|
||
|
||
**Влияние:** Все клиенты, использующие этот компонент, ограничены операциями с одним текстовым фрагментом.
|
||
|
||
#### 6. Инструменты командной строки
|
||
|
||
**Файл:** `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
||
|
||
Инструмент командной строки принимает один текстовый аргумент:
|
||
|
||
```python
|
||
def query(url, flow_id, text, token=None):
|
||
result = flow.embeddings(text=text) # Single text
|
||
vectors = result.get("vectors", [])
|
||
```
|
||
|
||
**Влияние:** Пользователи не могут выполнять пакетную вставку из командной строки. Обработка файла текстов требует N вызовов.
|
||
|
||
#### 7. Python SDK
|
||
|
||
Python SDK предоставляет два клиентских класса для взаимодействия со службами TrustGraph. Оба поддерживают только вставку одного текста.
|
||
|
||
**Файл:** `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"]
|
||
```
|
||
|
||
**Файл:** `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
|
||
)
|
||
```
|
||
|
||
**Влияние:** Разработчикам Python, использующим SDK, необходимо перебирать тексты и выполнять N отдельных API-запросов. Поддержка пакетной обработки векторов для пользователей SDK отсутствует.
|
||
|
||
### Влияние на производительность
|
||
|
||
Для типичного извлечения данных (1000 текстовых фрагментов):
|
||
**Текущая ситуация:** 1000 отдельных запросов, 1000 вызовов модели для получения векторов.
|
||
**Пакетная обработка (batch_size=32):** 32 запроса, 32 вызова модели для получения векторов (снижение на 96,8%).
|
||
|
||
Для получения векторов графа (сообщение с 50 сущностями):
|
||
**Текущая ситуация:** 50 последовательных вызовов `await`, ~5-10 секунд.
|
||
**Пакетная обработка:** 1-2 пакетных вызова, ~0,5-1 секунда (улучшение в 5-10 раз).
|
||
|
||
Библиотеки FastEmbed и аналогичные достигают почти линейного увеличения производительности при увеличении размера пакета до пределов аппаратного обеспечения (обычно 32-128 текстов на пакет).
|
||
|
||
## Техническое проектирование
|
||
|
||
### Архитектура
|
||
|
||
Оптимизация пакетной обработки векторов требует изменений в следующих компонентах:
|
||
|
||
#### 1. **Улучшение схемы данных**
|
||
Расширить `EmbeddingsRequest` для поддержки нескольких текстов.
|
||
Расширить `EmbeddingsResponse` для возврата нескольких наборов векторов.
|
||
Сохранить обратную совместимость с запросами для одного текста.
|
||
|
||
Модуль: `trustgraph-base/trustgraph/schema/services/llm.py`
|
||
|
||
#### 2. **Улучшение базового сервиса**
|
||
Обновить `EmbeddingsService` для обработки пакетных запросов.
|
||
Добавить конфигурацию размера пакета.
|
||
Реализовать обработку запросов с учетом пакетной обработки.
|
||
|
||
Модуль: `trustgraph-base/trustgraph/base/embeddings_service.py`
|
||
|
||
#### 3. **Обновления для процессоров провайдеров**
|
||
Обновить процессор FastEmbed для передачи полного пакета в `embed()`.
|
||
Обновить процессор Ollama для обработки пакетов (если поддерживается).
|
||
Добавить последовательную обработку в качестве запасного варианта для провайдеров, не поддерживающих пакетную обработку.
|
||
|
||
Модули:
|
||
`trustgraph-flow/trustgraph/embeddings/fastembed/processor.py`
|
||
`trustgraph-flow/trustgraph/embeddings/ollama/processor.py`
|
||
|
||
#### 4. **Улучшение клиентской библиотеки**
|
||
Добавить метод пакетной обработки векторов в `EmbeddingsClient`.
|
||
Поддерживать как одиночные, так и пакетные API.
|
||
Добавить автоматическую пакетную обработку для больших входных данных.
|
||
|
||
Модуль: `trustgraph-base/trustgraph/base/embeddings_client.py`
|
||
|
||
#### 5. **Обновления для вызывающего кода - процессоров потоков**
|
||
Обновить `graph_embeddings` для пакетной обработки контекстов сущностей.
|
||
Обновить `row_embeddings` для пакетной обработки текстов для индексации.
|
||
Обновить `document_embeddings`, если пакетная обработка сообщений возможна.
|
||
|
||
Модули:
|
||
`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. **Улучшение API-шлюза**
|
||
Добавить конечную точку для пакетной обработки векторов.
|
||
Поддерживать массив текстов в теле запроса.
|
||
|
||
Модуль: `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
||
|
||
#### 7. **Улучшение инструмента командной строки (CLI)**
|
||
Добавить поддержку нескольких текстов или ввода из файла.
|
||
Добавить параметр размера пакета.
|
||
|
||
Модуль: `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
||
|
||
#### 8. **Улучшение Python SDK**
|
||
Добавить метод `embeddings_batch()` в `FlowInstance`.
|
||
Добавить метод `embeddings_batch()` в `SocketFlowInstance`.
|
||
Поддерживать как одиночные, так и пакетные API для пользователей SDK.
|
||
|
||
Модули:
|
||
`trustgraph-base/trustgraph/api/flow.py`
|
||
`trustgraph-base/trustgraph/api/socket_client.py`
|
||
|
||
### Модели данных
|
||
|
||
#### EmbeddingsRequest
|
||
|
||
```python
|
||
@dataclass
|
||
class EmbeddingsRequest:
|
||
texts: list[str] = field(default_factory=list)
|
||
```
|
||
|
||
Использование:
|
||
Одиночный текст: `EmbeddingsRequest(texts=["hello world"])`
|
||
Пакетный режим: `EmbeddingsRequest(texts=["text1", "text2", "text3"])`
|
||
|
||
#### EmbeddingsResponse
|
||
|
||
```python
|
||
@dataclass
|
||
class EmbeddingsResponse:
|
||
error: Error | None = None
|
||
vectors: list[list[list[float]]] = field(default_factory=list)
|
||
```
|
||
|
||
Структура ответа:
|
||
`vectors[i]` содержит набор векторов для `texts[i]`
|
||
Каждый набор векторов имеет размер `list[list[float]]` (модели могут возвращать несколько векторов для одного текста)
|
||
Пример: 3 текста → `vectors` имеет 3 записи, каждая из которых содержит векторные представления этого текста
|
||
|
||
### API
|
||
|
||
#### 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
|
||
```
|
||
|
||
#### Конечная точка API Gateway для встраиваемых объектов
|
||
|
||
Обновленная конечная точка, поддерживающая однократную или пакетную генерацию встраиваемых объектов:
|
||
|
||
```
|
||
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, ...]]
|
||
]
|
||
}
|
||
```
|
||
|
||
### Детали реализации
|
||
|
||
#### Этап 1: Изменения схемы
|
||
|
||
**EmbeddingsRequest:**
|
||
```python
|
||
@dataclass
|
||
class EmbeddingsRequest:
|
||
texts: list[str] = field(default_factory=list)
|
||
```
|
||
|
||
**Ответ Embeddings:**
|
||
```python
|
||
@dataclass
|
||
class EmbeddingsResponse:
|
||
error: Error | None = None
|
||
vectors: list[list[list[float]]] = field(default_factory=list)
|
||
```
|
||
|
||
**Обновлен класс 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})
|
||
```
|
||
|
||
#### Фаза 2: Обновление процессора FastEmbed
|
||
|
||
**Текущая (неэффективная):**
|
||
```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]
|
||
```
|
||
|
||
**Обновлено:**
|
||
```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]
|
||
```
|
||
|
||
#### Фаза 3: Обновление сервиса графовых вложений
|
||
|
||
**Текущая (последовательная):**
|
||
```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(...))
|
||
```
|
||
|
||
**Обновлено (пакетно):**
|
||
```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)
|
||
]
|
||
```
|
||
|
||
#### Фаза 4: Обновление сервиса встраивания данных.
|
||
|
||
**Текущая (последовательная):**
|
||
```python
|
||
for text, (index_name, index_value) in texts_to_embed.items():
|
||
vectors = await flow("embeddings-request").embed(text=text)
|
||
embeddings_list.append(RowIndexEmbedding(...))
|
||
```
|
||
|
||
**Обновлено (пакетно):**
|
||
```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)
|
||
]
|
||
```
|
||
|
||
#### Фаза 5: Улучшение инструмента командной строки (CLI).
|
||
|
||
**Обновленный CLI:**
|
||
```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)',
|
||
)
|
||
```
|
||
|
||
Использование:
|
||
```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
|
||
```
|
||
|
||
#### Фаза 6: Улучшение SDK для Python
|
||
|
||
**FlowInstance (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 (клиент 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"]
|
||
```
|
||
|
||
**Примеры использования 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")
|
||
```
|
||
|
||
## Соображения безопасности
|
||
|
||
**Ограничения на размер запроса**: Установите максимальный размер пакета для предотвращения исчерпания ресурсов.
|
||
**Обработка таймаутов**: Адаптируйте таймауты в соответствии с размером пакета.
|
||
**Ограничения памяти**: Отслеживайте использование памяти для больших пакетов.
|
||
**Проверка входных данных**: Проверяйте все тексты в пакете перед обработкой.
|
||
|
||
## Соображения производительности
|
||
|
||
### Ожидаемые улучшения
|
||
|
||
**Производительность:**
|
||
Для одного текста: ~10-50 текстов/секунду (в зависимости от модели).
|
||
Для пакета (размер 32): ~200-500 текстов/секунду (улучшение в 5-10 раз).
|
||
|
||
**Задержка на текст:**
|
||
Для одного текста: 50-200 мс на текст.
|
||
Для пакета (размер 32): 5-20 мс на текст (в среднем).
|
||
|
||
**Улучшения для конкретных сервисов:**
|
||
|
||
| Сервис | Текущее значение | Пакетный режим | Улучшение |
|
||
|---------|---------|---------|-------------|
|
||
| Векторные представления графов (50 сущностей) | 5-10 секунд | 0.5-1 секунда | 5-10x |
|
||
| Векторные представления строк (100 текстов) | 10-20 секунд | 1-2 секунды | 5-10x |
|
||
| Импорт документов (1000 фрагментов) | 100-200 секунд | 10-30 секунд | 5-10x |
|
||
|
||
### Параметры конфигурации
|
||
|
||
```python
|
||
# Recommended defaults
|
||
DEFAULT_BATCH_SIZE = 32
|
||
MAX_BATCH_SIZE = 128
|
||
BATCH_TIMEOUT_MULTIPLIER = 2.0
|
||
```
|
||
|
||
## Стратегия тестирования
|
||
|
||
### Модульное тестирование
|
||
Обработка однострочных вложений (обратная совместимость)
|
||
Обработка пустых пакетов
|
||
Применение максимального размера пакета
|
||
Обработка ошибок при частичных сбоях пакета
|
||
|
||
### Интеграционное тестирование
|
||
Полная обработка пакетов через Pulsar
|
||
Обработка пакетов сервисом графовых вложений
|
||
Обработка пакетов сервисом строковых вложений
|
||
API-шлюз для пакетных операций
|
||
|
||
### Тестирование производительности
|
||
Сравнение производительности при обработке отдельных элементов и пакетов
|
||
Использование памяти при различных размерах пакетов
|
||
Анализ распределения задержек
|
||
|
||
## План миграции
|
||
|
||
Это версия с критическими изменениями. Все этапы реализованы одновременно.
|
||
|
||
### Этап 1: Изменения схемы
|
||
Заменить `text: str` на `texts: list[str]` в EmbeddingsRequest
|
||
Изменить тип `vectors` на `list[list[list[float]]]` в EmbeddingsResponse
|
||
|
||
### Этап 2: Обновление процессоров
|
||
Обновить сигнатуру `on_embeddings` в процессорах FastEmbed и Ollama
|
||
Обрабатывать полный пакет за один вызов модели
|
||
|
||
### Этап 3: Обновление клиентской части
|
||
Обновить `EmbeddingsClient.embed()` для приема `texts: list[str]`
|
||
|
||
### Этап 4: Обновление вызывающего кода
|
||
Обновить graph_embeddings для пакетной обработки контекстов сущностей
|
||
Обновить row_embeddings для пакетной обработки текстов индекса
|
||
Обновить document_embeddings для использования новой схемы
|
||
Обновить инструмент командной строки
|
||
|
||
### Этап 5: API-шлюз
|
||
Обновить конечную точку для вложений в соответствии с новой схемой
|
||
|
||
### Этап 6: Python SDK
|
||
Обновить сигнатуру `FlowInstance.embeddings()`
|
||
Обновить сигнатуру `SocketFlowInstance.embeddings()`
|
||
|
||
## Открытые вопросы
|
||
|
||
**Потоковая передача больших пакетов**: Следует ли нам поддерживать потоковую передачу результатов для очень больших пакетов (>100 текстов)?
|
||
**Ограничения, специфичные для поставщиков**: Как нам обрабатывать поставщиков с разными максимальными размерами пакетов?
|
||
**Обработка частичных сбоев**: Если один текст в пакете завершается сбоем, следует ли нам завершать весь пакет или возвращать частичные результаты?
|
||
**Пакетная обработка документов**: Следует ли нам выполнять пакетную обработку по нескольким сообщениям Chunk или сохранять обработку для каждого сообщения?
|
||
|
||
## Ссылки
|
||
|
||
[Документация FastEmbed](https://github.com/qdrant/fastembed)
|
||
[API вложений Ollama](https://github.com/ollama/ollama)
|
||
[Реализация сервиса вложений](trustgraph-base/trustgraph/base/embeddings_service.py)
|
||
[Оптимизация производительности GraphRAG](graphrag-performance-optimization.md)
|