Skip to content

Commit

Permalink
Editable settings
Browse files Browse the repository at this point in the history
  • Loading branch information
Matvey-Kuk committed Nov 10, 2024
1 parent 2383f94 commit ba21be4
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 83 deletions.
104 changes: 61 additions & 43 deletions keep-ui/app/ai/ai.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
"use client";
import { Card, List, ListItem, Title, Subtitle } from "@tremor/react";
import { useAIStats, usePollAILogs, useUpdateAISettings } from "utils/hooks/useAI";
import { useAIStats, usePollAILogs, UseAIActions } from "utils/hooks/useAI";
import { useSession } from "next-auth/react";
import { useEffect, useState, useRef, FormEvent } from "react";
import { AILogs } from "./model";

export default function Ai() {
const { data: aistats, isLoading } = useAIStats();
const { data: session } = useSession();
const [text, setText] = useState("");
const [basicAlgorithmLog, setBasicAlgorithmLog] = useState("");

const mutateAILogs = (logs: AILogs) => {
setBasicAlgorithmLog(logs.log);
};
usePollAILogs(mutateAILogs);
const { data: aistats, isLoading, refetch: refetchAIStats } = useAIStats();
const { updateAISettings } = UseAIActions();

return (
<main className="p-4 md:p-10 mx-auto max-w-full">
Expand All @@ -30,7 +23,8 @@ export default function Ai() {
<Card className="mt-10 p-4 md:p-10 mx-auto">
<div>
<div>
<div className="grid grid-cols-2 gap-4 mt-6">
<div className="grid grid-cols-1 gap-4 mt-6">
{isLoading ? <p>Loading algorithms and settings...</p> : null}
{aistats?.algorithm_configs?.map((algorithm_config, index) => (
<Card
key={index}
Expand All @@ -43,46 +37,70 @@ export default function Ai() {
{algorithm_config.algorithm.description}
{/* {algorithm_config.settings} */}
</p>
{algorithm_config.settings.map(
(setting: any) => (
<div key={setting} className="mt-2">
{setting.name}
<p className="text-sm text-gray-500">{setting.description}</p>
{setting.type === "bool" ? (
<input
type="checkbox"
id={`checkbox-${index}`}
name={`checkbox-${index}`}
checked={setting.value}
onChange={(e) => {
const newValue = e.target.checked;
setting.value = newValue;
console.log(setting);
updateAISettings({
[algorithm_config.algorithm.name]: algorithm_config.settings,
});
}}
className="mt-2"
/>
) : null}
{setting.type === "float" ? (
{algorithm_config.settings.map((setting: any) => (
<div key={setting} className="mt-2">
{setting.name}
<p className="text-sm text-gray-500">
{setting.description}
</p>
{setting.type === "bool" ? (
<input
type="checkbox"
id={`checkbox-${index}`}
name={`checkbox-${index}`}
checked={setting.value}
onChange={(e) => {
const newValue = e.target.checked;
setting.value = newValue;
updateAISettings(
algorithm_config.algorithm_id,
algorithm_config
);
refetchAIStats();
}}
className="mt-2"
/>
) : null}
{setting.type === "float" ? (
<div>
<p>Value: {setting.value}</p>
<input
type="range"
id={`slider-${index}`}
name={`slider-${index}`}
className=""
step={(setting.max - setting.min) / 100}
min={setting.min}
max={setting.max}
value={setting.value}
// value={setting.value}
onChange={(e) => {
const newValue = e.target.value;
const newValue = parseFloat(e.target.value);
setting.value = newValue;
updateAISettings(
algorithm_config.algorithm_id,
algorithm_config
);
refetchAIStats();
}}
className="mt-2 w-full"
/>
) : null}
</div>
)
)}
{/* <p>Value: {setting.value}</p>
<input
type="range"
id={`slider-${index}`}
name={`slider-${index}`}
// min={setting.min}
// max={setting.max}
value={setting.value}
// onChange={(e) => {
// const newValue = parseFloat(e.target.value);
// setting.value = newValue;
// updateAISettings(algorithm_config.algorithm_id, algorithm_config);
// refetchAIStats();
// }}
className="mt-2 w-full"
/> */}
</div>
) : null}
</div>
))}
<h4 className="text-md font-medium mt-4">Execution logs:</h4>
<pre className="text-sm bg-gray-100 p-2 rounded">
{algorithm_config.feedback_log
Expand Down
19 changes: 11 additions & 8 deletions keep-ui/app/ai/model.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
export interface AIConfig {
algorithm_id: string;
settings: any;
feedback_log: string;
algorithm: {
name: string;
description: string;
}
}

export interface AIStats {
alerts_count: number;
incidents_count: number;
first_alert_datetime?: Date;
algorithm_configs: {
settings: any;
feedback_log: string;
algorithm: {
name: string;
description: string;
}
}[];
algorithm_configs: AIConfig[];
}

export interface AILogs {
Expand Down
58 changes: 39 additions & 19 deletions keep-ui/utils/hooks/useAI.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AILogs, AIStats } from "app/ai/model";
import { AIConfig, AILogs, AIStats } from "app/ai/model";
import { useSession } from "next-auth/react";
import useSWR, { SWRConfiguration } from "swr";
import { useApiUrl } from "./useConfig";
Expand All @@ -15,30 +15,19 @@ export const useAIStats = (
const apiUrl = useApiUrl();
const { data: session } = useSession();

return useSWR<AIStats>(
const { data, error, mutate } = useSWR<AIStats>(
() => (session ? `${apiUrl}/ai/stats` : null),
(url) => fetcher(url, session?.accessToken),
options
);
};

export const useUpdateAISettings = () => {
const apiUrl = useApiUrl();
const { data: session } = useSession();

return async (settings: Record<string, any>) => {
const response = await fetch(`${apiUrl}/ai/settings`, {
method: "PUT",
headers: {
Authorization: `Bearer ${session?.accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(settings),
});

return response.ok;
return {
data,
isLoading: !data && !error,
error,
refetch: mutate,
};
}
};

export const usePollAILogs = (mutateAILogs: (logs: AILogs) => void) => {
const { bind, unbind } = useWebsocket();
Expand All @@ -56,3 +45,34 @@ export const usePollAILogs = (mutateAILogs: (logs: AILogs) => void) => {
};
}, [bind, unbind, handleIncoming]);
};

type UseAIActionsValue = {
updateAISettings: (algorithm_id: string, settings: AIConfig) => Promise<AIStats>;
};

export function UseAIActions(): UseAIActionsValue {

const apiUrl = useApiUrl();
const { data: session } = useSession();

const updateAISettings = async (algorithm_id:string, settings: AIConfig): Promise<AIStats> => {
const response = await fetch(`${apiUrl}/ai/${algorithm_id}/settings`, {
method: "PUT",
headers: {
Authorization: `Bearer ${session?.accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(settings),
});

if (!response.ok) {
throw new Error('Failed to update AI settings');
}

return response.json();
};

return {
updateAISettings: updateAISettings,
};
}
13 changes: 7 additions & 6 deletions keep/api/core/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@
from keep.api.models.ai_external import (
ExternalAIConfigAndMetadata,
ExternalAIConfigAndMetadataDto,
ExternalAITransformers,
)
from keep.api.models.alert import (
AlertStatus,
IncidentDto,
IncidentDtoIn,
IncidentSorting,
)
from keep.api.models.time_stamp import TimeStampFilter
from keep.api.models.db.action import Action
from keep.api.models.db.alert import * # pylint: disable=unused-wildcard-import
from keep.api.models.db.dashboard import * # pylint: disable=unused-wildcard-import
Expand Down Expand Up @@ -4385,10 +4385,11 @@ def get_or_create_external_ai_settings(tenant_id: str) -> List[ExternalAIConfigA

def update_extrnal_ai_settings(tenant_id: str, ai_settings: ExternalAIConfigAndMetadata) -> ExternalAIConfigAndMetadataDto:
with Session(engine) as session:
session.query(ExternalAIConfigAndMetadata).filter(
setting = session.query(ExternalAIConfigAndMetadata).filter(
ExternalAIConfigAndMetadata.tenant_id == tenant_id,
ExternalAIConfigAndMetadata.id == ai_settings.id
).update(ai_settings.dict())
ExternalAIConfigAndMetadata.id == ai_settings.id,
).first()
setting.settings = json.dumps(ai_settings.settings)
session.add(setting)
session.commit()
session.refresh(ai_settings)
return ai_settings
return setting
3 changes: 1 addition & 2 deletions keep/api/models/ai_external.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class ExternalAIConfigAndMetadataDto(BaseModel):
id: str
algorithm_id: str
tenant_id: str
settings: Json[Any]
settings: list[Any] | Json[Any]
feedback_logs: str | None
algorithm: ExternalAIDto

Expand All @@ -38,4 +38,3 @@ def from_orm(cls, _object: ExternalAIConfigAndMetadata) -> "ExternalAIConfigAndM
feedback_logs=_object.feedback_logs,
algorithm=ExternalAIDto.from_orm(_object.algorithm)
)

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""AI config
Revision ID: 3f056d747d9e
Revises: 991b30bcf0b9
Revises: ef0b5b0df41c
Create Date: 2024-10-26 17:03:02.383942
"""
Expand All @@ -12,7 +12,7 @@

# revision identifiers, used by Alembic.
revision = "3f056d747d9e"
down_revision = "991b30bcf0b9"
down_revision = "ef0b5b0df41c"
branch_labels = None
depends_on = None

Expand Down
11 changes: 8 additions & 3 deletions keep/api/routes/ai.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import logging
from typing import List
from typing import Any
from pydantic import BaseModel, Json

from fastapi import APIRouter, Depends
from fastapi import APIRouter, Body, Depends, Request

from keep.api.core.db import (
get_alerts_count,
Expand All @@ -9,6 +12,7 @@
get_or_create_external_ai_settings,
update_extrnal_ai_settings,
)
from keep.api.models.ai_external import ExternalAIConfigAndMetadataDto
from keep.api.utils.import_ee import ALGORITHM_VERBOSE_NAME
from keep.identitymanager.authenticatedentity import AuthenticatedEntity
from keep.identitymanager.identitymanagerfactory import IdentityManagerFactory
Expand All @@ -35,17 +39,18 @@ def get_stats(
"algorithm_configs": get_or_create_external_ai_settings(tenant_id),
}


@router.put(
"/{algorithm_id}/settings",
description="Update settings for an external AI",
include_in_schema=False,
)
def update_settings(
algorithm_id: str,
settings: dict,
body: ExternalAIConfigAndMetadataDto,
authenticated_entity: AuthenticatedEntity = Depends(
IdentityManagerFactory.get_auth_verifier(["write:alert"])
),
):
tenant_id = authenticated_entity.tenant_id
return update_extrnal_ai_settings(tenant_id, settings)
return update_extrnal_ai_settings(tenant_id, body)

0 comments on commit ba21be4

Please sign in to comment.