PMFlow/backend/app/api/rag_api/helpers.py

53 lines
2.0 KiB
Python

from __future__ import annotations
from .shared import *
def _resolve_tenant_id(user: User, fallback_tenant_id: int) -> int:
try:
return int(getattr(user, "tenant_id") or fallback_tenant_id or 1)
except Exception:
return int(fallback_tenant_id or 1)
def _safe_decode_bytes(raw: bytes) -> str:
for encoding in ("utf-8", "utf-8-sig", "gb18030", "latin-1"):
try:
return raw.decode(encoding)
except Exception:
continue
return raw.decode("utf-8", errors="ignore")
def _extract_text_from_upload(filename: str, raw: bytes) -> tuple[str, str]:
name = str(filename or "uploaded.txt")
suffix = name.rsplit(".", 1)[-1].lower() if "." in name else "txt"
if suffix in {"txt", "md", "markdown", "csv", "json", "py", "ts", "tsx", "js", "jsx"}:
return ("md" if suffix in {"md", "markdown"} else "txt", _safe_decode_bytes(raw))
if suffix == "pdf":
try:
from pypdf import PdfReader # type: ignore
except Exception as exc:
raise HTTPException(status_code=400, detail=f"PDF 解析依赖缺失: {exc}") from exc
reader = PdfReader(io.BytesIO(raw))
parts: list[str] = []
for idx, page in enumerate(reader.pages, start=1):
page_text = (page.extract_text() or "").strip()
if not page_text:
continue
# 写入页码标记,向量分块时会保留 page_number 元数据,便于引用来源页码。
parts.append(f"[[PAGE:{idx}]]\n{page_text}")
text = "\n\n".join(parts)
return ("pdf", text)
if suffix in {"docx", "doc"}:
try:
from docx import Document # type: ignore
except Exception as exc:
raise HTTPException(status_code=400, detail=f"Word 解析依赖缺失: {exc}") from exc
doc = Document(io.BytesIO(raw))
text = "\n".join([p.text for p in doc.paragraphs if p.text])
return ("word", text)
raise HTTPException(status_code=400, detail=f"不支持的文件类型: .{suffix}")