Docs do Nodaro
DocumentaçãoReferência de nósModelosAgentes de IA (MCP)DesenvolvedoresSelf-hostingPesquisa
SDK para TypeScript

LLM e Reduce

Obtenha JSON validado de um modelo de linguagem com client.llm e use client.reduce para escolher o melhor de vários resultados, votar, juntar ou mesclar.

client.llm pede a um modelo de linguagem uma saída estruturada: você envia um prompt de sistema, uma entrada e um JSON Schema, e recebe de volta um objeto que segue o schema. client.reduce executa isoladamente a etapa de fan-in do Reduce: escolhe o melhor de vários resultados, conta os resultados, faz uma votação, junta textos ou mescla JSON. É o trabalho que o nó Escolher o melhor (Choose Best) faz em um workflow. Os dois custam créditos conforme o nível do modelo.

Métodos

MétodoO que faz
llm.structured(input)Obtém um objeto validado de um modelo de linguagem, em uma única requisição
llm.structuredJob(input)A mesma chamada, como um job que você consulta periodicamente
reduce.run(input)Escolhe, conta, vota, junta ou mescla muitas entradas em uma só

client.llm

Saída estruturada: entram seu prompt de sistema e seu JSON Schema, sai um objeto validado. A plataforma escolhe a rota do modelo, força a saída em JSON, valida essa saída com o seu schema e devolve as respostas inválidas ao modelo antes de desistir. A cobrança é feita como llm-structured, conforme o nível do modelo.

llm.structured(input)

Pergunta ao modelo e espera a resposta (POST /v1/llm/structured). Uma chamada pode levar vários minutos, mais que o tempo limite padrão de 60 segundos do cliente. Para ela, crie o cliente com um timeoutMs maior ou use structuredJob().

structured<T>(input: LlmStructuredInput): Promise<{
  jobId: string
  output: T
  usage: { inputTokens: number; outputTokens: number }
}>

Prop

Type

type Plan = { title: string; scenes: string[] }

const { output } = await client.llm.structured<Plan>({
  system: "You write production plans for short films.",
  input: "A rainy chase through Rome, 60 seconds.",
  jsonSchema: {
    type: "object",
    properties: {
      title: { type: "string" },
      scenes: { type: "array", items: { type: "string" } },
    },
    required: ["title", "scenes"],
  },
  schemaName: "production_plan",
})
console.log(output.title, output.scenes.length)

llm.structuredJob(input)

A mesma chamada, como um job (POST /v1/llm/structured/jobs). Retorna um jobId na hora; consulte o job periodicamente com client.jobs.getStatus(). Um job também pode criar o rascunho a partir de um vídeo: a plataforma analisa o vídeo primeiro e depois acrescenta a análise à sua entrada.

structuredJob(input: LlmStructuredJobInput): Promise<{ jobId: string }>

Prop

Type

const { jobId } = await client.llm.structuredJob({
  system: "You write production plans.",
  input: "A rainy chase through Rome.",
  jsonSchema: { type: "object", properties: { title: { type: "string" } }, required: ["title"] },
  origin: "my-app",
  label: "Rome chase",
})

// later, even from another session
const { data } = await client.jobs.getStatus(jobId)
if (data.status === "completed") {
  console.log((data.output_data as { output: { title: string } }).output.title)
}
const { data: runs } = await client.jobs.list({ type: "llm-structured", origin: "my-app" })

Enquanto o job é executado, o output_data dele contém stage: analyzing (nos rascunhos a partir de vídeo) ou drafting. Quando o job termina, output_data contém output, inputTokens e outputTokens, além de analysisJobId e analysisCredits no caso de um rascunho a partir de vídeo.

  • analysisJobId falha com 422 quando o job não é seu, não existe ou não é uma análise de vídeo concluída. Os códigos são analysis_not_found, not_analysis, analysis_failed, analysis_not_ready e invalid_analysis.
  • Em uma plataforma sem esta rota, o método lança NotFoundError.
  • Uma instância self-hosted que envia as chamadas de modelo de linguagem ao Nodaro Cloud responde 503 provider_unavailable. Trate isso como um recurso indisponível nessa instância, não como um erro passageiro.

client.reduce

reduce.run(input)

Reduz muitas entradas a uma só. Equivale à ferramenta reduce do MCP e ao nó Escolher o melhor.

run(input: ReduceInput): Promise<ReduceResult>

Prop

Type

EstratégiastrategyConfigO que retorna
pick-best-llm{ criteria, inputKind?, llmModel? }. inputKind é "text" ou "image-url". llmModel escolhe o modelo juiz, e o nível de créditos dele se aplica.A entrada que um modelo de linguagem julga a melhor, com o índice e o raciocínio
concat{ separator? }, uma linha em branco por padrãoTodas as entradas unidas em um único texto
first-non-emptynenhumaA primeira entrada que não está vazia
countnenhumaO número de entradas
vote{ caseSensitive? }, false por padrãoA entrada mais frequente. Em caso de empate, vence a primeira.
merge-json{ strategy? }: "deep" (o padrão) ou "shallow"As entradas JSON mescladas em um único objeto
const result = await client.reduce.run({
  strategyId: "pick-best-llm",
  strategyConfig: { criteria: "The sharpest image with no artifacts", inputKind: "image-url" },
  inputs: [url1, url2, url3, url4, url5],
})
console.log(result.output)             // the chosen URL
console.log(result.meta.selectedIndex) // 0 to 4
console.log(result.meta.reasoning)     // why the model chose it

O resultado é { jobId, output, meta }. output é o valor escolhido ou combinado, como string. meta.summary sempre vem preenchido. pick-best-llm e vote preenchem meta.selectedIndex, e pick-best-llm também preenche meta.reasoning.

// Majority vote
const winner = await client.reduce.run({ strategyId: "vote", inputs: ["red", "blue", "red"] })

// Deep-merge JSON fragments
const merged = await client.reduce.run({
  strategyId: "merge-json",
  inputs: [JSON.stringify({ a: 1, nested: { x: 1 } }), JSON.stringify({ b: 2, nested: { y: 2 } })],
})
JSON.parse(merged.output) // { a: 1, b: 2, nested: { x: 1, y: 2 } }

Quando todas as entradas estão vazias ou têm só espaços em branco, a chamada falha com um NodaroError de status 400 e code igual a no_valid_inputs. Os créditos são reservados como em qualquer geração, então um saldo insuficiente lança InsufficientCreditsError.

Perguntas frequentes

Última atualização

Nesta página