OpenAI Chat Example

Real use-case of text streaming with async generators using OpenAI API.

OpenAiController.ts
OpenAiExample.tsx
1import { type VovkRequest, post, prefix, HttpException, HttpStatus } from 'vovk';
2import OpenAI from 'openai';
3
4@prefix('openai')
5export default class OpenAiController {
6 private static _openai: OpenAI;
7
8 private static get openai() {
9 // to avoid compilation errors if OPENAI_API_KEY is not set
10 return (this._openai ??= new OpenAI());
11 }
12
13 @post('chat', { cors: true, headers: { 'Access-Control-Allow-Origin': 'https://vovk.dev' } })
14 static async *createChatCompletion(
15 req: VovkRequest<{ messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[] }>
16 ) {
17 const { messages } = await req.json();
18 const LIMIT = 5;
19
20 if (messages.filter(({ role }) => role === 'user').length > LIMIT) {
21 throw new HttpException(HttpStatus.BAD_REQUEST, `You can only send ${LIMIT} messages at a time`);
22 }
23
24 yield* await this.openai.chat.completions.create({
25 messages,
26 model: 'gpt-3.5-turbo',
27 stream: true,
28 });
29 }
30}
1import { type VovkRequest, post, prefix, HttpException, HttpStatus } from 'vovk';
2import OpenAI from 'openai';
3
4@prefix('openai')
5export default class OpenAiController {
6 private static _openai: OpenAI;
7
8 private static get openai() {
9 // to avoid compilation errors if OPENAI_API_KEY is not set
10 return (this._openai ??= new OpenAI());
11 }
12
13 @post('chat', { cors: true, headers: { 'Access-Control-Allow-Origin': 'https://vovk.dev' } })
14 static async *createChatCompletion(
15 req: VovkRequest<{ messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[] }>
16 ) {
17 const { messages } = await req.json();
18 const LIMIT = 5;
19
20 if (messages.filter(({ role }) => role === 'user').length > LIMIT) {
21 throw new HttpException(HttpStatus.BAD_REQUEST, `You can only send ${LIMIT} messages at a time`);
22 }
23
24 yield* await this.openai.chat.completions.create({
25 messages,
26 model: 'gpt-3.5-turbo',
27 stream: true,
28 });
29 }
30}