Backend Flask aufsetzen (Ticket #4)
parent
cfb67439ba
commit
ed7e01a395
|
|
@ -0,0 +1,11 @@
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/psf/black
|
||||||
|
rev: 23.3.0
|
||||||
|
hooks:
|
||||||
|
- id: black
|
||||||
|
language_version: python3
|
||||||
|
|
||||||
|
- repo: https://github.com/pycqa/flake8
|
||||||
|
rev: 6.1.0
|
||||||
|
hooks:
|
||||||
|
- id: flake8
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
services:
|
||||||
|
backend:
|
||||||
|
build: ./project/backend
|
||||||
|
container_name: fundfuechse-backend
|
||||||
|
ports:
|
||||||
|
- "5000:5000"
|
||||||
|
restart: always
|
||||||
|
|
||||||
|
# frontend:
|
||||||
|
# build: ./project/frontend
|
||||||
|
# container_name: fundfuechse-frontend
|
||||||
|
# ports:
|
||||||
|
# - "3000:80"
|
||||||
|
# restart: always
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
# 1. Python-Image verwenden
|
||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
# 2. Arbeitsverzeichnis im Container setzen
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 3. requirements.txt kopieren und Pakete installieren
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# 4. Quellcode kopieren (z. B. app.py)
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# 5. Flask-App starten
|
||||||
|
CMD ["python", "app.py"]
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
### Voraussetzungen
|
||||||
|
|
||||||
|
- Python 3.11+
|
||||||
|
- pip
|
||||||
|
- Docker (Desktop)
|
||||||
|
- Optional: `pre-commit`
|
||||||
|
|
||||||
|
### Abhängigkeiten installieren
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
|
# Codequalität (lokal prüfen)
|
||||||
|
black app.py
|
||||||
|
flake8 app.py
|
||||||
|
|
||||||
|
|
||||||
|
## Anwendung starten
|
||||||
|
|
||||||
|
### Lokal
|
||||||
|
|
||||||
|
1. Abhängigkeiten installieren:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Flask-App starten:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python app.py
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Aufrufen im Browser:
|
||||||
|
|
||||||
|
```
|
||||||
|
http://localhost:5000/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Option 2: Mit Docker
|
||||||
|
|
||||||
|
1. Image bauen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -t fundfuechse-backend .
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Container starten:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -p 5000:5000 fundfuechse-backend
|
||||||
|
```
|
||||||
|
|
||||||
|
Die API läuft dann unter:
|
||||||
|
|
||||||
|
```
|
||||||
|
http://localhost:5000/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Option 3: Mit docker-compose
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose up --build
|
||||||
|
```
|
||||||
|
|
||||||
|
Danach ist der Service erreichbar unter:
|
||||||
|
|
||||||
|
```
|
||||||
|
http://localhost:5000/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Testaufruf per curl (PDF hochladen)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl.exe -X POST -F "file=@Pitchbook 1.pdf" http://localhost:5000/upload
|
||||||
|
```
|
||||||
|
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
from flask import Flask, jsonify
|
||||||
|
from flask import request
|
||||||
|
import os
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
# Startseite
|
||||||
|
@app.route("/")
|
||||||
|
def hello():
|
||||||
|
return "Startseite"
|
||||||
|
|
||||||
|
|
||||||
|
# gibt Beispiel-Konfig der Kennzahlen zurück (für die UI)
|
||||||
|
@app.route("/config", methods=["GET"])
|
||||||
|
def get_config():
|
||||||
|
config = [
|
||||||
|
{"name": "Fondname", "format": "Text", "required": True},
|
||||||
|
{"name": "IRR", "format": "Prozent", "required": False},
|
||||||
|
]
|
||||||
|
return jsonify(config)
|
||||||
|
|
||||||
|
|
||||||
|
# liefert Beispiel-Ergebnisse der Extraktion
|
||||||
|
@app.route("/dummy_results", methods=["GET"])
|
||||||
|
def get_dummy_results():
|
||||||
|
results = [
|
||||||
|
{"label": "Fondname", "entity": "ABC Fonds", "page": 1, "status": "validated"},
|
||||||
|
{
|
||||||
|
"label": "IRR",
|
||||||
|
"entity": "6,0%",
|
||||||
|
"page": 3,
|
||||||
|
"status": "single-source",
|
||||||
|
"source": "spaCy",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
return jsonify(results)
|
||||||
|
|
||||||
|
|
||||||
|
# legt Upload-Ordner an, falls nicht vorhanden
|
||||||
|
UPLOAD_FOLDER = "uploads"
|
||||||
|
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
|
||||||
|
|
||||||
|
|
||||||
|
# nimmt eine PDF-Datei per POST entgegen und speichert sie
|
||||||
|
@app.route("/upload", methods=["POST"])
|
||||||
|
def upload_pdf():
|
||||||
|
if "file" not in request.files:
|
||||||
|
return {"error": "Keine Datei hochgeladen."}, 400
|
||||||
|
|
||||||
|
file = request.files["file"]
|
||||||
|
|
||||||
|
if file.filename == "":
|
||||||
|
return {"error": "Dateiname fehlt."}, 400
|
||||||
|
|
||||||
|
if not file.filename.endswith(".pdf"):
|
||||||
|
return {"error": "Nur PDF-Dateien erlaubt."}, 400
|
||||||
|
|
||||||
|
file_path = os.path.join(UPLOAD_FOLDER, file.filename)
|
||||||
|
file.save(file_path)
|
||||||
|
|
||||||
|
return {"message": f"Datei {file.filename} erfolgreich gespeichert!"}, 200
|
||||||
|
|
||||||
|
|
||||||
|
# für Docker wichtig: host='0.0.0.0'
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run(debug=True, host="0.0.0.0")
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
Flask
|
||||||
|
black
|
||||||
|
flake8
|
||||||
|
pre-commit
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
{"text": "Das geplante Projektvolumen beträgt 120 Mio. €.", "entities": [[28, 44, "KENNZAHL"]]}
|
||||||
|
{"text": "Das geplante Projektvolumen beträgt 120 Mio. €.", "entities": [[28, 44, "KENNZAHL"]]}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
import streamlit as st
|
||||||
|
import json
|
||||||
|
|
||||||
|
st.title("Neue Kennzahl annotieren")
|
||||||
|
|
||||||
|
text = st.text_area("Text", "Das geplante Projektvolumen beträgt 120 Mio. €.")
|
||||||
|
start = st.number_input("Start-Position", min_value=0, max_value=len(text), value=28)
|
||||||
|
end = st.number_input("End-Position", min_value=0, max_value=len(text), value=44)
|
||||||
|
label = st.text_input("Label (z. B. KENNZAHL)", "KENNZAHL")
|
||||||
|
|
||||||
|
if st.button("Speichern"):
|
||||||
|
example = {"text": text, "entities": [[start, end, label]]}
|
||||||
|
|
||||||
|
with open("annotated_data.json", "a", encoding="utf-8") as f:
|
||||||
|
f.write(json.dumps(example, ensure_ascii=False) + "\n")
|
||||||
|
|
||||||
|
st.success("✅ Annotation gespeichert!")
|
||||||
Loading…
Reference in New Issue