Skip to content

Commit

Permalink
chore: wip
Browse files Browse the repository at this point in the history
Signed-off-by: sarthakjdev <[email protected]>
  • Loading branch information
sarthakjdev committed Jul 14, 2024
1 parent 77eb80c commit 13d3b54
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 87 deletions.
3 changes: 3 additions & 0 deletions apps/wapi-ai-chatbot/environment.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ declare global {
WHATSAPP_BUSINESS_ACCOUNT_ID: string
WHATSAPP_WEBHOOK_SECRET: string
OPEN_AI_API_KEY: string
OPEN_AI_ORG_ID: string
OPEN_AI_PROJECT_ID: string

}
}
}
Expand Down
5 changes: 3 additions & 2 deletions apps/wapi-ai-chatbot/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@
"license": "MIT",
"dependencies": {
"@wapijs/wapi.js": "workspace:*",
"cache-manager": "^4.0.0",
"ms": "^2.1.3",
"node-cache": "^5.1.2",
"openai": "^4.52.7"
},
"devDependencies": {
"@esbuild-plugins/tsconfig-paths": "^0.1.2",
"@types/node": "^20.10.2",
"@types/cache-manager": "^4.0.6",
"@types/node": "^20.12.12",
"@wapijs/eslint-config": "workspace:*",
"@wapijs/prettier-config": "workspace:*",
"@wapijs/typescript-config": "workspace:*",
Expand Down
19 changes: 3 additions & 16 deletions apps/wapi-ai-chatbot/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { TextMessage, type TextMessageEvent } from '@wapijs/wapi.js'
import { whatsappClient } from './utils/client'
import { askAi } from './utils/gpt'
import { getCache, setCache } from './utils/cache'
import { cacheData, computeCacheKey, getCachedData } from './utils/cache'

Check failure on line 4 in apps/wapi-ai-chatbot/src/index.ts

View workflow job for this annotation

GitHub Actions / build-and-lint

'cacheData' is defined but never used

Check failure on line 4 in apps/wapi-ai-chatbot/src/index.ts

View workflow job for this annotation

GitHub Actions / build-and-lint

'computeCacheKey' is defined but never used

Check failure on line 4 in apps/wapi-ai-chatbot/src/index.ts

View workflow job for this annotation

GitHub Actions / build-and-lint

'getCachedData' is defined but never used

async function init() {

Check warning on line 6 in apps/wapi-ai-chatbot/src/index.ts

View workflow job for this annotation

GitHub Actions / build-and-lint

Async function 'init' has no 'await' expression
try {
Expand All @@ -14,23 +14,10 @@ async function init() {
})

whatsappClient.on('TextMessage', async (event: TextMessageEvent) => {

Check warning on line 16 in apps/wapi-ai-chatbot/src/index.ts

View workflow job for this annotation

GitHub Actions / build-and-lint

Promise returned in function argument where a void return was expected
const cachedResponse = await getCache(event.text.data.text)
console.log({ cachedResponse })
let response = 'Sorry, I am not able to understand that.'
if (cachedResponse) {
response = String(cachedResponse)
} else {
const aiResponse = await askAi(event.text.data.text)
response = aiResponse || response
if (aiResponse) {
setCache(event.text.data.text, aiResponse)
}
}

console.log({ response })
const aiResponse = await askAi(event.text.data.text, event.context.from)
await event.reply({
message: new TextMessage({
text: response
text: aiResponse
})
})
})
Expand Down
9 changes: 9 additions & 0 deletions apps/wapi-ai-chatbot/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export enum AiConversationRoleEnum {
User = 'user',
Ai = 'assistant'
}

export type ConversationMessageType = {
role: AiConversationRoleEnum
content: string
}
29 changes: 23 additions & 6 deletions apps/wapi-ai-chatbot/src/utils/cache.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
import NodeCache from 'node-cache'
import { AiConversationRoleEnum, ConversationMessageType } from '~/types'

Check failure on line 1 in apps/wapi-ai-chatbot/src/utils/cache.ts

View workflow job for this annotation

GitHub Actions / build-and-lint

'AiConversationRoleEnum' is defined but never used

Check failure on line 1 in apps/wapi-ai-chatbot/src/utils/cache.ts

View workflow job for this annotation

GitHub Actions / build-and-lint

'ConversationMessageType' is defined but never used
import { caching } from 'cache-manager'

const cache = new NodeCache()
const cacheStore = caching({
store: 'memory'
})

export const setCache = (key: string, value: any, ttl: number = 3600) => {
cache.set(key, value, ttl)
export async function cacheData(params: { key: string; data: any; ttl?: number }) {

Check warning on line 8 in apps/wapi-ai-chatbot/src/utils/cache.ts

View workflow job for this annotation

GitHub Actions / build-and-lint

Unexpected any. Specify a different type
const { key, ttl, data } = params
await cacheStore.set(key, data, { ...(ttl ? { ttl: ttl } : {}) })
}

export const getCache = (key: string) => {
return cache.get(key)
export async function getCachedData<T>(key: string): Promise<T> {
const response = await cacheStore.get(key)
console.log(response)
return response as T
}

export function computeCacheKey(params: { id: string; context: string }) {
return `${params.id}-${params.context}`
}

export function getConversationContextCacheKey(phoneNumber: string) {
return computeCacheKey({
id: phoneNumber,
context: 'conversation'
})
}
77 changes: 62 additions & 15 deletions apps/wapi-ai-chatbot/src/utils/gpt.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,81 @@
import { OpenAI } from 'openai'
import { cacheData, computeCacheKey, getCachedData, getConversationContextCacheKey } from './cache'
import { AiConversationRoleEnum, ConversationMessageType } from '~/types'

Check failure on line 3 in apps/wapi-ai-chatbot/src/utils/gpt.ts

View workflow job for this annotation

GitHub Actions / build-and-lint

Import "ConversationMessageType" is only used as types

const openAiApiKey = process.env.OPEN_AI_API_KEY
const organizationId = process.env.OPEN_AI_ORG_ID
const projectId = process.env.OPEN_AI_PROJECT_ID

if (!openAiApiKey) {
if (!openAiApiKey || !organizationId || !projectId) {
throw new Error('OPEN_AI_API_KEY not defined!')
}

const OpenApiClient = new OpenAI({
apiKey: openAiApiKey,
project: 'proj_viwVq5nzCR5Mj4TnIw4FQoNO',
organization: 'org-wwfaGhYXIA7CBUSg6x8DbKYj'
project: projectId,
organization: organizationId
})

export async function askAi(message: string): Promise<string | null> {

export async function askAi(message: string, fromPhoneNumber: string): Promise<string> {
try {
const chatCompletion = await OpenApiClient.chat.completions.create({
messages: [{ role: 'user', content: message }],
model: 'gpt-3.5-turbo'
const contextCacheKey = getConversationContextCacheKey(fromPhoneNumber)
const context = await getCachedData<ConversationMessageType[]>(contextCacheKey)

let response = 'Sorry, I am not able to understand that.'
const responseCacheKey = computeCacheKey({
context: 'response_cache',
id: message.trim()
})
const cachedResponse = await getCachedData<string>(responseCacheKey)
if (cachedResponse) {
response = cachedResponse
} else {
const chatCompletion = await OpenApiClient.chat.completions.create({
messages: [
{
role: 'system',
content: `You are an intelligent assistant helping a user with their queries. You can provide information, answer questions, and help the user complete tasks.
You are a developer relation engineer for a product named as Wapi.js.
Wapi.js is an SDK to build chat bots and to integrate WhatsApp API with your application very easily.
The SDK is authored by Sarthak Jain having github at https://github.com/sarthakjdev and is an open-source SDk which is free to use.
Users can use the SDK to build chatbots for customer support, marketing, notifications, and more! Leverage WhatsApp Business API.
You are required to give very to the point and very clear answers to the user queries.
Also, you can reveal your identity, ack like a human, and provide information about the product.
Never ever accept that you are an AI or a chatbot or an intelligent assistant.
`
},
...(context ? context : []),
{
role: 'user',
content: message
}
],
model: 'gpt-4'
})
console.log(JSON.stringify({ chatCompletion }))
const aiResponse = chatCompletion.choices[0].message.content
if (aiResponse) response = aiResponse
}

console.log(JSON.stringify({ chatCompletion }))
await cacheData({
key: contextCacheKey,
data: [
...(context ? context : []),
{
role: AiConversationRoleEnum.User,
content: message
},
{
role: AiConversationRoleEnum.Ai,
content: response
},

return chatCompletion.choices[0].message.content
]
})
return response
} catch (error) {
console.log({ error })
return null
return 'Sorry, I am not able to understand that.'
}
}


export async function generateTranscription(){

}
Loading

0 comments on commit 13d3b54

Please sign in to comment.