reality-divergence / model_client.py
prashantAI's picture
Wire up working Qwen/FLUX inference, fix Gradio 5 build, add safety fallbacks
f8c1b4a
Raw
History Blame Contribute Delete
3.79 kB
"""Text inference client (HF Inference API, chat_completion) with graceful fallbacks."""
import json
import re
from typing import Optional, Dict, Any
try:
from huggingface_hub import InferenceClient
except ImportError:
InferenceClient = None
import config
class TextClient:
"""Wrapper for text inference via the Hugging Face Inference API."""
def __init__(self, hf_token: Optional[str] = None):
self.hf_token = hf_token or config.HF_TOKEN
self.model = config.MODEL_NAME_TEXT
self.client = None
self.available = False
if not InferenceClient:
print("[warn]huggingface_hub not installed; text generation disabled")
return
if not self.hf_token:
print("[warn]HF_TOKEN not set; text generation disabled (using fallbacks)")
return
try:
self.client = InferenceClient(token=self.hf_token, timeout=config.TIMEOUT_INFERENCE)
self.available = True
except Exception as e:
print(f"[warn]Text client initialization failed: {e}")
self.available = False
def infer(
self,
system_prompt: str,
user_prompt: str,
temperature: float = 0.65,
max_tokens: int = 512,
) -> Optional[str]:
"""Generate text via chat completion."""
if not self.available:
return None
try:
response = self.client.chat_completion(
model=self.model,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt},
],
temperature=max(temperature, 0.01),
max_tokens=max_tokens,
top_p=0.9,
)
content = response.choices[0].message.content
return content.strip() if content else None
except Exception as e:
print(f"[warn]Text inference error: {e}")
return None
def infer_json(
self,
system_prompt: str,
user_prompt: str,
temperature: float = 0.1,
max_tokens: int = 1024,
) -> Optional[Dict[str, Any]]:
"""Generate and parse a JSON response."""
raw = self.infer(system_prompt, user_prompt, temperature, max_tokens)
if not raw:
return None
# Try direct JSON parse
try:
return json.loads(raw)
except json.JSONDecodeError:
pass
# Try stripping markdown fences
try:
clean = re.sub(r"```(?:json)?\n?(.*?)\n?```", r"\1", raw, flags=re.DOTALL)
return json.loads(clean)
except json.JSONDecodeError:
pass
# Try extracting the first JSON object
try:
match = re.search(r"\{.*\}", raw, flags=re.DOTALL)
if match:
return json.loads(match.group(0))
except json.JSONDecodeError:
pass
return None
# Global client instance
_client = None
def get_client() -> TextClient:
"""Get or create the global text client."""
global _client
if _client is None:
_client = TextClient()
return _client
def infer_text(
system_prompt: str,
user_prompt: str,
temperature: float = 0.65,
max_tokens: int = 512,
) -> Optional[str]:
"""Inference wrapper function."""
return get_client().infer(system_prompt, user_prompt, temperature, max_tokens)
def infer_json(
system_prompt: str,
user_prompt: str,
temperature: float = 0.1,
max_tokens: int = 1024,
) -> Optional[Dict[str, Any]]:
"""JSON inference wrapper function."""
return get_client().infer_json(system_prompt, user_prompt, temperature, max_tokens)