Spaces:
Runtime error
Runtime error
refactor(api): remove deprecated API files and streamline document handling
Browse files- api/__init__.py +0 -19
- api/api.py +0 -73
- api/document_service.py +0 -60
api/__init__.py
DELETED
@@ -1,19 +0,0 @@
|
|
1 |
-
"""Public interface for the API package."""
|
2 |
-
|
3 |
-
from .api import create_app, app
|
4 |
-
from .document_service import (
|
5 |
-
save_document,
|
6 |
-
list_documents,
|
7 |
-
get_document,
|
8 |
-
read_content,
|
9 |
-
)
|
10 |
-
|
11 |
-
__all__ = [
|
12 |
-
"create_app",
|
13 |
-
"app",
|
14 |
-
"save_document",
|
15 |
-
"list_documents",
|
16 |
-
"get_document",
|
17 |
-
"read_content",
|
18 |
-
]
|
19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
api/api.py
DELETED
@@ -1,73 +0,0 @@
|
|
1 |
-
from __future__ import annotations
|
2 |
-
|
3 |
-
from typing import List
|
4 |
-
from datetime import datetime
|
5 |
-
|
6 |
-
from fastapi import FastAPI, UploadFile, File, HTTPException
|
7 |
-
from pydantic import BaseModel
|
8 |
-
from fastapi.responses import PlainTextResponse
|
9 |
-
|
10 |
-
from .document_service import (
|
11 |
-
save_document,
|
12 |
-
list_documents,
|
13 |
-
get_document,
|
14 |
-
read_content,
|
15 |
-
)
|
16 |
-
from src.log import get_logger
|
17 |
-
|
18 |
-
|
19 |
-
class DocumentInfo(BaseModel):
|
20 |
-
id: int
|
21 |
-
original_name: str
|
22 |
-
file_path: str
|
23 |
-
created_at: datetime
|
24 |
-
|
25 |
-
class Config:
|
26 |
-
from_attributes = True
|
27 |
-
|
28 |
-
|
29 |
-
class DocumentDetail(DocumentInfo):
|
30 |
-
content: str
|
31 |
-
|
32 |
-
|
33 |
-
def create_app() -> FastAPI:
|
34 |
-
app = FastAPI(title="LLM Backend API")
|
35 |
-
log = get_logger(__name__)
|
36 |
-
|
37 |
-
@app.post("/users/{username}/documents", response_model=DocumentInfo)
|
38 |
-
async def upload(username: str, file: UploadFile = File(...)) -> DocumentInfo:
|
39 |
-
log.info("Uploading document %s for %s", file.filename, username)
|
40 |
-
doc = save_document(username, file)
|
41 |
-
return DocumentInfo.model_validate(doc.__data__)
|
42 |
-
|
43 |
-
@app.get("/users/{username}/documents", response_model=List[DocumentInfo])
|
44 |
-
async def list_docs(username: str) -> List[DocumentInfo]:
|
45 |
-
docs = list_documents(username)
|
46 |
-
return [DocumentInfo.model_validate(d.__data__) for d in docs]
|
47 |
-
|
48 |
-
@app.get("/users/{username}/documents/{doc_id}", response_model=DocumentDetail)
|
49 |
-
async def inspect(username: str, doc_id: int) -> DocumentDetail:
|
50 |
-
doc = get_document(username, doc_id)
|
51 |
-
if not doc:
|
52 |
-
raise HTTPException(status_code=404, detail="Document not found")
|
53 |
-
content = read_content(doc)
|
54 |
-
data = DocumentDetail.model_validate(doc.__data__)
|
55 |
-
data.content = content
|
56 |
-
return data
|
57 |
-
|
58 |
-
@app.get("/users/{username}/documents/{doc_id}/raw", response_class=PlainTextResponse)
|
59 |
-
async def download(username: str, doc_id: int) -> PlainTextResponse:
|
60 |
-
doc = get_document(username, doc_id)
|
61 |
-
if not doc:
|
62 |
-
raise HTTPException(status_code=404, detail="Document not found")
|
63 |
-
return PlainTextResponse(read_content(doc))
|
64 |
-
|
65 |
-
return app
|
66 |
-
|
67 |
-
|
68 |
-
app = create_app()
|
69 |
-
|
70 |
-
if __name__ == "__main__":
|
71 |
-
import uvicorn
|
72 |
-
|
73 |
-
uvicorn.run(app, host="0.0.0.0", port=8000)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
api/document_service.py
DELETED
@@ -1,60 +0,0 @@
|
|
1 |
-
from __future__ import annotations
|
2 |
-
|
3 |
-
from pathlib import Path
|
4 |
-
import shutil
|
5 |
-
from typing import List, Optional
|
6 |
-
|
7 |
-
from fastapi import UploadFile
|
8 |
-
|
9 |
-
from src.config import UPLOAD_DIR
|
10 |
-
from src.db import Document, User, init_db
|
11 |
-
|
12 |
-
|
13 |
-
def _ensure_user_dir(username: str) -> Path:
|
14 |
-
path = Path(UPLOAD_DIR) / username
|
15 |
-
path.mkdir(parents=True, exist_ok=True)
|
16 |
-
return path
|
17 |
-
|
18 |
-
|
19 |
-
def save_document(username: str, file: UploadFile) -> Document:
|
20 |
-
"""Persist an uploaded file and return its database entry."""
|
21 |
-
init_db()
|
22 |
-
user, _ = User.get_or_create(username=username)
|
23 |
-
dest_dir = _ensure_user_dir(username)
|
24 |
-
dest = dest_dir / file.filename
|
25 |
-
with dest.open('wb') as buffer:
|
26 |
-
shutil.copyfileobj(file.file, buffer)
|
27 |
-
doc = Document.create(user=user, file_path=str(dest), original_name=file.filename)
|
28 |
-
return doc
|
29 |
-
|
30 |
-
|
31 |
-
def list_documents(username: str) -> List[Document]:
|
32 |
-
"""Return all documents for ``username`` sorted by creation time."""
|
33 |
-
init_db()
|
34 |
-
try:
|
35 |
-
user = User.get(User.username == username)
|
36 |
-
except User.DoesNotExist:
|
37 |
-
return []
|
38 |
-
docs = Document.select().where(Document.user == user).order_by(Document.created_at)
|
39 |
-
return list(docs)
|
40 |
-
|
41 |
-
|
42 |
-
def get_document(username: str, doc_id: int) -> Optional[Document]:
|
43 |
-
"""Retrieve a single document for ``username`` by id."""
|
44 |
-
init_db()
|
45 |
-
try:
|
46 |
-
user = User.get(User.username == username)
|
47 |
-
except User.DoesNotExist:
|
48 |
-
return None
|
49 |
-
try:
|
50 |
-
return Document.get(Document.id == doc_id, Document.user == user)
|
51 |
-
except Document.DoesNotExist:
|
52 |
-
return None
|
53 |
-
|
54 |
-
|
55 |
-
def read_content(doc: Document) -> str:
|
56 |
-
"""Read and return the text content of ``doc``. Errors yield empty string."""
|
57 |
-
try:
|
58 |
-
return Path(doc.file_path).read_text(encoding='utf-8', errors='replace')
|
59 |
-
except Exception:
|
60 |
-
return ''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|