Skip to Content
OpenAI chat

OpenAI chat example

Text streaming with OpenAI API showcasing async generators and JSONLines streaming.

Result

Code

OpenAiController.ts
OpenAiExample.tsx
1import { type VovkRequest, post, prefix, openapi, HttpException, HttpStatus } from 'vovk';
2import OpenAI from 'openai';
3
4@prefix('openai')
5export default class OpenAiController {
6 @openapi({
7 summary: 'Create a chat completion',
8 description: 'Create a chat completion using OpenAI and yield the response',
9 })
10 @post('chat', { cors: true, headers: { 'Access-Control-Allow-Origin': 'https://vovk.dev' } })
11 static async *createChatCompletion(
12 req: VovkRequest<{ messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[] }>
13 ) {
14 const { messages } = await req.json();
15 const LIMIT = 5;
16 const openai = new OpenAI();
17
18 if (messages.filter(({ role }) => role === 'user').length > LIMIT) {
19 throw new HttpException(HttpStatus.BAD_REQUEST, `You can only send ${LIMIT} messages at a time`);
20 }
21
22 yield* await openai.chat.completions.create({
23 messages,
24 model: 'gpt-4.1-nano',
25 stream: true,
26 });
27 }
28}
1import { type VovkRequest, post, prefix, openapi, HttpException, HttpStatus } from 'vovk';
2import OpenAI from 'openai';
3
4@prefix('openai')
5export default class OpenAiController {
6 @openapi({
7 summary: 'Create a chat completion',
8 description: 'Create a chat completion using OpenAI and yield the response',
9 })
10 @post('chat', { cors: true, headers: { 'Access-Control-Allow-Origin': 'https://vovk.dev' } })
11 static async *createChatCompletion(
12 req: VovkRequest<{ messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[] }>
13 ) {
14 const { messages } = await req.json();
15 const LIMIT = 5;
16 const openai = new OpenAI();
17
18 if (messages.filter(({ role }) => role === 'user').length > LIMIT) {
19 throw new HttpException(HttpStatus.BAD_REQUEST, `You can only send ${LIMIT} messages at a time`);
20 }
21
22 yield* await openai.chat.completions.create({
23 messages,
24 model: 'gpt-4.1-nano',
25 stream: true,
26 });
27 }
28}
Last updated on