Spaces:
Sleeping
Sleeping
| """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) | |