2
0
Files
bot/packages/bot-engine/blocks/integrations/zemanticAi/executeZemanticAiBlock.ts

148 lines
4.0 KiB
TypeScript
Raw Normal View History

import { SessionState } from '@typebot.io/schemas'
import {
ZemanticAiBlock,
ZemanticAiCredentials,
ZemanticAiResponse,
} from '@typebot.io/schemas/features/blocks/integrations/zemanticAi'
import ky from 'ky'
import { decrypt } from '@typebot.io/lib/api/encryption/decrypt'
import { byId, isDefined, isEmpty } from '@typebot.io/lib'
import { ExecuteIntegrationResponse } from '../../../types'
import { updateVariablesInSession } from '@typebot.io/variables/updateVariablesInSession'
:zap: Introduce a new high-performing standalone chat API (#1200) Closes #1154 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added authentication functionality for user sessions in chat API. - Introduced chat-related API endpoints for starting, previewing, and continuing chat sessions, and streaming messages. - Implemented WhatsApp API webhook handling for receiving and processing messages. - Added environment variable `NEXT_PUBLIC_CHAT_API_URL` for chat API URL configuration. - **Bug Fixes** - Adjusted file upload logic to correctly determine the API host. - Fixed message streaming URL in chat integration with OpenAI. - **Documentation** - Updated guides for creating blocks, local installation, self-hosting, and deployment to use `bun` instead of `pnpm`. - **Refactor** - Refactored chat API functionalities to use modular architecture. - Simplified client log saving and session update functionalities by using external functions. - Transitioned package management and workflow commands to use `bun`. - **Chores** - Switched to `bun` for package management in Dockerfiles and GitHub workflows. - Added new Dockerfile for chat API service setup with Bun framework. - Updated `.prettierignore` and documentation with new commands. - **Style** - No visible changes to end-users. - **Tests** - No visible changes to end-users. - **Revert** - No reverts in this release. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
2024-03-21 10:23:23 +01:00
import { getCredentials } from '../../../queries/getCredentials'
import { parseAnswers } from '@typebot.io/results/parseAnswers'
const URL = 'https://api.zemantic.ai/v1/search-documents'
export const executeZemanticAiBlock = async (
state: SessionState,
block: ZemanticAiBlock
): Promise<ExecuteIntegrationResponse> => {
let newSessionState = state
let setVariableHistory = []
if (!block.options?.credentialsId)
return {
outgoingEdgeId: block.outgoingEdgeId,
}
:zap: Introduce a new high-performing standalone chat API (#1200) Closes #1154 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added authentication functionality for user sessions in chat API. - Introduced chat-related API endpoints for starting, previewing, and continuing chat sessions, and streaming messages. - Implemented WhatsApp API webhook handling for receiving and processing messages. - Added environment variable `NEXT_PUBLIC_CHAT_API_URL` for chat API URL configuration. - **Bug Fixes** - Adjusted file upload logic to correctly determine the API host. - Fixed message streaming URL in chat integration with OpenAI. - **Documentation** - Updated guides for creating blocks, local installation, self-hosting, and deployment to use `bun` instead of `pnpm`. - **Refactor** - Refactored chat API functionalities to use modular architecture. - Simplified client log saving and session update functionalities by using external functions. - Transitioned package management and workflow commands to use `bun`. - **Chores** - Switched to `bun` for package management in Dockerfiles and GitHub workflows. - Added new Dockerfile for chat API service setup with Bun framework. - Updated `.prettierignore` and documentation with new commands. - **Style** - No visible changes to end-users. - **Tests** - No visible changes to end-users. - **Revert** - No reverts in this release. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
2024-03-21 10:23:23 +01:00
const credentials = await getCredentials(block.options.credentialsId)
if (!credentials) {
return {
outgoingEdgeId: block.outgoingEdgeId,
logs: [
{
status: 'error',
description: 'Make sure to select a Zemantic AI account',
},
],
}
}
const { apiKey } = (await decrypt(
credentials.data,
credentials.iv
)) as ZemanticAiCredentials['data']
const { typebot, answers } = newSessionState.typebotsQueue[0]
const templateVars = parseAnswers({
variables: typebot.variables,
answers: answers,
})
try {
const res: ZemanticAiResponse = await ky
.post(URL, {
headers: {
Authorization: `Bearer ${apiKey}`,
},
json: {
projectId: block.options.projectId,
query: replaceTemplateVars(
block.options.query as string,
templateVars
),
maxResults: block.options.maxResults,
summarize: true,
summaryOptions: {
system_prompt:
replaceTemplateVars(
block.options.systemPrompt as string,
templateVars
) ?? '',
prompt:
replaceTemplateVars(
block.options.prompt as string,
templateVars
) ?? '',
},
},
})
.json()
for (const r of block.options.responseMapping || []) {
const variable = typebot.variables.find(byId(r.variableId))
let newVariables = []
switch (r.valueToExtract) {
case 'Summary':
if (isDefined(variable) && !isEmpty(res.summary)) {
newVariables.push({ ...variable, value: res.summary })
}
break
case 'Results':
if (isDefined(variable) && res.results.length) {
newVariables.push({
...variable,
value: JSON.stringify(res.results),
})
}
break
default:
break
}
if (newVariables.length > 0) {
const { newSetVariableHistory, updatedState } =
updateVariablesInSession({
newVariables,
state: newSessionState,
currentBlockId: block.id,
})
newSessionState = updatedState
setVariableHistory.push(...newSetVariableHistory)
}
}
} catch (e) {
console.error(e)
return {
startTimeShouldBeUpdated: true,
outgoingEdgeId: block.outgoingEdgeId,
logs: [
{
status: 'error',
description: 'Could not execute Zemantic AI request',
},
],
newSetVariableHistory: setVariableHistory,
}
}
return {
outgoingEdgeId: block.outgoingEdgeId,
newSessionState,
startTimeShouldBeUpdated: true,
}
}
const replaceTemplateVars = (
template: string,
vars: Record<string, string>
) => {
if (!template) return
let result = template
for (const [key, value] of Object.entries(vars)) {
result = result.replaceAll(`{{${key}}}`, value)
}
return result
}