File size: 1,806 Bytes
9884451
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
"""Digest renderer — turns top-N ranked items into a readable briefing."""
from __future__ import annotations

import json

from config import DIGEST_TOP_N
from rank import RankerConfig, _chat


_DIGEST_SYSTEM = "You write tight, useful AI-news briefings. No fluff."


_DIGEST_PROMPT = """Write a 2-hour AI-news briefing from the items below.

RULES:
- Group by theme if obvious (Models / Research / Tools / Industry); otherwise a flat list.
- Each item: 1-2 lines in plain English. End the item with the URL on its own line.
- Lead with WHAT CHANGED and WHY IT MATTERS — not the source name.
- No markdown headers, no bold asterisks. Optional bullet (•).
- Skip items that are obvious duplicates or hype with no concrete new info.
- Close with a one-line meta note ("3 from labs, 2 from research, 1 from tools" style).
- Target ~1500 chars total. Stay short. Skip filler.

Items (ranked by importance, highest first):
{items_json}
"""


def make_digest(ranked: list[dict], cfg: RankerConfig | None = None) -> str:
    """Render the top-N ranked items as a readable briefing."""
    if not ranked:
        return "_(no high-signal items in window)_"
    cfg = cfg or RankerConfig()
    top = ranked[:DIGEST_TOP_N]
    indexed = [
        {
            "source":  it.get("source", ""),
            "title":   (it.get("title") or "")[:200],
            "url":     it.get("url", ""),
            "summary": (it.get("summary") or "")[:300],
            "score":   it.get("score", 5),
            "reason":  it.get("reason", ""),
        }
        for it in top
    ]
    return _chat(
        cfg,
        _DIGEST_SYSTEM,
        _DIGEST_PROMPT.format(items_json=json.dumps(indexed, ensure_ascii=False, indent=2)),
        json_mode=False,
        temperature=0.3,
        max_tokens=2000,
    ).strip()