Integração com LlamaIndex
O Laya oferece componentes de decisão não autorregressivos abaixo de 35 ms para pipelines RAG do
LlamaIndex, RouterQueryEngine e seleção de ferramentas (latência de uma única pergunta medida
em 32.8 ms com laya-multilingual e 39.5 ms com laya em uma GPU Tesla T4; 193–464 ms em
CPU):
LayaSingleSelector: Seletor de escolha única abaixo de 35 ms que substitui oLLMSingleSelectornoRouterQueryEngine.LayaMultiSelector: Seletor de múltipla escolha que substitui oLLMMultiSelectorpara consultas compostas que abrangem várias fontes de dados.LayaQueryRouter: Despachante de consultas autônomo que roteia solicitações que chegam diretamente para query engines ou callables de destino.
Suporta tanto inferência local em processo (Agent ou Router) quanto inferência remota por
HTTP contra sua própria instância de laya-serve, sem exigir PyTorch nos clientes de borda.
Instalação
pip install "laya[llamaindex]"
1. Roteamento de escolha única com RouterQueryEngine
No LlamaIndex, o RouterQueryEngine usa um seletor para decidir qual query engine ou ferramenta
subjacente deve responder a uma pergunta. Seletores LLM autorregressivos (LLMSingleSelector) levam
1.000–2.000 ms gerando texto. LayaSingleSelector avalia as ferramentas candidatas em ~33 ms sem
geração de tokens:
from llama_index.core.query_engine import RouterQueryEngine
from llama_index.core.tools import QueryEngineTool, ToolMetadata
from laya.integrations.llamaindex import LayaSingleSelector
# Define query engine tools
docs_tool = QueryEngineTool(
query_engine=vector_index.as_query_engine(),
metadata=ToolMetadata(
name="vector_documentation",
description="Semantic search over technical user documentation and API guides.",
),
)
sql_tool = QueryEngineTool(
query_engine=sql_index.as_query_engine(),
metadata=ToolMetadata(
name="sql_database",
description="Structured SQL database containing customer accounts, billing, and orders.",
),
)
# Initialize Laya sub-35ms selector with confidence fallback
selector = LayaSingleSelector(
confidence_threshold=0.80, # If confidence < 0.80, fall back to index 0
fallback_index=0,
)
router_engine = RouterQueryEngine(
selector=selector,
query_engine_tools=[docs_tool, sql_tool],
)
response = router_engine.query("What is the shipping address for order #4912?")
print(response)
2. Seleção de múltipla escolha para consultas compostas
Para consultas que exigem síntese entre vários índices (por exemplo, comparar especificações de
documentação com registros transacionais de banco de dados), LayaMultiSelector avalia a relevância
dos candidatos e retorna várias ferramentas selecionadas:
from laya.integrations.llamaindex import LayaMultiSelector
multi_selector = LayaMultiSelector(
probability_threshold=0.25, # Select all tools with probability >= 0.25
max_outputs=2,
)
tools = [docs_tool.metadata, sql_tool.metadata, summary_tool.metadata]
result = multi_selector.select(
tools,
"How does the database security policy compare with our published compliance guide?"
)
for sel in result.selections:
print(f"Tool: {tools[sel.index].name} | {sel.reason}")
3. Despacho direto de consultas com LayaQueryRouter
Para roteamento direto sem o overhead do RouterQueryEngine, LayaQueryRouter roteia consultas
diretamente para engines registradas em um dicionário:
from laya.integrations.llamaindex import LayaQueryRouter
router = LayaQueryRouter(
query_engines={
"vector": vector_query_engine,
"sql": sql_query_engine,
"summary": summary_query_engine,
},
descriptions={
"vector": "Semantic search over product documentation and guides",
"sql": "Structured SQL queries for user accounts and transactions",
"summary": "Quarterly reports and high-level business summaries",
},
confidence_threshold=0.75,
fallback_key="vector",
)
# Route and execute in one call:
response = router.query("How many active subscriptions were renewed in Q3?")
print(response)
Tanto o query() síncrono quanto o aquery() assíncrono são suportados.
4. Gating por limiar de confiança
Como a integração do Laya com o LangChain, LayaSingleSelector e LayaQueryRouter leem a
answer_confidence calibrada (max(p)):
- Fallback automático: Especifique
fallback_index(oufallback_key) para desviar consultas incertas de forma fluida para uma engine padrão segura. - Guarda estrita: Defina
raise_on_low_confidence=TruenoLayaSingleSelectorpara lançarLayaLowConfidenceErrorquando a entrada for ambígua, permitindo o escalonamento pelo chamador.
5. Implantações HTTP remotas
Para RAG serverless, ambientes de borda ou ambientes sem GPUs locais:
from laya.integrations.llamaindex import LayaSingleSelector
selector = LayaSingleSelector(
base_url="http://laya-serve.internal:8080",
confidence_threshold=0.85,
fallback_index=0,
)
O cliente remoto usa a urllib da biblioteca padrão do Python, sem dependências pesadas, o que evita
o encaminhamento de credenciais entre origens e segue a especificação de /v1/systemone.
6. Controles de decisão por chamada
LayaSingleSelector, LayaMultiSelector e LayaQueryRouter aceitam os mesmos argumentos por chamada
que a API do core: os dois orçamentos de tokens (max_len, head_max_len), os controles de idioma e abstenção (lang, min_confidence), e os cinco argumentos de
hooks de predição (hooks, on_predict_start, on_predict_end, hooks_raise, hooks_timeout). Eles
são por seletor, então um passo de roteamento largo pode receber mais espaço enquanto o resto do
pipeline mantém os padrões do checkpoint.
As opções de uma pergunta choice compartilham o orçamento de opções do checkpoint – head_max_len,
192 tokens em laya – e cada candidato contribui com seu nome e descrição, então a partir de cerca de
20 ferramentas as descrições começam a chegar ao modelo como o mesmo texto.
selector = LayaSingleSelector(
instructions="Which tool or query engine is best suited to answer this query?",
max_len=1024, # total window
head_max_len=512, # tokens shared by the option prompt
)
result = selector.select(tools, query) # tools: 59 descriptions
Medido em laya (silício da Apple, uma passada direta por consulta, pontuado sobre a ferramenta
escolhida) com um elenco de 59 ferramentas construído a partir dos rótulos de intenção em inglês do
MASSIVE e um enunciado por rótulo, de modo que a verdade de referência é exata. Cada célula é quantas
das 59 consultas chegaram à sua própria ferramenta; ambas as repetições deram a mesma contagem.
| Elenco de 59 ferramentas | Orçamento padrão | max_len=1024, head_max_len=384 |
…, head_max_len=512 |
|---|---|---|---|
| Consultas na própria ferramenta | 2/59 | 8/59 | 15/59 |
| Mediana de ms por consulta | 160 | 172 | 184 |
A precisão absoluta não é o que se afirma aqui: o checkpoint não é um classificador de MASSIVE, e 59 rótulos semelhantes são uma forma de estresse. O que se afirma é a direção e o preço – um elenco que o orçamento padrão reduz a quase nada fica legível, e nesse tamanho a janela custa pouco tempo. Com menos de cerca de 20 opções os rótulos já cabem e alargar pode mover as respostas na direção errada, por isso os dois argumentos são opt-in por seletor. Veja a integração com LangChain para esse penhasco medido.
Os hooks rodam apenas no caminho local. Um seletor com um base_url e hooks=[...] lança
ValueError em vez de reportar um sucesso cujo cache nunca rodou – um hook é um callable Python que
roda dentro de predict, e nenhum formato de transmissão o carrega. Instale hooks no processo que roda
a inferência. Os dois orçamentos de fato viajam para um nó remoto, no corpo da solicitação, até seu
teto de LAYA_MAX_TOKEN_BUDGET; um valor maior volta como um 422.
Idioma e abstenção
lang fixa o idioma em que a consulta é roteada e respondida – seleciona a calibração por idioma do checkpoint que responde em vez de depender da detecção integrada – e min_confidence é o gate de abstenção do core: uma decisão abaixo dele volta como uma abstenção em vez de uma seleção forçada. Os dois são lidos igualmente por Agent.predict e Router.predict e aceitos pelo laya-serve no corpo da solicitação, então um seletor os encaminha tanto no caminho local quanto no remoto. O que não estiver definido é omitido, não enviado como None, então não pode ofuscar o padrão da própria implantação; min_confidence=0.0 e lang="" são valores reais e são encaminhados como estão.
selector = LayaSingleSelector(
instructions="Which tool or query engine is best suited to answer this query?",
lang="de", # answer German queries in German
min_confidence=0.3, # abstain when no tool clears a 0.3 confidence
)