ch404 commited on
Commit
348e214
·
1 Parent(s): 607e6d2

First commit

Browse files
__init__.py ADDED
File without changes
app/card_renderer.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from PIL import Image, ImageDraw, ImageFont
2
+ import uuid
3
+ from pathlib import Path
4
+
5
+ def generate_card(tarot_id: int, symbol_ids: list[int], text: str) -> str:
6
+ base_path = Path(__file__).parent
7
+ tarot_img = Image.open(base_path / f"assets/images/base/{tarot_id}.png").convert("RGBA")
8
+
9
+ # Symbole hinzufügen
10
+ for sid in symbol_ids:
11
+ symbol = Image.open(base_path / f"assets/images/symbols/{sid}.png").convert("RGBA")
12
+ tarot_img.paste(symbol, (50 + sid*10, 400), symbol) # Positionierung frei wählbar
13
+
14
+ # Text hinzufügen
15
+ draw = ImageDraw.Draw(tarot_img)
16
+ font = ImageFont.truetype(str(base_path / "assets/fonts/hand.ttf"), 20)
17
+ draw.text((50, tarot_img.height - 150), text, font=font, fill="black")
18
+
19
+ # Speichern
20
+ output_dir = base_path / "assets/images/generated"
21
+ output_dir.mkdir(exist_ok=True)
22
+ file_id = str(uuid.uuid4())
23
+ output_path = output_dir / f"{file_id}.png"
24
+ tarot_img.save(output_path)
25
+
26
+ return file_id # nur ID zurückgeben
app/constraints.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # constraints.py
2
+ # Constraints: Begriffe prüfen, Filter
3
+
4
+ def check_constraints(output: str, terms: list[str]) -> bool:
5
+ return all(term.lower() in output.lower() for term in terms)
6
+
7
+ def generate_with_retry(prompt, generator, terms, max_retries=3):
8
+ for _ in range(max_retries):
9
+ response = generator(prompt)[0]["generated_text"]
10
+ if check_constraints(response, terms):
11
+ return response
12
+ return "Leider konnte kein gültiger Text erzeugt werden."
app/generator.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+
4
+
5
+ from jinja2 import Template
6
+ from pathlib import Path
7
+ import datetime
8
+
9
+ """ MMDD → MM = Monat, DD = Tag
10
+ 120 = 01.20. → Ende Steinbock
11
+ 218 = 02.18. → Ende Wassermann
12
+ """
13
+
14
+ def get_zodiac(birthdate: str) -> str:
15
+ """Leitet das Sternzeichen aus dem Geburtsdatum ab."""
16
+ date = datetime.datetime.strptime(birthdate, "%Y-%m-%d").date()
17
+ zodiacs = [
18
+ (120, "Steinbock"), (218, "Wassermann"), (320, "Fische"), (420, "Widder"),
19
+ (521, "Stier"), (621, "Zwillinge"), (722, "Krebs"), (823, "Löwe"),
20
+ (923, "Jungfrau"), (1023, "Waage"), (1122, "Skorpion"), (1222, "Schütze"), (1231, "Steinbock")
21
+ ]
22
+ date_as_number = int(f"{date.month:02d}{date.day:02d}")
23
+ for boundary, sign in zodiacs:
24
+ if date_as_number <= boundary:
25
+ return sign
26
+ return "Steinbock"
27
+
28
+ def build_prompt(lang: str, birthdate: str, terms: list[str]) -> str:
29
+ template_path = Path(__file__).parent / "templates" / lang / "base.txt"
30
+ if not template_path.exists():
31
+ raise FileNotFoundError(f"Template nicht gefunden: {template_path}")
32
+
33
+ template = Template(template_path.read_text(encoding="utf-8"))
34
+ sternzeichen = get_zodiac(birthdate)
35
+
36
+ prompt = template.render(
37
+ birthdate=birthdate,
38
+ terms=', '.join(terms),
39
+ sternzeichen=sternzeichen
40
+ )
41
+ return prompt
app/hf_api.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ # hf_api.py
2
+ # Optional: HuggingFace API-Wrapper
app/lora_config.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ # lora_config.py
2
+ # LoRA-Config (separat gehalten für Training)
app/main.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from fastapi import FastAPI, Request
3
+ from pydantic import BaseModel
4
+ from generator import build_prompt, generate_with_retry
5
+ from model_loader import generator
6
+
7
+ SECRET_KEY = os.getenv("SECRET_KEY")
8
+
9
+ app = FastAPI()
10
+
11
+ class GenRequest(BaseModel):
12
+ birthdate: str
13
+ terms: list[str]
14
+
15
+ @app.post("/generate")
16
+ def generate_text(req: GenRequest):
17
+ prompt = build_prompt(req.birthdate, req.terms)
18
+ output = generate_with_retry(prompt, generator, req.terms)
19
+ return {"output": output}
app/model_loader.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ # model_loader.py
2
+ # LLM laden (lokal oder remote)
app/qr_utils.py ADDED
File without changes
assets/fonts/hand.ttf ADDED
Binary file (72.3 kB). View file
 
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn[standard]
3
+ jinja2
4
+ qrcode
5
+ pillow
6
+ transformers
7
+ peft
templates/de/base.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Erstelle ein humorvolles, sex-positives Horoskop im Tarot-Stil.
2
+
3
+ Eingaben:
4
+ - Geburtsdatum: {{birthdate}}
5
+ - Begriffe: {{terms}}
6
+
7
+ Format:
8
+ Titel: [Kreativer Titel]
9
+ Sternzeichen: [aus Geburtsdatum ableiten]
10
+ Text:
11
+ [3–5 Sätze, die alle Begriffe enthalten, lustig, doppeldeutig, aber niemals beleidigend oder vulgär]
templates/en/base.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Erstelle ein humorvolles, sex-positives Horoskop im Tarot-Stil.
2
+
3
+ Eingaben:
4
+ - Geburtsdatum: {{birthdate}}
5
+ - Begriffe: {{terms}}
6
+
7
+ Format:
8
+ Titel: [Kreativer Titel]
9
+ Sternzeichen: [aus Geburtsdatum ableiten]
10
+ Text:
11
+ [3–5 Sätze, die alle Begriffe enthalten, lustig, doppeldeutig, aber niemals beleidigend oder vulgär]