Documentação

Integração com LlamaIndex

O Laya fornece componentes de decisão abaixo de 35 ms e não autorregressivos para pipelines RAG do LlamaIndex, o RouterQueryEngine e a seleção de ferramentas (latência de pergunta única medida em 32.8 ms com laya-multilingual e 39.5 ms com laya numa GPU Tesla T4; 193–464 ms em CPU):

  • LayaSingleSelector: Seletor de escolha única abaixo de 35 ms que substitui o LLMSingleSelector para o RouterQueryEngine.
  • LayaMultiSelector: Seletor de escolha múltipla que substitui o LLMMultiSelector para consultas compostas que abrangem várias fontes de dados.
  • LayaQueryRouter: Despachante de consultas autónomo que encaminha os pedidos recebidos diretamente para os motores de consulta ou invocáveis alvo.

Suporta tanto inferência local em processo (Agent ou Router) como inferência HTTP remota contra a tua própria instância laya-serve, sem exigir PyTorch em clientes de periferia.


Instalação

pip install "laya[llamaindex]"

1. Encaminhamento de escolha única com o RouterQueryEngine

No LlamaIndex, o RouterQueryEngine usa um seletor para decidir que motor de consulta ou ferramenta subjacente deve responder a uma pergunta. Os seletores LLM autorregressivos (LLMSingleSelector) levam 1,000–2,000 ms a gerar texto. O 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 escolha múltipla para consultas compostas

Para consultas que exigem síntese entre vários índices (por exemplo, comparar especificações de documentação com registos de bases de dados transacionais), o LayaMultiSelector avalia a relevância dos candidatos e devolve 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 o LayaQueryRouter

Para encaminhamento direto sem a sobrecarga do RouterQueryEngine, o LayaQueryRouter encaminha as consultas diretamente para motores registados num 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)

Ambos são suportados: o query() síncrono e o aquery() assíncrono.


4. Gating por limiar de confiança

Tal como a integração do Laya com o LangChain, o LayaSingleSelector e o LayaQueryRouter leem a answer_confidence calibrada (max(p)):

  • Fallback automático: Especifica fallback_index (ou fallback_key) para desviar sem falhas as consultas incertas para um motor predefinido seguro.
  • Guarda estrita: Define raise_on_low_confidence=True no LayaSingleSelector para levantar LayaLowConfidenceError quando a entrada é ambígua, permitindo o escalonamento pelo autor da chamada.

5. Implementações HTTP remotas

Para RAG serverless, ambientes de periferia, 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 biblioteca padrão do Python urllib com zero dependências pesadas, evitando o encaminhamento de credenciais entre origens e correspondendo à especificação /v1/systemone.


6. Controlos de decisão por chamada

LayaSingleSelector, LayaMultiSelector e LayaQueryRouter aceitam os mesmos argumentos por chamada que a API core: os dois orçamentos de tokens (max_len, head_max_len), os controlos de idioma e abstenção (lang, min_confidence), e os cinco argumentos de hook de predição (hooks, on_predict_start, on_predict_end, hooks_raise, hooks_timeout). São por seletor, por isso um passo de encaminhamento largo pode receber espaço enquanto o resto do pipeline mantém as predefinições do checkpoint.

As opções de uma pergunta choice partilham o orçamento de opções do checkpoint – head_max_len, 192 tokens no laya – e cada candidato contribui com o seu nome e descrição, por isso 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 no laya (Apple silicon, uma passagem direta por consulta, pontuado na ferramenta escolhida) com um roster de 59 ferramentas construído a partir das etiquetas de intenção MASSIVE en e uma utterance por etiqueta, para que a verdade de referência seja exata. Cada célula é quantas das 59 consultas chegaram à sua própria ferramenta; ambas as repetições deram a mesma contagem.

Roster de 59 ferramentas Orçamento predefinido max_len=1024, head_max_len=384 …, head_max_len=512
Consultas na sua própria ferramenta 2/59 8/59 15/59
Mediana de ms por consulta 160 172 184

A precisão absoluta não é a alegação aqui: o checkpoint não é um classificador MASSIVE, e 59 etiquetas semelhantes são uma forma de stress. A alegação é a direção e o preço – um roster que o orçamento predefinido colapsa para quase nada é legível, e com este tamanho a janela custa pouco tempo. Com menos de cerca de 20 opções as etiquetas já cabem e alargar pode mover respostas na direção errada, e é por isso que ambos os argumentos são opt-in por seletor. Vê a integração com LangChain para esse precipício medido.

Os hooks correm apenas no caminho local. Um seletor com um base_url e hooks=[...] levanta ValueError em vez de reportar um sucesso cuja cache nunca correu – um hook é um invocável Python que corre dentro de predict, e nenhum formato wire o transporta. Instala os hooks no processo que corre a inferência. Os dois orçamentos viajam até um nó remoto, no corpo do pedido, até ao seu teto LAYA_MAX_TOKEN_BUDGET; um valor maior volta como um 422.

Idioma e abstenção

lang fixa o idioma em que a consulta é encaminhada e respondida – seleciona a calibração por idioma do checkpoint que responde em vez de depender da deteçã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. Ambos são lidos de igual forma por Agent.predict e Router.predict e aceites pelo laya-serve no corpo do pedido, por isso um seletor reencaminha-os tanto no caminho local como no remoto. O que não estiver definido é omitido, não enviado como None, para que não possa ofuscar a predefinição da própria implementação; min_confidence=0.0 e lang="" são valores reais e são reencaminhados tal 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
)