Spaces:
Sleeping
Sleeping
File size: 5,979 Bytes
280a261 5136e53 280a261 5136e53 280a261 5136e53 280a261 acc03ea 280a261 5136e53 280a261 5136e53 acc03ea 5136e53 acc03ea 5136e53 280a261 5136e53 280a261 5136e53 280a261 bc84d34 280a261 5136e53 280a261 5136e53 280a261 | 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 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | import os
from typing import Optional
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from groq import Groq
from huggingface_hub import InferenceClient
from pydantic import BaseModel, Field
from config import (
DEFAULT_GROQ_MODEL,
DEFAULT_HF_MODEL,
FALLBACK_GROQ_MODEL,
TAROT_DECK,
get_active_provider,
get_groq_api_key,
get_groq_client,
get_hf_token,
list_available_models,
)
from personas import get_dynamic_persona, normalize_lang
app = FastAPI(title="AI Pantheon API", version="0.2.5")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
class TarotRequest(BaseModel):
cards: list[str]
topic: str
query: str
lang: str = Field(default="한국어")
class FengShuiRequest(BaseModel):
year: int
gender: str
door_dir: str
head_dir: str
query: str
lang: str = Field(default="한국어")
address: Optional[str] = None
family_info: Optional[str] = None
class SajuRequest(BaseModel):
year: int
month: int
day: int
hour: int
minute: int
calendar_type: str
query: str
lang: str = Field(default="한국어")
def _call_groq(system_prompt: str, user_prompt: str, temperature: float = 0.85) -> str:
client = get_groq_client()
models = [DEFAULT_GROQ_MODEL, FALLBACK_GROQ_MODEL]
for model in list_available_models():
if model not in models:
models.append(model)
last_error: Exception | None = None
for model in models:
try:
response = client.chat.completions.create(
model=model,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt},
],
temperature=temperature,
max_tokens=2048,
)
content = response.choices[0].message.content
if content:
return content.strip()
except Exception as exc:
last_error = exc
continue
raise RuntimeError(f"All Groq models failed: {last_error}")
def _call_hf_inference(system_prompt: str, user_prompt: str, temperature: float = 0.85) -> str:
token = get_hf_token()
if not token:
raise RuntimeError("HF_TOKEN is not set")
client = InferenceClient(model=DEFAULT_HF_MODEL, token=token, timeout=90)
response = client.chat_completion(
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt},
],
max_tokens=1200,
temperature=temperature,
)
content = response.choices[0].message.content
if not content:
raise RuntimeError("Empty response from Hugging Face Inference")
return content.strip()
def _call_llm(system_prompt: str, user_prompt: str, temperature: float = 0.85) -> str:
provider = get_active_provider()
if provider == "groq":
return _call_groq(system_prompt, user_prompt, temperature)
if provider == "huggingface":
return _call_hf_inference(system_prompt, user_prompt, temperature)
raise HTTPException(
status_code=503,
detail="No AI provider configured. Set GROQ_API_KEY or HF_TOKEN in Space secrets.",
)
@app.get("/")
def read_root():
return {"message": "Server is Running!"}
@app.get("/health")
def health():
provider = get_active_provider()
return {
"status": "ok" if provider != "none" else "degraded",
"provider": provider,
"version": app.version,
}
@app.get("/models")
def get_models():
provider = get_active_provider()
models = list_available_models()
if provider == "groq":
return {"provider": "groq", "models": models, "default": DEFAULT_GROQ_MODEL, "fallback": FALLBACK_GROQ_MODEL}
return {"provider": provider, "models": models, "default": DEFAULT_HF_MODEL}
@app.get("/tarot/deck")
def get_tarot_deck():
return TAROT_DECK
@app.post("/tarot/read")
def read_tarot(request: TarotRequest):
try:
lang = normalize_lang(request.lang)
system = get_dynamic_persona(lang, "tarot")
cards_text = ", ".join(request.cards)
user = (
f"Topic: {request.topic}\n"
f"Selected cards: {cards_text}\n"
f"Question: {request.query}\n\n"
f"Give a tarot reading as Emily. Interpret each card for this topic and weave them together."
)
result = _call_llm(system, user)
return {"result": result}
except HTTPException:
raise
except Exception as exc:
raise HTTPException(status_code=502, detail=str(exc)) from exc
@app.post("/fengshui/analyze")
def analyze_fengshui(request: FengShuiRequest):
lang = normalize_lang(request.lang)
system = get_dynamic_persona(lang, "fengshui")
user = (
f"Birth year: {request.year}\n"
f"Gender: {request.gender}\n"
f"Front door direction: {request.door_dir}\n"
f"Sleeping head direction: {request.head_dir}\n"
f"Question: {request.query}"
)
result = _call_llm(system, user)
return {"result": result}
@app.post("/shaman/read")
def read_saju(request: SajuRequest):
lang = normalize_lang(request.lang)
system = get_dynamic_persona(lang, "shaman")
user = (
f"Birth: {request.year}-{request.month:02d}-{request.day:02d} "
f"{request.hour:02d}:{request.minute:02d} ({request.calendar_type})\n"
f"Question: {request.query}\n\n"
f"Deliver a spirit oracle (공수) as Emily the young shaman. "
f"Reference birth elements naturally but stay in Emily's voice."
)
result = _call_llm(system, user, temperature=0.9)
return {"result": result}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=int(os.getenv("PORT", "7860")))
|