Plugin do Model Serving
Plugin do Model Serving
Fornece um proxy autenticado para endpoints do Databricks Model Serving, com suporte a invocação e streaming.
Principais recursos:
- Aliases nomeados para múltiplos serving endpoints
- Invocação sem streaming (
invoke) e com streaming SSE (stream) - Geração automática de tipos OpenAPI para os esquemas de requisição/resposta
- Filtragem do corpo da requisição com base no esquema do endpoint
- Execução em nome do usuário (OBO)
Uso básico
import { createApp, server, serving } from "@databricks/appkit";
await createApp({
plugins: [
server(),
serving(),
],
});Sem nenhuma configuração, o plugin lê DATABRICKS_SERVING_ENDPOINT_NAME do ambiente e o registra com o alias default.
Opções de configuração
| Opção | Tipo | Padrão | Descrição |
|---|---|---|---|
endpoints | Record<string, EndpointConfig> | { default: { env: "DATABRICKS_SERVING_ENDPOINT_NAME" } } | Mapa de aliases para configurações de endpoint |
timeout | number | 120000 | Tempo limite da requisição em ms |
Aliases de endpoint
Os aliases de endpoint permitem referenciar vários serving endpoints pelo nome:
serving({
endpoints: {
llm: { env: "DATABRICKS_SERVING_ENDPOINT_NAME" },
classifier: { env: "DATABRICKS_SERVING_ENDPOINT_CLASSIFIER" },
},
})Cada alias é mapeado para uma variável de ambiente que contém o nome real do endpoint. Se um endpoint atender a vários modelos, você pode usar servedModel para ignorar o roteamento de tráfego e direcionar a chamada diretamente a um modelo específico:
serving({
endpoints: {
llm: { env: "DATABRICKS_SERVING_ENDPOINT_NAME", servedModel: "llama-v2" },
},
})Geração de tipos
O plugin do Vite appKitServingTypesPlugin() gera tipos TypeScript a partir dos esquemas OpenAPI dos seus serving endpoints. Nenhuma configuração manual é necessária — o servidor de desenvolvimento do AppKit já inclui esse plugin automaticamente.
O plugin descobre automaticamente a configuração do endpoint a partir do seu arquivo de servidor (server/index.ts ou server/server.ts).
Os tipos gerados oferecem:
- Autocompletar de alias tanto no backend (
AppKit.serving("alias")) quanto nos hooks do frontend (useServingStream,useServingInvoke) - Requisição/resposta/chunk tipados por endpoint, com base nos esquemas OpenAPI
Se o esquema OpenAPI de um endpoint não estiver disponível (não implantado, variável de ambiente não definida), o plugin gera tipos genéricos de fallback. O endpoint continua utilizável — apenas sem requisição/resposta tipadas.
Endpoints que não definem um esquema de resposta de streaming em sua especificação OpenAPI terão chunk: unknown. Para esses endpoints, use useServingInvoke em vez de useServingStream — o tipo response continuará devidamente tipado.
Variáveis de ambiente
| Variável | Descrição |
|---|---|
DATABRICKS_SERVING_ENDPOINT_NAME | Nome do endpoint padrão (usado quando a configuração endpoints é omitida) |
Ao usar endpoints nomeados, defina uma variável de ambiente personalizada para cada alias (por exemplo, DATABRICKS_SERVING_ENDPOINT_CLASSIFIER).
Contexto de execução
Por padrão, todas as rotas de serving são executadas em nome do usuário autenticado (OBO), de forma consistente com os plugins Genie e Files. Isso garante que as permissões CAN_QUERY de cada usuário sejam aplicadas no serving endpoint.
Para acesso programático via exports(), use .asUser(req) para executar no contexto do usuário:
// Contexto do service principal (padrão)
const result = await AppKit.serving("llm").invoke({ messages });
// Contexto do usuário (recomendado em handlers de rota)
const result = await AppKit.serving("llm").asUser(req).invoke({ messages });Endpoints HTTP
Modo nomeado (com configuração endpoints)
POST /api/serving/:alias/invoke— Invocação sem streamingPOST /api/serving/:alias/stream— Invocação com streaming SSE
Modo padrão (sem configuração de endpoints)
POST /api/serving/invoke— Invocação sem streamingPOST /api/serving/stream— Invocação com streaming SSE
Formato da requisição
POST /api/serving/:alias/invoke
Content-Type: application/json
{
"messages": [
{ "role": "user", "content": "Hello" }
]
}Acesso programático
O plugin exporta os métodos invoke e stream para uso no lado do servidor:
const AppKit = await createApp({
plugins: [
server(),
serving({
endpoints: {
llm: { env: "DATABRICKS_SERVING_ENDPOINT_NAME" },
},
}),
],
});
// Sem streaming
const result = await AppKit.serving("llm").invoke({
messages: [{ role: "user", content: "Hello" }],
});
// Com streaming
for await (const chunk of AppKit.serving("llm").stream({
messages: [{ role: "user", content: "Hello" }],
})) {
console.log(chunk);
}Hooks de frontend
O pacote @databricks/appkit-ui fornece hooks React para serving endpoints:
useServingStream
Invocação com streaming via SSE:
import { useServingStream } from "@databricks/appkit-ui/react";
function ChatStream() {
const { stream, chunks, streaming, error, reset } = useServingStream(
{ messages: [{ role: "user", content: "Hello" }] },
{
alias: "llm",
onComplete: (finalChunks) => {
// Chamado com todos os chunks acumulados quando o stream termina
console.log("Stream done, got", finalChunks.length, "chunks");
},
},
);
return (
<>
<button onClick={stream} disabled={streaming}>Send</button>
<button onClick={reset}>Reset</button>
{chunks.map((chunk, i) => <pre key={i}>{JSON.stringify(chunk)}</pre>)}
{error && <p>{error}</p>}
</>
);
}useServingInvoke
Invocação sem streaming. invoke() retorna uma promise com os dados da resposta (ou null em caso de erro):
import { useServingInvoke } from "@databricks/appkit-ui/react";
function Classify() {
const { invoke, data, loading, error } = useServingInvoke(
{ inputs: ["sample text"] },
{ alias: "classifier" },
);
async function handleClick() {
const result = await invoke();
if (result) {
console.log("Classification result:", result);
}
}
return (
<>
<button onClick={handleClick} disabled={loading}>Classify</button>
{data && <pre>{JSON.stringify(data)}</pre>}
{error && <p>{error}</p>}
</>
);
}Ambos os hooks aceitam autoStart: true para serem invocados automaticamente na montagem.