Documentação

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 o LLMSingleSelector no RouterQueryEngine.
  • LayaMultiSelector: Seletor de múltipla escolha que substitui o LLMMultiSelector para 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 (ou fallback_key) para desviar consultas incertas de forma fluida para uma engine padrão segura.
  • Guarda estrita: Defina raise_on_low_confidence=True no LayaSingleSelector para lançar LayaLowConfidenceError quando 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
)