Skip to main content

Basic Streaming

Problem

Waiting for a complete AI response before displaying anything creates a sluggish user experience. Users see nothing for seconds, then the entire response appears at once. For long responses, this delay is especially painful.

Solution

Use neurolink.stream() to receive the response in real time, chunk by chunk. The result contains a .stream async iterable that yields content objects as they arrive from the provider.

Code

import { NeuroLink } from "@juspay/neurolink";

async function basicStream() {
const neurolink = new NeuroLink();

// Start a streaming request
const result = await neurolink.stream({
input: { text: "Explain how neural networks learn, step by step." },
provider: "openai",
model: "gpt-4",
});

// Consume the stream chunk by chunk
for await (const chunk of result.stream) {
if ("content" in chunk && chunk.content) {
process.stdout.write(chunk.content);
}
}

console.log("\n");

// After the stream completes, metadata is available
console.log("Provider:", result.provider);
console.log("Model:", result.model);

if (result.usage) {
console.log("Prompt tokens:", result.usage.promptTokens);
console.log("Completion tokens:", result.usage.completionTokens);
}
}

basicStream();

Explanation

1. Calling neurolink.stream()

The stream() method accepts the same input object as generate(). The key difference is the return type: instead of a single content string, you get a StreamResult with a .stream async iterable.

const result = await neurolink.stream({
input: { text: "Your prompt here" },
provider: "openai",
});

2. Consuming the Stream

The .stream property is an AsyncIterable that yields objects with a content field. Use a for await...of loop to process each chunk as it arrives:

for await (const chunk of result.stream) {
if ("content" in chunk && chunk.content) {
process.stdout.write(chunk.content);
}
}

The "content" in chunk guard handles the discriminated union -- stream chunks can be text, audio, or image types depending on your configuration.

3. Accessing Metadata After Completion

Token usage, provider name, model name, and finish reason are available on the result object. Some fields (like usage) resolve after the stream finishes.

4. Stream Options

stream() accepts the same core options as generate():

OptionDescription
providerAI provider name (e.g., "openai")
modelSpecific model (e.g., "gpt-4")
temperatureResponse randomness (0.0 - 1.0)
maxTokensMaximum tokens in the response
systemPromptSystem-level instructions
timeoutRequest timeout (number or string)
abortSignalExternal cancellation via AbortSignal

Variations

Accumulate the Full Response

Collect all chunks into a single string while still displaying them in real time:

async function streamAndCollect(neurolink: NeuroLink, prompt: string) {
const result = await neurolink.stream({
input: { text: prompt },
provider: "anthropic",
model: "claude-sonnet-4-20250514",
});

let fullResponse = "";

for await (const chunk of result.stream) {
if ("content" in chunk && chunk.content) {
fullResponse += chunk.content;
process.stdout.write(chunk.content);
}
}

console.log("\n\nTotal length:", fullResponse.length, "characters");
return fullResponse;
}

Stream with a System Prompt

Set instructions that guide the model's behavior:

const result = await neurolink.stream({
input: { text: "What are the benefits of TypeScript?" },
provider: "openai",
model: "gpt-4",
systemPrompt:
"You are a senior software engineer. Be concise and use bullet points.",
temperature: 0.3,
maxTokens: 500,
});

for await (const chunk of result.stream) {
if ("content" in chunk && chunk.content) {
process.stdout.write(chunk.content);
}
}

Cancel a Stream with AbortSignal

Stop a long-running stream programmatically:

const controller = new AbortController();

// Cancel after 5 seconds
setTimeout(() => controller.abort(), 5000);

try {
const result = await neurolink.stream({
input: { text: "Write a very long essay about the history of computing." },
provider: "openai",
abortSignal: controller.signal,
});

for await (const chunk of result.stream) {
if ("content" in chunk && chunk.content) {
process.stdout.write(chunk.content);
}
}
} catch (error: any) {
if (error.name === "AbortError") {
console.log("\nStream cancelled by user.");
} else {
throw error;
}
}

Stream to a Web Response (Server-Side)

Pipe the stream to an HTTP response for real-time delivery to a browser:

import { NeuroLink } from "@juspay/neurolink";

async function handleStreamRequest(req: Request): Promise<Response> {
const neurolink = new NeuroLink();

const result = await neurolink.stream({
input: { text: "Explain distributed systems" },
provider: "openai",
});

const encoder = new TextEncoder();
const readable = new ReadableStream({
async start(controller) {
for await (const chunk of result.stream) {
if ("content" in chunk && chunk.content) {
controller.enqueue(encoder.encode(chunk.content));
}
}
controller.close();
},
});

return new Response(readable, {
headers: { "Content-Type": "text/plain; charset=utf-8" },
});
}

See Also