add dashboard

This commit is contained in:
Litlyx
2024-06-01 15:27:40 +02:00
parent 75f0787c3b
commit df4faf366f
201 changed files with 91267 additions and 0 deletions

View File

@@ -0,0 +1,144 @@
import { getVisitsCountFromDateRange } from '~/server/api/ai/functions/AI_Visits';
import OpenAI from "openai";
import { AiChatModel } from '@schema/ai/AiChatSchema';
import { AI_EventsFunctions, AI_EventsTools } from '../api/ai/functions/AI_Events';
import { ProjectCountModel } from '@schema/ProjectsCounts';
import { getCurrentProjectCountId } from '@functions/UtilsProjectCounts';
const { AI_ORG, AI_PROJECT, AI_KEY } = useRuntimeConfig();
const openai = new OpenAI({
organization: AI_ORG,
project: AI_PROJECT,
apiKey: AI_KEY
});
// const get_current_date: OpenAI.Chat.Completions.ChatCompletionTool = {
// type: 'function',
// function: {
// name: 'get_current_date',
// description: 'Gets the current date as ISO string',
// }
// }
const get_visits_count_Schema: OpenAI.Chat.Completions.ChatCompletionTool = {
type: 'function',
function: {
name: 'get_visits_count',
description: 'Gets the number of visits received on a date range',
parameters: {
type: 'object',
properties: {
from: { type: 'string', description: 'ISO string of start date including hours' },
to: { type: 'string', description: 'ISO string of end date including hours' }
},
required: ['from', 'to']
}
}
}
const tools: OpenAI.Chat.Completions.ChatCompletionTool[] = [
get_visits_count_Schema,
...AI_EventsTools
]
const functions: any = {
get_current_date: async ({ }) => {
return new Date().toISOString();
},
get_visits_count: async ({ pid, from, to }: any) => {
return await getVisitsCountFromDateRange(pid, from, to);
},
...AI_EventsFunctions
}
async function getMessagesFromChatId(chat_id?: string) {
if (!chat_id) return;
const chatItem = await AiChatModel.findById(chat_id);
if (!chatItem) return;
return chatItem.messages;
}
async function addMessageToChat(message: any, chat_id?: string) {
if (!chat_id) return;
await AiChatModel.updateOne({ _id: chat_id }, { $push: { messages: message } });
}
async function createChatIfNotExist(pid: string, chat_id?: string) {
const chatItem = await AiChatModel.exists({ _id: chat_id });
if (chatItem) return chatItem._id.toString();
const newChatItem = await AiChatModel.create({ messages: [], project_id: pid, title: 'new chat' });
return newChatItem._id.toString();
}
async function setChatTitle(title: string, chat_id?: string) {
if (!chat_id) return;
await AiChatModel.updateOne({ _id: chat_id }, { title });
}
export async function sendMessageOnChat(text: string, pid: string, initial_chat_id?: string) {
const messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[] = []
const chat_id = await createChatIfNotExist(pid, initial_chat_id);
const chatMessages = await getMessagesFromChatId(chat_id);
if (chatMessages && chatMessages.length > 0) {
messages.push(...chatMessages);
} else {
const roleMessage: OpenAI.Chat.Completions.ChatCompletionMessageParam = {
role: 'system', content: "Today is " + new Date().toISOString()
}
messages.push(roleMessage);
await addMessageToChat(roleMessage, chat_id);
await setChatTitle(text.substring(0, 110), chat_id);
}
const userMessage: OpenAI.Chat.Completions.ChatCompletionMessageParam = {
role: 'user', content: text
}
messages.push(userMessage);
await addMessageToChat(userMessage, chat_id);
let response = await openai.chat.completions.create({ model: 'gpt-3.5-turbo', messages, n: 1, tools });
let responseMessage = response.choices[0].message;
let toolCalls = responseMessage.tool_calls;
await addMessageToChat(responseMessage, chat_id);
messages.push(responseMessage);
if (toolCalls) {
console.log({ toolCalls: toolCalls.length });
for (const toolCall of toolCalls) {
const functionName = toolCall.function.name;
const functionToCall = functions[functionName];
const functionArgs = JSON.parse(toolCall.function.arguments);
console.log('CALLING FUNCTION', functionName, 'WITH PARAMS', functionArgs);
const functionResponse = await functionToCall({ pid, ...functionArgs });
console.log('RESPONSE FUNCTION', functionName, 'WITH VALUE', functionResponse);
messages.push({ tool_call_id: toolCall.id, role: "tool", content: JSON.stringify(functionResponse) });
await addMessageToChat({ tool_call_id: toolCall.id, role: "tool", content: JSON.stringify(functionResponse) }, chat_id);
}
response = await openai.chat.completions.create({ model: 'gpt-3.5-turbo', messages, n: 1, tools });
responseMessage = response.choices[0].message;
toolCalls = responseMessage.tool_calls;
await addMessageToChat(responseMessage, chat_id);
}
const currentCountId = await getCurrentProjectCountId(pid);
if (!currentCountId) console.error('Project not exist');
await ProjectCountModel.updateOne({ _id: currentCountId }, { $inc: { ai_messages: 1 } })
return responseMessage.content;
}

View File

@@ -0,0 +1,63 @@
import { createClient } from 'redis';
const runtimeConfig = useRuntimeConfig();
export const DATA_EXPIRE_TIME = 30;
export const TIMELINE_EXPIRE_TIME = 60 * 5;
export const COUNTS_EXPIRE_TIME = 10;
export const COUNTS_OLD_SESSIONS_EXPIRE_TIME = 60 * 5;
export const COUNTS_SESSIONS_EXPIRE_TIME = 60 * 3;
export const EVENT_NAMES_EXPIRE_TIME = 60;
export class Redis {
private static client = createClient({
url: runtimeConfig.REDIS_URL,
username: runtimeConfig.REDIS_USERNAME,
password: runtimeConfig.REDIS_PASSWORD,
});
static async init() {
await this.client.connect();
}
static async setString(key: string, value: string, exp: number) {
await this.client.set(key, value, { EX: exp });
}
static async set<T extends any>(key: string, value: T, exp: number) {
const stringValue = JSON.stringify(value);
this.setString(key, stringValue, exp);
}
static async getString(key: string) {
return await this.client.get(key);
}
static async get<T extends any>(key: string): Promise<undefined | T> {
const data = await this.getString(key);
if (!data) return;
return JSON.parse(data);
}
static async del(key: string) {
await this.client.del(key);
}
static async useCache<T extends any>(options: { key: string, exp: number }, action: (noStore: () => void) => Promise<T>): Promise<T> {
const cached = await this.get<T>(options.key);
if (cached) return cached;
let storeResult = true;
const noStore = () => storeResult = false;
const result = await action(noStore);
if (!storeResult) return result;
await this.set(options.key, result, options.exp);
return result;
}
}

View File

@@ -0,0 +1,36 @@
class PerformanceThing {
public min: number = Infinity;
public max: number = -Infinity;
private things: number[] = [];
private slice: number = 0;
constructor(public id: string, private maxThings: number) { }
start() { this.slice = performance.now(); }
stop() {
const time = performance.now() - this.slice;
if (time > this.max) this.max = time;
if (time < this.min) this.min = time;
this.things.push(time);
if (this.things.length > this.maxThings) {
this.things.shift();
}
return time;
}
avg() {
return this.things.reduce((a, e) => a + e, 0) / this.things.length;
}
print() {
console.log(`${this.id} | Avg: ${this.avg().toFixed(0)} ms | Min: ${this.min.toFixed(0)} ms | Max: ${this.max.toFixed(0)} ms`)
}
get data() { return this.things; }
}
export class PerformanceService {
static create(id: string, maxThings: number = 100) {
const thing = new PerformanceThing(id, maxThings);
return thing;
}
}