Spaces:
Running
Running
Update app/sentiment.py
Browse files- app/sentiment.py +47 -67
app/sentiment.py
CHANGED
@@ -1,70 +1,50 @@
|
|
1 |
"""
|
2 |
-
|
3 |
"""
|
4 |
-
import httpx
|
5 |
-
import logging
|
6 |
-
|
7 |
-
# Primary and secondary APIs for crypto prices
|
8 |
-
COINGECKO_URL = (
|
9 |
-
"https://api.coingecko.com/api/v3/simple/price"
|
10 |
-
"?ids=bitcoin,ethereum,dogecoin&vs_currencies=usd"
|
11 |
-
)
|
12 |
-
COINCAP_URL = (
|
13 |
-
"https://api.coincap.io/v2/assets?ids=bitcoin,ethereum,dogecoin"
|
14 |
-
)
|
15 |
-
|
16 |
-
# Shared price cache
|
17 |
-
CURRENT_PRICES = {"bitcoin": "--", "ethereum": "--", "dogecoin": "--"}
|
18 |
-
|
19 |
-
# How often to retry each API before falling back (seconds)
|
20 |
-
RETRY_DELAY = 5
|
21 |
-
|
22 |
-
|
23 |
-
def fetch_prices() -> None:
|
24 |
-
"""
|
25 |
-
Try CoinGecko first; on 429 or error, fall back to CoinCap.
|
26 |
-
Updates CURRENT_PRICES in-place.
|
27 |
-
"""
|
28 |
-
global CURRENT_PRICES
|
29 |
-
apis = [
|
30 |
-
("CoinGecko", COINGECKO_URL),
|
31 |
-
("CoinCap", COINCAP_URL)
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
"""
|
2 |
+
Safe lazy-loading sentiment pipeline that works in Hugging Face Spaces (no /.cache error).
|
3 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
+
import os
|
6 |
+
import hashlib
|
7 |
+
import logging
|
8 |
+
from functools import lru_cache
|
9 |
+
|
10 |
+
# Redirect the HF model cache to a writable directory
|
11 |
+
os.environ["TRANSFORMERS_CACHE"] = "/tmp/huggingface"
|
12 |
+
os.makedirs("/tmp/huggingface", exist_ok=True)
|
13 |
+
|
14 |
+
from transformers import pipeline
|
15 |
+
|
16 |
+
class SentimentCache:
|
17 |
+
latest_id: int = 0
|
18 |
+
latest_result: dict = {}
|
19 |
+
_pipeline = None # Lazy init
|
20 |
+
|
21 |
+
@classmethod
|
22 |
+
def _get_pipeline(cls):
|
23 |
+
if cls._pipeline is None:
|
24 |
+
logging.info("🔄 Loading sentiment model…")
|
25 |
+
cls._pipeline = pipeline(
|
26 |
+
"sentiment-analysis",
|
27 |
+
model="distilbert-base-uncased-finetuned-sst-2-english"
|
28 |
+
)
|
29 |
+
return cls._pipeline
|
30 |
+
|
31 |
+
@classmethod
|
32 |
+
def _hash(cls, text: str) -> str:
|
33 |
+
return hashlib.sha256(text.encode()).hexdigest()
|
34 |
+
|
35 |
+
@classmethod
|
36 |
+
@lru_cache(maxsize=128)
|
37 |
+
def _analyze(cls, text: str):
|
38 |
+
pipe = cls._get_pipeline()
|
39 |
+
return pipe(text)[0]
|
40 |
+
|
41 |
+
@classmethod
|
42 |
+
def compute(cls, text: str):
|
43 |
+
res = cls._analyze(text)
|
44 |
+
cls.latest_id += 1
|
45 |
+
cls.latest_result = {
|
46 |
+
"text": text,
|
47 |
+
"label": res["label"],
|
48 |
+
"score": round(res["score"], 4)
|
49 |
+
}
|
50 |
+
logging.info("✅ Sentiment computed: %s", cls.latest_result)
|