UNPKG

@convo-lang/convo-lang-aws-cdk

Version:
105 lines 3.6 kB
import { convoRoles, convoTags, unknownConvoTokenPrice } from "@convo-lang/convo-lang"; import { createConvoLangApiRoutes } from "@convo-lang/convo-lang-api-routes"; import { NotFoundError, asArrayItem, createFnHandler, queryParamsToObject } from '@iyio/common'; import { getHttpRoute } from '@iyio/node-common'; import { initBackend } from "../convo-lang-aws-cdk-lib"; import { checkTokenQuotaAsync, getTokenQuotaAsync, storeTokenUsageAsync } from '../price-capping'; initBackend(); class TokenLimitError extends Error { } let currentRemoteAddress = '0.0.0.0'; let routes = null; const getRoutes = () => { return routes ?? (routes = createConvoLangApiRoutes({ enableMockRoute: true, prefix: '', onCompletion: async ({ result, flat }) => { if (flat.apiKeyUsedForCompletion) { return; } let price = 0; for (const m of result) { if (m.tokenPrice) { price += m.tokenPrice; } else { price += ((m.inputTokens ?? 0) * unknownConvoTokenPrice) + ((m.outputTokens ?? 0) * unknownConvoTokenPrice); } } await storeTokenUsageAsync(price, { remoteAddress: currentRemoteAddress }); }, completionCtx: { beforeComplete: async (service, input, flat) => { if (flat.apiKeyUsedForCompletion) { return; } const quota = await checkTokenQuotaAsync({ remoteAddress: currentRemoteAddress }); if (!quota.allow) { throw new TokenLimitError('Token limit reached'); } }, }, getUsage: async () => { return await getTokenQuotaAsync({ remoteAddress: currentRemoteAddress }); } })); }; const ConvoLangAPi = async (fnEvt, input) => { const routes = getRoutes(); const method = fnEvt.method; let path = fnEvt.path; if (path.startsWith('/api/')) { path = path.substring(4); } currentRemoteAddress = fnEvt.remoteAddress || '0.0.0.0'; const qi = path.indexOf('?'); const query = qi === -1 ? {} : queryParamsToObject(path.substring(qi)); if (qi !== -1) { path = path.substring(0, qi); } const route = getHttpRoute(path, method, routes); if (!route) { throw new NotFoundError('Route not found'); } const regex = asArrayItem(route.match); if (regex) { const match = regex.exec(path); if (match) { for (let i = 1; i < match.length; i++) { const value = match[i]; query[i.toString()] = decodeURIComponent(value ?? ''); } } } try { return await route.handler({ req: {}, // convo-lang routes do not use the req object res: {}, // convo-lang routes do not use the res object path, filePath: '.', body: input, method, query }); } catch (ex) { if (ex instanceof TokenLimitError) { const msg = { tags: { [convoTags.tokenLimit]: '' }, role: convoRoles.assistant, content: ex.message }; return [msg]; } else { throw ex; } } finally { currentRemoteAddress = '0.0.0.0'; } }; export const handler = createFnHandler(ConvoLangAPi, {}); //# sourceMappingURL=ConvoLangApi.js.map