File size: 5,438 Bytes
280a261
 
5136e53
280a261
 
 
 
 
 
 
 
 
 
5136e53
 
acc03ea
280a261
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5136e53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280a261
5136e53
280a261
5136e53
280a261
 
 
5136e53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import os
from groq import Groq
from huggingface_hub import InferenceClient

# Groq production models (updated June 2026)
GROQ_MODELS = [
    "openai/gpt-oss-120b",
    "openai/gpt-oss-20b",
    "qwen/qwen3.6-27b",
    "llama-3.3-70b-versatile",
    "llama-3.1-8b-instant",
]

DEFAULT_GROQ_MODEL = os.getenv("GROQ_MODEL", "openai/gpt-oss-120b")
FALLBACK_GROQ_MODEL = os.getenv("GROQ_FALLBACK_MODEL", "openai/gpt-oss-20b")
DEFAULT_HF_MODEL = os.getenv("HF_MODEL", "Qwen/Qwen2.5-7B-Instruct")

TAROT_DECK = [
    {"name": "The Fool", "id": 0, "desc": "์ƒˆ๋กœ์šด ์‹œ์ž‘, ๋ชจํ—˜, ์ˆœ์ˆ˜ํ•จ", "image": "https://upload.wikimedia.org/wikipedia/commons/9/90/RWS_Tarot_00_Fool.jpg"},
    {"name": "The Magician", "id": 1, "desc": "์ฐฝ์กฐ๋ ฅ, ๊ธฐ์ˆ , ์˜์ง€", "image": "https://upload.wikimedia.org/wikipedia/commons/d/de/RWS_Tarot_01_Magician.jpg"},
    {"name": "The High Priestess", "id": 2, "desc": "์ง€ํ˜œ, ์ง๊ด€, ์‹ ๋น„", "image": "https://upload.wikimedia.org/wikipedia/commons/8/88/RWS_Tarot_02_High_Priestess.jpg"},
    {"name": "The Empress", "id": 3, "desc": "ํ’์š”, ๋ชจ์„ฑ, ์ž์—ฐ", "image": "https://upload.wikimedia.org/wikipedia/commons/d/d2/RWS_Tarot_03_Empress.jpg"},
    {"name": "The Emperor", "id": 4, "desc": "๊ถŒ์œ„, ๊ตฌ์กฐ, ์•„๋ฒ„์ง€", "image": "https://upload.wikimedia.org/wikipedia/commons/c/c3/RWS_Tarot_04_Emperor.jpg"},
    {"name": "The Hierophant", "id": 5, "desc": "์ „ํ†ต, ์‹ ๋…, ๊ต์œก", "image": "https://upload.wikimedia.org/wikipedia/commons/8/8d/RWS_Tarot_05_Hierophant.jpg"},
    {"name": "The Lovers", "id": 6, "desc": "์‚ฌ๋ž‘, ์กฐํ™”, ์„ ํƒ", "image": "https://upload.wikimedia.org/wikipedia/commons/3/3a/TheLovers.jpg"},
    {"name": "The Chariot", "id": 7, "desc": "์Šน๋ฆฌ, ์˜์ง€๋ ฅ, ์ „์ง„", "image": "https://upload.wikimedia.org/wikipedia/commons/9/9b/RWS_Tarot_07_Chariot.jpg"},
    {"name": "Strength", "id": 8, "desc": "์ธ๋‚ด, ์šฉ๊ธฐ, ๋‚ด๋ฉด์˜ ํž˜", "image": "https://upload.wikimedia.org/wikipedia/commons/f/f5/RWS_Tarot_08_Strength.jpg"},
    {"name": "The Hermit", "id": 9, "desc": "์„ฑ์ฐฐ, ๊ณ ๋…, ํƒ๊ตฌ", "image": "https://upload.wikimedia.org/wikipedia/commons/4/4d/RWS_Tarot_09_Hermit.jpg"},
    {"name": "Wheel of Fortune", "id": 10, "desc": "์šด๋ช…, ๋ณ€ํ™”, ์ฃผ๊ธฐ", "image": "https://upload.wikimedia.org/wikipedia/commons/3/3c/RWS_Tarot_10_Wheel_of_Fortune.jpg"},
    {"name": "Justice", "id": 11, "desc": "์ •์˜, ์ง„์‹ค, ์ธ๊ณผ์‘๋ณด", "image": "https://upload.wikimedia.org/wikipedia/commons/e/e0/RWS_Tarot_11_Justice.jpg"},
    {"name": "The Hanged Man", "id": 12, "desc": "ํฌ์ƒ, ์ƒˆ๋กœ์šด ๊ด€์ , ์ •์ง€", "image": "https://upload.wikimedia.org/wikipedia/commons/2/2b/RWS_Tarot_12_Hanged_Man.jpg"},
    {"name": "Death", "id": 13, "desc": "๋ณ€ํ™”, ์ข…๋ฃŒ, ์žฌํƒ„์ƒ", "image": "https://upload.wikimedia.org/wikipedia/commons/d/d7/RWS_Tarot_13_Death.jpg"},
    {"name": "Temperance", "id": 14, "desc": "๊ท ํ˜•, ์กฐํ™”, ์ธ๋‚ด", "image": "https://upload.wikimedia.org/wikipedia/commons/f/f8/RWS_Tarot_14_Temperance.jpg"},
    {"name": "The Devil", "id": 15, "desc": "์œ ํ˜น, ์†๋ฐ•, ์ง‘์ฐฉ", "image": "https://upload.wikimedia.org/wikipedia/commons/5/55/RWS_Tarot_15_Devil.jpg"},
    {"name": "The Tower", "id": 16, "desc": "ํŒŒ๊ดด, ๊ธ‰๋ณ€, ๊นจ๋‹ฌ์Œ", "image": "https://upload.wikimedia.org/wikipedia/commons/5/53/RWS_Tarot_16_Tower.jpg"},
    {"name": "The Star", "id": 17, "desc": "ํฌ๋ง, ์˜๊ฐ, ์น˜์œ ", "image": "https://upload.wikimedia.org/wikipedia/commons/d/db/RWS_Tarot_17_Star.jpg"},
    {"name": "The Moon", "id": 18, "desc": "ํ™˜์ƒ, ๋ถˆ์•ˆ, ๋ฌด์˜์‹", "image": "https://upload.wikimedia.org/wikipedia/commons/7/7f/RWS_Tarot_18_Moon.jpg"},
    {"name": "The Sun", "id": 19, "desc": "์„ฑ๊ณต, ํ™œ๋ ฅ, ๊ธฐ์จ", "image": "https://upload.wikimedia.org/wikipedia/commons/1/17/RWS_Tarot_19_Sun.jpg"},
    {"name": "Judgement", "id": 20, "desc": "์‹ฌํŒ, ๋ถ€ํ™œ, ๊ฐ์„ฑ", "image": "https://upload.wikimedia.org/wikipedia/commons/d/dd/RWS_Tarot_20_Judgement.jpg"},
    {"name": "The World", "id": 21, "desc": "์™„์„ฑ, ์„ฑ์ทจ, ํ†ตํ•ฉ", "image": "https://upload.wikimedia.org/wikipedia/commons/f/ff/RWS_Tarot_21_World.jpg"},
]


def get_groq_api_key() -> str | None:
    for name in ("GROQ_API_KEY", "GROQ_KEY"):
        value = os.getenv(name)
        if value:
            return value
    return None


def get_hf_token() -> str | None:
    for name in ("HF_TOKEN", "HUGGINGFACEHUB_API_TOKEN"):
        value = os.getenv(name)
        if value:
            return value
    return None


def get_active_provider() -> str:
    if get_groq_api_key():
        return "groq"
    if get_hf_token():
        return "huggingface"
    return "none"


def get_groq_client() -> Groq:
    api_key = get_groq_api_key()
    if not api_key:
        raise RuntimeError("GROQ_API_KEY is not set")
    return Groq(api_key=api_key)


def list_available_models() -> list[str]:
    if get_groq_api_key():
        try:
            client = get_groq_client()
            live = [
                m.id
                for m in client.models.list().data
                if "whisper" not in m.id
                and "orpheus" not in m.id
                and "prompt-guard" not in m.id
                and "safeguard" not in m.id
            ]
            ordered = [m for m in GROQ_MODELS if m in live]
            extras = [m for m in live if m not in ordered]
            return ordered + extras
        except Exception:
            return GROQ_MODELS.copy()
    return [DEFAULT_HF_MODEL]