completed the script - readme

This commit is contained in:
Madhu 2025-04-13 22:10:33 +05:30
parent ac3bc19a52
commit 9975e7eea2
4 changed files with 520 additions and 129 deletions

View file

@ -1 +1 @@
GOOGLE_API_KEY=
GOOGLE_API_KEY=your_gemini_api_key_here

View file

@ -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.

View file

@ -2,7 +2,7 @@ import streamlit as st
import pandas as pd
import plotly.express as px
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 asyncio
from datetime import datetime
@ -10,6 +10,8 @@ from dotenv import load_dotenv
import json
import logging
from pydantic import BaseModel, Field
import csv
from io import StringIO
from google.adk.agents import LlmAgent, SequentialAgent, BaseAgent
from google.adk.agents.invocation_context import InvocationContext
@ -540,145 +542,456 @@ def display_debt_reduction(plan: Dict[str, Any]):
if "impact" in rec:
st.markdown(f"_Impact: {rec['impact']}_")
def main():
st.set_page_config(page_title="AI Personal Finance Coach", layout="wide")
def parse_csv_transactions(file_content) -> List[Dict[str, Any]]:
"""Parse CSV file content into a list of transactions"""
try:
# Read CSV content
df = pd.read_csv(StringIO(file_content.decode('utf-8')))
# 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")
# Sidebar with API key info
# 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:
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.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:
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
st.title("📊 AI Personal Finance Coach")
st.subheader("Get personalized financial advice from AI agents")
st.info("This tool analyzes your financial data and provides tailored recommendations for budgeting, savings, and debt management.")
st.markdown("---")
# Main content
st.title("📊 AI Financial Coach with Google ADK")
st.caption("Powered by Google's Agent Development Kit (ADK) and Gemini AI")
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")
st.caption("All data is processed locally and not stored anywhere.")
# Create tabs for different sections
input_tab, about_tab = st.tabs(["💼 Financial Information", " About"])
col1, col2 = st.columns(2)
with col1:
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:
st.subheader("Expense Data")
expense_option = st.radio(
"How do you want to enter expenses?",
("Upload CSV Transactions", "Enter Manually"),
key="expense_option"
)
with input_tab:
st.header("Enter Your Financial Information")
st.caption("All data is processed locally and not stored anywhere.")
transaction_file = None
manual_expenses = {}
use_manual_expenses = False
transactions_df = None
# 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"
)
st.divider()
# Expenses section
with st.container():
st.subheader("💳 Expenses")
expense_option = st.radio(
"How would you like to enter your expenses?",
("📤 Upload CSV Transactions", "✍️ Enter Manually"),
key="expense_option",
horizontal=True
)
transaction_file = None
manual_expenses = {}
use_manual_expenses = False
transactions_df = None
if expense_option == "Upload CSV Transactions":
st.write("Upload a CSV with columns: Date, Category, Amount")
transaction_file = st.file_uploader("Upload CSV of transactions", type=["csv"], key="transaction_file")
if transaction_file is not None:
if expense_option == "📤 Upload CSV Transactions":
col1, col2 = st.columns([2, 1])
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:
# Validate CSV format
is_valid, message = validate_csv_format(transaction_file)
if is_valid:
try:
# Parse CSV content
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:
st.error(f"❌ Error processing CSV file: {str(e)}")
transactions_df = None
else:
st.error(message)
transactions_df = None
else:
use_manual_expenses = True
st.markdown("#### Enter your monthly expenses by category")
# Define expense categories with emojis
categories = [
("🏠 Housing", "Housing"),
("🔌 Utilities", "Utilities"),
("🍽️ 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()):
st.markdown("#### 📊 Summary of Entered Expenses")
manual_df_disp = pd.DataFrame({
'Category': list(manual_expenses.keys()),
'Amount': list(manual_expenses.values())
})
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.divider()
# 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 = []
if num_debts > 0:
# Create columns for debts
cols = st.columns(min(num_debts, 3)) # Max 3 columns per row
for i in range(num_debts):
col_idx = i % 3
with cols[col_idx]:
st.markdown(f"##### Debt #{i+1}")
debt_name = st.text_input(
"Name",
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({
"name": debt_name,
"amount": debt_amount,
"interest_rate": interest_rate,
"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.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 expense_option == "Upload CSV Transactions" and transactions_df is None:
st.error("Please upload a valid transaction CSV file or choose manual entry.")
return
if use_manual_expenses and not any(manual_expenses.values()):
st.warning("No manual expenses entered. Analysis might be limited.")
st.header("Financial Analysis Results")
with st.spinner("🤖 AI agents are analyzing your financial data..."):
financial_data = {
"monthly_income": monthly_income,
"dependants": dependants,
"transactions": transactions_df.to_dict('records') if transactions_df is not None else None,
"manual_expenses": manual_expenses if use_manual_expenses else None,
"debts": debts
}
finance_system = FinanceAdvisorSystem()
try:
transactions_df = pd.read_csv(transaction_file)
st.success("Transaction file uploaded successfully!")
results = asyncio.run(finance_system.analyze_finances(financial_data))
tabs = st.tabs(["💰 Budget Analysis", "📈 Savings Strategy", "💳 Debt Reduction"])
with tabs[0]:
st.subheader("Budget Analysis")
if "budget_analysis" in results and results["budget_analysis"]:
display_budget_analysis(results["budget_analysis"])
else:
st.write("No budget analysis available.")
with tabs[1]:
st.subheader("Savings Strategy")
if "savings_strategy" in results and results["savings_strategy"]:
display_savings_strategy(results["savings_strategy"])
else:
st.write("No savings strategy available.")
with tabs[2]:
st.subheader("Debt Reduction Plan")
if "debt_reduction" in results and results["debt_reduction"]:
display_debt_reduction(results["debt_reduction"])
else:
st.write("No debt reduction plan available.")
except Exception as e:
st.error(f"Error reading CSV: {e}")
transactions_df = None
else:
use_manual_expenses = True
st.write("Enter monthly expenses by category:")
categories = ["Housing", "Utilities", "Food", "Transportation", "Healthcare",
"Entertainment", "Personal", "Savings", "Other"]
exp_col1, exp_col2 = st.columns(2)
for i, category in enumerate(categories):
col = exp_col1 if i < (len(categories) + 1) // 2 else exp_col2
manual_expenses[category] = col.number_input(f"{category} ($)", min_value=0.0, step=50.0, value=0.0, key=f"manual_{category}")
if any(manual_expenses.values()):
st.write("Entered Manual Expenses:")
manual_df_disp = pd.DataFrame({
'Category': list(manual_expenses.keys()),
'Amount': list(manual_expenses.values())
})
st.dataframe(manual_df_disp[manual_df_disp['Amount'] > 0])
st.subheader("Debt Information")
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")
st.error(f"An error occurred during analysis: {str(e)}")
debts = []
if num_debts > 0:
debt_cols = st.columns(num_debts)
for i in range(num_debts):
with debt_cols[i]:
st.markdown(f"**Debt #{i+1}**")
debt_name = st.text_input(f"Name", value=f"Debt {i+1}", key=f"debt_name_{i}")
debt_amount = st.number_input(f"Amount $", min_value=0.01, step=100.0, value=1000.0, key=f"debt_amount_{i}")
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}")
min_payment = st.number_input(f"Min. Payment $", min_value=0.0, step=10.0, value=50.0, key=f"debt_min_payment_{i}")
debts.append({
"name": debt_name,
"amount": debt_amount,
"interest_rate": interest_rate,
"min_payment": min_payment
})
st.markdown("---")
analyze_button = st.button("Analyze My Finances", key="analyze_button")
st.markdown("---")
if analyze_button:
if expense_option == "Upload CSV Transactions" and transactions_df is None:
st.error("Please upload a valid transaction CSV file or choose manual entry.")
return
if use_manual_expenses and not any(manual_expenses.values()):
st.warning("No manual expenses entered. Analysis might be limited.")
st.header("Step 2: Financial Analysis Results")
with st.spinner("AI agents are analyzing your financial data..."):
financial_data = {
"monthly_income": monthly_income,
"dependants": dependants,
"transactions": transactions_df.to_dict('records') if transactions_df is not None else None,
"manual_expenses": manual_expenses if use_manual_expenses else None,
"debts": debts
}
finance_system = FinanceAdvisorSystem()
try:
results = asyncio.run(finance_system.analyze_finances(financial_data))
tabs = st.tabs(["💰 Budget Analysis", "📈 Savings Strategy", "💳 Debt Reduction"])
with tabs[0]:
st.subheader("Budget Analysis")
if "budget_analysis" in results and results["budget_analysis"]:
display_budget_analysis(results["budget_analysis"])
else:
st.write("No budget analysis available.")
with tabs[1]:
st.subheader("Savings Strategy")
if "savings_strategy" in results and results["savings_strategy"]:
display_savings_strategy(results["savings_strategy"])
else:
st.write("No savings strategy available.")
with tabs[2]:
st.subheader("Debt Reduction Plan")
if "debt_reduction" in results and results["debt_reduction"]:
display_debt_reduction(results["debt_reduction"])
else:
st.write("No debt reduction plan available.")
except Exception as 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__":
main()

View file

@ -1,5 +1,5 @@
google-adk==0.4.0
streamlit==1.31.0
google-adk==0.1.0
streamlit
pandas==2.1.1
matplotlib==3.8.0
numpy==1.26.0