feat: AI-generated title+tldr, subfolder structure, backlinks in transkript/zusammenfassung
- llm: generate_title_and_tldr() returns concise title and 2-3 sentence summary
- output: index in root, transkript+zusammenfassung in {base}/ subdir with backlinks
- pipeline: call generate_title_and_tldr for both solo and meeting recordings
- router: mirror subdir structure when copying to Obsidian vault
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+6
-8
@@ -81,13 +81,8 @@ async def _run_solo_pipeline(cfg, wav_path, output_dir, instructions):
|
||||
)
|
||||
|
||||
dt = datetime.now()
|
||||
paths = write_solo_docs(raw_text=raw_text, refined=refined, output_dir=output_dir, dt=dt)
|
||||
|
||||
title = "Diktat"
|
||||
for line in refined.splitlines():
|
||||
if line.startswith("# "):
|
||||
title = line[2:].strip()
|
||||
break
|
||||
title, tldr = await client.generate_title_and_tldr(refined, model=cfg["ollama"]["model"])
|
||||
paths = write_solo_docs(raw_text=raw_text, refined=refined, output_dir=output_dir, dt=dt, title=title, tldr=tldr)
|
||||
|
||||
await state.set_status(Status.IDLE)
|
||||
await broadcast({
|
||||
@@ -152,6 +147,7 @@ async def _run_meeting_pipeline(cfg, wav_path, output_dir, instructions, diar_cf
|
||||
|
||||
transcript_text = "\n\n".join(f"**{spk}:** {txt}" for spk, txt in named_aligned)
|
||||
summary = await client.summarize(transcript_text, model=cfg["ollama"]["model"])
|
||||
title, tldr = await client.generate_title_and_tldr(summary, model=cfg["ollama"]["model"])
|
||||
|
||||
dt = datetime.now()
|
||||
paths = write_meeting_docs(
|
||||
@@ -161,13 +157,15 @@ async def _run_meeting_pipeline(cfg, wav_path, output_dir, instructions, diar_cf
|
||||
duration_min=duration_min,
|
||||
output_dir=output_dir,
|
||||
dt=dt,
|
||||
title=title,
|
||||
tldr=tldr,
|
||||
)
|
||||
|
||||
await state.set_status(Status.IDLE)
|
||||
await broadcast({
|
||||
"event": "saved",
|
||||
"path": paths["index"],
|
||||
"title": f"Meeting {dt.strftime('%d.%m.%Y %H:%M')}",
|
||||
"title": title,
|
||||
"meeting": True,
|
||||
"paths": paths,
|
||||
})
|
||||
|
||||
+9
-5
@@ -223,22 +223,26 @@ async def open_file(body: dict, user: dict = Depends(current_user)):
|
||||
from urllib.parse import quote
|
||||
cfg = load_config()
|
||||
vault = cfg.get("obsidian", {}).get("vault", "").strip()
|
||||
# If only the index was passed, also include sibling transkript/zusammenfassung
|
||||
# If only the index was passed, also include siblings from subdir
|
||||
all_paths = list(paths)
|
||||
for p in paths:
|
||||
if p.endswith("-index.md"):
|
||||
base = p[: -len("-index.md")]
|
||||
base = os.path.basename(p)[: -len("-index.md")]
|
||||
subdir = os.path.join(os.path.dirname(p), base)
|
||||
for suffix in ("-transkript.md", "-zusammenfassung.md"):
|
||||
sibling = base + suffix
|
||||
sibling = os.path.join(subdir, base + suffix)
|
||||
if os.path.exists(sibling) and sibling not in all_paths:
|
||||
all_paths.append(sibling)
|
||||
|
||||
open_target = all_paths[0]
|
||||
if vault and os.path.isdir(vault):
|
||||
# Mirror directory structure: index → vault root, others → vault/{base}/
|
||||
for p in all_paths:
|
||||
dest = os.path.join(vault, os.path.basename(p))
|
||||
rel = os.path.relpath(p, abs_user_dir)
|
||||
dest = os.path.join(vault, rel)
|
||||
os.makedirs(os.path.dirname(dest), exist_ok=True)
|
||||
shutil.copy2(p, dest)
|
||||
open_target = os.path.join(vault, os.path.basename(all_paths[0]))
|
||||
open_target = os.path.join(vault, os.path.relpath(all_paths[0], abs_user_dir))
|
||||
vault_name = os.path.basename(vault.rstrip("/")) if vault else ""
|
||||
file_name = os.path.basename(open_target)
|
||||
if vault_name:
|
||||
|
||||
Reference in New Issue
Block a user