CoolFace
Apppublic

chwellofficial/nt360Slides

sourceHugging Faceupdated 5mo agoView on Hugging Face
0likes
llm_utils.py135 linesDownload Raw Back to utils
1import asyncio2import json3from collections.abc import AsyncGenerator, Sequence4from typing import Any, Optional5 6import dirtyjson7from llmai.shared import (8    LLMTool,9    Message,10    ResponseFormat,11    normalize_content_parts,12)13 14from utils.llm_config import get_extra_body15 16 17def get_generate_kwargs(18    model: str,19    messages: Sequence[Message],20    max_tokens: Optional[int] = None,21    tools: Optional[list[LLMTool]] = None,22    response_format: Optional[ResponseFormat] = None,23    stream: bool = False,24) -> dict[str, Any]:25    kwargs: dict[str, Any] = {26        "model": model,27        "messages": list(messages),28        "stream": stream,29    }30    if max_tokens is not None:31        kwargs["max_tokens"] = max_tokens32    if tools:33        kwargs["tools"] = tools34    if response_format is not None:35        kwargs["response_format"] = response_format36 37    extra_body = get_extra_body()38    if extra_body:39        kwargs["extra_body"] = extra_body40 41    return kwargs42 43 44def extract_text(content: Any) -> Optional[str]:45    if content is None:46        return None47    if isinstance(content, str):48        return content49    if isinstance(content, Sequence) and not isinstance(content, (bytes, bytearray)):50        parts: list[str] = []51        for part in content:52            if isinstance(part, str):53                parts.append(part)54                continue55            text = getattr(part, "text", None)56            if isinstance(text, str):57                parts.append(text)58        joined = "".join(parts)59        return joined or None60    text = getattr(content, "text", None)61    if isinstance(text, str):62        return text63    return None64 65 66def extract_structured_content(content: Any) -> Optional[dict]:67    if content is None:68        return None69    if isinstance(content, dict):70        return content71    if hasattr(content, "model_dump"):72        dumped = content.model_dump(mode="json")73        if isinstance(dumped, dict):74            return dumped75 76    raw_text = extract_text(content)77    if not raw_text:78        return None79 80    try:81        parsed = dirtyjson.loads(raw_text)82    except Exception:83        return None84 85    if isinstance(parsed, dict):86        return dict(parsed)87    return None88 89 90def serialize_structured_content(content: Any) -> Optional[str]:91    parsed = extract_structured_content(content)92    if parsed is not None:93        return json.dumps(parsed, ensure_ascii=False)94 95    raw_text = extract_text(content)96    if raw_text:97        return raw_text98    return None99 100 101def message_content_to_text(content: Sequence[Any] | str | None) -> Optional[str]:102    joined = "".join(103        part.text104        for part in normalize_content_parts(content)105        if isinstance(getattr(part, "text", None), str)106    )107    return joined or None108 109 110async def stream_generate_events(client: Any, **kwargs) -> AsyncGenerator[Any, None]:111    loop = asyncio.get_running_loop()112    queue: asyncio.Queue[Any] = asyncio.Queue()113    sentinel = object()114 115    def worker():116        try:117            for event in client.generate(**kwargs):118                loop.call_soon_threadsafe(queue.put_nowait, event)119        except Exception as exc:120            loop.call_soon_threadsafe(queue.put_nowait, exc)121        finally:122            loop.call_soon_threadsafe(queue.put_nowait, sentinel)123 124    worker_task = asyncio.create_task(asyncio.to_thread(worker))125    try:126        while True:127            item = await queue.get()128            if item is sentinel:129                break130            if isinstance(item, Exception):131                raise item132            yield item133    finally:134        await worker_task135