Corin1998 commited on
Commit
f65a047
·
verified ·
1 Parent(s): 1bfa547

Update irpr/main.py

Browse files
Files changed (1) hide show
  1. irpr/main.py +43 -14
irpr/main.py CHANGED
@@ -9,7 +9,7 @@ import os, traceback
9
  from irpr.models import IngestRequest, GenerateRequest
10
  from irpr.config import settings
11
 
12
- app = FastAPI(title="IR/PR Co-Pilot Pro", version="0.4.1 (OpenAI)")
13
 
14
  app.add_middleware(
15
  CORSMiddleware, allow_origins=["*"], allow_credentials=True,
@@ -19,7 +19,6 @@ app.add_middleware(
19
  def _ensure_dir_writable(path: str) -> bool:
20
  try:
21
  os.makedirs(path, exist_ok=True)
22
- # 可能なら権限を広めに
23
  try:
24
  os.chmod(path, 0o777)
25
  except Exception:
@@ -36,25 +35,26 @@ def _pick_writable_dir() -> str:
36
  """
37
  優先順位:
38
  1) DATA_DIR (env で指示)
39
- 2) /mnt/data (この環境最も安全)
40
  3) /data
41
  4) ./var
42
  5) /tmp/irpr
43
- 6) カレント
44
  """
45
  candidates = []
46
- if settings.DATA_DIR: candidates.append(settings.DATA_DIR)
 
47
  candidates += ["/mnt/data", "/data", "./var", "/tmp/irpr", "."]
48
  for base in candidates:
49
- if not base:
50
- continue
51
  if _ensure_dir_writable(base):
52
  return base
53
  return "."
54
 
55
  BASE_DIR = _pick_writable_dir()
56
  UPLOAD_DIR = os.path.join(BASE_DIR, "uploads")
 
57
  _ensure_dir_writable(UPLOAD_DIR)
 
58
 
59
  # 静的
60
  os.makedirs("static", exist_ok=True)
@@ -82,6 +82,13 @@ def ingest_edinet(req: IngestRequest):
82
  except Exception as e:
83
  return {"ok": False, "error": repr(e)}
84
 
 
 
 
 
 
 
 
85
  @app.post("/ingest/upload")
86
  async def ingest_upload(files: list[UploadFile] = File(...)):
87
  from rag.ingest import ingest_pdf_bytes
@@ -90,21 +97,42 @@ async def ingest_upload(files: list[UploadFile] = File(...)):
90
  # 念のため再確認
91
  if not _ensure_dir_writable(UPLOAD_DIR):
92
  raise PermissionError(f"UPLOAD_DIR not writable: {UPLOAD_DIR}")
 
 
 
 
93
  for f in files:
94
- if not f.filename.lower().endswith(".pdf"):
 
 
95
  continue
 
96
  blob = await f.read()
97
- save_path = os.path.join(UPLOAD_DIR, f.filename)
 
 
 
 
98
  try:
 
99
  with open(save_path, "wb") as w:
100
  w.write(blob)
101
  except Exception as e:
102
- # 失敗したパスも返す
103
- return {"ok": False, "error": f"{repr(e)} at path={save_path}", "base_dir": BASE_DIR}
104
- source_url = f"/files/uploads/{f.filename}"
105
- total += ingest_pdf_bytes(title=f.filename, source_url=source_url, pdf_bytes=blob)
 
 
 
 
 
 
 
106
  saved.append(source_url)
 
107
  return {"ok": True, "ingested_chunks": total, "saved": saved, "base_dir": BASE_DIR}
 
108
  except Exception as e:
109
  return {"ok": False, "error": repr(e), "ingested_chunks": total, "saved": saved, "base_dir": BASE_DIR}
110
 
@@ -162,4 +190,5 @@ from starlette.requests import Request as SRequest
162
  @app.exception_handler(Exception)
163
  async def _all_exception_handler(request: SRequest, exc: Exception):
164
  traceback.print_exc()
165
- return JSONResponse(status_code=200, content={"ok": False, "error": repr(exc), "base_dir": BASE_DIR})
 
 
9
  from irpr.models import IngestRequest, GenerateRequest
10
  from irpr.config import settings
11
 
12
+ app = FastAPI(title="IR/PR Co-Pilot Pro", version="0.4.2 (OpenAI)")
13
 
14
  app.add_middleware(
15
  CORSMiddleware, allow_origins=["*"], allow_credentials=True,
 
19
  def _ensure_dir_writable(path: str) -> bool:
20
  try:
21
  os.makedirs(path, exist_ok=True)
 
22
  try:
23
  os.chmod(path, 0o777)
24
  except Exception:
 
35
  """
36
  優先順位:
37
  1) DATA_DIR (env で指示)
38
+ 2) /mnt/data (Spaces等で最も安全)
39
  3) /data
40
  4) ./var
41
  5) /tmp/irpr
42
+ 6) .
43
  """
44
  candidates = []
45
+ if settings.DATA_DIR:
46
+ candidates.append(settings.DATA_DIR)
47
  candidates += ["/mnt/data", "/data", "./var", "/tmp/irpr", "."]
48
  for base in candidates:
 
 
49
  if _ensure_dir_writable(base):
50
  return base
51
  return "."
52
 
53
  BASE_DIR = _pick_writable_dir()
54
  UPLOAD_DIR = os.path.join(BASE_DIR, "uploads")
55
+ INDEX_DIR = os.path.join(BASE_DIR, "simple_index")
56
  _ensure_dir_writable(UPLOAD_DIR)
57
+ _ensure_dir_writable(INDEX_DIR)
58
 
59
  # 静的
60
  os.makedirs("static", exist_ok=True)
 
82
  except Exception as e:
83
  return {"ok": False, "error": repr(e)}
84
 
85
+ def _safe_filename(name: str) -> str:
86
+ # パス区切り無効化 + 先頭末尾空白削除
87
+ name = os.path.basename(name or "").strip()
88
+ if not name:
89
+ name = "upload.pdf"
90
+ return name
91
+
92
  @app.post("/ingest/upload")
93
  async def ingest_upload(files: list[UploadFile] = File(...)):
94
  from rag.ingest import ingest_pdf_bytes
 
97
  # 念のため再確認
98
  if not _ensure_dir_writable(UPLOAD_DIR):
99
  raise PermissionError(f"UPLOAD_DIR not writable: {UPLOAD_DIR}")
100
+
101
+ if not files:
102
+ return {"ok": False, "error": "no files", "ingested_chunks": 0, "saved": [], "base_dir": BASE_DIR}
103
+
104
  for f in files:
105
+ fname = _safe_filename(f.filename)
106
+ if not fname.lower().endswith(".pdf"):
107
+ # PDF以外はスキップ
108
  continue
109
+
110
  blob = await f.read()
111
+ if not blob:
112
+ return {"ok": False, "error": f"empty file: {fname}", "ingested_chunks": 0, "saved": [], "base_dir": BASE_DIR}
113
+
114
+ # 親ディレクトリを都度保証
115
+ os.makedirs(UPLOAD_DIR, exist_ok=True)
116
  try:
117
+ save_path = os.path.join(UPLOAD_DIR, fname)
118
  with open(save_path, "wb") as w:
119
  w.write(blob)
120
  except Exception as e:
121
+ return {"ok": False, "error": f"{repr(e)} at path={os.path.join(UPLOAD_DIR, fname)}", "ingested_chunks": total, "saved": saved, "base_dir": BASE_DIR}
122
+
123
+ source_url = f"/files/uploads/{fname}"
124
+
125
+ try:
126
+ added = ingest_pdf_bytes(title=fname, source_url=source_url, pdf_bytes=blob)
127
+ except Exception as e:
128
+ # 解析側での例外も捕捉し、どのファイルで落ちたか返す
129
+ return {"ok": False, "error": f"{repr(e)} while ingesting file={fname}", "ingested_chunks": total, "saved": saved, "base_dir": BASE_DIR}
130
+
131
+ total += added
132
  saved.append(source_url)
133
+
134
  return {"ok": True, "ingested_chunks": total, "saved": saved, "base_dir": BASE_DIR}
135
+
136
  except Exception as e:
137
  return {"ok": False, "error": repr(e), "ingested_chunks": total, "saved": saved, "base_dir": BASE_DIR}
138
 
 
190
  @app.exception_handler(Exception)
191
  async def _all_exception_handler(request: SRequest, exc: Exception):
192
  traceback.print_exc()
193
+ tb = "".join(traceback.format_exception(type(exc), exc, exc.__traceback__))[-2000:]
194
+ return JSONResponse(status_code=200, content={"ok": False, "error": repr(exc), "trace": tb, "base_dir": BASE_DIR})