Skip to content

Instantly share code, notes, and snippets.

@celsowm
Created June 1, 2025 23:54
Show Gist options
  • Save celsowm/082aa881413eec853757f691cd8fb548 to your computer and use it in GitHub Desktop.
Save celsowm/082aa881413eec853757f691cd8fb548 to your computer and use it in GitHub Desktop.
stream_mode_json_chat_completion.js
(async () => {
// 1) Ajuste para o URL do seu servidor
const ENDPOINT = "http://localhost:8081/v1/chat/completions";
// 2) Use exatamente o mesmo nome de modelo que funcionou no Python
const MODEL = "seu-modelo-aqui";
// 3) Prompt de teste (igual ao Python: "Who won the world series in 2020")
const PROMPT = "Who won the world series in 2020";
// 4) Definimos o JSON‐schema idêntico ao do Python
const schema = {
type: "object",
properties: {
team_name: { type: "string" },
year: { type: "integer" },
world_series_winner: { type: "string" },
opponent: { type: "string" },
series_result: { type: "string" }
},
required: ["team_name", "year", "world_series_winner", "opponent", "series_result"],
additionalProperties: false
};
// 5) Construímos o “system prompt” exatamente como no Python
const systemPrompt =
"Você responde em formato JSON seguindo estritamente este schema:\n\n" +
JSON.stringify(schema, null, 2) +
"\n\nNada fora desse objeto JSON.";
// 6) Montamos o corpo da requisição, incluindo stream:true e response_format
const body = {
model: MODEL,
messages: [
{ role: "system", content: systemPrompt },
{ role: "user", content: PROMPT }
],
stream: true,
response_format: {
type: "json_object",
schema
},
temperature: 0.7
};
console.log("→ Enviando requisição para o servidor…");
console.log("Request body:", JSON.stringify(body, null, 2));
try {
// 7) Fazer o fetch com método POST
const resp = await fetch(ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body)
});
console.log("→ Resposta HTTP recebida. Status:", resp.status);
if (!resp.ok) {
console.error("Erro HTTP:", resp.status, resp.statusText);
return;
}
// 8) Lêmos o body como ReadableStream
const reader = resp.body.getReader();
const decoder = new TextDecoder("utf-8");
let acumulado = ""; // vai armazenar o JSON inteiro
console.log("→ Iniciando leitura do stream. Aguarde…");
while (true) {
const { done, value } = await reader.read();
if (done) {
console.log("→ Stream finalizado.");
break;
}
// 9) Decodifica o chunk atual para string (pode conter múltiplas linhas "data:")
const chunkTexto = decoder.decode(value, { stream: true });
console.log("[STREAM] Novo chunk recebido:\n", chunkTexto);
// 10) Cada payload “válido” começa com "data:"
for (const linhaBruta of chunkTexto.split("\n")) {
if (!linhaBruta.trimStart().startsWith("data:")) {
continue;
}
// Remove o prefixo “data:” e espaços em branco
const payload = linhaBruta.replace(/^data:\s*/, "").trim();
if (payload === "[DONE]") {
console.log("[STREAM] Payload '[DONE]' recebido. Encerrando leitura.");
break;
}
// 11) Tentamos fazer JSON.parse no payload (que deve ter a forma
// {"choices":[{"delta":{"content":"...parte do JSON..."}}], ...})
let delta;
try {
const obj = JSON.parse(payload);
delta = obj.choices?.[0]?.delta;
} catch (err) {
console.warn("[STREAM] Erro ao parsear JSON do payload:", err);
continue;
}
if (!delta || typeof delta.content !== "string") {
console.warn("[STREAM] Delta sem conteúdo textual válido. Pulando...");
continue;
}
// 12) “delta.content” contém um fragmento da string JSON. Exemplo:
// "{\"team_name\":\"Los Angeles Dodgers\",\"year\":2020"
// (pode ser apenas parte de uma chave/valor, pois é streaming)
const fragmento = delta.content.replace(/\r/g, "");
acumulado += fragmento;
// 13) Em vez de usar process.stdout.write (Node.js), só logamos:
console.log("[FRAGMENTO RECEBIDO]", fragmento);
}
}
// 14) Após sair do while, “acumulado” deve conter o JSON completo (em teoria)
const resultadoBruto = acumulado.trim();
console.log("→ Conteúdo bruto acumulado:\n", resultadoBruto);
// 15) Tentar parsear o JSON inteiro
console.log("→ Tentando dar JSON.parse no resultado completo:");
try {
const parsed = JSON.parse(resultadoBruto);
console.log(parsed);
} catch (err) {
console.error("❌ Falha ao parsear JSON final:", err);
console.log("Texto bruto para debug:", JSON.stringify(resultadoBruto));
}
} catch (err) {
console.error("❌ Erro ao fazer fetch/stream:", err);
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment