Nest.js

Learn how to use the AI TOOLKIT in a Nest.js server

2 min readapi serversstreamingView source

You can use the AI TOOLKIT in a Nest.js server to generate and stream text and objects to the client.

Run it locally

$ npm install ai

Examples

The examples show how to implement a Nest.js controller that uses the AI TOOLKIT to stream text and objects to the client.

Full example: github.com/khulnasoft/ai-toolkit/examples/nest

### UI Message Stream

You can use the pipeUIMessageStreamToResponse method to pipe the stream data to the server response.

import { Controller, Post, Res } from '@nestjs/common';

import { streamText } from 'ai-toolkit';

import { Response } from 'express';

@Controller()

export class AppController {

@Post('/')

async root(@Res() res: Response) {

const result = streamText({

model: 'openai/gpt-4o',

prompt: 'Invent a new holiday and describe its traditions.',

});

result.pipeUIMessageStreamToResponse(res);

}

}

### Sending Custom Data

createUIMessageStream and pipeUIMessageStreamToResponse can be used to send custom data to the client.

import { Controller, Post, Res } from '@nestjs/common';

import {

createUIMessageStream,

streamText,

pipeUIMessageStreamToResponse,

} from 'ai-toolkit';

import { Response } from 'express';

@Controller()

export class AppController {

@Post('/stream-data')

async streamData(@Res() response: Response) {

const stream = createUIMessageStream({

execute: ({ writer }) => {

// write some data

writer.write({ type: 'start' });

writer.write({

type: 'data-custom',

data: {

custom: 'Hello, world!',

},

});

const result = streamText({

model: 'openai/gpt-4o',

prompt: 'Invent a new holiday and describe its traditions.',

});

writer.merge(

result.toUIMessageStream({

sendStart: false,

onError: error => {

// Error messages are masked by default for security reasons.

// If you want to expose the error message to the client, you can do so here:

return error instanceof Error ? error.message : String(error);

},

}),

);

},

});

pipeUIMessageStreamToResponse({ stream, response });

}

}

### Text Stream

You can use the pipeTextStreamToResponse method to get a text stream from the result and then pipe it to the response.

import { Controller, Post, Res } from '@nestjs/common';

import { streamText } from 'ai-toolkit';

import { Response } from 'express';

@Controller()

export class AppController {

@Post()

async example(@Res() res: Response) {

const result = streamText({

model: 'openai/gpt-4o',

prompt: 'Invent a new holiday and describe its traditions.',

});

result.pipeTextStreamToResponse(res);

}

}

app.controller.ts
ts
  1. 1import { Controller, Post, Res } from '@nestjs/common';
  2. 2import { streamText } from 'ai-toolkit';
  3. 3import { Response } from 'express';
  4. 4@Controller()
  5. 5export class AppController {
  6. 6 @Post('/')
  7. 7 async root(@Res() res: Response) {
  8. 8 const result = streamText({
  9. 9 model: 'openai/gpt-4o',
  10. 10 prompt: 'Invent a new holiday and describe its traditions.',
  11. 11 });
  12. 12 result.pipeUIMessageStreamToResponse(res);
  13. 13 }
  14. 14}
app.controller.ts
ts
  1. 1import { Controller, Post, Res } from '@nestjs/common';
  2. 2import {
  3. 3 createUIMessageStream,
  4. 4 streamText,
  5. 5 pipeUIMessageStreamToResponse,
  6. 6} from 'ai-toolkit';
  7. 7import { Response } from 'express';
  8. 8@Controller()
  9. 9export class AppController {
  10. 10 @Post('/stream-data')
  11. 11 async streamData(@Res() response: Response) {
  12. 12 const stream = createUIMessageStream({
  13. 13 execute: ({ writer }) => {
  14. 14 // write some data
  15. 15 writer.write({ type: 'start' });
  16. 16 writer.write({
  17. 17 type: 'data-custom',
  18. 18 data: {
  19. 19 custom: 'Hello, world!',
  20. 20 },
  21. 21 });
  22. 22 const result = streamText({
  23. 23 model: 'openai/gpt-4o',
  24. 24 prompt: 'Invent a new holiday and describe its traditions.',
  25. 25 });
  26. 26 writer.merge(
  27. 27 result.toUIMessageStream({
  28. 28 sendStart: false,
  29. 29 onError: error => {
  30. 30 // Error messages are masked by default for security reasons.
  31. 31 // If you want to expose the error message to the client, you can do so here:
  32. 32 return error instanceof Error ? error.message : String(error);
  33. 33 },
  34. 34 }),
  35. 35 );
  36. 36 },
  37. 37 });
  38. 38 pipeUIMessageStreamToResponse({ stream, response });
  39. 39 }
  40. 40}
app.controller.ts
ts
  1. 1import { Controller, Post, Res } from '@nestjs/common';
  2. 2import { streamText } from 'ai-toolkit';
  3. 3import { Response } from 'express';
  4. 4@Controller()
  5. 5export class AppController {
  6. 6 @Post()
  7. 7 async example(@Res() res: Response) {
  8. 8 const result = streamText({
  9. 9 model: 'openai/gpt-4o',
  10. 10 prompt: 'Invent a new holiday and describe its traditions.',
  11. 11 });
  12. 12 result.pipeTextStreamToResponse(res);
  13. 13 }
  14. 14}

Troubleshooting

- Streaming not working when proxied