FeedSummary är en liten pipeline + webbapp för att:
- hämta artiklar via RSS,
- extrahera brödtext,
- batch-summera med en LLM,
- skapa en metasammanfattning,
- spara resultatet som
summary_docsoch visa i ett enkelt web-UI.
Färdiga moduler för att använda Ollama Cloud eller Ollama Local, med fallback-policy, som LLM finns men det är möjligt att lägga till moduler för andra LLMer.
Moduler för att lagra data i en flatfile JSON-databas (TinyDB) eller SQLite finns färdigt, men moduler för andra lagringsformat kan läggas till och användas.
Det var längesen jag kodade något större och även om jag förespråkar TDD så lever jag inte som jag lär. Koden är väldigt mycket på formen "just works" och innehåller både dupliceringar, döda funktioner och allmänt håriga konstruktioner.
You've been warned...
Kopiera exempelkonfigen:
cp config.yaml.dist config.yamlJustera minst:
llm.api_key(om du körollama_cloud)- paths för store/checkpoints om du vill
Repo:t innehåller inte alltid en låst requirements-fil, men koden använder typiskt:
- flask
- pyyaml
- markdown
- tinydb (om store=TinyDB)
- aiohttp
- feedparser
- trafilatura
- aiolimiter
- tenacity
Exempel:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtStarta servern:
python webapp.pyÖppna sedan:
Du kan peka på en annan config med env-var:
FEEDSUMMARY_CONFIG=/path/till/config.yaml python webapp.pyStartsidan visar:
- en sidomeny med tidigare sammanfattningar (från
summary_docs) - den valda sammanfattningen renderad som HTML (Markdown → HTML)
- en statusrad som visar körningsstatus (SSE)
Knappen Refresh öppnar en modal där du väljer:
- Tidsperspektiv (lookback)
- t.ex.
24h,3d,1wosv. - styr vilka RSS-items som hämtas och vilka artiklar som väljs till sammanfattningen.
- Prompt-paket
- väljer ett promptpaket ur
config/prompts.yaml - valet gäller per körning (UI skickar override)
- Ämnen (topics) (om dina feeds har
topics)
- markerar matchande källor automatiskt
- om du inte manuellt markerar källor kan körningen göras baserat på ämnen
- Källor (sources)
- checkboxlista över feeds
- “Markera alla / Avmarkera alla”
När du trycker Kör refresh startas en pipeline i bakgrunden. UI lyssnar på status via SSE och uppdaterar statusrad.
Visar en lista över artiklar i store och har filter (infällbar panel):
- datumintervall (
from/to) - ämnen (topics)
- källor (sources)
Om du väljer ämnen markeras matchande källor i UI. På servern gäller:
- om
sourcesär valda → filtrera på exakt de källorna - annars om
topicsär valda → härled tillåtna källor från config och filtrera på dem
- Ingest
- Hämtar RSS via
feedparser - Filtrerar per lookback (t.ex. 1 dygn)
- Extraherar brödtext med
trafilatura - Sparar artiklar i store (
articles)
- Urval
- Väljer artiklar för sammanfattning baserat på:
- lookback
- valda källor (eller härledda via ämnen)
- (store kan ha
list_articles_by_filterför effektivare urval)
- Summering
- Artiklar batchas (max antal / max chars)
- För varje batch: LLM skapar batch-sammanfattning
- Meta-steget bygger en övergripande sammanfattning från batch-sammanfattningarna
- Resultatet sparas som
summary_doc
- Ämnesindelade sammanfattningar (valfritt/om aktiverat i koden) Om du har topic-baserad pipeline:
- artiklar grupperas per “primärt ämne” (första taggen på källan)
- en sammanfattning körs per ämnesområde
- slutresultatet blir ett dokument med en sektion per ämne
summary_docinnehåller bådesummary(hela dokumentet) ochsections[](per ämne)
Baseras ofta på config.yaml.dist.
Väljer lagring. Exempel TinyDB:
store:
provider: tinydb
path: ~/.local/share/FeedSummary/news_docs.jsonOm du har SQLite-stöd:
store:
provider: sqlite
path: ~/.local/share/FeedSummary/news_docs.sqliteCheckpoint/resume för långkörningar:
checkpointing:
enabled: true
dir: ~/.local/share/FeedSummary/checkpointsPekar ut feeds-filen:
feeds:
path: "config/feeds.yaml"Ingest-beteende:
ingest:
lookback: 1d
max_items_per_feed: 100
article_timeout_s: 20lookback: hur långt bak RSS-items tas med.max_items_per_feed: safety cap per feed.article_timeout_s: timeout när en artikel hämtas.
Batch- och meta-budgets:
batching:
max_articles_per_batch: 15
max_chars_per_batch: 14500
article_clip_chars: 3500
meta_batch_clip_chars: 1500
meta_sources_clip_chars: 100
retry_user_clip_chars: 9000max_articles_per_batch: max artiklar i en batch.max_chars_per_batch: max textmängd per batch (tecken).article_clip_chars: klipper varje artikeltext.meta_*: styr hur mycket som får plats i meta-steget.
Primary LLM och fallback:
llm:
provider: ollama_cloud
host: https://ollama.com
model: gemma3:27b-cloud
api_key: CHANGE-ME
context_window_tokens: 24576
max_output_tokens: 500
prompt_safety_margin: 1600
token_chars_per_token: 2.4
prompt_too_long_max_attempts: 6
prompt_too_long_structural_threshold_tokens: 1200
quota:
preflight: true
min_interval_seconds: 2
llm_fallback:
provider: ollama_local
model: gemma3:1b
base_url: http://localhost:11434
max_rps: 1
timeout_s: 6000
sock_read_timeout_s: 360
max_retries: 3
retry_backoff_s: 2.0
context_window_tokens: 24576
max_output_tokens: 500
prompt_safety_margin: 1600
token_chars_per_token: 2.4
prompt_too_long_max_attempts: 6
prompt_too_long_structural_threshold_tokens: 1200Viktiga begrepp:
context_window_tokens: total plats för input+output.max_output_tokens: hur långt svaret får bli.prompt_safety_margin: buffert för att undvika att slå i context-taket.
Listar RSS-källor. Minsta fält:
name: källnamn (används somsource)url: RSS/Atom URL
Exempel:
- name: SVT
url: https://www.svt.se/rss.xmlValfria fält:
Ämnestaggar för UI-snabbval och ämnesindelad summering:
- name: CERT-SE
url: https://www.cert.se/feed.rss
topics: ["Cyber", "Sårbarheter", "Sverige"]Om ämnesindelning används blir första topic ofta “primär”.
Filter per feed baserat på RSS-entry tags/kategorier:
- name: TV4
url: https://www.tv4.se/rss
category_include: ["Inrikes", "Utrikes"]Innehåller prompt-paket (”packages”). Varje package är en nyckel i YAML och innehåller fyra fält:
batch_systembatch_user_templatemeta_systemmeta_user_template
Exempelstruktur:
MyPackage:
batch_system: |
...
batch_user_template: |
... {articles_corpus} ...
meta_system: |
...
meta_user_template: |
... {batch_summaries} ...Vanliga placeholders:
{articles_corpus}: injiceras i batch-steget (artiklar + metadata){batch_summaries}: injiceras i meta-steget
I config.yaml väljer du default/selected:
prompts:
path: "config/prompts.yaml"
default_package: "SecurityAnalyst"
selected: "" # tom => default; webapp kan override per körning- Om inga artiklar kommer med:
- öka
ingest.lookback - kontrollera att dina feeds svarar och att artikelsidorna går att hämta
- öka
- Om LLM klagar på för lång prompt:
- minska
batching.max_chars_per_batch - minska
batching.article_clip_chars - öka
llm.context_window_tokens(om modellen stödjer) - eller minska
llm.max_output_tokensoch/eller ökaprompt_safety_margin
- minska
- Om UI visar “Status-anslutning bröts”:
- refresh-sidan reloadas normalt när jobbet blir
done - annars kontrollera serverloggar
- refresh-sidan reloadas normalt när jobbet blir
BSD 3-Clause (se headers i källfilerna).
- C. Strömblad för inspiration till detta lilla projekt