Skip to content

Commit

Permalink
Merge branch 'pandasai' into ui
Browse files Browse the repository at this point in the history
  • Loading branch information
tylerwong1 committed Dec 1, 2024
2 parents c17a479 + 0ed95ac commit 944a823
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 40 deletions.
Binary file added .coverage
Binary file not shown.
52 changes: 24 additions & 28 deletions client/src/components/UserPages/HandleUser.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,45 @@
import { useState, useEffect } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { useState, useEffect } from "react";
import { useNavigate, useLocation } from "react-router-dom";

/**
* Custom Enums to track where the user is for the NavBar to adjust with its links
*/
export enum NavigationState {
INTRO = 'INTRO',
LOG_IN = 'LOG-IN',
MAIN_PAGES = 'MAIN-PAGES',
INTRO = "INTRO",
LOG_IN = "LOG-IN",
MAIN_PAGES = "MAIN-PAGES",
}

/**
/**
* Custom hook for checking if user is logged in.
* When invoked, if the user isn't logged in, it returns them to the log in page!
*/
*/
export const useCheckLoggedIn = (): void => {
const navigate = useNavigate();
const location = useLocation();

useEffect(() => {
const isLoggedIn = localStorage.getItem('isLoggedIn');
const isLoggedIn = localStorage.getItem("isLoggedIn");

if (!isLoggedIn || isLoggedIn !== 'true') {
navigate('/login');
if (!isLoggedIn || isLoggedIn !== "true") {
navigate("/login");
}
}, [navigate, location]);
};

/**
/**
* Custom hook for checking if user is logged in.
* When invoked, if the user is logged in, it returns them to the home page!
*/
*/
export const useCheckSaveLogin = (): void => {
const navigate = useNavigate();
const location = useLocation();

useEffect(() => {
const isLoggedIn = localStorage.getItem('isLoggedIn');
const isLoggedIn = localStorage.getItem("isLoggedIn");

if (isLoggedIn === 'true') {
navigate('/home');
if (isLoggedIn === "true") {
navigate("/home");
}
}, [navigate, location]);
};
Expand All @@ -49,18 +49,20 @@ export const useCheckSaveLogin = (): void => {
*/
export const useNavigationState = (): NavigationState => {
const location = useLocation();
const [currentState, setCurrentState] = useState<NavigationState>(NavigationState.LOG_IN);
const [currentState, setCurrentState] = useState<NavigationState>(
NavigationState.LOG_IN,
);

useEffect(() => {
switch (location.pathname) {
case '/login':
case '/signup':
case "/login":
case "/signup":
setCurrentState(NavigationState.LOG_IN);
break;
case '/home':
case '/upload':
case '/analysis':
case '/chat':
case "/home":
case "/upload":
case "/analysis":
case "/chat":
setCurrentState(NavigationState.MAIN_PAGES);
break;
default:
Expand All @@ -70,9 +72,3 @@ export const useNavigationState = (): NavigationState => {

return currentState;
};

export const getUserTrends = () => {
return (["You spent 5% less on leisure this month",
"Your spending is down 2.5% this month",
"Your spending this year went down by $318!"]);
};
46 changes: 35 additions & 11 deletions client/src/components/UserPages/LandingPage.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,49 @@
import {
useCheckLoggedIn,
getUserTrends,
} from "@/components/UserPages/HandleUser";
import { useCheckLoggedIn } from "@/components/UserPages/HandleUser";
import { SpendingChart } from "../ui/SpendingChart";
import { apiRequest } from "@/api";
import { useEffect, useState } from "react";

async function getUserTrends(): Promise<string[]> {
const response = await apiRequest("/chat/insights", "GET");
console.log(response);
const insights = response?.insights;
return typeof insights === "string" ? insights.split("\n") : [];
}

function LandingPage() {
useCheckLoggedIn();
const [trends, setTrends] = useState<string[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchTrends = async () => {
try {
const data = await getUserTrends();
setTrends(data);
} catch (error) {
console.error("Error fetching trends..", error);
setTrends(["Unable to retrieve trends. Try again later."]);
} finally {
setLoading(false);
}
};
fetchTrends();
}, []);
return (
<div className="content-holder">
<div className="card bg-muted w-3/5 p-5">
<h1 className="grow text-center">Spending Chart</h1>
{/* <div className="card bg-foreground text-accent text-center"> */}
<SpendingChart></SpendingChart>
{/* </div> */}
<div className="flex flex-col items-center justify-center">
<h1 className="text-center">Your Trends</h1>
<ul className="list-dot">
{getUserTrends().map((trend, index) => (
<li key={index}>{trend}</li>
))}
</ul>
{loading ? (
<p>Loading Trends...</p>
) : (
<ul className="list-dot">
{trends.map((trend, index) => (
<li key={index}>{trend}</li>
))}
</ul>
)}
</div>
</div>
</div>
Expand Down
Binary file added server/cache/cache_db_0.9.db
Binary file not shown.
14 changes: 14 additions & 0 deletions server/pandasai.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"save_logs": true,
"verbose": false,
"enforce_privacy": false,
"enable_cache": true,
"use_error_correction_framework": true,
"max_retries": 3,
"open_charts": true,
"save_charts": false,
"save_charts_path": "exports/charts",
"custom_whitelisted_dependencies": [],
"llm": "BambooLLM",
"llm_options": null
}
3 changes: 3 additions & 0 deletions server/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ python-dotenv>=1.0.1
openai >= 1.52.2
httpie>=3.2.3
Flask-Cors==5.0.0
pandas==2.2.3
pandasai==2.0.24
pyyaml==6.0.2
38 changes: 38 additions & 0 deletions server/routes/chat_routes.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import os
import json
from flask import Blueprint, jsonify, request
import requests
from openai import AzureOpenAI
from dotenv import load_dotenv
import pandas as pd
from pandasai import Agent
from utils.query import Query

from utils.decorators import login_required

Expand Down Expand Up @@ -55,3 +59,37 @@ def ask_chatbot():
completion_json = json.loads(completion.to_json())
content = completion_json["choices"][0]["message"]["content"]
return jsonify({"response": content})


@chat_routes.route("/insights", methods=["GET"])
@login_required
def get_insights():
"""
Fetch transaction data, update the global PandasAI agent, and process the hardcoded prompt.
"""
# Step 1: Fetch transaction data
transactions = Query().get_transactions(response_type="list")

if not transactions:
return jsonify({"error": "No transaction data available"}), 404
print(transactions)

transactions_df = pd.DataFrame(transactions)
transactions_df['amount'] = pd.to_numeric(transactions_df['amount'], errors='coerce')
transactions_df['transaction_date'] = pd.to_datetime(transactions_df['transaction_date'], errors='coerce')

if transactions_df.empty:
return jsonify({"error": "Transaction data is empty"}), 404

agent = Agent([transactions_df])

# Step 4: Hardcoded prompt for insights
prompt = "Give me some general trends about my spending data!"

# Step 5: Use the global agent to analyze the data
try:
insights = agent.chat(prompt)
print(insights)
return jsonify({"insights": insights}), 200
except Exception as e:
return jsonify({"error": str(e)}), 500
4 changes: 3 additions & 1 deletion server/utils/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ def get_current_user_id(self):
# Return user_id, success message, and 200 status if all checks pass
return user_id, jsonify({"message": "User found"}), 200

def get_transactions(self):
def get_transactions(self, response_type="json"):
user_id, response, status_code = self.get_current_user_id()

if status_code != 200:
return response, status_code

transactions = list(self.db["transactions"].find({"user_id": user_id}))
if response_type == "list":
return transactions
return jsonify(transactions)

def get_by_category(self):
Expand Down

0 comments on commit 944a823

Please sign in to comment.