diff --git a/.gitignore b/.gitignore index b916b35..5454ac3 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,6 @@ output/* # Python cache __pycache__ *.pyc -.pytest_cache/ \ No newline at end of file +.pytest_cache/ + +local-run.sh diff --git a/compile_meeting.py b/compile_meeting.py index 1ce7bb8..3ef32e4 100755 --- a/compile_meeting.py +++ b/compile_meeting.py @@ -51,6 +51,12 @@ Rules: - Reorganize by TOPIC, not by conversation order. Merge new info into the right existing section rather than appending chronologically. - Anchor concrete items to the [mm:ss] where they were said/shown. +- ASR vigilance on TERMS, especially acronyms and product/tool names: this + transcript is machine-transcribed, so a term that reads oddly or makes no sense + in context is likely a mis-hearing (a slightly-off acronym, a homophone, a + split or merged word). Flag it like "(heard: X — likely Y?)", using context to + infer the intended term; never silently propagate a nonsensical token, and + never silently "correct" a term you are unsure about. - If something is unclear or only partially stated, mark it (e.g. "(unclear)") rather than guessing.""" @@ -101,6 +107,19 @@ def default_output(transcript, kind): return transcript.parent / f"{stem}_{kind}.md" +def content_tokens(content): + """Estimate input tokens of a chat content (str or multimodal list).""" + if isinstance(content, str): + return estimate_tokens(content) + total = 0 + for part in content: + if part.get("type") == "text": + total += estimate_tokens(part.get("text", "")) + else: # image_url etc. — rough per-image vision-token allowance + total += 800 + return total + + def parse_windows(path, window_tokens): """Split the enhanced transcript into windows of ~window_tokens, packing blank-line-separated blocks whole. Each window keeps the frame refs that @@ -208,7 +227,8 @@ def main(): p.add_argument("--api-key", default="local") p.add_argument("--frames", choices=["ondemand", "window", "none"], default="ondemand") p.add_argument("--window-tokens", type=int, default=3500, help="transcript tokens per refine step (default 3500)") - p.add_argument("--max-tokens", type=int, default=8192, help="generation cap; must fit the growing doc (default 8192)") + p.add_argument("--max-tokens", type=int, default=8192, help="upper bound on generation; auto-capped to fit --ctx (default 8192)") + p.add_argument("--ctx", type=int, default=16384, help="model context window; output is auto-capped so input+output fit (default 16384)") p.add_argument("--max-image-side", type=int, default=1280, help="downscale frames to this max side (0=off)") p.add_argument("--temperature", type=float, default=0.2) p.add_argument("--checkpoint", type=Path, help="write the running doc here after each window (resumable progress)") @@ -260,9 +280,13 @@ def main(): content = text log(f" window {wi}/{len(windows)}: text-only") - doc = call(client, args.model, - REFINE_SYS.format(instruction=args.instruction, rules=GROUNDING), - content, args.temperature, args.max_tokens) + sys_txt = REFINE_SYS.format(instruction=args.instruction, rules=GROUNDING) + in_tok = content_tokens(content) + estimate_tokens(sys_txt) + out_budget = max(512, min(args.max_tokens, args.ctx - in_tok - 256)) + if in_tok > args.ctx - 512: + log(f" WARNING: doc+window ~{in_tok} tok ≥ ctx {args.ctx}; output will truncate — " + f"use a 32k profile (qwen14b-gguf) or lower --window-tokens for the full training") + doc = call(client, args.model, sys_txt, content, args.temperature, out_budget) if args.checkpoint: args.checkpoint.write_text(doc + "\n") diff --git a/summarize_meeting.py b/summarize_meeting.py index c292b4f..e8040cd 100755 --- a/summarize_meeting.py +++ b/summarize_meeting.py @@ -54,7 +54,11 @@ Rules you must follow: - The transcript is machine-generated and may contain ASR errors; prefer the most consistent reading across the whole transcript over any single garbled line, and flag a name/term you are unsure about rather than normalizing it - silently.""" + silently. +- Pay special attention to acronyms and product/tool names: a slightly-off + acronym or a homophone that makes no sense in context is almost certainly an + ASR mis-hearing — flag it as "(heard: X — likely Y?)" using context to infer + the intended term, rather than repeating the nonsensical form.""" MAP_SYSTEM = """\ You are condensing ONE chunk of a longer meeting transcript.