Spaces:
Running
Running
Download unique_ext/grounding/api_check.py from RDS777/TARGET_SPACE: direct link, hf CLI and curl.
- Browser
- Download file 2.7 kB
-
https://huggingface.co/spaces/RDS777/TARGET_SPACE/resolve/main/unique_ext/grounding/api_check.py
- Command line
-
hf download hf://spaces/RDS777/TARGET_SPACE/unique_ext/grounding/api_check.py
-
curl -L -o api_check.py https://huggingface.co/spaces/RDS777/TARGET_SPACE/resolve/main/unique_ext/grounding/api_check.py
2.7 kB
| """Ancrage pour du code : les modules et les noms importés existent-ils vraiment dans l'environnement ? | |
| L'hallucination typique d'un petit modèle de code n'est pas une fausse citation mais une API inventée | |
| (`from math import sqrtt`). La vérification se fait dans le bac à sable, jamais dans le processus du Space. | |
| """ | |
| from __future__ import annotations | |
| import ast | |
| import json | |
| from mouh.skills.sandbox import SandboxLimits, run_in_sandbox | |
| _PROBE = ( | |
| "import importlib, json, sys\n" | |
| "bad = []\n" | |
| "for mod, names in json.loads(sys.argv[1]):\n" | |
| " try:\n" | |
| " m = importlib.import_module(mod)\n" | |
| " except Exception:\n" | |
| " bad.append(mod)\n" | |
| " continue\n" | |
| " for n in names:\n" | |
| " if not hasattr(m, n):\n" | |
| " try:\n" | |
| " importlib.import_module(mod + '.' + n)\n" | |
| " except Exception:\n" | |
| " bad.append(mod + '.' + n)\n" | |
| "print(json.dumps(bad))\n" | |
| ) | |
| def imported_names(files: dict[str, str]) -> list[tuple[str, list[str]]]: | |
| """[(module, [noms])] des imports absolus, hors modules fournis par la proposition elle-même.""" | |
| local = {name[:-3].replace("/", ".") for name in files if name.endswith(".py")} | |
| wanted: list[tuple[str, list[str]]] = [] | |
| for code in files.values(): | |
| try: | |
| tree = ast.parse(code) | |
| except SyntaxError: | |
| return [] # la porte de compilation et pytest le signalent mieux | |
| for node in ast.walk(tree): | |
| if isinstance(node, ast.Import): | |
| wanted += [(a.name, []) for a in node.names] | |
| elif isinstance(node, ast.ImportFrom) and node.module and node.level == 0: | |
| wanted.append((node.module, [a.name for a in node.names if a.name != "*"])) | |
| return [(m, n) for m, n in wanted if m.split(".")[0] not in local] | |
| class ApiCheck: | |
| def __init__(self, timeout_s: float = 10.0) -> None: | |
| self.timeout_s = timeout_s | |
| self._memo: dict[str, list[str]] = {} | |
| def check(self, files, notes=None) -> list[str]: | |
| wanted = imported_names(files) | |
| if not wanted: | |
| return [] | |
| key = json.dumps(wanted, sort_keys=True) | |
| if key not in self._memo: | |
| run = run_in_sandbox(["probe.py", key], {"probe.py": _PROBE}, timeout_s=self.timeout_s, | |
| limits=SandboxLimits(cpu_seconds=int(self.timeout_s))) | |
| try: | |
| bad = json.loads(run.stdout.strip().splitlines()[-1]) | |
| except (ValueError, IndexError): | |
| bad = [] | |
| self._memo[key] = [f"API introuvable : {b}" for b in bad] | |
| return list(self._memo[key]) | |