mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-04-25 08:26:21 +02:00
297 lines
12 KiB
Markdown
297 lines
12 KiB
Markdown
|
|
---
|
||
|
|
layout: default
|
||
|
|
title: "Especificação Técnica de Suporte a Streaming RAG"
|
||
|
|
parent: "Portuguese (Beta)"
|
||
|
|
---
|
||
|
|
|
||
|
|
# Especificação Técnica de Suporte a Streaming RAG
|
||
|
|
|
||
|
|
> **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 a adição de suporte a streaming aos serviços GraphRAG e DocumentRAG, permitindo respostas em tempo real, token por token, para consultas de grafos de conhecimento e recuperação de documentos. Isso estende a arquitetura de streaming existente já implementada para serviços de preenchimento de texto, prompt e agente LLM.
|
||
|
|
|
||
|
|
## Objetivos
|
||
|
|
|
||
|
|
**Experiência de streaming consistente**: Fornecer a mesma experiência de streaming em todos os serviços TrustGraph.
|
||
|
|
**Alterações mínimas na API**: Adicionar suporte a streaming com um único sinalizador `streaming`, seguindo padrões estabelecidos.
|
||
|
|
**Compatibilidade com versões anteriores**: Manter o comportamento padrão existente sem streaming.
|
||
|
|
**Reutilizar infraestrutura existente**: Aproveitar o streaming do PromptClient já implementado.
|
||
|
|
**Suporte a gateway**: Permitir o streaming através do gateway WebSocket para aplicativos cliente.
|
||
|
|
|
||
|
|
## Contexto
|
||
|
|
|
||
|
|
Serviços de streaming atualmente implementados:
|
||
|
|
**Serviço de preenchimento de texto LLM**: Fase 1 - streaming de provedores LLM.
|
||
|
|
**Serviço de prompt**: Fase 2 - streaming através de modelos de prompt.
|
||
|
|
**Serviço de agente**: Fase 3-4 - streaming de respostas ReAct com fragmentos incrementais de pensamento/observação/resposta.
|
||
|
|
|
||
|
|
Limitações atuais para serviços RAG:
|
||
|
|
GraphRAG e DocumentRAG suportam apenas respostas bloqueadas.
|
||
|
|
Os usuários devem esperar pela resposta completa do LLM antes de ver qualquer saída.
|
||
|
|
Má experiência do usuário para respostas longas de grafos de conhecimento ou consultas de documentos.
|
||
|
|
Experiência inconsistente em comparação com outros serviços TrustGraph.
|
||
|
|
|
||
|
|
Esta especificação aborda essas lacunas adicionando suporte a streaming ao GraphRAG e ao DocumentRAG. Ao permitir respostas token por token, o TrustGraph pode:
|
||
|
|
Fornecer uma experiência de streaming consistente em todos os tipos de consulta.
|
||
|
|
Reduzir a latência percebida para consultas RAG.
|
||
|
|
Permitir um melhor feedback de progresso para consultas de longa duração.
|
||
|
|
Suportar a exibição em tempo real em aplicativos cliente.
|
||
|
|
|
||
|
|
## Design Técnico
|
||
|
|
|
||
|
|
### Arquitetura
|
||
|
|
|
||
|
|
A implementação de streaming RAG aproveita a infraestrutura existente:
|
||
|
|
|
||
|
|
1. **Streaming do PromptClient** (Já implementado)
|
||
|
|
`kg_prompt()` e `document_prompt()` já aceitam parâmetros `streaming` e `chunk_callback`.
|
||
|
|
Isso chama `prompt()` internamente com suporte a streaming.
|
||
|
|
Não são necessárias alterações no PromptClient.
|
||
|
|
|
||
|
|
Módulo: `trustgraph-base/trustgraph/base/prompt_client.py`
|
||
|
|
|
||
|
|
2. **Serviço GraphRAG** (Precisa de passagem de parâmetro de streaming)
|
||
|
|
Adicionar parâmetro `streaming` ao método `query()`.
|
||
|
|
Passar o sinalizador de streaming e os callbacks para `prompt_client.kg_prompt()`.
|
||
|
|
O esquema GraphRagRequest precisa do campo `streaming`.
|
||
|
|
|
||
|
|
Módulos:
|
||
|
|
`trustgraph-flow/trustgraph/retrieval/graph_rag/graph_rag.py`
|
||
|
|
`trustgraph-flow/trustgraph/retrieval/graph_rag/rag.py` (Processador)
|
||
|
|
`trustgraph-base/trustgraph/schema/graph_rag.py` (Esquema de solicitação)
|
||
|
|
`trustgraph-flow/trustgraph/gateway/dispatch/graph_rag.py` (Gateway)
|
||
|
|
|
||
|
|
3. **Serviço DocumentRAG** (Precisa de passagem de parâmetro de streaming)
|
||
|
|
Adicionar parâmetro `streaming` ao método `query()`.
|
||
|
|
Passar o sinalizador de streaming e os callbacks para `prompt_client.document_prompt()`.
|
||
|
|
O esquema DocumentRagRequest precisa do campo `streaming`.
|
||
|
|
|
||
|
|
Módulos:
|
||
|
|
`trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py`
|
||
|
|
`trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` (Processador)
|
||
|
|
`trustgraph-base/trustgraph/schema/document_rag.py` (Esquema de solicitação)
|
||
|
|
`trustgraph-flow/trustgraph/gateway/dispatch/document_rag.py` (Gateway)
|
||
|
|
|
||
|
|
### Fluxo de Dados
|
||
|
|
|
||
|
|
**Não streaming (atual)**:
|
||
|
|
```
|
||
|
|
Client → Gateway → RAG Service → PromptClient.kg_prompt(streaming=False)
|
||
|
|
↓
|
||
|
|
Prompt Service → LLM
|
||
|
|
↓
|
||
|
|
Complete response
|
||
|
|
↓
|
||
|
|
Client ← Gateway ← RAG Service ← Response
|
||
|
|
```
|
||
|
|
|
||
|
|
**Streaming (proposto):**
|
||
|
|
```
|
||
|
|
Client → Gateway → RAG Service → PromptClient.kg_prompt(streaming=True, chunk_callback=cb)
|
||
|
|
↓
|
||
|
|
Prompt Service → LLM (streaming)
|
||
|
|
↓
|
||
|
|
Chunk → callback → RAG Response (chunk)
|
||
|
|
↓ ↓
|
||
|
|
Client ← Gateway ← ────────────────────────────────── Response stream
|
||
|
|
```
|
||
|
|
|
||
|
|
### APIs
|
||
|
|
|
||
|
|
**Alterações no GraphRAG**:
|
||
|
|
|
||
|
|
1. **GraphRag.query()** - Adicionar parâmetros de streaming
|
||
|
|
```python
|
||
|
|
async def query(
|
||
|
|
self, query, user, collection,
|
||
|
|
verbose=False, streaming=False, chunk_callback=None # NEW
|
||
|
|
):
|
||
|
|
# ... existing entity/triple retrieval ...
|
||
|
|
|
||
|
|
if streaming and chunk_callback:
|
||
|
|
resp = await self.prompt_client.kg_prompt(
|
||
|
|
query, kg,
|
||
|
|
streaming=True,
|
||
|
|
chunk_callback=chunk_callback
|
||
|
|
)
|
||
|
|
else:
|
||
|
|
resp = await self.prompt_client.kg_prompt(query, kg)
|
||
|
|
|
||
|
|
return resp
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **Esquema GraphRagRequest** - Adicionar campo de streaming.
|
||
|
|
```python
|
||
|
|
class GraphRagRequest(Record):
|
||
|
|
query = String()
|
||
|
|
user = String()
|
||
|
|
collection = String()
|
||
|
|
streaming = Boolean() # NEW
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **Esquema GraphRagResponse** - Adicionar campos de streaming (seguir o padrão do Agente).
|
||
|
|
```python
|
||
|
|
class GraphRagResponse(Record):
|
||
|
|
response = String() # Legacy: complete response
|
||
|
|
chunk = String() # NEW: streaming chunk
|
||
|
|
end_of_stream = Boolean() # NEW: indicates last chunk
|
||
|
|
```
|
||
|
|
|
||
|
|
4. **Processador** - Permitir a passagem de dados em fluxo contínuo.
|
||
|
|
```python
|
||
|
|
async def handle(self, msg):
|
||
|
|
# ... existing code ...
|
||
|
|
|
||
|
|
async def send_chunk(chunk):
|
||
|
|
await self.respond(GraphRagResponse(
|
||
|
|
chunk=chunk,
|
||
|
|
end_of_stream=False,
|
||
|
|
response=None
|
||
|
|
))
|
||
|
|
|
||
|
|
if request.streaming:
|
||
|
|
full_response = await self.rag.query(
|
||
|
|
query=request.query,
|
||
|
|
user=request.user,
|
||
|
|
collection=request.collection,
|
||
|
|
streaming=True,
|
||
|
|
chunk_callback=send_chunk
|
||
|
|
)
|
||
|
|
# Send final message
|
||
|
|
await self.respond(GraphRagResponse(
|
||
|
|
chunk=None,
|
||
|
|
end_of_stream=True,
|
||
|
|
response=full_response
|
||
|
|
))
|
||
|
|
else:
|
||
|
|
# Existing non-streaming path
|
||
|
|
response = await self.rag.query(...)
|
||
|
|
await self.respond(GraphRagResponse(response=response))
|
||
|
|
```
|
||
|
|
|
||
|
|
**Alterações no DocumentRAG:**
|
||
|
|
|
||
|
|
Padrão idêntico ao GraphRAG:
|
||
|
|
1. Adicionar parâmetros `streaming` e `chunk_callback` a `DocumentRag.query()`
|
||
|
|
2. Adicionar campo `streaming` a `DocumentRagRequest`
|
||
|
|
3. Adicionar campos `chunk` e `end_of_stream` a `DocumentRagResponse`
|
||
|
|
4. Atualizar o Processador para lidar com streaming com callbacks
|
||
|
|
|
||
|
|
**Alterações no Gateway:**
|
||
|
|
|
||
|
|
Tanto `graph_rag.py` quanto `document_rag.py` no gateway/dispatch precisam de atualizações para encaminhar trechos de streaming para o websocket:
|
||
|
|
|
||
|
|
```python
|
||
|
|
async def handle(self, message, session, websocket):
|
||
|
|
# ... existing code ...
|
||
|
|
|
||
|
|
if request.streaming:
|
||
|
|
async def recipient(resp):
|
||
|
|
if resp.chunk:
|
||
|
|
await websocket.send(json.dumps({
|
||
|
|
"id": message["id"],
|
||
|
|
"response": {"chunk": resp.chunk},
|
||
|
|
"complete": resp.end_of_stream
|
||
|
|
}))
|
||
|
|
return resp.end_of_stream
|
||
|
|
|
||
|
|
await self.rag_client.request(request, recipient=recipient)
|
||
|
|
else:
|
||
|
|
# Existing non-streaming path
|
||
|
|
resp = await self.rag_client.request(request)
|
||
|
|
await websocket.send(...)
|
||
|
|
```
|
||
|
|
|
||
|
|
### Detalhes de Implementação
|
||
|
|
|
||
|
|
**Ordem de implementação**:
|
||
|
|
1. Adicionar campos de esquema (Request + Response para ambos os serviços RAG)
|
||
|
|
2. Atualizar os métodos GraphRag.query() e DocumentRag.query()
|
||
|
|
3. Atualizar Processadores para lidar com streaming
|
||
|
|
4. Atualizar manipuladores de despacho do Gateway
|
||
|
|
5. Adicionar `--no-streaming` flags a `tg-invoke-graph-rag` e `tg-invoke-document-rag` (streaming habilitado por padrão, seguindo o padrão da CLI do agente)
|
||
|
|
|
||
|
|
**Padrão de callback**:
|
||
|
|
Seguir o mesmo padrão de callback assíncrono estabelecido no streaming do Agente:
|
||
|
|
O Processador define o `async def send_chunk(chunk)` callback
|
||
|
|
Passa o callback para o serviço RAG
|
||
|
|
O serviço RAG passa o callback para o PromptClient
|
||
|
|
O PromptClient invoca o callback para cada chunk do LLM
|
||
|
|
O Processador envia uma mensagem de resposta de streaming para cada chunk
|
||
|
|
|
||
|
|
**Tratamento de erros**:
|
||
|
|
Erros durante o streaming devem enviar uma resposta de erro com `end_of_stream=True`
|
||
|
|
Seguir os padrões existentes de propagação de erros do streaming do Agente
|
||
|
|
|
||
|
|
## Considerações de Segurança
|
||
|
|
|
||
|
|
Não há novas considerações de segurança além dos serviços RAG existentes:
|
||
|
|
As respostas de streaming usam o mesmo isolamento de usuário/coleção
|
||
|
|
Não há alterações na autenticação ou autorização
|
||
|
|
Os limites de chunk não expõem dados sensíveis
|
||
|
|
|
||
|
|
## Considerações de Desempenho
|
||
|
|
|
||
|
|
**Benefícios**:
|
||
|
|
Latência percebida reduzida (os primeiros tokens chegam mais rápido)
|
||
|
|
Melhor experiência do usuário para respostas longas
|
||
|
|
Menor uso de memória (não é necessário armazenar em buffer a resposta completa)
|
||
|
|
|
||
|
|
**Preocupações potenciais**:
|
||
|
|
Mais mensagens Pulsar para respostas de streaming
|
||
|
|
Ligeiramente maior uso de CPU para a sobrecarga de chunking/callback
|
||
|
|
Mitigado por: o streaming é opcional, o padrão permanece não-streaming
|
||
|
|
|
||
|
|
**Considerações de teste**:
|
||
|
|
Testar com grafos de conhecimento grandes (muitos triplos)
|
||
|
|
Testar com muitos documentos recuperados
|
||
|
|
Medir a sobrecarga do streaming versus não-streaming
|
||
|
|
|
||
|
|
## Estratégia de Teste
|
||
|
|
|
||
|
|
**Testes unitários**:
|
||
|
|
Testar GraphRag.query() com streaming=True/False
|
||
|
|
Testar DocumentRag.query() com streaming=True/False
|
||
|
|
Simular o PromptClient para verificar as invocações de callback
|
||
|
|
|
||
|
|
**Testes de integração**:
|
||
|
|
Testar o fluxo completo de streaming do GraphRAG (semelhante aos testes existentes de streaming do agente)
|
||
|
|
Testar o fluxo completo de streaming do DocumentRAG
|
||
|
|
Testar o encaminhamento de streaming do Gateway
|
||
|
|
Testar a saída de streaming da CLI
|
||
|
|
|
||
|
|
**Testes manuais**:
|
||
|
|
`tg-invoke-graph-rag -q "What is machine learning?"` (streaming por padrão)
|
||
|
|
`tg-invoke-document-rag -q "Summarize the documents about AI"` (streaming por padrão)
|
||
|
|
`tg-invoke-graph-rag --no-streaming -q "..."` (testar o modo não-streaming)
|
||
|
|
Verificar se a saída incremental aparece no modo de streaming
|
||
|
|
|
||
|
|
## Plano de Migração
|
||
|
|
|
||
|
|
Nenhuma migração necessária:
|
||
|
|
O streaming é opcional por meio do parâmetro `streaming` (o padrão é Falso)
|
||
|
|
Os clientes existentes continuam a funcionar sem alterações
|
||
|
|
Novos clientes podem optar por usar o streaming
|
||
|
|
|
||
|
|
## Cronograma
|
||
|
|
|
||
|
|
Tempo estimado de implementação: 4-6 horas
|
||
|
|
Fase 1 (2 horas): suporte de streaming do GraphRAG
|
||
|
|
Fase 2 (2 horas): suporte de streaming do DocumentRAG
|
||
|
|
Fase 3 (1-2 horas): atualizações do Gateway e flags da CLI
|
||
|
|
Testes: integrados em cada fase
|
||
|
|
|
||
|
|
## Perguntas Abertas
|
||
|
|
|
||
|
|
Devemos adicionar suporte de streaming ao serviço de consulta NLP também?
|
||
|
|
Queremos transmitir etapas intermediárias (por exemplo, "Recuperando entidades...", "Consultando o grafo...") ou apenas a saída do LLM?
|
||
|
|
As respostas do GraphRAG/DocumentRAG devem incluir metadados do chunk (por exemplo, número do chunk, total esperado)?
|
||
|
|
|
||
|
|
## Referências
|
||
|
|
|
||
|
|
Implementação existente: `docs/tech-specs/streaming-llm-responses.md`
|
||
|
|
Streaming do Agente: `trustgraph-flow/trustgraph/agent/react/agent_manager.py`
|
||
|
|
Streaming do PromptClient: `trustgraph-base/trustgraph/base/prompt_client.py`
|