File size: 1,781 Bytes
31fa536
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""Shared helpers for talking to HF Inference Providers with the user's token.

Every call here is billed to whoever owns `hf_token`. A single InferenceClient is
built per request in app.py and threaded through the pipeline.
"""
from __future__ import annotations

from typing import List, Optional

from huggingface_hub import InferenceClient


def make_client(hf_token: str) -> InferenceClient:
    """Build an InferenceClient bound to the user's token (auto provider selection)."""
    token = (hf_token or "").strip()
    if not token:
        raise ValueError("A Hugging Face token is required (paid calls are billed to it).")
    return InferenceClient(token=token)


def chat(
    client: InferenceClient,
    model: str,
    system: str,
    user: str,
    *,
    max_tokens: int = 1024,
    temperature: float = 0.7,
    fallback_model: Optional[str] = None,
) -> str:
    """Run a chat completion and return the assistant text.

    Falls back to `fallback_model` once if the primary model errors (e.g. no provider).
    """
    messages = [
        {"role": "system", "content": system},
        {"role": "user", "content": user},
    ]
    models: List[str] = [model] + ([fallback_model] if fallback_model else [])
    last_err: Optional[Exception] = None
    for m in models:
        try:
            resp = client.chat.completions.create(
                model=m,
                messages=messages,
                max_tokens=max_tokens,
                temperature=temperature,
            )
            return (resp.choices[0].message.content or "").strip()
        except Exception as e:  # noqa: BLE001 - surface a clean error after trying fallback
            last_err = e
            continue
    raise RuntimeError(f"LLM call failed for {models}: {last_err}")