Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Llms refactoring #362

Merged
merged 35 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
a00a6da
add basic claude bot logic
fegloff Apr 2, 2024
f836e19
fix new command, minimun balance for llmsBot, anthropic token counter,
fegloff Apr 3, 2024
c87e464
update grammy and grammy plugins packages
fegloff Apr 4, 2024
28304b7
add min balance to openAI bot
fegloff Apr 4, 2024
cd4f284
add llmsBase class, and vertexBot, claudeBot, llmBot derived classes
fegloff Apr 5, 2024
e1868f8
Merge branch 'logic-fixes' into llms-refactoring
fegloff Apr 5, 2024
9799be1
add llmsSessionData handling
fegloff Apr 5, 2024
f60636b
add llmsBase extended classes OpenAIBot, DalleBot
fegloff Apr 7, 2024
7d431ea
refactore openai module into a llmsBase dervived subclass + add first…
fegloff Apr 11, 2024
b13f260
fix agent/subagent naming
fegloff Apr 11, 2024
f455545
fix url llamaSubagent logic + improve user prompt and bot context
fegloff Apr 13, 2024
da64b5f
improve agent processing performance
fegloff Apr 15, 2024
ead1e50
add pdf agent
fegloff Apr 16, 2024
36b20bf
add llama agent logic for multiple urls
fegloff Apr 16, 2024
147b336
add gemmini 1.5 commands
fegloff Apr 16, 2024
ce88b3a
refactor session data
fegloff Apr 17, 2024
5533711
delete unused module document-handler
fegloff Apr 17, 2024
02962a3
add ctx and pdf commands
fegloff Apr 19, 2024
a54ce98
add tools logic
fegloff Apr 22, 2024
3dbb85b
optimize anthropic tool call + add sonnet tool command + fix new comm…
fegloff Apr 29, 2024
6d14ef0
add api token to axios request header
fegloff May 3, 2024
4b7194e
remove translate prefixes
fegloff May 3, 2024
27517fa
fix concurrent command calls
fegloff May 25, 2024
95e6de2
add gpt-4o
fegloff May 25, 2024
47489f3
update default model to gpt-4o + fix edit message error on streaming …
fegloff May 27, 2024
e0707d9
update grammy to 1.23.1 version
fegloff May 28, 2024
e0d9657
update gpt4 and gpt4o openai commands
fegloff May 28, 2024
b7c39da
add llms/completion call and stream normalization for vertex and clau…
fegloff May 28, 2024
64cfa38
Merge pull request #363 from harmony-one/grammy-update
fegloff May 29, 2024
48b53cf
fix system message for openai model
fegloff May 30, 2024
b6d703d
add error handling to stats, botstats, allstats commands
fegloff Jul 6, 2024
d78126f
add content_policy_violation error handling on errorhandler class
fegloff Jul 10, 2024
61fbcbd
disable bard commands
fegloff Jul 16, 2024
02af912
add sonnet 3.5 model + upgrade error logging
fegloff Aug 27, 2024
63eb084
enable 1country subdomain activation feature for localuse
fegloff Sep 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:16
FROM node:20

WORKDIR /usr/src/app

Expand Down
11,311 changes: 7,084 additions & 4,227 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@
"@google-cloud/translate": "^8.0.2",
"@grammyjs/auto-chat-action": "^0.1.1",
"@grammyjs/auto-retry": "^1.1.1",
"@grammyjs/conversations": "^1.1.2",
"@grammyjs/files": "^1.0.4",
"@grammyjs/conversations": "^1.2.0",
"@grammyjs/files": "^1.1.0",
"@grammyjs/menu": "^1.2.1",
"@grammyjs/ratelimiter": "^1.2.0",
"@grammyjs/runner": "^2.0.3",
"@sentry/node": "^7.69.0",
"@sentry/profiling-node": "^1.2.1",
"@sentry/profiling-node": "^1.3.5",
"@walletconnect/sign-client": "^2.9.2",
"axios": "^1.4.0",
"bignumber.js": "^9.1.1",
Expand All @@ -95,8 +95,8 @@
"express": "^4.18.2",
"express-async-handler": "^1.2.0",
"form-data": "^4.0.0",
"gpt-tokenizer": "^2.1.1",
"grammy": "^1.18.3",
"gpt-tokenizer": "^2.1.2",
"grammy": "^1.23.1",
"jsqr": "^1.4.0",
"litllm": "^3.0.0",
"lokijs": "^1.5.12",
Expand Down
127 changes: 51 additions & 76 deletions src/bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ import { TranslateBot } from './modules/translate/TranslateBot'
import { VoiceMemo } from './modules/voice-memo'
// import { QRCodeBot } from './modules/qrcode/QRCodeBot'
// import { SDImagesBot } from './modules/sd-images'
import { OpenAIBot } from './modules/open-ai'
// import { OpenAIBot } from './modules/open-ai'
import { DalleBot, OpenAIBot, ClaudeBot, VertexBot } from './modules/llms'

import { OneCountryBot } from './modules/1country'
import { WalletConnect } from './modules/walletconnect'
import { BotPayments } from './modules/payment'
Expand All @@ -51,9 +53,10 @@ import { VoiceTranslateBot } from './modules/voice-translate'
import { TextToSpeechBot } from './modules/text-to-speech'
import { VoiceToTextBot } from './modules/voice-to-text'
import { now } from './utils/perf'
import { hasPrefix } from './modules/open-ai/helpers'
import { VoiceToVoiceGPTBot } from './modules/voice-to-voice-gpt'
import { VoiceCommand } from './modules/voice-command'
// import { VoiceCommand } from './modules/voice-command'
import { createInitialSessionData } from './helpers'
import { LlamaAgent } from './modules/subagents'

Events.EventEmitter.defaultMaxListeners = 30

Expand Down Expand Up @@ -138,10 +141,7 @@ bot.use(async (ctx: BotContext, next: NextFunction): Promise<void> => {
break
}
}
const prefix = hasPrefix(ctx.message?.text ?? '')
if (!command && prefix) {
command = prefix
}

await next()
transaction.finish()

Expand Down Expand Up @@ -181,54 +181,6 @@ bot.use(async (ctx: BotContext, next: NextFunction): Promise<void> => {
}
})

function createInitialSessionData (): BotSessionData {
return {
openAi: {
imageGen: {
numImages: config.openAi.dalle.sessionDefault.numImages,
imgSize: config.openAi.dalle.sessionDefault.imgSize,
isEnabled: config.openAi.dalle.isEnabled,
imgRequestQueue: [],
isProcessingQueue: false,
imageGenerated: [],
isInscriptionLotteryEnabled: config.openAi.dalle.isInscriptionLotteryEnabled,
imgInquiried: []
},
chatGpt: {
model: config.openAi.chatGpt.model,
isEnabled: config.openAi.chatGpt.isEnabled,
isFreePromptChatGroups: config.openAi.chatGpt.isFreePromptChatGroups,
chatConversation: [],
price: 0,
usage: 0,
isProcessingQueue: false,
requestQueue: []
}
},
oneCountry: { lastDomain: '' },
translate: {
languages: [],
enable: false
},
collections: {
activeCollections: [],
collectionRequestQueue: [],
isProcessingQueue: false,
currentCollection: '',
collectionConversation: []
},
llms: {
model: config.llms.model,
isEnabled: config.llms.isEnabled,
chatConversation: [],
price: 0,
usage: 0,
isProcessingQueue: false,
requestQueue: []
}
}
}

bot.use(
session({
initial: createInitialSessionData,
Expand All @@ -247,15 +199,20 @@ const voiceMemo = new VoiceMemo()
const walletConnect = new WalletConnect()
const payments = new BotPayments()
const schedule = new BotSchedule(bot)
const openAiBot = new OpenAIBot(payments)
const llamaAgent = new LlamaAgent(payments, 'llamaService')
const openAiBot = new OpenAIBot(payments, [llamaAgent])
const dalleBot = new DalleBot(payments)
const claudeBot = new ClaudeBot(payments)
const vertexBot = new VertexBot(payments, [llamaAgent])
const oneCountryBot = new OneCountryBot(payments)
const translateBot = new TranslateBot()
const telegramPayments = new TelegramPayments(payments)
const voiceTranslateBot = new VoiceTranslateBot(payments)
const textToSpeechBot = new TextToSpeechBot(payments)
const voiceToTextBot = new VoiceToTextBot(payments)
const voiceToVoiceGPTBot = new VoiceToVoiceGPTBot(payments)
const voiceCommand = new VoiceCommand(openAiBot)

// const voiceCommand = new VoiceCommand(openAiBot)

bot.on('message:new_chat_members:me', async (ctx) => {
try {
Expand Down Expand Up @@ -363,7 +320,7 @@ const writeCommandLog = async (
}

const PayableBots: Record<string, PayableBotConfig> = {
voiceCommand: { bot: voiceCommand },
// voiceCommand: { bot: voiceCommand },
// qrCodeBot: { bot: qrCodeBot },
// sdImagesBot: { bot: sdImagesBot },
voiceTranslate: { bot: voiceTranslateBot },
Expand All @@ -372,8 +329,11 @@ const PayableBots: Record<string, PayableBotConfig> = {
textToSpeech: { bot: textToSpeechBot },
voiceToVoiceGPTBot: { bot: voiceToVoiceGPTBot },
voiceToText: { bot: voiceToTextBot },
dalleBot: { bot: dalleBot },
claudeBot: { bot: claudeBot },
vertexBot: { bot: vertexBot },
openAiBot: {
enabled: (ctx: OnMessageContext) => ctx.session.openAi.imageGen.isEnabled,
enabled: (ctx: OnMessageContext) => ctx.session.dalle.isEnabled,
bot: openAiBot
},
oneCountryBot: { bot: oneCountryBot }
Expand All @@ -385,9 +345,9 @@ const UtilityBots: Record<string, UtilityBot> = {
schedule
}

const executeOrRefund = (ctx: OnMessageContext, price: number, bot: PayableBot): void => {
const executeOrRefund = async (ctx: OnMessageContext, price: number, bot: PayableBot): Promise<void> => {
const refund = (reason?: string): void => {}
bot.onEvent(ctx, refund).catch((ex: any) => {
await bot.onEvent(ctx, refund).catch((ex: any) => {
Sentry.captureException(ex)
logger.error(ex?.message ?? 'Unknown error')
})
Expand All @@ -396,9 +356,14 @@ const executeOrRefund = (ctx: OnMessageContext, price: number, bot: PayableBot):
const onMessage = async (ctx: OnMessageContext): Promise<void> => {
try {
// bot doesn't handle forwarded messages
if (!ctx.message.forward_from) {
if (!ctx.message.forward_origin) {
await assignFreeCredits(ctx)

if (llamaAgent.isSupportedEvent(ctx)) {
await llamaAgent.onEvent(ctx)
return
}

if (telegramPayments.isSupportedEvent(ctx)) {
await telegramPayments.onEvent(ctx)
return
Expand All @@ -416,7 +381,7 @@ const onMessage = async (ctx: OnMessageContext): Promise<void> => {
const isPaid = await payments.pay(ctx, price)
if (isPaid) {
logger.info(`command controller: ${bot.constructor.name}`)
executeOrRefund(ctx, price, bot)
await executeOrRefund(ctx, price, bot)
}
return
}
Expand All @@ -429,7 +394,7 @@ const onMessage = async (ctx: OnMessageContext): Promise<void> => {
return
}
// Any message interacts with ChatGPT (only for private chats or /ask on enabled on group chats)
if (ctx.update.message.chat && (ctx.chat.type === 'private' || ctx.session.openAi.chatGpt.isFreePromptChatGroups)) {
if (ctx.update.message.chat && (ctx.chat.type === 'private' || ctx.session.chatGpt.isFreePromptChatGroups)) {
await openAiBot.onEvent(ctx, (e) => {
logger.error(e)
})
Expand Down Expand Up @@ -467,8 +432,8 @@ const onCallback = async (ctx: OnCallBackQueryData): Promise<void> => {
// return
// }

if (openAiBot.isSupportedEvent(ctx)) {
await openAiBot.onEvent(ctx, (e) => {
if (dalleBot.isSupportedEvent(ctx)) {
await dalleBot.onEvent(ctx, (e) => {
logger.error(e)
})
}
Expand Down Expand Up @@ -501,7 +466,7 @@ bot.command(['start', 'help', 'menu'], async (ctx) => {
await ctx.reply(startText, {
parse_mode: 'Markdown',
reply_markup: mainMenu,
disable_web_page_preview: true,
link_preview_options: { is_disabled: true },
message_thread_id: ctx.message?.message_thread_id
})
})
Expand All @@ -515,7 +480,7 @@ bot.command('more', async (ctx) => {
writeCommandLog(ctx as OnMessageContext).catch(logErrorHandler)
return await ctx.reply(commandsHelpText.more, {
parse_mode: 'Markdown',
disable_web_page_preview: true,
link_preview_options: { is_disabled: true },
message_thread_id: ctx.message?.message_thread_id
})
})
Expand All @@ -524,7 +489,7 @@ bot.command('terms', async (ctx) => {
writeCommandLog(ctx as OnMessageContext).catch(logErrorHandler)
return await ctx.reply(TERMS.text, {
parse_mode: 'Markdown',
disable_web_page_preview: true,
link_preview_options: { is_disabled: true },
message_thread_id: ctx.message?.message_thread_id
})
})
Expand All @@ -533,7 +498,7 @@ bot.command('support', async (ctx) => {
writeCommandLog(ctx as OnMessageContext).catch(logErrorHandler)
return await ctx.reply(SUPPORT.text, {
parse_mode: 'Markdown',
disable_web_page_preview: true,
link_preview_options: { is_disabled: true },
message_thread_id: ctx.message?.message_thread_id
})
})
Expand All @@ -542,23 +507,23 @@ bot.command('models', async (ctx) => {
writeCommandLog(ctx as OnMessageContext).catch(logErrorHandler)
return await ctx.reply(MODELS.text, {
parse_mode: 'Markdown',
disable_web_page_preview: true
link_preview_options: { is_disabled: true }
})
})

bot.command('lang', async (ctx) => {
writeCommandLog(ctx as OnMessageContext).catch(logErrorHandler)
return await ctx.reply(LANG.text, {
parse_mode: 'Markdown',
disable_web_page_preview: true
link_preview_options: { is_disabled: true }
})
})

bot.command('feedback', async (ctx) => {
writeCommandLog(ctx as OnMessageContext).catch(logErrorHandler)
return await ctx.reply(FEEDBACK.text, {
parse_mode: 'Markdown',
disable_web_page_preview: true,
link_preview_options: { is_disabled: true },
message_thread_id: ctx.message?.message_thread_id
})
})
Expand All @@ -567,14 +532,15 @@ bot.command('love', async (ctx) => {
writeCommandLog(ctx as OnMessageContext).catch(logErrorHandler)
return await ctx.reply(LOVE.text, {
parse_mode: 'Markdown',
disable_web_page_preview: true,
link_preview_options: { is_disabled: true },
message_thread_id: ctx.message?.message_thread_id
})
})

bot.command('stop', async (ctx) => {
logger.info('/stop command')
await openAiBot.onStop(ctx as OnMessageContext)
await claudeBot.onStop(ctx as OnMessageContext)
ctx.session.translate.enable = false
ctx.session.translate.languages = []
ctx.session.oneCountry.lastDomain = ''
Expand All @@ -584,15 +550,24 @@ bot.command(['alias', 'aliases'], async (ctx) => {
logger.info('/alias command')
return await ctx.reply(ALIAS.text, {
parse_mode: 'Markdown',
disable_web_page_preview: true,
link_preview_options: { is_disabled: true },
message_thread_id: ctx.message?.message_thread_id
})
})

// bot.command(['end'], async (ctx) => {
// logger.info('/end command')
// return await ctx.reply(ALIAS.text, {
// parse_mode: 'Markdown',
// link_preview_options: { is_disabled: true },
// message_thread_id: ctx.message?.message_thread_id
// })
// })

// bot.command("memo", (ctx) => {
// ctx.reply(MEMO.text, {
// parse_mode: "Markdown",
// disable_web_page_preview: true,
// link_preview_options: { is_disabled: true },
// });
// });

Expand Down
11 changes: 6 additions & 5 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ export default {
? parseInt(process.env.SESSION_TIMEOUT)
: 48, // in hours
llms: {
apiEndpoint: process.env.LLMS_ENDPOINT, // 'http://127.0.0.1:5000',
apiEndpoint: process.env.LLMS_ENDPOINT, // // process.env.LLMS_ENDPOINT, // 'http://127.0.0.1:5000',
apiKey: process.env.LLMS_API_KEY ?? '',
wordLimit: 50,
model: 'chat-bison',
minimumBalance: 0,
Expand Down Expand Up @@ -61,9 +62,9 @@ export default {
}
},
chatGpt: {
chatCompletionContext: `You are an AI Bot powered by Harmony. Your strengths are ai api aggregation for chat,
image, and voice interactions using OpenAI’s chatgpt, Stable Diffusion, and more.
Respond flexibly, but try to stay within 100 words in your response.`,
chatCompletionContext:
'You are an AI Bot powered by Harmony. Your strengths are ai api aggregation for chat, image, and voice interactions. Leveraging a suite of sophisticated subagents, you have the capability to perform tasks such as internet browsing and accessing various services. Your responses should be adaptable to the conversation while maintaining brevity, ideally not exceeding 100 words.',
// 'You are an AI Bot powered dby Harmony. Your strengths are ai api aggregation for chat, image, and voice interactions, and more. You have subagents that helps you with task like browsing the internet, and other services. Respond flexibly, but try to stay within 100 words in all of your responses.',
webCrawlerContext: 'You will receive a web crawling text. Please get keys concepts, but try to stay within 4000 words in your response.',
visionCompletionContext: `You are a concise AI Bot powered by Harmony, capable of providing complete responses within a 100-word limit.
For each additional image, extend your response by 30 words. Your responses should be informative and comprehensive,
Expand Down Expand Up @@ -142,7 +143,7 @@ export default {
explorerRestApiKey: process.env.EXPLORER_REST_API_KEY ?? '',
swapSubgraphApiUrl:
process.env.SWAP_SUBGRAPH_API_URL ??
'https://api.thegraph.com/subgraphs/name/nick8319/uniswap-v3-harmony'
'https://api.thegraph.com/subgraphs/name/nick8319/uniswap-v3-harmony' // 'https://api.thegraph.com/subgraphs/name/potvik/uniswap-v3-harmony'
},
walletConnect: { projectId: process.env.WALLET_CONNECT_PROJECT_ID ?? '' },
voiceTranslate: { isEnabled: Boolean(parseInt(process.env.BOT_VOICE_TRANSLATE_ENABLE ?? '0')) },
Expand Down
Loading
Loading