09-agentic-workflow-sys / src /hf_provider.py
FlyingNunchucks's picture
Sync from GitHub via hub-sync
5806fe4 verified
Raw History Blame Contribute Delete
3.26 kB
"""Hugging Face Inference Providers adapter for the bounded onboarding AI node.
This module intentionally knows nothing about workflow state, routes, retries, or
human decisions. It converts one text prompt into one text response. The existing
Pydantic model boundary in ``src.model_assist`` remains responsible for validating
that response before the workflow can use it.
"""
from __future__ import annotations
import os
from collections.abc import Callable
from huggingface_hub import InferenceClient
DEFAULT_MODEL_ID = "Qwen/Qwen2.5-7B-Instruct-1M"
def live_ai_enabled_from_env() -> bool:
"""Return whether the deployment explicitly opted into live inference."""
value = os.getenv("LIVE_AI_ENABLED", "false").strip().lower()
return value in {"1", "true", "yes", "on"}
def configured_model_id() -> str:
"""Return the configured model id without exposing any credentials."""
value = os.getenv("MODEL_ID", DEFAULT_MODEL_ID).strip()
return value or DEFAULT_MODEL_ID
def build_hf_onboarding_model_from_env() -> Callable[[str], str] | None:
"""Build a live HF model callable only when deployment explicitly enables it.
Both ``LIVE_AI_ENABLED=true`` and a non-blank ``HF_TOKEN`` are required. This
avoids accidental provider usage just because a token happens to exist in the
environment.
"""
if not live_ai_enabled_from_env():
return None
token = os.getenv("HF_TOKEN", "").strip()
if not token:
return None
return build_hf_onboarding_model(token=token, model_id=configured_model_id())
def build_hf_onboarding_model(
*,
token: str,
model_id: str,
client_factory: Callable[..., InferenceClient] = InferenceClient,
) -> Callable[[str], str]:
"""Return a provider callable compatible with ``ModelCall``.
The provider is asked for JSON to improve reliability, but its output is still
treated as untrusted text. ``organize_onboarding_with_model`` performs the strict
schema validation and rejects extra workflow-control fields.
"""
normalized_token = token.strip()
normalized_model_id = model_id.strip()
if not normalized_token:
raise ValueError("token must be non-blank")
if not normalized_model_id:
raise ValueError("model_id must be non-blank")
client = client_factory(api_key=normalized_token, provider="auto")
def model_call(prompt: str) -> str:
completion = client.chat.completions.create(
model=normalized_model_id,
messages=[
{
"role": "system",
"content": (
"Return only a valid JSON object matching the user's requested "
"schema. Do not include Markdown fences or commentary."
),
},
{"role": "user", "content": prompt},
],
temperature=0.1,
max_tokens=220,
response_format={"type": "json_object"},
)
content = completion.choices[0].message.content
if not isinstance(content, str) or not content.strip():
raise ValueError("provider returned an empty response")
return content.strip()
return model_call