completed the script - readme
This commit is contained in:
parent
ac3bc19a52
commit
9975e7eea2
4 changed files with 520 additions and 129 deletions
|
|
@ -1 +1 @@
|
||||||
GOOGLE_API_KEY=
|
GOOGLE_API_KEY=your_gemini_api_key_here
|
||||||
|
|
@ -1 +1,79 @@
|
||||||
|
# AI Financial Coach Agent with Google ADK 💰
|
||||||
|
|
||||||
|
The **AI Financial Coach** is a personalized financial advisor powered by Google's ADK (Agent Development Kit) framework. This app provides comprehensive financial analysis and recommendations based on user inputs including income, expenses, debts, and financial goals.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Multi-Agent Financial Analysis System**
|
||||||
|
- Budget Analysis Agent: Analyzes spending patterns and recommends optimizations
|
||||||
|
- Savings Strategy Agent: Creates personalized savings plans and emergency fund strategies
|
||||||
|
- Debt Reduction Agent: Develops optimized debt payoff strategies using avalanche and snowball methods
|
||||||
|
|
||||||
|
- **Expense Analysis**:
|
||||||
|
- Supports both CSV upload and manual expense entry
|
||||||
|
- CSV transaction analysis with date, category, and amount tracking
|
||||||
|
- Visual breakdown of spending by category
|
||||||
|
- Automated expense categorization and pattern detection
|
||||||
|
|
||||||
|
- **Savings Recommendations**:
|
||||||
|
- Emergency fund sizing and building strategies
|
||||||
|
- Custom savings allocations across different goals
|
||||||
|
- Practical automation techniques for consistent saving
|
||||||
|
- Progress tracking and milestone recommendations
|
||||||
|
|
||||||
|
- **Debt Management**:
|
||||||
|
- Multiple debt handling with interest rate optimization
|
||||||
|
- Comparison between avalanche and snowball methods
|
||||||
|
- Visual debt payoff timeline and interest savings analysis
|
||||||
|
- Actionable debt reduction recommendations
|
||||||
|
|
||||||
|
- **Interactive Visualizations**:
|
||||||
|
- Pie charts for expense breakdown
|
||||||
|
- Bar charts for income vs. expenses
|
||||||
|
- Debt comparison graphs
|
||||||
|
- Progress tracking metrics
|
||||||
|
|
||||||
|
|
||||||
|
## How to Run
|
||||||
|
|
||||||
|
Follow the steps below to set up and run the application:
|
||||||
|
|
||||||
|
1. **Get API Key**:
|
||||||
|
- Get a free Gemini API Key from Google AI Studio: https://aistudio.google.com/apikey
|
||||||
|
- Create a `.env` file in the project root and add your API key:
|
||||||
|
```
|
||||||
|
GOOGLE_API_KEY=your_api_key_here
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Clone the Repository**:
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||||
|
cd awesome-llm-apps/ai_agent_tutorials/ai_financial_coach_agent
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Install Dependencies**:
|
||||||
|
```bash
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Run the Streamlit App**:
|
||||||
|
```bash
|
||||||
|
streamlit run ai_financial_coach_agent.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## CSV File Format
|
||||||
|
|
||||||
|
The application accepts CSV files with the following required columns:
|
||||||
|
- `Date`: Transaction date in YYYY-MM-DD format
|
||||||
|
- `Category`: Expense category
|
||||||
|
- `Amount`: Transaction amount (supports currency symbols and comma formatting)
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```csv
|
||||||
|
Date,Category,Amount
|
||||||
|
2024-01-01,Housing,1200.00
|
||||||
|
2024-01-02,Food,150.50
|
||||||
|
2024-01-03,Transportation,45.00
|
||||||
|
```
|
||||||
|
|
||||||
|
A template CSV file can be downloaded directly from the application's sidebar.
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import streamlit as st
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import plotly.express as px
|
import plotly.express as px
|
||||||
import plotly.graph_objects as go
|
import plotly.graph_objects as go
|
||||||
from typing import Dict, List, Optional, Tuple, Any, AsyncGenerator
|
from typing import Dict, List, Optional, Tuple, Any
|
||||||
import os
|
import os
|
||||||
import asyncio
|
import asyncio
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
@ -10,6 +10,8 @@ from dotenv import load_dotenv
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
|
import csv
|
||||||
|
from io import StringIO
|
||||||
|
|
||||||
from google.adk.agents import LlmAgent, SequentialAgent, BaseAgent
|
from google.adk.agents import LlmAgent, SequentialAgent, BaseAgent
|
||||||
from google.adk.agents.invocation_context import InvocationContext
|
from google.adk.agents.invocation_context import InvocationContext
|
||||||
|
|
@ -540,39 +542,189 @@ def display_debt_reduction(plan: Dict[str, Any]):
|
||||||
if "impact" in rec:
|
if "impact" in rec:
|
||||||
st.markdown(f"_Impact: {rec['impact']}_")
|
st.markdown(f"_Impact: {rec['impact']}_")
|
||||||
|
|
||||||
def main():
|
def parse_csv_transactions(file_content) -> List[Dict[str, Any]]:
|
||||||
st.set_page_config(page_title="AI Personal Finance Coach", layout="wide")
|
"""Parse CSV file content into a list of transactions"""
|
||||||
|
try:
|
||||||
|
# Read CSV content
|
||||||
|
df = pd.read_csv(StringIO(file_content.decode('utf-8')))
|
||||||
|
|
||||||
# Sidebar with API key info
|
# Validate required columns
|
||||||
|
required_columns = ['Date', 'Category', 'Amount']
|
||||||
|
missing_columns = [col for col in required_columns if col not in df.columns]
|
||||||
|
|
||||||
|
if missing_columns:
|
||||||
|
raise ValueError(f"Missing required columns: {', '.join(missing_columns)}")
|
||||||
|
|
||||||
|
# Convert date strings to datetime and then to string format YYYY-MM-DD
|
||||||
|
df['Date'] = pd.to_datetime(df['Date']).dt.strftime('%Y-%m-%d')
|
||||||
|
|
||||||
|
# Convert amount strings to float, handling currency symbols and commas
|
||||||
|
df['Amount'] = df['Amount'].replace('[\$,]', '', regex=True).astype(float)
|
||||||
|
|
||||||
|
# Group by category and calculate totals
|
||||||
|
category_totals = df.groupby('Category')['Amount'].sum().reset_index()
|
||||||
|
|
||||||
|
# Convert to list of dictionaries
|
||||||
|
transactions = df.to_dict('records')
|
||||||
|
|
||||||
|
return {
|
||||||
|
'transactions': transactions,
|
||||||
|
'category_totals': category_totals.to_dict('records')
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
raise ValueError(f"Error parsing CSV file: {str(e)}")
|
||||||
|
|
||||||
|
def validate_csv_format(file) -> bool:
|
||||||
|
"""Validate CSV file format and content"""
|
||||||
|
try:
|
||||||
|
content = file.read().decode('utf-8')
|
||||||
|
dialect = csv.Sniffer().sniff(content)
|
||||||
|
has_header = csv.Sniffer().has_header(content)
|
||||||
|
file.seek(0) # Reset file pointer
|
||||||
|
|
||||||
|
if not has_header:
|
||||||
|
return False, "CSV file must have headers"
|
||||||
|
|
||||||
|
df = pd.read_csv(StringIO(content))
|
||||||
|
required_columns = ['Date', 'Category', 'Amount']
|
||||||
|
missing_columns = [col for col in required_columns if col not in df.columns]
|
||||||
|
|
||||||
|
if missing_columns:
|
||||||
|
return False, f"Missing required columns: {', '.join(missing_columns)}"
|
||||||
|
|
||||||
|
# Validate date format
|
||||||
|
try:
|
||||||
|
pd.to_datetime(df['Date'])
|
||||||
|
except:
|
||||||
|
return False, "Invalid date format in Date column"
|
||||||
|
|
||||||
|
# Validate amount format (should be numeric after removing currency symbols)
|
||||||
|
try:
|
||||||
|
df['Amount'].replace('[\$,]', '', regex=True).astype(float)
|
||||||
|
except:
|
||||||
|
return False, "Invalid amount format in Amount column"
|
||||||
|
|
||||||
|
return True, "CSV format is valid"
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"Invalid CSV format: {str(e)}"
|
||||||
|
|
||||||
|
def display_csv_preview(df: pd.DataFrame):
|
||||||
|
"""Display a preview of the CSV data with basic statistics"""
|
||||||
|
st.subheader("CSV Data Preview")
|
||||||
|
|
||||||
|
# Show basic statistics
|
||||||
|
total_transactions = len(df)
|
||||||
|
total_amount = df['Amount'].sum()
|
||||||
|
|
||||||
|
# Convert dates for display
|
||||||
|
df_dates = pd.to_datetime(df['Date'])
|
||||||
|
date_range = f"{df_dates.min().strftime('%Y-%m-%d')} to {df_dates.max().strftime('%Y-%m-%d')}"
|
||||||
|
|
||||||
|
col1, col2, col3 = st.columns(3)
|
||||||
|
with col1:
|
||||||
|
st.metric("Total Transactions", total_transactions)
|
||||||
|
with col2:
|
||||||
|
st.metric("Total Amount", f"${total_amount:,.2f}")
|
||||||
|
with col3:
|
||||||
|
st.metric("Date Range", date_range)
|
||||||
|
|
||||||
|
# Show category breakdown
|
||||||
|
st.subheader("Spending by Category")
|
||||||
|
category_totals = df.groupby('Category')['Amount'].agg(['sum', 'count']).reset_index()
|
||||||
|
category_totals.columns = ['Category', 'Total Amount', 'Transaction Count']
|
||||||
|
st.dataframe(category_totals)
|
||||||
|
|
||||||
|
# Show sample transactions
|
||||||
|
st.subheader("Sample Transactions")
|
||||||
|
st.dataframe(df.head())
|
||||||
|
|
||||||
|
def main():
|
||||||
|
st.set_page_config(
|
||||||
|
page_title="AI Financial Coach with Google ADK",
|
||||||
|
layout="wide",
|
||||||
|
initial_sidebar_state="expanded"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Sidebar with API key info and CSV template
|
||||||
with st.sidebar:
|
with st.sidebar:
|
||||||
|
st.title("🔑 Setup & Templates")
|
||||||
st.info("📝 Please ensure you have your Gemini API key in the .env file:\n```\nGOOGLE_API_KEY=your_api_key_here\n```")
|
st.info("📝 Please ensure you have your Gemini API key in the .env file:\n```\nGOOGLE_API_KEY=your_api_key_here\n```")
|
||||||
st.caption("This application uses Google's Gemini AI to provide personalized financial advice.")
|
st.caption("This application uses Google's ADK (Agent Development Kit) and Gemini AI to provide personalized financial advice.")
|
||||||
|
|
||||||
|
st.divider()
|
||||||
|
|
||||||
|
# Add CSV template download
|
||||||
|
st.subheader("📊 CSV Template")
|
||||||
|
st.markdown("""
|
||||||
|
Download the template CSV file with the required format:
|
||||||
|
- Date (YYYY-MM-DD)
|
||||||
|
- Category
|
||||||
|
- Amount (numeric)
|
||||||
|
""")
|
||||||
|
|
||||||
|
# Create sample CSV content
|
||||||
|
sample_csv = """Date,Category,Amount
|
||||||
|
2024-01-01,Housing,1200.00
|
||||||
|
2024-01-02,Food,150.50
|
||||||
|
2024-01-03,Transportation,45.00"""
|
||||||
|
|
||||||
|
st.download_button(
|
||||||
|
label="📥 Download CSV Template",
|
||||||
|
data=sample_csv,
|
||||||
|
file_name="expense_template.csv",
|
||||||
|
mime="text/csv"
|
||||||
|
)
|
||||||
|
|
||||||
if not GEMINI_API_KEY:
|
if not GEMINI_API_KEY:
|
||||||
st.error("GOOGLE_API_KEY not found in environment variables. Please add it to your .env file.")
|
st.error("🔑 GOOGLE_API_KEY not found in environment variables. Please add it to your .env file.")
|
||||||
return
|
return
|
||||||
|
|
||||||
st.title("📊 AI Personal Finance Coach")
|
# Main content
|
||||||
st.subheader("Get personalized financial advice from AI agents")
|
st.title("📊 AI Financial Coach with Google ADK")
|
||||||
st.info("This tool analyzes your financial data and provides tailored recommendations for budgeting, savings, and debt management.")
|
st.caption("Powered by Google's Agent Development Kit (ADK) and Gemini AI")
|
||||||
st.markdown("---")
|
st.info("This tool analyzes your financial data and provides tailored recommendations for budgeting, savings, and debt management using multiple specialized AI agents.")
|
||||||
|
st.divider()
|
||||||
|
|
||||||
st.header("Step 1: Enter Your Financial Information")
|
# Create tabs for different sections
|
||||||
|
input_tab, about_tab = st.tabs(["💼 Financial Information", "ℹ️ About"])
|
||||||
|
|
||||||
|
with input_tab:
|
||||||
|
st.header("Enter Your Financial Information")
|
||||||
st.caption("All data is processed locally and not stored anywhere.")
|
st.caption("All data is processed locally and not stored anywhere.")
|
||||||
|
|
||||||
col1, col2 = st.columns(2)
|
# Income and Dependants section in a container
|
||||||
|
with st.container():
|
||||||
|
st.subheader("💰 Income & Household")
|
||||||
|
income_col, dependants_col = st.columns([2, 1])
|
||||||
|
with income_col:
|
||||||
|
monthly_income = st.number_input(
|
||||||
|
"Monthly Income ($)",
|
||||||
|
min_value=0.0,
|
||||||
|
step=100.0,
|
||||||
|
value=3000.0,
|
||||||
|
key="income",
|
||||||
|
help="Enter your total monthly income after taxes"
|
||||||
|
)
|
||||||
|
with dependants_col:
|
||||||
|
dependants = st.number_input(
|
||||||
|
"Number of Dependants",
|
||||||
|
min_value=0,
|
||||||
|
step=1,
|
||||||
|
value=0,
|
||||||
|
key="dependants",
|
||||||
|
help="Include all dependants in your household"
|
||||||
|
)
|
||||||
|
|
||||||
with col1:
|
st.divider()
|
||||||
st.subheader("Income & Dependants")
|
|
||||||
monthly_income = st.number_input("Monthly Income ($)", min_value=0.0, step=100.0, value=3000.0, key="income")
|
|
||||||
dependants = st.number_input("Number of Dependants", min_value=0, step=1, value=0, key="dependants")
|
|
||||||
|
|
||||||
with col2:
|
# Expenses section
|
||||||
st.subheader("Expense Data")
|
with st.container():
|
||||||
|
st.subheader("💳 Expenses")
|
||||||
expense_option = st.radio(
|
expense_option = st.radio(
|
||||||
"How do you want to enter expenses?",
|
"How would you like to enter your expenses?",
|
||||||
("Upload CSV Transactions", "Enter Manually"),
|
("📤 Upload CSV Transactions", "✍️ Enter Manually"),
|
||||||
key="expense_option"
|
key="expense_option",
|
||||||
|
horizontal=True
|
||||||
)
|
)
|
||||||
|
|
||||||
transaction_file = None
|
transaction_file = None
|
||||||
|
|
@ -580,47 +732,163 @@ def main():
|
||||||
use_manual_expenses = False
|
use_manual_expenses = False
|
||||||
transactions_df = None
|
transactions_df = None
|
||||||
|
|
||||||
if expense_option == "Upload CSV Transactions":
|
if expense_option == "📤 Upload CSV Transactions":
|
||||||
st.write("Upload a CSV with columns: Date, Category, Amount")
|
col1, col2 = st.columns([2, 1])
|
||||||
transaction_file = st.file_uploader("Upload CSV of transactions", type=["csv"], key="transaction_file")
|
with col1:
|
||||||
|
st.markdown("""
|
||||||
|
#### Upload your transaction data
|
||||||
|
Your CSV file should have these columns:
|
||||||
|
- 📅 Date (YYYY-MM-DD)
|
||||||
|
- 📝 Category
|
||||||
|
- 💲 Amount
|
||||||
|
""")
|
||||||
|
|
||||||
|
transaction_file = st.file_uploader(
|
||||||
|
"Choose your CSV file",
|
||||||
|
type=["csv"],
|
||||||
|
key="transaction_file",
|
||||||
|
help="Upload a CSV file containing your transactions"
|
||||||
|
)
|
||||||
|
|
||||||
if transaction_file is not None:
|
if transaction_file is not None:
|
||||||
|
# Validate CSV format
|
||||||
|
is_valid, message = validate_csv_format(transaction_file)
|
||||||
|
|
||||||
|
if is_valid:
|
||||||
try:
|
try:
|
||||||
transactions_df = pd.read_csv(transaction_file)
|
# Parse CSV content
|
||||||
st.success("Transaction file uploaded successfully!")
|
transaction_file.seek(0)
|
||||||
|
file_content = transaction_file.read()
|
||||||
|
parsed_data = parse_csv_transactions(file_content)
|
||||||
|
|
||||||
|
# Create DataFrame
|
||||||
|
transactions_df = pd.DataFrame(parsed_data['transactions'])
|
||||||
|
|
||||||
|
# Display preview
|
||||||
|
display_csv_preview(transactions_df)
|
||||||
|
|
||||||
|
st.success("✅ Transaction file uploaded and validated successfully!")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
st.error(f"Error reading CSV: {e}")
|
st.error(f"❌ Error processing CSV file: {str(e)}")
|
||||||
|
transactions_df = None
|
||||||
|
else:
|
||||||
|
st.error(message)
|
||||||
transactions_df = None
|
transactions_df = None
|
||||||
else:
|
else:
|
||||||
use_manual_expenses = True
|
use_manual_expenses = True
|
||||||
st.write("Enter monthly expenses by category:")
|
st.markdown("#### Enter your monthly expenses by category")
|
||||||
categories = ["Housing", "Utilities", "Food", "Transportation", "Healthcare",
|
|
||||||
"Entertainment", "Personal", "Savings", "Other"]
|
# Define expense categories with emojis
|
||||||
exp_col1, exp_col2 = st.columns(2)
|
categories = [
|
||||||
for i, category in enumerate(categories):
|
("🏠 Housing", "Housing"),
|
||||||
col = exp_col1 if i < (len(categories) + 1) // 2 else exp_col2
|
("🔌 Utilities", "Utilities"),
|
||||||
manual_expenses[category] = col.number_input(f"{category} ($)", min_value=0.0, step=50.0, value=0.0, key=f"manual_{category}")
|
("🍽️ Food", "Food"),
|
||||||
|
("🚗 Transportation", "Transportation"),
|
||||||
|
("🏥 Healthcare", "Healthcare"),
|
||||||
|
("🎭 Entertainment", "Entertainment"),
|
||||||
|
("👤 Personal", "Personal"),
|
||||||
|
("💰 Savings", "Savings"),
|
||||||
|
("📦 Other", "Other")
|
||||||
|
]
|
||||||
|
|
||||||
|
# Create three columns for better layout
|
||||||
|
col1, col2, col3 = st.columns(3)
|
||||||
|
cols = [col1, col2, col3]
|
||||||
|
|
||||||
|
# Distribute categories across columns
|
||||||
|
for i, (emoji_cat, cat) in enumerate(categories):
|
||||||
|
with cols[i % 3]:
|
||||||
|
manual_expenses[cat] = st.number_input(
|
||||||
|
emoji_cat,
|
||||||
|
min_value=0.0,
|
||||||
|
step=50.0,
|
||||||
|
value=0.0,
|
||||||
|
key=f"manual_{cat}",
|
||||||
|
help=f"Enter your monthly {cat.lower()} expenses"
|
||||||
|
)
|
||||||
|
|
||||||
if any(manual_expenses.values()):
|
if any(manual_expenses.values()):
|
||||||
st.write("Entered Manual Expenses:")
|
st.markdown("#### 📊 Summary of Entered Expenses")
|
||||||
manual_df_disp = pd.DataFrame({
|
manual_df_disp = pd.DataFrame({
|
||||||
'Category': list(manual_expenses.keys()),
|
'Category': list(manual_expenses.keys()),
|
||||||
'Amount': list(manual_expenses.values())
|
'Amount': list(manual_expenses.values())
|
||||||
})
|
})
|
||||||
st.dataframe(manual_df_disp[manual_df_disp['Amount'] > 0])
|
manual_df_disp = manual_df_disp[manual_df_disp['Amount'] > 0]
|
||||||
|
if not manual_df_disp.empty:
|
||||||
|
col1, col2 = st.columns([2, 1])
|
||||||
|
with col1:
|
||||||
|
st.dataframe(
|
||||||
|
manual_df_disp,
|
||||||
|
column_config={
|
||||||
|
"Category": "Category",
|
||||||
|
"Amount": st.column_config.NumberColumn(
|
||||||
|
"Amount",
|
||||||
|
format="$%.2f"
|
||||||
|
)
|
||||||
|
},
|
||||||
|
hide_index=True
|
||||||
|
)
|
||||||
|
with col2:
|
||||||
|
st.metric(
|
||||||
|
"Total Monthly Expenses",
|
||||||
|
f"${manual_df_disp['Amount'].sum():,.2f}"
|
||||||
|
)
|
||||||
|
|
||||||
st.subheader("Debt Information")
|
st.divider()
|
||||||
st.info("Enter your debts to get personalized payoff strategies.")
|
|
||||||
num_debts = st.number_input("Number of Debts", min_value=0, max_value=10, step=1, value=0, key="num_debts")
|
# Debt Information section
|
||||||
|
with st.container():
|
||||||
|
st.subheader("🏦 Debt Information")
|
||||||
|
st.info("Enter your debts to get personalized payoff strategies using both avalanche and snowball methods.")
|
||||||
|
|
||||||
|
num_debts = st.number_input(
|
||||||
|
"How many debts do you have?",
|
||||||
|
min_value=0,
|
||||||
|
max_value=10,
|
||||||
|
step=1,
|
||||||
|
value=0,
|
||||||
|
key="num_debts"
|
||||||
|
)
|
||||||
|
|
||||||
debts = []
|
debts = []
|
||||||
if num_debts > 0:
|
if num_debts > 0:
|
||||||
debt_cols = st.columns(num_debts)
|
# Create columns for debts
|
||||||
|
cols = st.columns(min(num_debts, 3)) # Max 3 columns per row
|
||||||
for i in range(num_debts):
|
for i in range(num_debts):
|
||||||
with debt_cols[i]:
|
col_idx = i % 3
|
||||||
st.markdown(f"**Debt #{i+1}**")
|
with cols[col_idx]:
|
||||||
debt_name = st.text_input(f"Name", value=f"Debt {i+1}", key=f"debt_name_{i}")
|
st.markdown(f"##### Debt #{i+1}")
|
||||||
debt_amount = st.number_input(f"Amount $", min_value=0.01, step=100.0, value=1000.0, key=f"debt_amount_{i}")
|
debt_name = st.text_input(
|
||||||
interest_rate = st.number_input(f"Interest Rate (%)", min_value=0.0, max_value=100.0, step=0.1, value=5.0, key=f"debt_rate_{i}")
|
"Name",
|
||||||
min_payment = st.number_input(f"Min. Payment $", min_value=0.0, step=10.0, value=50.0, key=f"debt_min_payment_{i}")
|
value=f"Debt {i+1}",
|
||||||
|
key=f"debt_name_{i}",
|
||||||
|
help="Enter a name for this debt (e.g., Credit Card, Student Loan)"
|
||||||
|
)
|
||||||
|
debt_amount = st.number_input(
|
||||||
|
"Amount ($)",
|
||||||
|
min_value=0.01,
|
||||||
|
step=100.0,
|
||||||
|
value=1000.0,
|
||||||
|
key=f"debt_amount_{i}",
|
||||||
|
help="Enter the current balance of this debt"
|
||||||
|
)
|
||||||
|
interest_rate = st.number_input(
|
||||||
|
"Interest Rate (%)",
|
||||||
|
min_value=0.0,
|
||||||
|
max_value=100.0,
|
||||||
|
step=0.1,
|
||||||
|
value=5.0,
|
||||||
|
key=f"debt_rate_{i}",
|
||||||
|
help="Enter the annual interest rate"
|
||||||
|
)
|
||||||
|
min_payment = st.number_input(
|
||||||
|
"Minimum Payment ($)",
|
||||||
|
min_value=0.0,
|
||||||
|
step=10.0,
|
||||||
|
value=50.0,
|
||||||
|
key=f"debt_min_payment_{i}",
|
||||||
|
help="Enter the minimum monthly payment required"
|
||||||
|
)
|
||||||
|
|
||||||
debts.append({
|
debts.append({
|
||||||
"name": debt_name,
|
"name": debt_name,
|
||||||
|
|
@ -629,9 +897,20 @@ def main():
|
||||||
"min_payment": min_payment
|
"min_payment": min_payment
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if col_idx == 2 or i == num_debts - 1: # Add spacing after every 3 debts or last debt
|
||||||
st.markdown("---")
|
st.markdown("---")
|
||||||
analyze_button = st.button("Analyze My Finances", key="analyze_button")
|
|
||||||
st.markdown("---")
|
st.divider()
|
||||||
|
|
||||||
|
# Analysis button
|
||||||
|
col1, col2, col3 = st.columns([1, 2, 1])
|
||||||
|
with col2:
|
||||||
|
analyze_button = st.button(
|
||||||
|
"🔄 Analyze My Finances",
|
||||||
|
key="analyze_button",
|
||||||
|
use_container_width=True,
|
||||||
|
help="Click to get your personalized financial analysis"
|
||||||
|
)
|
||||||
|
|
||||||
if analyze_button:
|
if analyze_button:
|
||||||
if expense_option == "Upload CSV Transactions" and transactions_df is None:
|
if expense_option == "Upload CSV Transactions" and transactions_df is None:
|
||||||
|
|
@ -640,8 +919,8 @@ def main():
|
||||||
if use_manual_expenses and not any(manual_expenses.values()):
|
if use_manual_expenses and not any(manual_expenses.values()):
|
||||||
st.warning("No manual expenses entered. Analysis might be limited.")
|
st.warning("No manual expenses entered. Analysis might be limited.")
|
||||||
|
|
||||||
st.header("Step 2: Financial Analysis Results")
|
st.header("Financial Analysis Results")
|
||||||
with st.spinner("AI agents are analyzing your financial data..."):
|
with st.spinner("🤖 AI agents are analyzing your financial data..."):
|
||||||
financial_data = {
|
financial_data = {
|
||||||
"monthly_income": monthly_income,
|
"monthly_income": monthly_income,
|
||||||
"dependants": dependants,
|
"dependants": dependants,
|
||||||
|
|
@ -680,5 +959,39 @@ def main():
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
st.error(f"An error occurred during analysis: {str(e)}")
|
st.error(f"An error occurred during analysis: {str(e)}")
|
||||||
|
|
||||||
|
with about_tab:
|
||||||
|
st.markdown("""
|
||||||
|
### About AI Financial Coach
|
||||||
|
|
||||||
|
This application uses Google's Agent Development Kit (ADK) to provide comprehensive financial analysis and advice through multiple specialized AI agents:
|
||||||
|
|
||||||
|
1. **🔍 Budget Analysis Agent**
|
||||||
|
- Analyzes spending patterns
|
||||||
|
- Identifies areas for cost reduction
|
||||||
|
- Provides actionable recommendations
|
||||||
|
|
||||||
|
2. **💰 Savings Strategy Agent**
|
||||||
|
- Creates personalized savings plans
|
||||||
|
- Calculates emergency fund requirements
|
||||||
|
- Suggests automation techniques
|
||||||
|
|
||||||
|
3. **💳 Debt Reduction Agent**
|
||||||
|
- Develops optimal debt payoff strategies
|
||||||
|
- Compares different repayment methods
|
||||||
|
- Provides actionable debt reduction tips
|
||||||
|
|
||||||
|
### Privacy & Security
|
||||||
|
|
||||||
|
- All data is processed locally
|
||||||
|
- No financial information is stored or transmitted
|
||||||
|
- Secure API communication with Google's services
|
||||||
|
|
||||||
|
### Need Help?
|
||||||
|
|
||||||
|
For support or questions:
|
||||||
|
- Check the [documentation](https://github.com/Shubhamsaboo/awesome-llm-apps)
|
||||||
|
- Report issues on [GitHub](https://github.com/Shubhamsaboo/awesome-llm-apps/issues)
|
||||||
|
""")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
google-adk==0.4.0
|
google-adk==0.1.0
|
||||||
streamlit==1.31.0
|
streamlit
|
||||||
pandas==2.1.1
|
pandas==2.1.1
|
||||||
matplotlib==3.8.0
|
matplotlib==3.8.0
|
||||||
numpy==1.26.0
|
numpy==1.26.0
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue