v2.4 — Character Editor + Image-to-Image Portrait Consistency
Features:
- /edit/{name} route: Character nachträglich bearbeiten
- /api/character/update/{name}: API zum Aktualisieren
- create.html dient als Editor und Creator (mode=edit/create)
- Index-Seite: ✏️ Button pro Character
- Portrait-Vorschau im Editor
- Image-to-Image: Folge-Portraits nutzen bestehendes Bild als Referenz
- LoadImage → ImageScale → VAEEncode → KSampler (denoise=0.45)
- Aussehen bleibt konsistent über mehrere Generierungen
- Fallback auf Text-to-Image wenn kein Referenzbild existiert
- ComfyUI Image Upload via /upload/image API
- Jinja2 if-Expressions für vorausgefüllte Formularfelder
This commit is contained in:
@@ -295,7 +295,17 @@ async def index(request: Request, session_id: str = Cookie(None, alias=SESSION_C
|
||||
|
||||
@app.get("/create", response_class=HTMLResponse)
|
||||
async def create_page(request: Request):
|
||||
return templates.TemplateResponse(request, "create.html", {})
|
||||
return templates.TemplateResponse(request, "create.html", {"mode": "create", "character": None})
|
||||
|
||||
@app.get("/edit/{character_name}", response_class=HTMLResponse)
|
||||
async def edit_page(request: Request, character_name: str):
|
||||
char = load_character(character_name)
|
||||
safe_name = character_name.lower().replace(" ", "_")
|
||||
return templates.TemplateResponse(request, "create.html", {
|
||||
"mode": "edit",
|
||||
"character": char,
|
||||
"character_filename": safe_name,
|
||||
})
|
||||
|
||||
@app.get("/chat/{character_name}", response_class=HTMLResponse)
|
||||
async def chat_page(request: Request, character_name: str, session_id: str = Cookie(None, alias=SESSION_COOKIE_NAME)):
|
||||
@@ -463,6 +473,34 @@ async def api_create_character(request: Request):
|
||||
|
||||
return JSONResponse({"status": "ok", "character": safe_name})
|
||||
|
||||
@app.post("/api/character/update/{character_name}")
|
||||
async def api_update_character(character_name: str, request: Request):
|
||||
"""Aktualisiert einen bestehenden Character."""
|
||||
path = CHARACTERS_DIR / f"{character_name}.json"
|
||||
if not path.exists():
|
||||
raise HTTPException(status_code=404, detail=f"Character {character_name} not found")
|
||||
|
||||
body = await request.json()
|
||||
|
||||
# Load existing, update fields
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
char = json.load(f)
|
||||
|
||||
# Update all fields
|
||||
for key in ["name", "avatar", "description", "personality", "background",
|
||||
"behavior", "tone", "scenario", "nsfw", "greeting", "model", "temperature"]:
|
||||
if key in body:
|
||||
char[key] = body[key]
|
||||
|
||||
# Update appearance
|
||||
if "appearance" in body:
|
||||
char["appearance"] = body["appearance"]
|
||||
|
||||
with open(path, "w", encoding="utf-8") as f:
|
||||
json.dump(char, f, indent=2, ensure_ascii=False)
|
||||
|
||||
return JSONResponse({"status": "ok", "character": character_name})
|
||||
|
||||
@app.get("/api/character/{name}")
|
||||
async def api_get_character(name: str):
|
||||
char = load_character(name)
|
||||
|
||||
Reference in New Issue
Block a user