Spaces:
Sleeping
Sleeping
File size: 5,367 Bytes
673ebf8 54f8754 e9275ec 6cce8c7 e9275ec 6cce8c7 e9275ec 6cce8c7 b76ceb5 6cce8c7 9de2bf4 6cce8c7 1b2d77c 54f8754 1b2d77c e9275ec 1b2d77c 6cce8c7 e9275ec 6cce8c7 e9275ec 6cce8c7 e9275ec 54f8754 6cce8c7 54f8754 6cce8c7 c2a3a55 6cce8c7 c2a3a55 e02af7d b4c9087 6cce8c7 5703cae 6cce8c7 54f8754 b4c9087 6cce8c7 e02af7d 6cce8c7 b4c9087 6cce8c7 a4d5268 6cce8c7 |
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 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
import streamlit as st
import pandas as pd
import os
import asyncio
from llama_index.llms.openai import OpenAI
from llama_index.core.agent import ReActAgent
from llama_index.core.workflow import Context
from llama_index.core.tools import FunctionTool
# --- Import tools class ---
from tools import PokemonAdvisorTools
# --- 1. Page Configuration (MUST be first Streamlit command) ---
st.set_page_config(page_title="cAsh Robo-Advisor", page_icon="π€")
# --- 2. Initialize Agent & Tools (with caching to avoid recreating on every rerun) ---
@st.cache_resource
def initialize_agent():
"""Initialize the agent and tools once and cache them."""
# Instantiate the class to load data
advisor = PokemonAdvisorTools("/app/src")
# Create the list of tool methods to wrap
tool_methods = [
advisor.get_card_info,
advisor.find_grading_opportunities,
advisor.assess_risk_volatility,
advisor.get_roi_metrics,
advisor.get_recent_price_spikes,
advisor.analyze_set_performance,
advisor.find_cards_by_artist,
advisor.get_market_movers
]
# Wrap tools into LlamaIndex FunctionTools
tools = [FunctionTool.from_defaults(fn=func) for func in tool_methods]
# Initialize the LLM (Ensure OPENAI_API_KEY is set in your env)
llm = OpenAI(model="gpt-4o-mini", temperature=0.5)
# System Prompt
system_prompt = """
### ROLE
You are **cAsh**, a sophisticated Pokemon Investment Advisor.
While you rely **strictly** on data and tools, your goal is to provide a helpful, engaging experience similar to a professional financial consultant.
### CONVERSATIONAL STYLE
- **Opening:** Start with a brief, friendly acknowledgment of the user's request.
- **Interpretation:** Don't just list numbers. Explain *why* these numbers matter (e.g., "The market is showing a significant spike for high-end Tag Team cards...").
- **Formatting:** Use bolding for card names and bullet points for readability, but keep the sentences flowing naturally.
- **Closing:** End with a helpful follow-up suggestion or a brief summary of the risk/opportunity.
### TOOL USAGE PROTOCOL
1. **Verify First:** ALWAYS use `get_card_info` first for specific card queries.
2. **Safety Check:** BEFORE recommending ANY card, you MUST call `assess_risk_volatility`.
3. **Data Integrity:** Never hallucinate. If the tool returns nothing, say "My database doesn't have the specific stats for that card yet."
### TONE
Professional, objective, insightful, and conversational. Always answer in English.
"""
# Initialize Agent
agent = ReActAgent(
tools=tools,
llm=llm,
verbose=True,
system_prompt=system_prompt,
timeout=120
)
return agent
# Get cached agent
agent = initialize_agent()
# --- 3. Initialize Session State ---
if "messages" not in st.session_state:
st.session_state.messages = []
if "context" not in st.session_state:
# Create a new Context for this session
st.session_state.context = Context(agent)
# --- 4. Define the Chat Function (Sync wrapper for async) ---
async def ask_advisor_async(user_message, ctx):
"""Async function to handle the chat."""
if not user_message:
return "Please enter a message."
try:
# Execute the agent workflow
response = await agent.run(user_msg=user_message, ctx=ctx)
return str(response)
except Exception as e:
return f"β οΈ **Agent Error:** {str(e)}\n\n*Check the console logs for detailed tool output.*"
def ask_advisor(user_message):
"""Synchronous wrapper for the async function."""
return asyncio.run(ask_advisor_async(user_message, st.session_state.context))
# --- 5. Styling & Header ---
st.title("π π₯ cAsh π§ β‘")
st.markdown("""
**π€ Your AI Quantitative Analyst for Pokemon Cards.**
"""
)
# --- 6. Sidebar Examples ---
st.sidebar.header("Example Queries")
examples = [
"What are the top 3 grading opportunities right now?",
"What cards are trending down?",
"Show me profitable cards by Tomokazu Komiya."
]
for ex in examples:
if st.sidebar.button(ex, key=f"example_{ex}"):
# Add to messages and set a flag to process
st.session_state.messages.append({"role": "user", "content": ex})
# Process the example query
with st.spinner("Thinking..."):
response = ask_advisor(ex)
st.session_state.messages.append({"role": "assistant", "content": response})
st.rerun()
# --- 7. Display Chat History ---
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
# --- 8. Chat Input Logic ---
if prompt := st.chat_input("Ask cAsh..."):
# Display user message
with st.chat_message("user"):
st.markdown(prompt)
st.session_state.messages.append({"role": "user", "content": prompt})
# Generate Response
with st.chat_message("assistant"):
with st.spinner("Analyzing..."):
response = ask_advisor(prompt)
st.markdown(response)
st.session_state.messages.append({"role": "assistant", "content": response})
# Force a rerun to update the chat display
st.rerun() |