Spaces:
Running
Running
CryptoCreeper commited on
Update app.py
Browse files
app.py
CHANGED
|
@@ -22,12 +22,10 @@ def fetch_crypto_data():
|
|
| 22 |
|
| 23 |
try:
|
| 24 |
response = requests.get(url, params=params, timeout=10)
|
| 25 |
-
|
| 26 |
if response.status_code != 200:
|
| 27 |
return None
|
| 28 |
|
| 29 |
data = response.json()
|
| 30 |
-
|
| 31 |
context_parts = []
|
| 32 |
processed_data = []
|
| 33 |
|
|
@@ -40,98 +38,64 @@ def fetch_crypto_data():
|
|
| 40 |
history = coin.get('sparkline_in_7d', {}).get('price', [])
|
| 41 |
|
| 42 |
context_parts.append(f"[{symbol}: ${price}, 24h:{chg_24:.1f}%, 7d:{chg_7d:.1f}%]")
|
| 43 |
-
|
| 44 |
processed_data.append({
|
| 45 |
-
"name": coin['name'],
|
| 46 |
-
"
|
| 47 |
-
"price": price,
|
| 48 |
-
"chg_24": chg_24,
|
| 49 |
-
"chg_7d": chg_7d,
|
| 50 |
-
"mcap": mcap,
|
| 51 |
-
"history": history
|
| 52 |
})
|
| 53 |
|
| 54 |
MARKET_CONTEXT = " | ".join(context_parts)
|
| 55 |
return processed_data
|
| 56 |
-
|
| 57 |
-
except Exception as e:
|
| 58 |
-
print(f"API Error: {e}")
|
| 59 |
return None
|
| 60 |
|
| 61 |
def create_sparkline(history, chg_24):
|
| 62 |
color = "#10B981" if chg_24 >= 0 else "#EF4444"
|
| 63 |
-
|
| 64 |
fig = go.Figure()
|
| 65 |
fig.add_trace(go.Scatter(
|
| 66 |
-
y=history,
|
| 67 |
-
mode='lines',
|
| 68 |
-
fill='tozeroy',
|
| 69 |
line=dict(color=color, width=2),
|
| 70 |
fillcolor=f"rgba({int(color[1:3], 16)}, {int(color[3:5], 16)}, {int(color[5:7], 16)}, 0.1)"
|
| 71 |
))
|
| 72 |
-
|
| 73 |
fig.update_layout(
|
| 74 |
-
template="plotly_dark",
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
margin=dict(l=0, r=0, t=10, b=0),
|
| 78 |
-
xaxis=dict(visible=False, fixedrange=True),
|
| 79 |
-
yaxis=dict(visible=False, fixedrange=True),
|
| 80 |
-
showlegend=False,
|
| 81 |
-
height=80,
|
| 82 |
)
|
| 83 |
return fig
|
| 84 |
|
| 85 |
def create_card_html(coin):
|
| 86 |
-
if not coin:
|
| 87 |
-
return "<div style='color:white;'>Error Loading</div>"
|
| 88 |
-
|
| 89 |
color_24 = "#10B981" if coin['chg_24'] >= 0 else "#EF4444"
|
| 90 |
arrow = "▲" if coin['chg_24'] >= 0 else "▼"
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
<div style="background-color: #1F2937; padding: 20px; border-radius: 12px; border: 1px solid #374151; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);">
|
| 94 |
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
|
| 95 |
<div style="display: flex; align-items: baseline; gap: 8px;">
|
| 96 |
-
<h2 style="margin: 0; font-size: 1.25rem;
|
| 97 |
-
<span style="
|
| 98 |
</div>
|
| 99 |
-
<span style="font-size: 1.25rem;
|
| 100 |
</div>
|
| 101 |
-
<div style="display: flex; justify-content: space-between;
|
| 102 |
-
<div style="color: {color_24}; font-weight: 600;">
|
| 103 |
-
|
| 104 |
-
</div>
|
| 105 |
-
<div style="color: #9CA3AF;">
|
| 106 |
-
MCap: ${coin['mcap']/1e9:.1f}B
|
| 107 |
-
</div>
|
| 108 |
</div>
|
| 109 |
</div>
|
| 110 |
"""
|
| 111 |
-
return html
|
| 112 |
|
| 113 |
def refresh_dashboard():
|
| 114 |
data = fetch_crypto_data()
|
| 115 |
-
|
| 116 |
-
if not data:
|
| 117 |
-
return [gr.update()] * 8
|
| 118 |
-
|
| 119 |
outputs = []
|
| 120 |
for coin in data:
|
| 121 |
outputs.append(create_card_html(coin))
|
| 122 |
outputs.append(create_sparkline(coin['history'], coin['chg_24']))
|
| 123 |
-
|
| 124 |
return outputs
|
| 125 |
|
| 126 |
def chat_logic(message, history):
|
| 127 |
-
API_URL = "https://api-inference.huggingface.co/models/Qwen/Qwen2.5-
|
| 128 |
-
|
| 129 |
-
system_prompt = f"""You are a professional Crypto Dashboard Assistant.
|
| 130 |
-
LIVE MARKET DATA: {MARKET_CONTEXT}
|
| 131 |
-
1. Use live data for prices/stats.
|
| 132 |
-
2. Answer general questions normally.
|
| 133 |
-
3. Be concise and professional."""
|
| 134 |
|
|
|
|
| 135 |
payload_messages = [{"role": "system", "content": system_prompt}]
|
| 136 |
for human, assistant in history:
|
| 137 |
payload_messages.append({"role": "user", "content": human})
|
|
@@ -139,68 +103,48 @@ def chat_logic(message, history):
|
|
| 139 |
payload_messages.append({"role": "user", "content": message})
|
| 140 |
|
| 141 |
payload = {
|
| 142 |
-
"
|
| 143 |
-
"
|
| 144 |
-
"parameters": {"max_new_tokens": 512, "temperature": 0.7}
|
| 145 |
}
|
| 146 |
|
| 147 |
try:
|
|
|
|
| 148 |
response = requests.post(API_URL, json=payload, timeout=20)
|
| 149 |
if response.status_code == 200:
|
| 150 |
result = response.json()
|
| 151 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 152 |
else:
|
| 153 |
-
yield f"⚠️ API Error: {response.status_code}
|
| 154 |
except Exception as e:
|
| 155 |
yield f"⚠️ Connection Error: {str(e)}"
|
| 156 |
|
| 157 |
-
custom_css = ""
|
| 158 |
-
body { background-color: #111827; }
|
| 159 |
-
.contain { max-width: 1400px; margin: auto; padding-top: 20px; }
|
| 160 |
-
h1 { color: #F3F4F6; text-align: center; margin-bottom: 30px; }
|
| 161 |
-
.plot-container { border: none !important; background: transparent !important; }
|
| 162 |
-
footer { visibility: hidden; }
|
| 163 |
-
"""
|
| 164 |
|
| 165 |
with gr.Blocks(css=custom_css, theme=gr.themes.Soft(primary_hue="indigo", neutral_hue="slate")) as demo:
|
| 166 |
-
|
| 167 |
-
gr.HTML("<h1>⚡ CryptoDash AI</h1>")
|
| 168 |
-
|
| 169 |
with gr.Row():
|
| 170 |
with gr.Column():
|
| 171 |
-
c1_html = gr.HTML()
|
| 172 |
-
c1_plot = gr.Plot(show_label=False, container=False)
|
| 173 |
with gr.Column():
|
| 174 |
-
c2_html = gr.HTML()
|
| 175 |
-
c2_plot = gr.Plot(show_label=False, container=False)
|
| 176 |
with gr.Column():
|
| 177 |
-
c3_html = gr.HTML()
|
| 178 |
-
c3_plot = gr.Plot(show_label=False, container=False)
|
| 179 |
with gr.Column():
|
| 180 |
-
c4_html = gr.HTML()
|
| 181 |
-
c4_plot = gr.Plot(show_label=False, container=False)
|
| 182 |
|
| 183 |
btn_refresh = gr.Button("🔄 Refresh Market Data", variant="secondary")
|
|
|
|
| 184 |
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
chat = gr.ChatInterface(
|
| 189 |
-
fn=chat_logic,
|
| 190 |
-
examples=["What is the price of Bitcoin?", "Is the market up today?", "Explain market cap"],
|
| 191 |
-
)
|
| 192 |
-
|
| 193 |
-
demo.load(
|
| 194 |
-
fn=refresh_dashboard,
|
| 195 |
-
inputs=None,
|
| 196 |
-
outputs=[c1_html, c1_plot, c2_html, c2_plot, c3_html, c3_plot, c4_html, c4_plot]
|
| 197 |
-
)
|
| 198 |
-
|
| 199 |
-
btn_refresh.click(
|
| 200 |
-
fn=refresh_dashboard,
|
| 201 |
-
inputs=None,
|
| 202 |
-
outputs=[c1_html, c1_plot, c2_html, c2_plot, c3_html, c3_plot, c4_html, c4_plot]
|
| 203 |
-
)
|
| 204 |
|
| 205 |
if __name__ == "__main__":
|
| 206 |
demo.launch()
|
|
|
|
| 22 |
|
| 23 |
try:
|
| 24 |
response = requests.get(url, params=params, timeout=10)
|
|
|
|
| 25 |
if response.status_code != 200:
|
| 26 |
return None
|
| 27 |
|
| 28 |
data = response.json()
|
|
|
|
| 29 |
context_parts = []
|
| 30 |
processed_data = []
|
| 31 |
|
|
|
|
| 38 |
history = coin.get('sparkline_in_7d', {}).get('price', [])
|
| 39 |
|
| 40 |
context_parts.append(f"[{symbol}: ${price}, 24h:{chg_24:.1f}%, 7d:{chg_7d:.1f}%]")
|
|
|
|
| 41 |
processed_data.append({
|
| 42 |
+
"name": coin['name'], "symbol": symbol, "price": price,
|
| 43 |
+
"chg_24": chg_24, "chg_7d": chg_7d, "mcap": mcap, "history": history
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
})
|
| 45 |
|
| 46 |
MARKET_CONTEXT = " | ".join(context_parts)
|
| 47 |
return processed_data
|
| 48 |
+
except Exception:
|
|
|
|
|
|
|
| 49 |
return None
|
| 50 |
|
| 51 |
def create_sparkline(history, chg_24):
|
| 52 |
color = "#10B981" if chg_24 >= 0 else "#EF4444"
|
|
|
|
| 53 |
fig = go.Figure()
|
| 54 |
fig.add_trace(go.Scatter(
|
| 55 |
+
y=history, mode='lines', fill='tozeroy',
|
|
|
|
|
|
|
| 56 |
line=dict(color=color, width=2),
|
| 57 |
fillcolor=f"rgba({int(color[1:3], 16)}, {int(color[3:5], 16)}, {int(color[5:7], 16)}, 0.1)"
|
| 58 |
))
|
|
|
|
| 59 |
fig.update_layout(
|
| 60 |
+
template="plotly_dark", paper_bgcolor='rgba(0,0,0,0)', plot_bgcolor='rgba(0,0,0,0)',
|
| 61 |
+
margin=dict(l=0, r=0, t=10, b=0), xaxis=dict(visible=False), yaxis=dict(visible=False),
|
| 62 |
+
showlegend=False, height=80,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
)
|
| 64 |
return fig
|
| 65 |
|
| 66 |
def create_card_html(coin):
|
| 67 |
+
if not coin: return "<div style='color:white;'>Error Loading</div>"
|
|
|
|
|
|
|
| 68 |
color_24 = "#10B981" if coin['chg_24'] >= 0 else "#EF4444"
|
| 69 |
arrow = "▲" if coin['chg_24'] >= 0 else "▼"
|
| 70 |
+
return f"""
|
| 71 |
+
<div style="background-color: #1F2937; padding: 20px; border-radius: 12px; border: 1px solid #374151;">
|
|
|
|
| 72 |
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
|
| 73 |
<div style="display: flex; align-items: baseline; gap: 8px;">
|
| 74 |
+
<h2 style="margin: 0; font-size: 1.25rem; color: #F3F4F6;">{coin['name']}</h2>
|
| 75 |
+
<span style="color: #9CA3AF;">{coin['symbol']}</span>
|
| 76 |
</div>
|
| 77 |
+
<span style="font-size: 1.25rem; color: #F3F4F6;">${coin['price']:,.2f}</span>
|
| 78 |
</div>
|
| 79 |
+
<div style="display: flex; justify-content: space-between; font-size: 0.875rem;">
|
| 80 |
+
<div style="color: {color_24}; font-weight: 600;">{arrow} {coin['chg_24']:.2f}%</div>
|
| 81 |
+
<div style="color: #9CA3AF;">MCap: ${coin['mcap']/1e9:.1f}B</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
</div>
|
| 83 |
</div>
|
| 84 |
"""
|
|
|
|
| 85 |
|
| 86 |
def refresh_dashboard():
|
| 87 |
data = fetch_crypto_data()
|
| 88 |
+
if not data: return [gr.update()] * 8
|
|
|
|
|
|
|
|
|
|
| 89 |
outputs = []
|
| 90 |
for coin in data:
|
| 91 |
outputs.append(create_card_html(coin))
|
| 92 |
outputs.append(create_sparkline(coin['history'], coin['chg_24']))
|
|
|
|
| 93 |
return outputs
|
| 94 |
|
| 95 |
def chat_logic(message, history):
|
| 96 |
+
API_URL = "https://api-inference.huggingface.co/models/Qwen/Qwen2.5-7B-Instruct"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
|
| 98 |
+
system_prompt = f"You are a professional Crypto Dashboard Assistant. LIVE MARKET DATA: {MARKET_CONTEXT}"
|
| 99 |
payload_messages = [{"role": "system", "content": system_prompt}]
|
| 100 |
for human, assistant in history:
|
| 101 |
payload_messages.append({"role": "user", "content": human})
|
|
|
|
| 103 |
payload_messages.append({"role": "user", "content": message})
|
| 104 |
|
| 105 |
payload = {
|
| 106 |
+
"inputs": message, # Simple input format for public API requests
|
| 107 |
+
"parameters": {"max_new_tokens": 512, "temperature": 0.7},
|
|
|
|
| 108 |
}
|
| 109 |
|
| 110 |
try:
|
| 111 |
+
# Standard request without Authorization header
|
| 112 |
response = requests.post(API_URL, json=payload, timeout=20)
|
| 113 |
if response.status_code == 200:
|
| 114 |
result = response.json()
|
| 115 |
+
# Handle different return formats from HF API
|
| 116 |
+
if isinstance(result, list) and "generated_text" in result[0]:
|
| 117 |
+
yield result[0]["generated_text"]
|
| 118 |
+
elif isinstance(result, dict) and "generated_text" in result:
|
| 119 |
+
yield result["generated_text"]
|
| 120 |
+
else:
|
| 121 |
+
yield str(result)
|
| 122 |
+
elif response.status_code == 429:
|
| 123 |
+
yield "⚠️ Rate limit reached (Public requests are limited). Try again in a moment."
|
| 124 |
else:
|
| 125 |
+
yield f"⚠️ API Error: {response.status_code}"
|
| 126 |
except Exception as e:
|
| 127 |
yield f"⚠️ Connection Error: {str(e)}"
|
| 128 |
|
| 129 |
+
custom_css = "body { background-color: #111827; } .contain { max-width: 1400px; margin: auto; padding-top: 20px; }"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 130 |
|
| 131 |
with gr.Blocks(css=custom_css, theme=gr.themes.Soft(primary_hue="indigo", neutral_hue="slate")) as demo:
|
| 132 |
+
gr.HTML("<h1 style='color: white; text-align: center;'>⚡ CryptoDash AI (Qwen 7B)</h1>")
|
|
|
|
|
|
|
| 133 |
with gr.Row():
|
| 134 |
with gr.Column():
|
| 135 |
+
c1_html, c1_plot = gr.HTML(), gr.Plot(show_label=False, container=False)
|
|
|
|
| 136 |
with gr.Column():
|
| 137 |
+
c2_html, c2_plot = gr.HTML(), gr.Plot(show_label=False, container=False)
|
|
|
|
| 138 |
with gr.Column():
|
| 139 |
+
c3_html, c3_plot = gr.HTML(), gr.Plot(show_label=False, container=False)
|
|
|
|
| 140 |
with gr.Column():
|
| 141 |
+
c4_html, c4_plot = gr.HTML(), gr.Plot(show_label=False, container=False)
|
|
|
|
| 142 |
|
| 143 |
btn_refresh = gr.Button("🔄 Refresh Market Data", variant="secondary")
|
| 144 |
+
gr.ChatInterface(fn=chat_logic, examples=["What is the price of Bitcoin?"])
|
| 145 |
|
| 146 |
+
demo.load(fn=refresh_dashboard, outputs=[c1_html, c1_plot, c2_html, c2_plot, c3_html, c3_plot, c4_html, c4_plot])
|
| 147 |
+
btn_refresh.click(fn=refresh_dashboard, outputs=[c1_html, c1_plot, c2_html, c2_plot, c3_html, c3_plot, c4_html, c4_plot])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
|
| 149 |
if __name__ == "__main__":
|
| 150 |
demo.launch()
|