Files
ai_site/ai-service/demo_fixtures.py
2026-07-31 10:31:17 +08:00

84 lines
2.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""本地演示/测试素材:供控制台一键预填需求与上传文件。
目录默认:仓库 test/(可用 DEMO_FIXTURES_DIR 覆盖)。
"""
from __future__ import annotations
import mimetypes
import os
from pathlib import Path
from fastapi import HTTPException
from fastapi.responses import FileResponse
_ROOT = Path(__file__).resolve().parents[1]
def fixtures_root() -> Path:
raw = (os.getenv("DEMO_FIXTURES_DIR") or "").strip()
if raw:
return Path(raw).expanduser().resolve()
return (_ROOT / "test").resolve()
# 默认演示包:沉降观测(行业示例,仅测试用)
DEFAULT_PACK = {
"id": "settlement_demo",
"label": "沉降观测演示包test/",
"prompt": "prompts/prompt_1.txt",
"data": "data/settlement.xlsx",
"images": ["refs/board_a.png", "refs/board_b.png"],
"layouts": ["refs/dashboard.html", "refs/nav.html"],
"slug": "settlement_observation_system",
}
def _safe_file(rel: str) -> Path:
root = fixtures_root()
rel = (rel or "").replace("\\", "/").lstrip("/")
if not rel or ".." in rel.split("/"):
raise HTTPException(400, "非法路径")
path = (root / rel).resolve()
try:
path.relative_to(root)
except ValueError as e:
raise HTTPException(400, "越界路径") from e
if not path.is_file():
raise HTTPException(404, f"文件不存在: {rel}")
return path
def fixtures_manifest() -> dict:
root = fixtures_root()
pack = dict(DEFAULT_PACK)
pack["root"] = str(root)
pack["available"] = root.is_dir()
def ok(rel: str) -> bool:
try:
return _safe_file(rel).is_file()
except HTTPException:
return False
pack["files"] = {
"prompt": {"path": pack["prompt"], "ok": ok(pack["prompt"])},
"data": {"path": pack["data"], "ok": ok(pack["data"])},
"images": [{"path": p, "ok": ok(p)} for p in pack["images"]],
"layouts": [{"path": p, "ok": ok(p)} for p in pack["layouts"]],
}
return pack
def read_prompt_text() -> str:
return _safe_file(DEFAULT_PACK["prompt"]).read_text(encoding="utf-8")
def file_response(rel: str) -> FileResponse:
path = _safe_file(rel)
ctype, _ = mimetypes.guess_type(str(path))
return FileResponse(
path,
media_type=ctype or "application/octet-stream",
filename=path.name,
)