Spaces:
Sleeping
Sleeping
File size: 3,666 Bytes
31f5db3 efb0194 31f5db3 efb0194 31f5db3 efb0194 4ccfa13 efb0194 4ccfa13 efb0194 4ccfa13 efb0194 4ccfa13 efb0194 3ad19dc efb0194 31f5db3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | import gradio as gr
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.tools.decorator import tool
from datetime import datetime, timedelta
from dotenv import load_dotenv
load_dotenv()
# β
Tool definition
@tool(name="treasury_data", description="Returns detailed account balances, FX exposure, and liabilities")
def get_treasury_data(input: str) -> str:
today = datetime.now().strftime("%Y-%m-%d")
due_date = (datetime.now() + timedelta(days=5)).strftime("%Y-%m-%d")
return f"""
As of {today}, here is the treasury snapshot:
β
Cash Balances:
- USD Operating Account: $2,800,000
- EUR Revenue Account: β¬1,500,000
- GBP Payroll Account: Β£600,000
π FX Market Rates:
- EUR/USD: 1.08
- GBP/USD: 1.27
π§Ύ Upcoming Liabilities:
- USD Vendor Payments: $2,200,000 due on {due_date}
- EUR Convertible Bond Maturity: β¬900,000 due on {due_date}
- GBP Payroll Run: Β£500,000 due on {due_date}
π Policy Thresholds:
- Minimum USD liquidity buffer: $500,000
- FX hedge threshold for EUR: 70% exposure
"""
# β
Agent definition
agent = Agent(
model=OpenAIChat(id="gpt-4o"),
tools=[get_treasury_data],
instructions=[
"You are a Treasury Analyst AI.",
"Analyze liquidity and FX exposure.",
"Recommend actions such as FX hedging, internal fund transfers, or delay of liabilities.",
"Always ensure minimum liquidity buffers are met.",
"Convert foreign currency exposures to USD for a consolidated view.",
"Provide your analysis in bullet points with numbers.",
],
markdown=True,
)
def ask_agent(messages, history):
print("====== DEBUG: ask_agent START ======")
print("π₯ Incoming messages:", messages)
print("π Chat history:", history)
# β
Handle Hugging Face's tendency to send just a string
if isinstance(messages, str):
messages = [{"role": "user", "content": messages}]
elif isinstance(messages, list):
# Defensive fix: if list of strings, wrap each
if all(isinstance(m, str) for m in messages):
messages = [{"role": "user", "content": m} for m in messages]
# If it's a list but not valid messages, throw a descriptive error
elif not all(isinstance(m, dict) and "role" in m and "content" in m for m in messages):
print("β Malformed message list")
return {"role": "assistant", "content": "Sorry, I couldn't understand the message format."}
else:
print("β Completely invalid input type")
return {"role": "assistant", "content": "Sorry, I didn't understand that input."}
try:
latest_user_message = messages[-1]["content"]
print(f"π¬ Latest user message: {latest_user_message}")
except Exception as e:
print(f"β Error extracting latest message: {e}")
return {"role": "assistant", "content": "Sorry, I couldn't read your message."}
try:
response = agent.run(latest_user_message)
print(f"β
Agent response:\n{response}")
return {"role": "assistant", "content": response.content}
except Exception as e:
print(f"β Agent failed: {e}")
return {"role": "assistant", "content": "Something went wrong on my end. Try again?"}
def yes(message, history):
return "yes"
# β
Launch Gradio UI
gr.ChatInterface(
fn=ask_agent,
title="AI Treasury Assistant",
description="Ask about cash positions, FX risk, or liquidity outlook.",
chatbot=gr.Chatbot(show_copy_button=True, type="messages"), # β
Fix here
type="messages" # β
And here
).launch()
|