update
This commit is contained in:
@@ -24,7 +24,7 @@ from database import list_guides, update_guide
|
||||
from fsutil import atomic_write_json
|
||||
from jsonio import read_json_file as _json_datei
|
||||
from onepager import _generate_onepager
|
||||
from paths import bausteine_path, guide_content_path, project_dir
|
||||
from paths import bausteine_path, guide_content_path, project_dir, subbausteine_path
|
||||
from pipeline import (
|
||||
CANCELLED, FAILED, GenContext, _claude_error, _extra,
|
||||
_fail, _gather_error, _log, _prompt, _race, _rest_schema, _runde_schema,
|
||||
@@ -47,6 +47,41 @@ WRITER_SECTIONS = 30
|
||||
WRITER_MAX = 20
|
||||
|
||||
|
||||
def _load_subbausteine(topic: str) -> dict[str, list[dict]]:
|
||||
"""Sidecar laden: {Baustein-Titel: [{titel, stufe}, …]}. Fehlt sie → {} (Fallback)."""
|
||||
data = _json_datei(subbausteine_path(topic))
|
||||
if not isinstance(data, dict):
|
||||
return {}
|
||||
out: dict[str, list[dict]] = {}
|
||||
for titel, subs in data.items():
|
||||
if not isinstance(subs, list):
|
||||
continue
|
||||
gut = [s for s in subs if isinstance(s, dict) and str(s.get("titel", "")).strip()
|
||||
and s.get("stufe") in ("einfach", "mittel", "schwer")]
|
||||
if gut:
|
||||
out[titel] = gut
|
||||
return out
|
||||
|
||||
|
||||
def _section_markup(sec: dict) -> str:
|
||||
"""Section-Text mit Sub-Markern (für Lese-Check/Fix), damit die Struktur erhalten bleibt."""
|
||||
if not sec.get("subs"):
|
||||
return sec["md"]
|
||||
return "\n\n".join(f"<!-- sub: {s['stufe']} | {s['titel']} -->\n{s['md']}" for s in sec["subs"])
|
||||
|
||||
|
||||
def _zuteilung_subs(chunk: list[dict], entries: dict[int, str], subs_by_titel: dict[str, list[dict]]) -> str:
|
||||
"""Wie _zuteilung_text, aber listet pro Baustein seine Subbausteine mit Stufe."""
|
||||
lines: list[str] = []
|
||||
for ch in chunk:
|
||||
lines.append(f"KAPITEL: {ch['title']}")
|
||||
for num in ch["nums"]:
|
||||
lines.append(f"- {entries[num]}")
|
||||
for s in subs_by_titel.get(_titel(entries[num]), []):
|
||||
lines.append(f" [{s['stufe']}] {s['titel']}")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def _guide_files(content_path: Path) -> dict:
|
||||
d, stem = content_path.parent, content_path.stem
|
||||
runden = range(1, KONSENS_MAX_RUNDEN + 1)
|
||||
@@ -459,7 +494,10 @@ async def _generate_sections(
|
||||
# dieselbe Aufteilung: 1 Agent je ~30 Bausteine (gedeckelt).
|
||||
total_sections = sum(len(c["nums"]) for c in plan)
|
||||
chunks = _split_chunks(plan, min(WRITER_MAX, max(1, math.ceil(total_sections / WRITER_SECTIONS))))
|
||||
zuteilungen = [_zuteilung_text(chunk, entries) for chunk in chunks]
|
||||
# Subbausteine je Baustein (Sidecar). Fehlt sie → leer → Inhalte/Writer laufen
|
||||
# auf Baustein-Granularität weiter (Fallback für Alt-Themen ohne Sidecar).
|
||||
subs_by_titel = _load_subbausteine(topic)
|
||||
zuteilungen = [_zuteilung_subs(chunk, entries, subs_by_titel) for chunk in chunks]
|
||||
chunk_sizes = [sum(len(c["nums"]) for c in chunk) for chunk in chunks]
|
||||
writer_count = len(chunks)
|
||||
idx = _titel_index(entries)
|
||||
@@ -616,11 +654,11 @@ async def _generate_sections(
|
||||
chunk_nums = [[num for ch in chunk for num in ch["nums"] if num in by_num] for chunk in chunks]
|
||||
|
||||
def sections_text(nums: list[int]) -> str:
|
||||
return "\n\n".join(f"SECTION: {_titel(entries[num])}\n{by_num[num]['md']}" for num in nums)
|
||||
return "\n\n".join(f"SECTION: {_titel(entries[num])}\n{_section_markup(by_num[num])}" for num in nums)
|
||||
|
||||
def auftraege_text(nums: list[int], probleme: dict[int, str]) -> str:
|
||||
return "\n\n".join(
|
||||
f"SECTION: {_titel(entries[num])}\nPROBLEM: {probleme[num]}\nAKTUELLER INHALT:\n{by_num[num]['md']}"
|
||||
f"SECTION: {_titel(entries[num])}\nPROBLEM: {probleme[num]}\nAKTUELLER INHALT:\n{_section_markup(by_num[num])}"
|
||||
for num in nums
|
||||
)
|
||||
|
||||
@@ -702,12 +740,16 @@ async def _generate_sections(
|
||||
scope = [[num for num in nums if num in ersetzt] for nums in chunk_nums]
|
||||
|
||||
await _set_progress(guide_id, "Setze zusammen…")
|
||||
def _section(num: int) -> dict:
|
||||
sec = by_num[num]
|
||||
d = {"num": num, "title": _titel(entries[num]), "md": sec["md"]}
|
||||
if sec.get("subs"):
|
||||
d["subbausteine"] = [{"stufe": s["stufe"], "titel": s["titel"], "md": s["md"]} for s in sec["subs"]]
|
||||
return d
|
||||
|
||||
chapters: list[dict] = []
|
||||
for ch in plan:
|
||||
sections = [
|
||||
{"num": num, "title": _titel(entries[num]), "md": by_num[num]["md"]}
|
||||
for num in ch["nums"] if num in by_num
|
||||
]
|
||||
sections = [_section(num) for num in ch["nums"] if num in by_num]
|
||||
if sections:
|
||||
chapters.append({"title": ch["title"], "sections": sections})
|
||||
geplant = {num for ch in plan for num in ch["nums"]}
|
||||
|
||||
Reference in New Issue
Block a user