Skip to content

Feature/gen ai insights #21

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 14 additions & 0 deletions client/src/features/core/api/get-dashboard-genai-insights.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { apiSlice } from "../../api/apiSlice";
import { IResponse } from "../types";

interface Response extends IResponse {
data: string;
}

export const { useGetInsightsQuery } = apiSlice.injectEndpoints({
endpoints: (builder) => ({
getInsights: builder.query<Response, void>({
query: () => "/analytics/ai-insights",
}),
}),
});
30 changes: 30 additions & 0 deletions client/src/features/core/components/GenAIInsight/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { ReactNode } from "react";
import { Callout, Flex, Text, Box } from "@radix-ui/themes";
import { Link } from "react-router-dom";

type Props = {
insight: string | ReactNode;
};

export default function GenAIInsight({ insight }: Props) {
return (
<Box mb={"5"}>
<Callout.Root>
<Flex direction={"column"}>
<Flex gap={"2"} mb={"2"}>
<Callout.Icon>✨</Callout.Icon>
<Text weight="medium">
<Link
to={"/ai-insights"}
style={{ textDecoration: "underline", color: "inherit" }}
>
AI Insights
</Link>
</Text>
</Flex>
<Text as="p">{insight}</Text>
</Flex>
</Callout.Root>
</Box>
);
}
31 changes: 19 additions & 12 deletions client/src/features/core/routes/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,28 @@ import SummaryWidget from "../components/SummaryWidget";
import LastWeekSpendChart from "../components/LastWeekSpendChart";
import CategorySpendChart from "../components/CategorySpendChart";
import WidgetWrapper from "../components/WidgetWrapper";
import GenAIInsight from "../components/GenAIInsight";
import { useGetInsightsQuery } from "../api/get-dashboard-genai-insights";

import { Grid } from "@radix-ui/themes";
import { Grid, Spinner } from "@radix-ui/themes";

export default function HomePage() {
const { data, isLoading } = useGetInsightsQuery();

return (
<Grid columns={"2"} rows={"2"} gap={"5"}>
<WidgetWrapper>
<SummaryWidget />
</WidgetWrapper>
<WidgetWrapper>
<LastWeekSpendChart />
</WidgetWrapper>
<WidgetWrapper>
<CategorySpendChart />
</WidgetWrapper>
</Grid>
<>
<GenAIInsight insight={isLoading ? <Spinner /> : data?.data || ""} />
<Grid columns={{ xs: "1", md: "2" }} rows={"1fr 1fr"} gap={"5"}>
<WidgetWrapper>
<SummaryWidget />
</WidgetWrapper>
<WidgetWrapper>
<LastWeekSpendChart />
</WidgetWrapper>
<WidgetWrapper>
<CategorySpendChart />
</WidgetWrapper>
</Grid>
</>
);
}
2 changes: 1 addition & 1 deletion client/src/features/core/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export interface IResponse {
status: string;
message: string;
data: object | [];
data: unknown;
}
2 changes: 1 addition & 1 deletion client/src/styles/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
min-height: 100%;
height: 100vh;
overflow: visible;
width: 960px;
max-width: 960px;
margin: 0 auto 0;
padding: 0;
border-left: 0.1px solid var(--green-4);
Expand Down
22 changes: 22 additions & 0 deletions server/src/controllers/analytics/gen-ai.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Request, Response } from "express-serve-static-core";
import { getAiInsights } from "../../services/management/analytics/gen-ai.service.js";
import { createSuccessResponse } from "../../features/common/utils/response.js";
import { getCategoryWiseSpend } from "../../services/management/analytics/dashboard-analytics.service.js";

const BASE_PROMPT = `
Analyze my spending by category and generate
insights based on the same. Keep the insights simple
and limit the response to single paragraph.

Here is the data:
{}

Insights:

`
export async function dashboardGenAIInsightsController(req: Request, res: Response) {
const categorySpend = await getCategoryWiseSpend()
const prompt = BASE_PROMPT.replace("{}", JSON.stringify(categorySpend))
const insight = await getAiInsights(prompt)
return createSuccessResponse(req, res, 200, "", insight)
}
3 changes: 3 additions & 0 deletions server/src/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { router as labelRouter } from "./features/label/routes.js";
import { router as recurringRouter } from './features/recurring/routes.js'
import { router as managementRouter } from "./routes/management/credit-card-manager.routes.js";
import { router as analyticsRouter } from "./routes/analytics/dashboard-analytics.routes.js";
import { router as genAiRouter } from "./routes/analytics/gen-ai.routes.js";

export const router: Router = express.Router()
router.use(express.json())
Expand All @@ -22,3 +23,5 @@ router.use("/labels", labelRouter)
router.use("/recurring", recurringRouter)
router.use("/management/credit-card-settings", managementRouter)
router.use("/analytics", analyticsRouter)
router.use("/analytics", analyticsRouter)
router.use("/analytics", genAiRouter)
9 changes: 9 additions & 0 deletions server/src/routes/analytics/gen-ai.routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {
dashboardGenAIInsightsController,
} from "../../controllers/analytics/gen-ai.controller.js";

import express from "express";

export const router = express.Router()

router.get("/ai-insights", dashboardGenAIInsightsController)
21 changes: 21 additions & 0 deletions server/src/services/management/analytics/gen-ai.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

export async function getAiInsights(prompt: string) {
const body = {
model: "gemma:2b",
prompt: prompt,
stream: false,
}
const response = await fetch("http://localhost:11434/api/generate/", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(body)
})
if (response.ok) {
const data = await response.json()
const insights = data["response"]
return insights
}
return null
}