Download apps/core/llm/structured_output.py from jun2024/fc: direct link, hf CLI and curl.
- Browser
- Download file 2.94 kB
-
https://huggingface.co/spaces/jun2024/fc/resolve/main/apps/core/llm/structured_output.py
- Command line
-
hf download hf://spaces/jun2024/fc/apps/core/llm/structured_output.py
-
curl -L -o structured_output.py https://huggingface.co/spaces/jun2024/fc/resolve/main/apps/core/llm/structured_output.py
2.94 kB
| """Helpers for extracting structured JSON output from LLM responses.""" | |
| from __future__ import annotations | |
| import json | |
| import re | |
| from typing import Any, TypeVar, cast | |
| from pydantic import BaseModel | |
| TModel = TypeVar("TModel", bound=BaseModel) | |
| _CODE_FENCE_RE = re.compile(r"```(?:json)?\s*(.*?)\s*```", re.IGNORECASE | re.DOTALL) | |
| def clean_text(text: str) -> str: | |
| """Remove common wrappers around model output.""" | |
| cleaned = text or "" | |
| for marker in [ | |
| "```json", | |
| "```", | |
| "<|begin_of_text|>", | |
| "<|end_of_text|>", | |
| "<|begin_of_box|>", | |
| "<|end_of_box|>", | |
| ]: | |
| cleaned = cleaned.replace(marker, "") | |
| return cleaned.strip() | |
| def extract_json_text(text: str) -> str | None: | |
| """Extract the first valid JSON object/array text from a model response.""" | |
| cleaned = clean_text(text) | |
| if not cleaned: | |
| return None | |
| for candidate in [cleaned, *_CODE_FENCE_RE.findall(cleaned)]: | |
| snippet = (candidate or "").strip() | |
| if not snippet: | |
| continue | |
| try: | |
| json.loads(snippet) | |
| return snippet | |
| except json.JSONDecodeError: | |
| pass | |
| stack: list[str] = [] | |
| start_idx: int | None = None | |
| for idx, ch in enumerate(cleaned): | |
| if ch in "[{": | |
| if not stack: | |
| start_idx = idx | |
| stack.append(ch) | |
| continue | |
| if ch not in "]}": | |
| continue | |
| if not stack: | |
| continue | |
| opening = stack.pop() | |
| if (opening == "{" and ch != "}") or (opening == "[" and ch != "]"): | |
| stack = [] | |
| start_idx = None | |
| continue | |
| if not stack and start_idx is not None: | |
| snippet = cleaned[start_idx : idx + 1].strip() | |
| try: | |
| json.loads(snippet) | |
| return snippet | |
| except json.JSONDecodeError: | |
| start_idx = None | |
| continue | |
| return None | |
| def parse_json_content(text: str) -> Any: | |
| """Parse JSON payload from model response text.""" | |
| payload = extract_json_text(text) | |
| if not payload: | |
| raise ValueError("LLM response does not contain valid JSON") | |
| return json.loads(payload) | |
| def parse_model_content(text: str, model_cls: type[TModel]) -> TModel: | |
| """Parse and validate structured model output from model response text.""" | |
| parsed = parse_json_content(text) | |
| return cast(TModel, model_cls.model_validate(parsed)) | |
| def json_schema_instructions(model_cls: type[BaseModel]) -> str: | |
| """Return concise JSON-schema instructions for structured generation.""" | |
| schema_text = json.dumps(model_cls.model_json_schema(), ensure_ascii=False) | |
| return "\n".join( | |
| [ | |
| "请只输出一个 JSON,不要输出 Markdown、解释或额外文本。", | |
| "输出必须严格满足以下 JSON Schema:", | |
| schema_text, | |
| ] | |
| ) | |