Skip to content

Commit

Permalink
⬆️ (openai) Replace openai-edge with openai and upgrade next
Browse files Browse the repository at this point in the history
  • Loading branch information
baptisteArno committed Oct 6, 2023
1 parent dfcaa0f commit 225dfed
Show file tree
Hide file tree
Showing 15 changed files with 417 additions and 180 deletions.
8 changes: 4 additions & 4 deletions apps/builder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@trpc/next": "10.34.0",
"@trpc/react-query": "10.34.0",
"@trpc/server": "10.34.0",
"@typebot.io/bot-engine": "workspace:*",
"@typebot.io/emails": "workspace:*",
"@typebot.io/env": "workspace:*",
"@typebot.io/nextjs": "workspace:*",
Expand Down Expand Up @@ -65,13 +66,13 @@
"libphonenumber-js": "1.10.37",
"micro": "10.0.1",
"micro-cors": "0.1.1",
"next": "13.4.3",
"next": "13.5.4",
"next-auth": "4.22.1",
"next-international": "0.9.5",
"nextjs-cors": "^2.1.2",
"nodemailer": "6.9.3",
"nprogress": "0.2.0",
"openai-edge": "1.2.2",
"openai": "^4.11.1",
"papaparse": "5.4.1",
"posthog-js": "^1.77.1",
"posthog-node": "3.1.1",
Expand All @@ -89,8 +90,7 @@
"tinycolor2": "1.6.0",
"trpc-openapi": "1.2.0",
"unsplash-js": "^7.0.18",
"use-debounce": "9.0.4",
"@typebot.io/bot-engine": "workspace:*"
"use-debounce": "9.0.4"
},
"devDependencies": {
"@chakra-ui/styled-system": "2.9.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import { authenticatedProcedure } from '@/helpers/server/trpc'
import { TRPCError } from '@trpc/server'
import { z } from 'zod'
import { isReadWorkspaceFobidden } from '@/features/workspace/helpers/isReadWorkspaceFobidden'
import { Configuration, OpenAIApi, ResponseTypes } from 'openai-edge'
import { decrypt } from '@typebot.io/lib/api'
import {
OpenAICredentials,
defaultBaseUrl,
} from '@typebot.io/schemas/features/blocks/integrations/openai'
import { isNotEmpty } from '@typebot.io/lib/utils'
import { OpenAI, ClientOptions } from 'openai'

export const listModels = authenticatedProcedure
.meta({
Expand Down Expand Up @@ -79,41 +79,26 @@ export const listModels = authenticatedProcedure
credentials.iv
)) as OpenAICredentials['data']

const config = new Configuration({
const config = {
apiKey: data.apiKey,
basePath: baseUrl,
baseOptions: {
headers: {
'api-key': data.apiKey,
},
baseURL: baseUrl,
defaultHeaders: {
'api-key': data.apiKey,
},
defaultQueryParams: isNotEmpty(apiVersion)
? new URLSearchParams({
defaultQuery: isNotEmpty(apiVersion)
? {
'api-version': apiVersion,
})
}
: undefined,
})

const openai = new OpenAIApi(config)
} satisfies ClientOptions

const response = await openai.listModels()
const openai = new OpenAI(config)

const modelsData = (await response.json()) as
| ResponseTypes['listModels']
| {
error: unknown
}

if ('error' in modelsData)
throw new TRPCError({
code: 'INTERNAL_SERVER_ERROR',
message: 'Could not list models',
cause: modelsData.error,
})
const models = await openai.models.list()

return {
models:
modelsData.data
models.data
.sort((a, b) => b.created - a.created)
.map((model) => model.id) ?? [],
}
Expand Down
2 changes: 1 addition & 1 deletion apps/landing-page/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"aos": "2.3.4",
"focus-visible": "5.2.0",
"framer-motion": "10.12.20",
"next": "13.4.3",
"next": "13.5.4",
"react": "18.2.0",
"react-dom": "18.2.0"
},
Expand Down
10 changes: 5 additions & 5 deletions apps/viewer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,23 @@
"@planetscale/database": "^1.8.0",
"@sentry/nextjs": "7.66.0",
"@trpc/server": "10.34.0",
"@typebot.io/bot-engine": "workspace:*",
"@typebot.io/nextjs": "workspace:*",
"@typebot.io/prisma": "workspace:*",
"ai": "2.1.32",
"ai": "2.2.14",
"bot-engine": "workspace:*",
"cors": "2.8.5",
"google-spreadsheet": "4.0.2",
"got": "12.6.0",
"next": "13.4.3",
"next": "13.5.4",
"nextjs-cors": "2.1.2",
"nodemailer": "6.9.3",
"openai-edge": "1.2.2",
"openai": "^4.11.1",
"qs": "6.11.2",
"react": "18.2.0",
"react-dom": "18.2.0",
"stripe": "12.13.0",
"trpc-openapi": "1.2.0",
"@typebot.io/bot-engine": "workspace:*"
"trpc-openapi": "1.2.0"
},
"devDependencies": {
"@faire/mjml-react": "3.3.0",
Expand Down
85 changes: 56 additions & 29 deletions apps/viewer/src/pages/api/integrations/openai/streamer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@ import { connect } from '@planetscale/database'
import { env } from '@typebot.io/env'
import { IntegrationBlockType, SessionState } from '@typebot.io/schemas'
import { StreamingTextResponse } from 'ai'
import { ChatCompletionRequestMessage } from 'openai-edge'
import { getChatCompletionStream } from '@typebot.io/bot-engine/blocks/integrations/openai/getChatCompletionStream'
import OpenAI from 'openai'
import { NextResponse } from 'next/dist/server/web/spec-extension/response'

export const config = {
runtime: 'edge',
regions: ['lhr1'],
}

const responseHeaders = {
'Access-Control-Allow-Origin': '*',
}

const handler = async (req: Request) => {
if (req.method === 'OPTIONS') {
return new Response('ok', {
Expand All @@ -23,12 +28,20 @@ const handler = async (req: Request) => {
}
const { sessionId, messages } = (await req.json()) as {
sessionId: string
messages: ChatCompletionRequestMessage[]
messages: OpenAI.Chat.ChatCompletionMessage[]
}

if (!sessionId) return new Response('No session ID provided', { status: 400 })
if (!sessionId)
return NextResponse.json(
{ message: 'No session ID provided' },
{ status: 400, headers: responseHeaders }
)

if (!messages) return new Response('No messages provided', { status: 400 })
if (!messages)
return NextResponse.json(
{ message: 'No messages provided' },
{ status: 400, headers: responseHeaders }
)

const conn = connect({ url: env.DATABASE_URL })

Expand All @@ -40,7 +53,11 @@ const handler = async (req: Request) => {
const state = (chatSession.rows.at(0) as { state: SessionState } | undefined)
?.state

if (!state) return new Response('No state found', { status: 400 })
if (!state)
return NextResponse.json(
{ message: 'No state found' },
{ status: 400, headers: responseHeaders }
)

const group = state.typebotsQueue[0].typebot.groups.find(
(group) => group.id === state.currentBlock?.groupId
Expand All @@ -53,36 +70,46 @@ const handler = async (req: Request) => {
const block = blockIndex >= 0 ? group?.blocks[blockIndex ?? 0] : null

if (!block || !group)
return new Response('Current block not found', { status: 400 })
return NextResponse.json(
{ message: 'Current block not found' },
{ status: 400, headers: responseHeaders }
)

if (
block.type !== IntegrationBlockType.OPEN_AI ||
block.options.task !== 'Create chat completion'
)
return new Response('Current block is not an OpenAI block', { status: 400 })

const streamOrResponse = await getChatCompletionStream(conn)(
state,
block.options,
messages
)

if (!streamOrResponse)
return new Response('Could not create stream', { status: 400 })

if ('ok' in streamOrResponse)
return new Response(streamOrResponse.body, {
status: streamOrResponse.status,
headers: {
'Access-Control-Allow-Origin': '*',
},
return NextResponse.json(
{ message: 'Current block is not an OpenAI block' },
{ status: 400, headers: responseHeaders }
)

try {
const stream = await getChatCompletionStream(conn)(
state,
block.options,
messages
)
if (!stream)
return NextResponse.json(
{ message: 'Could not create stream' },
{ status: 400, headers: responseHeaders }
)

return new StreamingTextResponse(stream, {
headers: responseHeaders,
})

return new StreamingTextResponse(streamOrResponse, {
headers: {
'Access-Control-Allow-Origin': '*',
},
})
} catch (error) {
if (error instanceof OpenAI.APIError) {
const { name, status, message } = error
return NextResponse.json(
{ name, status, message },
{ status, headers: responseHeaders }
)
} else {
throw error
}
}
}

export default handler
Original file line number Diff line number Diff line change
Expand Up @@ -105,23 +105,23 @@ export const createChatCompletionOpenAI = async (
}
}

const { response, logs } = await executeChatCompletionOpenAIRequest({
const { chatCompletion, logs } = await executeChatCompletionOpenAIRequest({
apiKey,
messages,
model: options.model,
temperature,
baseUrl: options.baseUrl,
apiVersion: options.apiVersion,
})
if (!response)
if (!chatCompletion)
return {
outgoingEdgeId,
logs,
}
const messageContent = response.choices.at(0)?.message?.content
const totalTokens = response.usage?.total_tokens
const messageContent = chatCompletion.choices.at(0)?.message?.content
const totalTokens = chatCompletion.usage?.total_tokens
if (isEmpty(messageContent)) {
console.error('OpenAI block returned empty message', response)
console.error('OpenAI block returned empty message', chatCompletion.choices)
return { outgoingEdgeId, newSessionState }
}
return resumeChatCompletion(newSessionState, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@ import { isNotEmpty } from '@typebot.io/lib/utils'
import { ChatReply } from '@typebot.io/schemas'
import { OpenAIBlock } from '@typebot.io/schemas/features/blocks/integrations/openai'
import { HTTPError } from 'got'
import {
Configuration,
OpenAIApi,
type CreateChatCompletionRequest,
type CreateChatCompletionResponse,
ResponseTypes,
} from 'openai-edge'
import { ClientOptions, OpenAI } from 'openai'

type Props = Pick<CreateChatCompletionRequest, 'messages' | 'model'> & {
type Props = Pick<
OpenAI.Chat.ChatCompletionCreateParams,
'messages' | 'model'
> & {
apiKey: string
temperature: number | undefined
currentLogs?: ChatReply['logs']
Expand All @@ -27,38 +24,34 @@ export const executeChatCompletionOpenAIRequest = async ({
isRetrying,
currentLogs = [],
}: Props): Promise<{
response?: CreateChatCompletionResponse
chatCompletion?: OpenAI.Chat.Completions.ChatCompletion
logs?: ChatReply['logs']
}> => {
const logs: ChatReply['logs'] = currentLogs
if (messages.length === 0) return { logs }
try {
const config = new Configuration({
const config = {
apiKey,
basePath: baseUrl,
baseOptions: {
headers: {
'api-key': apiKey,
},
baseURL: baseUrl,
defaultHeaders: {
'api-key': apiKey,
},
defaultQueryParams: isNotEmpty(apiVersion)
? new URLSearchParams({
defaultQuery: isNotEmpty(apiVersion)
? {
'api-version': apiVersion,
})
}
: undefined,
})
} satisfies ClientOptions

const openai = new OpenAIApi(config)
const openai = new OpenAI(config)

const response = await openai.createChatCompletion({
const chatCompletion = await openai.chat.completions.create({
model,
messages,
temperature,
})

const completion =
(await response.json()) as ResponseTypes['createChatCompletion']
return { response: completion, logs }
return { chatCompletion, logs }
} catch (error) {
if (error instanceof HTTPError) {
if (
Expand Down
Loading

3 comments on commit 225dfed

@vercel
Copy link

@vercel vercel bot commented on 225dfed Oct 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 225dfed Oct 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

builder-v2 – ./apps/builder

app.typebot.io
builder-v2-git-main-typebot-io.vercel.app
builder-v2-typebot-io.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 225dfed Oct 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

viewer-v2 – ./apps/viewer

conversawpp.com
eventhub.com.au
feiraododia.com
fitness.riku.ai
games.klujo.com
ironcitygym.com
localove.online
projektelco.com
proscale.com.br
sellmycarbr.com
share.bot.gives
svhmapp.mprs.in
typebot.aloe.do
acordo-certo.com
app-liberado.pro
ask.pemantau.org
batepapo.digital
bot.contakit.com
bot.jogoquelucra.com
bot.leadbooster.help
bot.mycompay.reviews
bot.projetodashi.com
bot.socialcliques.me
cha.onewebcenter.com
chat.febredojogo.com
chat.gnipharmahq.com
chat.hayurihijab.com
chat.jottagreens.com
chatbee.agfunnel.com
click.sevenoways.com
connect.growthguy.in
demo.solidrock.space
detetivepatricia.com
drapamela.gikpro.com
drgisellegarcia.site
encodebot.share5.net
forms.bonanza.design
hello.advergreen.com
hello.doomsday.space
infomakeracademy.com
kuiz.sistemniaga.com
leoborges-app.online
linspecteuremma.site
malayanboosterhq.com
menukb.wpwakanda.com
offer.botscientis.us
ore.barrettamario.it
sales.doomsday.space
sellmycarglasgow.com
site100seguro.online
stephanesampa.online
superglicemia.com.br
talkbot.agfunnel.com
tenorioadvogados.com
uppity.wpwakanda.com
www.acordo-certo.com
83701274.21000000.lol
87186327.21000000.one
90945247.21000000.one
97320578.21000000.one
98650901.21000000.one
abutton.wpwakanda.com
acelera.maxbot.com.br
agendaestrategica.com
aidigitalmarketing.kr
atendimento.vrauu.com
viewer-v2-typebot-io.vercel.app
mdb.evento.equipeinterna.progenbr.com
bot.studiotecnicoimmobiliaremerelli.it
mdb.assessoria.boaventura.progenbr.com
mdb.assessoria.jtrebesqui.progenbr.com
pesquisa.escolamodacomproposito.com.br
anamnese.clinicaramosodontologia.com.br
gabinete.baleia.formulario.progenbr.com
mdb.assessoria.carreirinha.progenbr.com
chrome-os-inquiry-system.itschromeos.com
mdb.assessoria.paulomarques.progenbr.com
viewer-v2-git-main-typebot-io.vercel.app
main-menu-for-itschromeos.itschromeos.com
mdb.assessoria.qrcode.ademir.progenbr.com
mdb.assessoria.qrcode.arthur.progenbr.com
mdb.assessoria.qrcode.danilo.progenbr.com
mdb.assessoria.qrcode.marcao.progenbr.com
mdb.assessoria.qrcode.marcio.progenbr.com
mdb.assessoria.qrcode.aloisio.progenbr.com
mdb.assessoria.qrcode.girotto.progenbr.com
mdb.assessoria.qrcode.marinho.progenbr.com
mdb.assessoria.qrcode.rodrigo.progenbr.com
mdb.assessoria.carlosalexandre.progenbr.com
mdb.assessoria.qrcode.desideri.progenbr.com
mdb.assessoria.qrcode.fernanda.progenbr.com
mdb.assessoria.qrcode.jbatista.progenbr.com
mdb.assessoria.qrcode.mauricio.progenbr.com
mdb.assessoria.fernanda.regional.progenbr.com
mdb.assessoria.qrcode.boaventura.progenbr.com
mdb.assessoria.qrcode.jtrebesqui.progenbr.com
mdb.assessoria.qrcode.carreirinha.progenbr.com
mdb.assessoria.qrcode.paulomarques.progenbr.com
mdb.assessoria.qrcode.carlosalexandre.progenbr.com
mdb.assessoria.qrcode.fernanda.regional.progenbr.com

Please sign in to comment.